creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "src/settled-physical/CrossMarginPhysicalEngine.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\n// imported contracts and libraries\nimport {UUPSUpgradeable} from \"openzeppelin/proxy/utils/UUPSUpgradeable.sol\";\nimport {OwnableUpgradeable} from \"openzeppelin-upgradeable/access/OwnableUpgradeable.sol\";\nimport {ReentrancyGuardUpgradeable} from \"openzeppelin-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport {SafeCast} from \"openzeppelin/utils/math/SafeCast.sol\";\n\n// inheriting contracts\nimport {BaseEngine} from \"pomace/core/engines/BaseEngine.sol\";\nimport {AccountPhysicalEngine} from \"./AccountPhysicalEngine.sol\";\n\n// interfaces\nimport {IAuthority} from \"entitlements/src/interfaces/IAuthority.sol\";\nimport {IMarginEngine} from \"pomace/interfaces/IMarginEngine.sol\";\nimport {IWhitelist} from \"pomace/interfaces/IWhitelist.sol\";\nimport {IOracle} from \"pomace/interfaces/IOracle.sol\";\n\n// libraries\nimport {BalanceUtil} from \"pomace/libraries/BalanceUtil.sol\";\nimport {ProductIdUtil} from \"pomace/libraries/ProductIdUtil.sol\";\nimport {TokenIdUtil} from \"pomace/libraries/TokenIdUtil.sol\";\nimport {UintArrayLib} from \"array-lib/UintArrayLib.sol\";\n\n// Cross margin libraries\nimport {AccountUtil} from \"../libraries/AccountUtil.sol\";\nimport {CrossMarginPhysicalMath} from \"./CrossMarginPhysicalMath.sol\";\nimport {CrossMarginPhysicalLib} from \"./CrossMarginPhysicalLib.sol\";\n\n// Cross margin types\nimport \"./types.sol\";\nimport \"../config/errors.sol\";\n\n// global constants and types\nimport {BatchExecute, ActionArgs} from \"pomace/config/types.sol\";\nimport \"pomace/config/enums.sol\";\nimport \"pomace/config/constants.sol\";\nimport \"pomace/config/errors.sol\";\nimport {Role} from \"entitlements/src/config/enums.sol\";\n\n/**\n * @title   CrossMarginPhysicalEngine\n * @author  @dsshap, @antoncoding\n * @notice  Fully collateralized margin engine\n *             Users can deposit collateral into Cross Margin and mint optionTokens (debt) out of it.\n *             Interacts with PhysicalOptionToken to mint / burn\n *             Interacts with pomace to fetch registered asset info\n */\ncontract CrossMarginPhysicalEngine is\n    AccountPhysicalEngine,\n    IMarginEngine,\n    OwnableUpgradeable,\n    ReentrancyGuardUpgradeable,\n    UUPSUpgradeable\n{\n    using AccountUtil for Position[];\n    using BalanceUtil for Balance[];\n    using CrossMarginPhysicalLib for CrossMarginAccount;\n    using ProductIdUtil for uint32;\n    using SafeCast for uint256;\n    using SafeCast for int256;\n    using TokenIdUtil for uint256;\n\n    /*///////////////////////////////////////////////////////////////\n                            Immutables\n    //////////////////////////////////////////////////////////////*/\n\n    /// @dev initial chain id used in domain separator\n    uint256 public immutable initialChainId;\n\n    /// @notice authority to check entitlements\n    IAuthority public immutable authority;\n\n    /*///////////////////////////////////////////////////////////////\n                         State Variables V1\n    //////////////////////////////////////////////////////////////*/\n\n    ///@dev subAccount => CrossMarginAccount structure.\n    ///     subAccount can be an address similar to the primary account, but has the last 8 bits different.\n    ///     this give every account access to 256 sub-accounts\n    mapping(address => CrossMarginAccount) internal accounts;\n\n    ///@dev ***DEPRECATED*** contract that verifies permissions\n    ///     if not set allows anyone to transact\n    ///     checks msg.sender on execute & batchExecute\n    ///     checks recipient on payCashValue\n    IWhitelist private _w;\n\n    /// @dev token => SettlementTracker\n    mapping(uint256 => SettlementTracker) public tokenTracker;\n\n    /*///////////////////////////////////////////////////////////////\n                         State Variables V2\n    //////////////////////////////////////////////////////////////*/\n\n    /// @dev initial cached domain separator\n    bytes32 public initialDomainSeparator;\n\n    /// @dev nonce for signed messages to prevent replay attacks\n    ///      address => nonce\n    mapping(address => uint256) public nonces;\n\n    /*///////////////////////////////////////////////////////////////\n                Constructor for implementation Contract\n    //////////////////////////////////////////////////////////////*/\n\n    // solhint-disable-next-line no-empty-blocks\n    constructor(address _pomace, address _optionToken, address _authority) BaseEngine(_pomace, _optionToken) initializer {\n        // solhint-disable-next-line reason-string\n        if (_authority == address(0)) revert();\n\n        initialChainId = block.chainid;\n        authority = IAuthority(_authority);\n    }\n\n    /*///////////////////////////////////////////////////////////////\n                            Initializer\n    //////////////////////////////////////////////////////////////*/\n\n    function initialize(address _owner) external initializer {\n        // solhint-disable-next-line reason-string\n        if (_owner == address(0)) revert();\n\n        _transferOwnership(_owner);\n        __ReentrancyGuard_init_unchained();\n\n        initialDomainSeparator = _computeDomainSeparator();\n    }\n\n    /*///////////////////////////////////////////////////////////////\n                        Execute and BatchExecute\n    //////////////////////////////////////////////////////////////*/\n\n    /**\n     * @notice gets access status of an address\n     * @dev if whitelist address is not set, it ignores this\n     * @param _address address\n     */\n    function _checkPermissioned(address _address) internal view {\n        if (!authority.canCall(_address, address(this), msg.sig)) revert NoAccess();\n    }\n\n    /**\n     * @notice execute multiple actions on one subAccounts\n     * @dev    also check access of msg.sender\n     */\n    function _execute(address _subAccount, ActionArgs[] calldata actions) internal {\n        _assertCallerHasAccess(_subAccount);\n\n        // update the account storage and do external calls on the flight\n        for (uint256 i; i < actions.length;) {\n            if (actions[i].action == ActionType.AddCollateral) {\n                _addCollateral(_subAccount, actions[i].data);\n            } else if (actions[i].action == ActionType.RemoveCollateral) {\n                _removeCollateral(_subAccount, actions[i].data);\n            } else if (actions[i].action == ActionType.MintShort) {\n                _mintOption(_subAccount, actions[i].data);\n            } else if (actions[i].action == ActionType.MintShortIntoAccount) {\n                _mintOptionIntoAccount(_subAccount, actions[i].data);\n            } else if (actions[i].action == ActionType.BurnShort) {\n                _burnOption(_subAccount, actions[i].data);\n            } else if (actions[i].action == ActionType.BurnShortInAccount) {\n                _burnOptionFromAccount(_subAccount, actions[i].data);\n            } else if (actions[i].action == ActionType.TransferLong) {\n                _transferLong(_subAccount, actions[i].data);\n            } else if (actions[i].action == ActionType.TransferShort) {\n                _transferShort(_subAccount, actions[i].data);\n            } else if (actions[i].action == ActionType.TransferCollateral) {\n                _transferCollateral(_subAccount, actions[i].data);\n            } else if (actions[i].action == ActionType.AddLong) {\n                _addOption(_subAccount, actions[i].data);\n            } else if (actions[i].action == ActionType.RemoveLong) {\n                _removeOption(_subAccount, actions[i].data);\n            } else if (actions[i].action == ActionType.ExerciseToken) {\n                _exerciseToken(_subAccount, actions[i].data);\n            } else if (actions[i].action == ActionType.SettleAccount) {\n                _settle(_subAccount);\n            } else {\n                revert CM_UnsupportedAction();\n            }\n\n            // increase i without checking overflow\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    /**\n     * @notice batch execute on multiple subAccounts\n     * @dev    check margin after all subAccounts are updated\n     *         because we support actions like `TransferCollateral` that moves collateral between subAccounts\n     */\n    function batchExecute(BatchExecute[] calldata batchActions) external nonReentrant {\n        _checkPermissioned(msg.sender);\n\n        uint256 i;\n        for (i; i < batchActions.length;) {\n            address subAccount = batchActions[i].subAccount;\n            ActionArgs[] calldata actions = batchActions[i].actions;\n\n            _execute(subAccount, actions);\n\n            // increase i without checking overflow\n            unchecked {\n                ++i;\n            }\n        }\n\n        for (i = 0; i < batchActions.length;) {\n            if (!_isAccountAboveWater(batchActions[i].subAccount)) revert BM_AccountUnderwater();\n\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    /**\n     * @notice execute multiple actions on one subAccounts\n     * @dev    check margin all actions are applied\n     */\n    function execute(address _subAccount, ActionArgs[] calldata actions) external override nonReentrant {\n        _checkPermissioned(msg.sender);\n\n        _execute(_subAccount, actions);\n\n        if (!_isAccountAboveWater(_subAccount)) revert BM_AccountUnderwater();\n    }\n\n    /**\n     * @dev hook to be invoked by Grappa to handle custom logic of settlement\n     */\n    function handleExercise(uint256 _tokenId, uint256 _debtPaid, uint256 _amountPaidOut)\n        external\n        override(BaseEngine, IMarginEngine)\n    {\n        _checkIsPomace();\n\n        tokenTracker[_tokenId].totalDebt += _debtPaid.toUint80();\n        tokenTracker[_tokenId].totalPaid += _amountPaidOut.toUint80();\n    }\n\n    /**\n     * @dev gets the amount of debts and payouts that should be recorded for given short position amounts\n     * @dev this function should only be used after expiry to properly socialise all exercised amount to all physical settled options\n     */\n    function getBatchSettlementForShorts(uint256[] calldata _tokenIds, uint256[] calldata _amounts)\n        external\n        view\n        returns (Balance[] memory debts, Balance[] memory payouts)\n    {\n        // payouts and debts will be 0 for physical settlement options because it has\n        // passed the settlement window\n        (debts, payouts) = pomace.batchGetDebtAndPayouts(_tokenIds, _amounts);\n\n        for (uint256 i; i < _tokenIds.length;) {\n            SettlementTracker memory tracker = tokenTracker[_tokenIds[i]];\n\n            // if the token is physical settled and someone exercised within exercise window\n            // we socialized the payout and debt (total amount paid out and received during exercise window)\n            if (tracker.totalDebt > 0) {\n                (Balance memory debt, Balance memory payout) = _socializeSettlement(tracker, _tokenIds[i], _amounts[i]);\n                debts = _addToBalances(debts, debt.collateralId, debt.amount);\n                payouts = _addToBalances(payouts, payout.collateralId, payout.amount);\n            }\n\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    /**\n     * @notice payout to user on settlement.\n     * @dev this can only triggered by Grappa, would only be called on settlement.\n     * @param _asset asset to transfer\n     * @param _sender sender of debt\n     * @param _amount amount\n     */\n    function receiveDebtValue(address _asset, address _sender, uint256 _amount) external {\n        if (_sender == address(this)) return;\n\n        _checkPermissioned(_sender);\n\n        _receiveDebtValue(_asset, _sender, _amount);\n    }\n\n    /**\n     * @notice payout to user on settlement.\n     * @dev this can only triggered by Pomace, would only be called on settlement.\n     * @param _asset asset to transfer\n     * @param _recipient receiver\n     * @param _amount amount\n     */\n    function sendPayoutValue(address _asset, address _recipient, uint256 _amount) external {\n        if (_recipient == address(this)) return;\n\n        _checkPermissioned(_recipient);\n\n        _sendPayoutValue(_asset, _recipient, _amount);\n    }\n\n    /**\n     * @notice get minimum collateral needed for a margin account\n     * @param _subAccount account id.\n     * @return balances array of collaterals and amount (signed)\n     */\n    function getMinCollateral(address _subAccount) external view returns (Balance[] memory) {\n        CrossMarginAccount memory account = accounts[_subAccount];\n        return _getMinCollateral(account);\n    }\n\n    /**\n     * @dev view function to get all shorts, longs and collaterals\n     */\n    function marginAccounts(address _subAccount)\n        external\n        view\n        returns (Position[] memory shorts, Position[] memory longs, Balance[] memory collaterals)\n    {\n        CrossMarginAccount memory account = accounts[_subAccount];\n\n        return (account.shorts, account.longs, account.collaterals);\n    }\n\n    /**\n     * @notice get minimum collateral needed for a margin account\n     * @param shorts positions.\n     * @param longs positions.\n     * @return balances array of collaterals and amount\n     */\n    function previewMinCollateral(Position[] memory shorts, Position[] memory longs) external view returns (Balance[] memory) {\n        CrossMarginAccount memory account;\n\n        account.shorts = shorts;\n        account.longs = longs;\n\n        return _getMinCollateral(account);\n    }\n\n    /**\n     * @notice get collateral amount available after margin requirements\n     * @param shorts positions.\n     * @param longs positions.\n     * @param collaterals balances.\n     * @return addresses array of collateral\n     * @return amounts array of collateral\n     * @return isUnderWater boolean if NOT enough collateral (underwater)\n     */\n    function previewCollateralAvailable(Position[] memory shorts, Position[] memory longs, Balance[] memory collaterals)\n        external\n        view\n        returns (address[] memory, uint256[] memory, bool)\n    {\n        CrossMarginAccount memory account;\n\n        account.shorts = shorts;\n        account.longs = longs;\n        account.collaterals = collaterals;\n\n        return _getCollateralAvailable(account);\n    }\n\n    /**\n     * @notice  grant or revoke an account access to all your sub-accounts based on a signed message\n     * @dev     expected to have a valid signature signed with account private key\n     * @param   _subAccount account which grants the access\n     * @param   _actor account which is granted the access\n     * @param   _allowedExecutions how many times the account is authorized to update your accounts.\n     *          set to max(uint256) to allow permanent access\n     * @param   _v signature v\n     * @param   _r signature r\n     * @param   _s signature s\n     */\n    function permitAccountAccess(\n        address _subAccount,\n        address _actor,\n        uint256 _allowedExecutions,\n        uint8 _v,\n        bytes32 _r,\n        bytes32 _s\n    ) external {\n        // assert valid signature\n        // Unchecked because the only math done is incrementing\n        // the owner's nonce which cannot realistically overflow.\n        unchecked {\n            address recoveredAddress = ecrecover(\n                keccak256(\n                    abi.encodePacked(\n                        \"\\x19\\x01\",\n                        DOMAIN_SEPARATOR(),\n                        keccak256(\n                            abi.encode(\n                                keccak256(\n                                    \"PermitAccountAccess(address subAccount,address actor,uint256 allowedExecutions,uint256 nonce)\"\n                                ),\n                                _subAccount,\n                                _actor,\n                                _allowedExecutions,\n                                nonces[_subAccount]++\n                            )\n                        )\n                    )\n                ),\n                _v,\n                _r,\n                _s\n            );\n\n            if (recoveredAddress == address(0) || recoveredAddress != _subAccount) revert CM_InvalidSignature();\n        }\n\n        // update account access\n        uint160 maskedId = uint160(_subAccount) | 0xFF;\n        allowedExecutionLeft[maskedId][_actor] = _allowedExecutions;\n\n        emit AccountAuthorizationUpdate(maskedId, _actor, _allowedExecutions);\n    }\n\n    /*///////////////////////////////////////////////////////////////\n                                Public Functions\n    //////////////////////////////////////////////////////////////*/\n\n    function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {\n        return block.chainid == initialChainId ? initialDomainSeparator : _computeDomainSeparator();\n    }\n\n    /**\n     * ========================================================= **\n     *             Override Internal Functions For Each Action\n     * ========================================================= *\n     */\n\n    /**\n     * @notice  settle the margin account at expiry\n     * @dev     override this function from BaseEngine\n     *          because we get the payout while updating the storage during settlement\n     * @dev     this update the account storage\n     */\n    function _settle(address _subAccount) internal override {\n        // update the account in state\n        (, Balance[] memory payouts) = accounts[_subAccount].settleShorts();\n        emit AccountSettled(_subAccount, payouts);\n    }\n\n    /**\n     * ========================================================= **\n     *               Override Sate changing functions             *\n     * ========================================================= *\n     */\n\n    /**\n     * @dev mint option token to _subAccount, increase tracker issuance\n     * @param _data bytes data to decode\n     */\n    function _mintOption(address _subAccount, bytes calldata _data) internal virtual override {\n        super._mintOption(_subAccount, _data);\n\n        // decode tokenId\n        (uint256 tokenId,, uint64 amount) = abi.decode(_data, (uint256, address, uint64));\n\n        tokenTracker[tokenId].issued += amount;\n    }\n\n    /**\n     * @dev mint option token into account, increase tracker issuance\n     * @param _data bytes data to decode\n     */\n    function _mintOptionIntoAccount(address _subAccount, bytes calldata _data) internal virtual override {\n        super._mintOptionIntoAccount(_subAccount, _data);\n\n        // decode tokenId\n        (uint256 tokenId,, uint64 amount) = abi.decode(_data, (uint256, address, uint64));\n\n        tokenTracker[tokenId].issued += amount;\n    }\n\n    /**\n     * @dev burn option token from user, decrease tracker issuance\n     * @param _data bytes data to decode\n     */\n    function _burnOption(address _subAccount, bytes calldata _data) internal virtual override {\n        super._burnOption(_subAccount, _data);\n\n        // decode parameters\n        (uint256 tokenId,, uint64 amount) = abi.decode(_data, (uint256, address, uint64));\n\n        tokenTracker[tokenId].issued -= amount;\n    }\n\n    /**\n     * @dev burn option token from user margin account, decrease tracker issuance\n     * @param _data bytes data to decode\n     */\n    function _burnOptionFromAccount(address _subAccount, bytes calldata _data) internal virtual override {\n        super._burnOptionFromAccount(_subAccount, _data);\n\n        // decode parameters\n        (uint256 tokenId,, uint64 amount) = abi.decode(_data, (uint256, address, uint64));\n\n        tokenTracker[tokenId].issued -= amount;\n    }\n\n    function _addCollateralToAccount(address _subAccount, uint8 collateralId, uint80 amount) internal override {\n        accounts[_subAccount].addCollateral(collateralId, amount);\n    }\n\n    function _removeCollateralFromAccount(address _subAccount, uint8 collateralId, uint80 amount) internal override {\n        accounts[_subAccount].removeCollateral(collateralId, amount);\n    }\n\n    function _increaseShortInAccount(address _subAccount, uint256 tokenId, uint64 amount) internal override {\n        accounts[_subAccount].mintOption(tokenId, amount);\n    }\n\n    function _decreaseShortInAccount(address _subAccount, uint256 tokenId, uint64 amount) internal override {\n        accounts[_subAccount].burnOption(tokenId, amount);\n    }\n\n    function _increaseLongInAccount(address _subAccount, uint256 tokenId, uint64 amount) internal override {\n        accounts[_subAccount].addOption(tokenId, amount);\n    }\n\n    function _decreaseLongInAccount(address _subAccount, uint256 tokenId, uint64 amount) internal override {\n        accounts[_subAccount].removeOption(tokenId, amount);\n    }\n\n    function _exerciseTokenInAccount(address _subAccount, uint256 tokenId, uint64 amount) internal override {\n        accounts[_subAccount].exerciseToken(pomace, tokenId, amount);\n    }\n\n    /**\n     * ========================================================= **\n     *          Override view functions for BaseEngine\n     * ========================================================= *\n     */\n\n    /**\n     * @dev because we override _settle(), this function is not used\n     */\n    // solhint-disable-next-line no-empty-blocks\n    function _getAccountPayout(address) internal view override returns (uint8, int80) {}\n\n    /**\n     * @dev return whether if an account is healthy.\n     * @param _subAccount subaccount id\n     * @return isHealthy true if account is in good condition, false if it's underwater (liquidatable)\n     */\n    function _isAccountAboveWater(address _subAccount) internal view override returns (bool) {\n        CrossMarginAccount memory account = accounts[_subAccount];\n\n        // skip margin requirements check if no shorts\n        if (account.shorts.length == 0) return true;\n\n        (,, bool isUnderWater) = _getCollateralAvailable(account);\n        return !isUnderWater;\n    }\n\n    /**\n     * @notice returns the amount collateral being used and if account is underwater.\n     * @param account to check\n     */\n    function _getCollateralAvailable(CrossMarginAccount memory account)\n        internal\n        view\n        returns (address[] memory addresses, uint256[] memory amounts, bool isUnderWater)\n    {\n        Balance[] memory collaterals = account.collaterals;\n        Balance[] memory requirements = _getMinCollateral(account);\n\n        uint256 collatCount = collaterals.length;\n\n        uint256[] memory masks;\n        amounts = new uint256[](collatCount);\n        addresses = new address[](collatCount);\n\n        IOracle oracle;\n\n        unchecked {\n            for (uint256 x; x < requirements.length; ++x) {\n                uint8 reqCollatId = requirements[x].collateralId;\n                (address reqCollatAddr,) = pomace.assets(reqCollatId);\n                uint256 reqAmount = requirements[x].amount;\n\n                masks = new uint256[](collatCount);\n                uint256 y;\n\n                for (y; y < collatCount; ++y) {\n                    uint8 collatId = collaterals[y].collateralId;\n\n                    // only setting amount and address on first pass\n                    // dont need to repeat each inner loop\n                    if (x == 0) {\n                        amounts[y] = collaterals[y].amount;\n\n                        (address addr,) = pomace.assets(collatId);\n                        addresses[y] = addr;\n                    }\n\n                    if (reqCollatId == collatId) {\n                        masks[y] = 1 * UNIT;\n                    } else {\n                        // setting mask to price if reqCollateralId is collateralId\n                        if (_isCollateralizable(reqCollatId, collatId)) {\n                            if (address(oracle) == address(0)) oracle = pomace.oracle();\n\n                            masks[y] = oracle.getSpotPrice(addresses[y], reqCollatAddr);\n                        }\n                    }\n                }\n\n                uint256 marginValue = UintArrayLib.dot(amounts, masks) / UNIT;\n\n                // not enough collateral posted\n                if (marginValue < reqAmount) isUnderWater = true;\n\n                // reserving collateral to prevent double counting\n                for (y = 0; y < collatCount; ++y) {\n                    if (masks[y] == 0) continue;\n\n                    marginValue = amounts[y] * masks[y] / UNIT;\n\n                    if (reqAmount >= marginValue) {\n                        reqAmount = reqAmount - marginValue;\n                        amounts[y] = 0;\n\n                        if (reqAmount == 0) break;\n                    } else {\n                        amounts[y] = amounts[y] - (amounts[y] * reqAmount / marginValue);\n                        // reqAmount would now be set to zero,\n                        // no longer need to reserve, so breaking\n                        break;\n                    }\n                }\n            }\n        }\n    }\n\n    /**\n     * @dev reverts if the account cannot add this token into the margin account.\n     * @param tokenId tokenId\n     */\n    function _verifyLongTokenIdToAdd(uint256 tokenId) internal view override {\n        (TokenType tokenType,, uint64 expiry,,) = tokenId.parseTokenId();\n\n        // engine only supports calls and puts\n        if (tokenType != TokenType.CALL && tokenType != TokenType.PUT) revert CM_UnsupportedTokenType();\n\n        if (block.timestamp > expiry) revert CM_Token_Expired();\n\n        uint8 engineId = tokenId.parseEngineId();\n\n        // in the future reference a whitelist of engines\n        if (engineId != pomace.engineIds(address(this))) revert CM_Not_Authorized_Engine();\n    }\n\n    /**\n     * ========================================================= **\n     *                         Internal Functions\n     * ========================================================= *\n     */\n\n    /**\n     * @dev get minimum collateral requirement for an account\n     */\n    function _getMinCollateral(CrossMarginAccount memory account) internal view returns (Balance[] memory) {\n        return CrossMarginPhysicalMath.getMinCollateralForPositions(pomace, account.shorts, account.longs);\n    }\n\n    function _assertCallerHasAccess(address _subAccount) internal override {\n        if (_isPrimaryAccountFor(msg.sender, _subAccount)) return;\n\n        if (\n            authority.doesUserHaveRole(tx.origin, Role.System_FundAdmin)\n                && (msg.sender == tx.origin || authority.getUserRoles(msg.sender) != bytes32(0))\n        ) {\n            return;\n        }\n\n        super._assertCallerHasAccess(_subAccount);\n    }\n\n    /**\n     * @dev check if a pair of assetIds are collateralizable\n     */\n    function _isCollateralizable(uint8 _assetId0, uint8 _assetId1) internal view returns (bool) {\n        if (_assetId0 == _assetId1) return true;\n\n        return pomace.isCollateralizable(_assetId0, _assetId1);\n    }\n\n    function _socializeSettlement(SettlementTracker memory tracker, uint256 tokenId, uint256 shortAmount)\n        internal\n        pure\n        returns (Balance memory debt, Balance memory payout)\n    {\n        (TokenType tokenType, uint32 productId,,,) = TokenIdUtil.parseTokenId(tokenId);\n        (, uint8 underlyingId, uint8 strikeId, uint8 collateralId) = ProductIdUtil.parseProductId(productId);\n\n        payout.collateralId = collateralId;\n\n        if (tokenType == TokenType.CALL) debt.collateralId = strikeId;\n        else if (tokenType == TokenType.PUT) debt.collateralId = underlyingId;\n\n        debt.amount = (tracker.totalDebt * shortAmount / tracker.issued).toUint80();\n        payout.amount = (tracker.totalPaid * shortAmount / tracker.issued).toUint80();\n    }\n\n    /**\n     * @dev add an entry to array of Balance\n     * @param balances existing payout array\n     * @param _asset new collateralId\n     * @param _amount new payout\n     */\n    function _addToBalances(Balance[] memory balances, uint8 _asset, uint256 _amount)\n        internal\n        pure\n        returns (Balance[] memory newBalances)\n    {\n        (bool found, uint256 index) = balances.indexOf(_asset);\n\n        uint80 balance = _amount.toUint80();\n\n        if (!found) balances = balances.append(Balance(_asset, balance));\n        else balances[index].amount += balance;\n\n        return balances;\n    }\n\n    function _computeDomainSeparator() internal view returns (bytes32) {\n        return keccak256(\n            abi.encode(\n                keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"),\n                keccak256(\"Cross Margin Physical Engine\"),\n                keccak256(\"1\"),\n                block.chainid,\n                address(this)\n            )\n        );\n    }\n\n    /*///////////////////////////////////////////////////////////////\n                        Transfer Account Functions\n    //////////////////////////////////////////////////////////////*/\n\n    /**\n     * @notice  move an account to someone else\n     * @dev     expected to be call by account owner\n     * @param _subAccount the id of subaccount to transfer\n     * @param _newSubAccount the id of receiving account\n     */\n    function transferAccount(address _subAccount, address _newSubAccount) external {\n        if (!_isPrimaryAccountFor(msg.sender, _subAccount)) revert NoAccess();\n\n        if (!accounts[_newSubAccount].isEmpty()) revert CM_AccountIsNotEmpty();\n        accounts[_newSubAccount] = accounts[_subAccount];\n\n        delete accounts[_subAccount];\n    }\n\n    /*///////////////////////////////////////////////////////////////\n                    Override Upgrade Permission\n    //////////////////////////////////////////////////////////////*/\n\n    /**\n     * @dev Upgradable by the owner.\n     *\n     */\n    function _authorizeUpgrade(address /*newImplementation*/ ) internal view override {\n        _checkOwner();\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/proxy/utils/UUPSUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (proxy/utils/UUPSUpgradeable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../interfaces/draft-IERC1822.sol\";\nimport \"../ERC1967/ERC1967Upgrade.sol\";\n\n/**\n * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an\n * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.\n *\n * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is\n * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing\n * `UUPSUpgradeable` with a custom implementation of upgrades.\n *\n * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.\n *\n * _Available since v4.1._\n */\nabstract contract UUPSUpgradeable is IERC1822Proxiable, ERC1967Upgrade {\n    /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment\n    address private immutable __self = address(this);\n\n    /**\n     * @dev Check that the execution is being performed through a delegatecall call and that the execution context is\n     * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case\n     * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a\n     * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to\n     * fail.\n     */\n    modifier onlyProxy() {\n        require(address(this) != __self, \"Function must be called through delegatecall\");\n        require(_getImplementation() == __self, \"Function must be called through active proxy\");\n        _;\n    }\n\n    /**\n     * @dev Check that the execution is not being performed through a delegate call. This allows a function to be\n     * callable on the implementing contract but not through proxies.\n     */\n    modifier notDelegated() {\n        require(address(this) == __self, \"UUPSUpgradeable: must not be called through delegatecall\");\n        _;\n    }\n\n    /**\n     * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the\n     * implementation. It is used to validate the implementation's compatibility when performing an upgrade.\n     *\n     * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n     * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n     * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.\n     */\n    function proxiableUUID() external view virtual override notDelegated returns (bytes32) {\n        return _IMPLEMENTATION_SLOT;\n    }\n\n    /**\n     * @dev Upgrade the implementation of the proxy to `newImplementation`.\n     *\n     * Calls {_authorizeUpgrade}.\n     *\n     * Emits an {Upgraded} event.\n     */\n    function upgradeTo(address newImplementation) external virtual onlyProxy {\n        _authorizeUpgrade(newImplementation);\n        _upgradeToAndCallUUPS(newImplementation, new bytes(0), false);\n    }\n\n    /**\n     * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call\n     * encoded in `data`.\n     *\n     * Calls {_authorizeUpgrade}.\n     *\n     * Emits an {Upgraded} event.\n     */\n    function upgradeToAndCall(address newImplementation, bytes memory data) external payable virtual onlyProxy {\n        _authorizeUpgrade(newImplementation);\n        _upgradeToAndCallUUPS(newImplementation, data, true);\n    }\n\n    /**\n     * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by\n     * {upgradeTo} and {upgradeToAndCall}.\n     *\n     * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.\n     *\n     * ```solidity\n     * function _authorizeUpgrade(address) internal override onlyOwner {}\n     * ```\n     */\n    function _authorizeUpgrade(address newImplementation) internal virtual;\n}\n"
      },
      "lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {\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    function __Ownable_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal onlyInitializing {\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 anymore. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby removing 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    /**\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"
      },
      "lib/openzeppelin-contracts-upgradeable/contracts/security/ReentrancyGuardUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\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 ReentrancyGuardUpgradeable is Initializable {\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    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\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 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"
      },
      "lib/openzeppelin-contracts/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"
      },
      "lib/core-physical/src/core/engines/BaseEngine.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n// solhint-disable no-empty-blocks\n\n// imported contracts and libraries\nimport {SafeERC20} from \"openzeppelin/token/ERC20/utils/SafeERC20.sol\";\nimport {IERC20} from \"openzeppelin/token/ERC20/IERC20.sol\";\nimport {IERC1155} from \"openzeppelin/token/ERC1155/IERC1155.sol\";\n\n// interfaces\nimport {IPomace} from \"../../interfaces/IPomace.sol\";\nimport {IPhysicalOptionToken} from \"../../interfaces/IPhysicalOptionToken.sol\";\n\n// libraries\nimport {TokenIdUtil} from \"../../libraries/TokenIdUtil.sol\";\n\n// constants and types\nimport \"../../config/types.sol\";\nimport \"../../config/enums.sol\";\nimport \"../../config/constants.sol\";\nimport \"../../config/errors.sol\";\n\n/**\n * @title   BaeEngine\n * @author  @antoncoding, @dsshap\n * @dev  common functions / flow that can be shared among MarginEngines\n */\nabstract contract BaseEngine {\n    using SafeERC20 for IERC20;\n    using TokenIdUtil for uint256;\n\n    IPomace public immutable pomace;\n    IPhysicalOptionToken public immutable optionToken;\n\n    ///@dev maskedAccount => operator => allowedExecutionLeft\n    ///     every account can authorize any amount of addresses to modify all sub-accounts he controls.\n    ///     allowedExecutionLeft refers to how many times remain that the grantee can update the sub-accounts.\n    mapping(uint160 => mapping(address => uint256)) public allowedExecutionLeft;\n\n    /// Events\n    event AccountAuthorizationUpdate(uint160 maskId, address account, uint256 updatesAllowed);\n\n    event CollateralAdded(address subAccount, address collateral, uint256 amount);\n\n    event CollateralRemoved(address subAccount, address collateral, uint256 amount);\n\n    event PhysicalOptionTokenMinted(address subAccount, uint256 tokenId, uint256 amount);\n\n    event PhysicalOptionTokenBurned(address subAccount, uint256 tokenId, uint256 amount);\n\n    event PhysicalOptionTokenAdded(address subAccount, uint256 tokenId, uint64 amount);\n\n    event PhysicalOptionTokenRemoved(address subAccount, uint256 tokenId, uint64 amount);\n\n    event ExercisedToken(address subAccount, uint256 tokenId, uint256 amount);\n\n    /// @dev emitted when an account is settled, with array of payouts\n    event AccountSettled(address subAccount, Balance[] payouts);\n\n    /// @dev emitted when an account is settled, with single payout\n    event AccountSettledSingle(address subAccount, uint8 collateralId, int256 payout);\n\n    /**\n     * ========================================================= *\n     *                       Constructor\n     * ========================================================= *\n     */\n    constructor(address _pomace, address _optionToken) {\n        pomace = IPomace(_pomace);\n        optionToken = IPhysicalOptionToken(_optionToken);\n    }\n\n    /**\n     * ========================================================= *\n     *                         External Functions\n     * ========================================================= *\n     */\n\n    /**\n     * @notice  grant or revoke an account access to all your sub-accounts\n     * @dev     expected to be call by account owner\n     *          usually user should only give access to helper contracts\n     * @param   _account account to update authorization\n     * @param   _allowedExecutions how many times the account is authorized to update your accounts.\n     *          set to max(uint256) to allow permanent access\n     */\n    function setAccountAccess(address _account, uint256 _allowedExecutions) external {\n        uint160 maskedId = uint160(msg.sender) | 0xFF;\n        allowedExecutionLeft[maskedId][_account] = _allowedExecutions;\n\n        emit AccountAuthorizationUpdate(maskedId, _account, _allowedExecutions);\n    }\n\n    /**\n     * @dev resolve access granted to yourself\n     * @param _granter address that granted you access\n     */\n    function revokeSelfAccess(address _granter) external {\n        uint160 maskedId = uint160(_granter) | 0xFF;\n        allowedExecutionLeft[maskedId][msg.sender] = 0;\n\n        emit AccountAuthorizationUpdate(maskedId, msg.sender, 0);\n    }\n\n    /**\n     * @dev hook to be invoked by Pomace to handle custom logic of settlement\n     */\n    function handleExercise(uint256 _tokenId, uint256 _debtPaid, uint256 _amountPaidOut) external virtual {}\n\n    /**\n     * @notice payout to user on settlement.\n     * @dev this can only triggered by Pomace, would only be called on settlement.\n     * @param _asset asset to transfer\n     * @param _sender sender of debt\n     * @param _amount amount\n     */\n    function _receiveDebtValue(address _asset, address _sender, uint256 _amount) internal virtual {\n        _checkIsPomace();\n\n        if (_sender != address(this)) IERC20(_asset).safeTransferFrom(_sender, address(this), _amount);\n    }\n\n    /**\n     * @notice payout to user on settlement.\n     * @dev this can only triggered by Pomace, would only be called on settlement.\n     * @param _asset asset to transfer\n     * @param _recipient receiver\n     * @param _amount amount\n     */\n    function _sendPayoutValue(address _asset, address _recipient, uint256 _amount) internal virtual {\n        _checkIsPomace();\n\n        if (_recipient != address(this)) IERC20(_asset).safeTransfer(_recipient, _amount);\n    }\n\n    // /**\n    //  * @notice payout to user on settlement.\n    //  * @dev this can only triggered by Pomace, would only be called on settlement.\n    //  * @param _asset asset to transfer\n    //  * @param _recipient receiver address\n    //  * @param _amount amount\n    //  */\n    // function payCashValue(address _asset, address _recipient, uint256 _amount) public virtual {\n    //     if (msg.sender != address(pomace)) revert NoAccess();\n    //     if (_recipient != address(this)) IERC20(_asset).safeTransfer(_recipient, _amount);\n    // }\n\n    function onERC1155Received(address, address, uint256, uint256, bytes calldata) external virtual returns (bytes4) {\n        return this.onERC1155Received.selector;\n    }\n\n    function onERC1155BatchReceived(address, address, uint256[] memory, uint256[] memory, bytes memory)\n        external\n        virtual\n        returns (bytes4)\n    {\n        return this.onERC1155BatchReceived.selector;\n    }\n\n    /**\n     * ========================================================= *\n     *                Internal Functions For Each Action\n     * ========================================================= *\n     */\n\n    /**\n     * @dev pull token from user, increase collateral in account storage\n     *         the collateral has to be provided by either caller, or the primary owner of subaccount\n     */\n    function _addCollateral(address _subAccount, bytes calldata _data) internal virtual {\n        // decode parameters\n        (address from, uint80 amount, uint8 collateralId) = abi.decode(_data, (address, uint80, uint8));\n\n        if (from != msg.sender && !_isPrimaryAccountFor(from, _subAccount)) revert BM_InvalidFromAddress();\n\n        // update the account in state\n        _addCollateralToAccount(_subAccount, collateralId, amount);\n\n        (address collateral,) = pomace.assets(collateralId);\n\n        emit CollateralAdded(_subAccount, collateral, amount);\n\n        // this line will revert if collateral id is not registered.\n        IERC20(collateral).safeTransferFrom(from, address(this), amount);\n    }\n\n    /**\n     * @dev push token to user, decrease collateral in storage\n     * @param _data bytes data to decode\n     */\n    function _removeCollateral(address _subAccount, bytes calldata _data) internal virtual {\n        // decode parameters\n        (uint80 amount, address recipient, uint8 collateralId) = abi.decode(_data, (uint80, address, uint8));\n\n        // update the account in state\n        _removeCollateralFromAccount(_subAccount, collateralId, amount);\n\n        (address collateral,) = pomace.assets(collateralId);\n\n        emit CollateralRemoved(_subAccount, collateral, amount);\n\n        IERC20(collateral).safeTransfer(recipient, amount);\n    }\n\n    /**\n     * @dev mint option token to user, increase short position (debt) in storage\n     * @param _data bytes data to decode\n     */\n    function _mintOption(address _subAccount, bytes calldata _data) internal virtual {\n        // decode parameters\n        (uint256 tokenId, address recipient, uint64 amount) = abi.decode(_data, (uint256, address, uint64));\n\n        // update the account in state\n        _increaseShortInAccount(_subAccount, tokenId, amount);\n\n        emit PhysicalOptionTokenMinted(_subAccount, tokenId, amount);\n\n        // mint option token\n        optionToken.mint(recipient, tokenId, amount);\n    }\n\n    /**\n     * @dev burn option token from user, decrease short position (debt) in storage\n     *         the option has to be provided by either caller, or the primary owner of subaccount\n     * @param _data bytes data to decode\n     */\n    function _burnOption(address _subAccount, bytes calldata _data) internal virtual {\n        // decode parameters\n        (uint256 tokenId, address from, uint64 amount) = abi.decode(_data, (uint256, address, uint64));\n\n        // token being burn must come from caller or the primary account for this subAccount\n        if (from != msg.sender && !_isPrimaryAccountFor(from, _subAccount)) revert BM_InvalidFromAddress();\n\n        // update the account in state\n        _decreaseShortInAccount(_subAccount, tokenId, amount);\n\n        emit PhysicalOptionTokenBurned(_subAccount, tokenId, amount);\n\n        optionToken.burn(from, tokenId, amount);\n    }\n\n    /**\n     * @dev Add long token into the account to reduce capital requirement.\n     * @param _subAccount subaccount that will be update in place\n     */\n    function _addOption(address _subAccount, bytes calldata _data) internal virtual {\n        // decode parameters\n        (uint256 tokenId, uint64 amount, address from) = abi.decode(_data, (uint256, uint64, address));\n\n        // token being added must come from caller or the primary account for this subAccount\n        if (from != msg.sender && !_isPrimaryAccountFor(from, _subAccount)) revert BM_InvalidFromAddress();\n\n        _verifyLongTokenIdToAdd(tokenId);\n\n        // update the state\n        _increaseLongInAccount(_subAccount, tokenId, amount);\n\n        emit PhysicalOptionTokenAdded(_subAccount, tokenId, amount);\n\n        // transfer the option token in\n        IERC1155(address(optionToken)).safeTransferFrom(from, address(this), tokenId, amount, \"\");\n    }\n\n    /**\n     * @dev Remove long token from the account to increase capital requirement.\n     * @param _subAccount subaccount that will be update in place\n     */\n    function _removeOption(address _subAccount, bytes calldata _data) internal virtual {\n        // decode parameters\n        (uint256 tokenId, uint64 amount, address to) = abi.decode(_data, (uint256, uint64, address));\n\n        // update the state\n        _decreaseLongInAccount(_subAccount, tokenId, amount);\n\n        emit PhysicalOptionTokenRemoved(_subAccount, tokenId, amount);\n\n        // transfer the option token out\n        IERC1155(address(optionToken)).safeTransferFrom(address(this), to, tokenId, amount, \"\");\n    }\n\n    /**\n     * @notice  exercises a long token in margin account at expiry but before settlement window\n     * @dev     this updates the account storage\n     */\n    function _exerciseToken(address _subAccount, bytes calldata _data) internal virtual {\n        // decode parameters\n        (uint256 tokenId, uint64 amount) = abi.decode(_data, (uint256, uint64));\n\n        _exerciseTokenInAccount(_subAccount, tokenId, amount);\n\n        emit ExercisedToken(_subAccount, tokenId, amount);\n    }\n\n    /**\n     * @notice  settle the margin account at expiry\n     * @dev     this update the account storage\n     */\n    function _settle(address _subAccount) internal virtual {\n        // if payout is positive, the \"option token\" this account minted worth something\n        // so some collateral should be subtracted from the account.\n        // payout can be negative because the account could have spread positions that has positive PNL at the end\n        // for example if the account short a 1000-1100 call spread, and the price is 1050\n        // the account should earn $50 at expiry\n        (uint8 collateralId, int80 payout) = _getAccountPayout(_subAccount);\n\n        // update the account in state\n        _settleAccount(_subAccount, payout);\n\n        emit AccountSettledSingle(_subAccount, collateralId, payout);\n    }\n\n    /**\n     * ========================================================= *\n     *                State changing functions to override\n     * ========================================================= *\n     */\n    function _addCollateralToAccount(address _subAccount, uint8 collateralId, uint80 amount) internal virtual {}\n\n    function _removeCollateralFromAccount(address _subAccount, uint8 collateralId, uint80 amount) internal virtual {}\n\n    function _increaseShortInAccount(address _subAccount, uint256 tokenId, uint64 amount) internal virtual {}\n\n    function _decreaseShortInAccount(address _subAccount, uint256 tokenId, uint64 amount) internal virtual {}\n\n    function _increaseLongInAccount(address _subAccount, uint256 tokenId, uint64 amount) internal virtual {}\n\n    function _decreaseLongInAccount(address _subAccount, uint256 tokenId, uint64 amount) internal virtual {}\n\n    function _exerciseTokenInAccount(address _subAccount, uint256 tokenId, uint64 amount) internal virtual {}\n\n    function _settleAccount(address _subAccount, int80 payout) internal virtual {}\n\n    /**\n     * ========================================================= *\n     *                View functions to override\n     * ========================================================= *\n     */\n\n    /**\n     * @notice [MUST Implement] return amount of collateral that should be reserved to payout the counterparty\n     * @dev    if payout is positive: the account need to payout, the amount will be subtracted from collateral\n     *         if payout is negative: the account will receive payout, the amount will be added to collateral\n     *\n     * @dev    this function will revert when called before expiry\n     * @param _subAccount account id\n     */\n    function _getAccountPayout(address _subAccount) internal view virtual returns (uint8 collateralId, int80 payout) {}\n\n    /**\n     * @dev [MUST Implement] return whether if an account is healthy.\n     * @param _subAccount subaccount id\n     * @return isHealthy true if account is in good condition, false if it's underwater (liquidatable)\n     */\n    function _isAccountAboveWater(address _subAccount) internal view virtual returns (bool) {}\n\n    /**\n     * @dev reverts if the account cannot add this token into the margin account.\n     * @param tokenId tokenId\n     */\n    function _verifyLongTokenIdToAdd(uint256 tokenId) internal view virtual {}\n\n    /**\n     * ========================================================= **\n     *                Internal view functions\n     * ========================================================= *\n     */\n\n    /**\n     * @notice revert if the msg.sender is not authorized to access an subAccount id\n     * @param _subAccount subaccount id\n     */\n    function _assertCallerHasAccess(address _subAccount) internal virtual {\n        if (_isPrimaryAccountFor(msg.sender, _subAccount)) return;\n\n        // the sender is not the direct owner. check if they're authorized\n        uint160 maskedAccountId = (uint160(_subAccount) | 0xFF);\n\n        uint256 allowance = allowedExecutionLeft[maskedAccountId][msg.sender];\n        if (allowance == 0) revert NoAccess();\n\n        // if allowance is not set to max uint256, reduce the number\n        if (allowance != type(uint256).max) allowedExecutionLeft[maskedAccountId][msg.sender] = allowance - 1;\n    }\n\n    /**\n     * @notice return if {_primary} address is the primary account for {_subAccount}\n     */\n    function _isPrimaryAccountFor(address _primary, address _subAccount) internal pure returns (bool) {\n        return (uint160(_primary) | 0xFF) == (uint160(_subAccount) | 0xFF);\n    }\n\n    /**\n     * @dev check if msg.sender is the marginAccount\n     */\n    function _checkIsPomace() internal view {\n        if (msg.sender != address(pomace)) revert NoAccess();\n    }\n}\n"
      },
      "src/settled-physical/AccountPhysicalEngine.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// solhint-disable no-empty-blocks\npragma solidity ^0.8.0;\n\n// inheriting contracts\nimport {BaseEngine} from \"pomace/core/engines/BaseEngine.sol\";\n\n// constants and types\nimport \"pomace/config/enums.sol\";\nimport \"pomace/config/errors.sol\";\n\n/**\n * @title   AccountPhysicalEngine\n * @author  @dsshap\n * @notice  util functions to transfer positions between accounts \"without\" moving tokens externally\n */\nabstract contract AccountPhysicalEngine is BaseEngine {\n    event CollateralTransferred(address from, address to, uint8 collateralId, uint256 amount);\n\n    event PhysicalOptionTokenTransferred(address from, address to, uint256 tokenId, uint64 amount);\n\n    /**\n     * @dev Transfers collateral to another account.\n     * @param _subAccount subaccount that will be update in place\n     */\n    function _transferCollateral(address _subAccount, bytes calldata _data) internal virtual {\n        // decode parameters\n        (uint80 amount, address to, uint8 collateralId) = abi.decode(_data, (uint80, address, uint8));\n\n        // update the account in state\n        _removeCollateralFromAccount(_subAccount, collateralId, amount);\n        _addCollateralToAccount(to, collateralId, amount);\n\n        emit CollateralTransferred(_subAccount, to, collateralId, amount);\n    }\n\n    /**\n     * @dev Transfers short tokens to another account.\n     * @param _subAccount subaccount that will be update in place\n     */\n    function _transferShort(address _subAccount, bytes calldata _data) internal virtual {\n        // decode parameters\n        (uint256 tokenId, address to, uint64 amount) = abi.decode(_data, (uint256, address, uint64));\n\n        _assertCallerHasAccess(to);\n\n        // update the account in state\n        _decreaseShortInAccount(_subAccount, tokenId, amount);\n        _increaseShortInAccount(to, tokenId, amount);\n\n        emit PhysicalOptionTokenTransferred(_subAccount, to, tokenId, amount);\n\n        if (!_isAccountAboveWater(to)) revert BM_AccountUnderwater();\n    }\n\n    /**\n     * @dev Transfers long tokens to another account.\n     * @param _subAccount subaccount that will be update in place\n     */\n    function _transferLong(address _subAccount, bytes calldata _data) internal virtual {\n        // decode parameters\n        (uint256 tokenId, address to, uint64 amount) = abi.decode(_data, (uint256, address, uint64));\n\n        // update the account in state\n        _decreaseLongInAccount(_subAccount, tokenId, amount);\n        _increaseLongInAccount(to, tokenId, amount);\n\n        emit PhysicalOptionTokenTransferred(_subAccount, to, tokenId, amount);\n    }\n\n    /**\n     * @dev mint option token into another account\n     * @dev increase short position (debt) in the current account\n     * @dev increase long position another account's storage\n     * @param _data bytes data to decode\n     */\n    function _mintOptionIntoAccount(address _subAccount, bytes calldata _data) internal virtual {\n        // decode parameters\n        (uint256 tokenId, address recipientSubAccount, uint64 amount) = abi.decode(_data, (uint256, address, uint64));\n\n        // update the account in state\n        _increaseShortInAccount(_subAccount, tokenId, amount);\n\n        emit PhysicalOptionTokenMinted(_subAccount, tokenId, amount);\n\n        _verifyLongTokenIdToAdd(tokenId);\n\n        // update the account in state\n        _increaseLongInAccount(recipientSubAccount, tokenId, amount);\n\n        emit PhysicalOptionTokenAdded(recipientSubAccount, tokenId, amount);\n\n        // mint option token\n        optionToken.mint(address(this), tokenId, amount);\n    }\n\n    /**\n     * @dev burn option token from account\n     * @dev decrease short position (debt) in the current account\n     * @dev decrease long position another account's storage\n     * @param _data bytes data to decode\n     */\n    function _burnOptionFromAccount(address _subAccount, bytes calldata _data) internal virtual {\n        // decode parameters\n        (uint256 tokenId, address from, uint64 amount) = abi.decode(_data, (uint256, address, uint64));\n\n        // token being burn must come from caller or the primary account for this subAccount\n        if (from != msg.sender && !_isPrimaryAccountFor(from, _subAccount)) revert BM_InvalidFromAddress();\n\n        // update the account in state\n        _decreaseLongInAccount(from, tokenId, amount);\n\n        emit PhysicalOptionTokenBurned(from, tokenId, amount);\n\n        // update the account in state\n        _decreaseShortInAccount(_subAccount, tokenId, amount);\n\n        emit PhysicalOptionTokenRemoved(_subAccount, tokenId, amount);\n\n        // burn option token\n        optionToken.burn(address(this), tokenId, amount);\n    }\n}\n"
      },
      "lib/entitlements/src/interfaces/IAuthority.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"../config/enums.sol\";\n\n/// @notice A generic interface for a contract which provides authorization data to an Auth instance.\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Auth.sol)\n/// @author Modified from Dappsys (https://github.com/dapphub/ds-auth/blob/master/src/auth.sol)\ninterface IAuthority {\n    function canCall(address user, address target, bytes4 functionSig) external view returns (bool);\n\n    function doesUserHaveRole(address user, Role role) external view returns (bool);\n\n    function getUserRoles(address user) external view returns (bytes32);\n}\n"
      },
      "lib/core-physical/src/interfaces/IMarginEngine.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {ActionArgs} from \"../config/types.sol\";\n\ninterface IMarginEngine {\n    // function getMinCollateral(address _subAccount) external view returns (uint256);\n\n    function execute(address _subAccount, ActionArgs[] calldata actions) external;\n\n    function handleExercise(uint256 _tokenid, uint256 _debtAmount, uint256 _payoutAmount) external;\n\n    function receiveDebtValue(address _asset, address _recipient, uint256 _amount) external;\n\n    function sendPayoutValue(address _asset, address _recipient, uint256 _amount) external;\n}\n"
      },
      "lib/core-physical/src/interfaces/IWhitelist.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\ninterface IWhitelist {\n    function sanctioned(address _subAccount) external view returns (bool);\n\n    function isAllowed(address _subAccount) external view returns (bool);\n}\n"
      },
      "lib/core-physical/src/interfaces/IOracle.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IOracle {\n    /**\n     * @notice  get spot price of _base, denominated in _quote.\n     * @param _base base asset. for ETH/USD price, ETH is the base asset\n     * @param _quote quote asset. for ETH/USD price, USD is the quote asset\n     * @return price with 6 decimals\n     */\n    function getSpotPrice(address _base, address _quote) external view returns (uint256);\n\n    /**\n     * @dev get expiry price of underlying, denominated in strike asset.\n     * @param _base base asset. for ETH/USD price, ETH is the base asset\n     * @param _quote quote asset. for ETH/USD price, USD is the quote asset\n     * @param _expiry expiry timestamp\n     *\n     * @return price with 6 decimals\n     */\n    function getPriceAtExpiry(address _base, address _quote, uint256 _expiry)\n        external\n        view\n        returns (uint256 price, bool isFinalized);\n\n    /**\n     * @dev return the maximum dispute period for the oracle\n     * @dev this will only be checked during oracle registration, as a soft constraint on integrating oracles.\n     */\n    function maxDisputePeriod() external view returns (uint256 disputePeriod);\n}\n"
      },
      "lib/core-physical/src/libraries/BalanceUtil.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"../config/types.sol\";\n\n/**\n * Operations on Balance struct\n */\nlibrary BalanceUtil {\n    /**\n     * @dev create a new Balance array with 1 more element\n     * @param x balance array\n     * @param v new value to add\n     * @return y new balance array\n     */\n    function append(Balance[] memory x, Balance memory v) internal pure returns (Balance[] memory y) {\n        y = new Balance[](x.length + 1);\n        uint256 i;\n        for (i; i < x.length;) {\n            y[i] = x[i];\n            unchecked {\n                ++i;\n            }\n        }\n        y[i] = v;\n    }\n\n    /**\n     * @dev check if a balance object for collateral id already exists\n     * @param x balance array\n     * @param v collateral id to search\n     * @return f true if found\n     * @return b Balance object\n     * @return i index of the found entry\n     */\n    function find(Balance[] memory x, uint8 v) internal pure returns (bool f, Balance memory b, uint256 i) {\n        for (i; i < x.length;) {\n            if (x[i].collateralId == v) {\n                b = x[i];\n                f = true;\n                break;\n            }\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    /**\n     * @dev return the index of an element balance array\n     * @param x balance array\n     * @param v collateral id to search\n     * @return f true if found\n     * @return i index of the found entry\n     */\n    function indexOf(Balance[] memory x, uint8 v) internal pure returns (bool f, uint256 i) {\n        for (i; i < x.length;) {\n            if (x[i].collateralId == v) {\n                f = true;\n                break;\n            }\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    /**\n     * @dev remove index y from balance array\n     * @param x balance array\n     * @param i index to remove\n     */\n    function remove(Balance[] storage x, uint256 i) internal {\n        if (i >= x.length) return;\n        x[i] = x[x.length - 1];\n        x.pop();\n    }\n\n    /**\n     * @dev checks if balances are empty\n     */\n    function isEmpty(Balance[] memory x) internal pure returns (bool e) {\n        e = true;\n        for (uint256 i; i < x.length;) {\n            if (x[i].amount > 0) {\n                e = false;\n                break;\n            }\n            unchecked {\n                ++i;\n            }\n        }\n    }\n}\n"
      },
      "lib/core-physical/src/libraries/ProductIdUtil.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n// solhint-disable max-line-length\n\n/**\n * @title ProductIdUtil\n * @dev used to parse and compose productId\n * Product Id =\n * * ----------------- | ---------------------- | ------------------ | ---------------------- *\n * | engineId (8 bits) | underlying ID (8 bits) | strike ID (8 bits) | collateral ID (8 bits) |\n * * ----------------- | ---------------------- | ------------------ | ---------------------- *\n *\n */\nlibrary ProductIdUtil {\n    /**\n     * @dev parse product id into composing asset ids\n     *\n     * productId (32 bits) =\n     *\n     * @param _productId product id\n     */\n    function parseProductId(uint32 _productId)\n        internal\n        pure\n        returns (uint8 engineId, uint8 underlyingId, uint8 strikeId, uint8 collateralId)\n    {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            engineId := shr(24, _productId)\n            underlyingId := shr(16, _productId)\n            strikeId := shr(8, _productId)\n        }\n        collateralId = uint8(_productId);\n    }\n\n    /**\n     * @dev parse collateral id from product Id.\n     *      since collateral id is uint8 of the last 8 bits of productId, we can just cast to uint8\n     */\n    function getCollateralId(uint32 _productId) internal pure returns (uint8) {\n        return uint8(_productId);\n    }\n\n    /**\n     * @notice    get product id from underlying, strike and collateral address\n     * @dev       function will still return even if some of the assets are not registered\n     * @param engineId  engine id\n     * @param underlyingId  underlying id\n     * @param strikeId      strike id\n     * @param collateralId  collateral id\n     */\n    function getProductId(uint8 engineId, uint8 underlyingId, uint8 strikeId, uint8 collateralId)\n        internal\n        pure\n        returns (uint32 id)\n    {\n        unchecked {\n            id = (uint32(engineId) << 24) + (uint32(underlyingId) << 16) + (uint32(strikeId) << 8) + (uint32(collateralId));\n        }\n    }\n}\n"
      },
      "lib/core-physical/src/libraries/TokenIdUtil.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// solhint-disable max-line-length\n\npragma solidity ^0.8.0;\n\nimport \"../config/enums.sol\";\nimport \"../config/errors.sol\";\n\n/**\n * Token ID =\n *\n *  * ------------------- | ------------------- | ---------------- | ---------------- | -------------------------- *\n *  | tokenType (32 bits) | productId (32 bits) | expiry (64 bits) | strike (64 bits) | exerciseWindow (64 bits) |\n *  * ------------------- | ------------------- | ---------------- | ---------------- | -------------------------- *\n */\nlibrary TokenIdUtil {\n    /**\n     * @notice calculate ERC1155 token id for given option parameters. See table above for tokenId\n     * @param tokenType TokenType enum\n     * @param productId if of the product\n     * @param expiry timestamp of option expiry\n     * @param strike strike price of the long option, with 6 decimals\n     * @param exerciseWindow time after expiry in which the option can be exercised\n     * @return tokenId token id\n     */\n    function getTokenId(TokenType tokenType, uint32 productId, uint64 expiry, uint64 strike, uint64 exerciseWindow)\n        internal\n        pure\n        returns (uint256 tokenId)\n    {\n        unchecked {\n            tokenId = (uint256(tokenType) << 226) + (uint256(productId) << 192) + (uint256(expiry) << 128)\n                + (uint256(strike) << 64) + uint256(exerciseWindow);\n        }\n    }\n\n    /**\n     * @notice derive option, product, expiry and strike price from ERC1155 token id\n     * @dev    See table above for tokenId composition\n     * @param tokenId token id\n     * @return tokenType TokenType enum\n     * @return productId 32 bits product id\n     * @return expiry timestamp of option expiry\n     * @return strike strike price of the long option, with 6 decimals\n     * @return exerciseWindow time after expiry in which the option can be exercised\n     */\n    function parseTokenId(uint256 tokenId)\n        internal\n        pure\n        returns (TokenType tokenType, uint32 productId, uint64 expiry, uint64 strike, uint64 exerciseWindow)\n    {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            tokenType := shr(226, tokenId)\n            productId := shr(192, tokenId)\n            expiry := shr(128, tokenId)\n            strike := shr(64, tokenId)\n            exerciseWindow := tokenId\n        }\n    }\n\n    /**\n     * @notice parse collateral id from tokenId\n     * @dev more efficient than parsing tokenId and than parse productId\n     * @param tokenId token id\n     * @return collateralId\n     */\n    function parseCollateralId(uint256 tokenId) internal pure returns (uint8 collateralId) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // collateralId is the last bits of productId\n            collateralId := shr(192, tokenId)\n        }\n    }\n\n    /**\n     * @notice parse engine id from tokenId\n     * @dev more efficient than parsing tokenId and than parse productId\n     * @param tokenId token id\n     * @return engineId\n     */\n    function parseEngineId(uint256 tokenId) internal pure returns (uint8 engineId) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // collateralId is the last bits of productId\n            engineId := shr(216, tokenId) // 192 to get product id, another 24 to get engineId\n        }\n    }\n\n    /**\n     * @notice derive option type from ERC1155 token id\n     * @param tokenId token id\n     * @return tokenType TokenType enum\n     */\n    function parseTokenType(uint256 tokenId) internal pure returns (TokenType tokenType) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            tokenType := shr(232, tokenId)\n        }\n    }\n\n    /**\n     * @notice derive if option is expired from ERC1155 token id\n     * @param tokenId token id\n     * @return expired bool\n     */\n    function isExpired(uint256 tokenId) internal view returns (bool expired) {\n        uint64 expiry;\n\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            expiry := shr(128, tokenId)\n        }\n\n        expired = block.timestamp >= expiry;\n    }\n}\n"
      },
      "lib/array-lib/src/UintArrayLib.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {SafeCast} from \"openzeppelin/utils/math/SafeCast.sol\";\n\nlibrary UintArrayLib {\n    using SafeCast for uint256;\n\n    error IntegerOverflow();\n\n    /**\n     * @dev Returns maximal element in array\n     */\n    function max(uint256[] memory x) internal pure returns (uint256 m) {\n        m = x[0];\n        for (uint256 i; i < x.length;) {\n            if (x[i] > m) {\n                m = x[i];\n            }\n\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    /**\n     * @dev Returns minimum element in array\n     */\n    function min(uint256[] memory x) internal pure returns (uint256 m) {\n        m = x[0];\n        for (uint256 i = 1; i < x.length;) {\n            if (x[i] < m) {\n                m = x[i];\n            }\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    /**\n     * @dev return the min and max for an array.\n     */\n    function minMax(uint256[] memory x) internal pure returns (uint256 min_, uint256 max_) {\n        if (x.length == 1) return (x[0], x[0]);\n        (min_, max_) = (x[0], x[0]);\n\n        for (uint256 i = 1; i < x.length;) {\n            if (x[i] < min_) {\n                min_ = x[i];\n            } else if (x[i] > max_) {\n                max_ = x[i];\n            }\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    /**\n     * @dev return a new array that append element v at the end of array x\n     */\n    function append(uint256[] memory x, uint256 v) internal pure returns (uint256[] memory y) {\n        y = new uint256[](x.length + 1);\n        uint256 i;\n        for (i; i < x.length;) {\n            y[i] = x[i];\n\n            unchecked {\n                ++i;\n            }\n        }\n        y[i] = v;\n    }\n\n    /**\n     * @dev Return a new array that removes element at index z.\n     * @return y new array\n     */\n    function remove(uint256[] memory x, uint256 z) internal pure returns (uint256[] memory y) {\n        if (z >= x.length) return x;\n        y = new uint256[](x.length - 1);\n        for (uint256 i; i < x.length;) {\n            unchecked {\n                if (i < z) y[i] = x[i];\n                else if (i > z) y[i - 1] = x[i];\n                ++i;\n            }\n        }\n    }\n\n    /**\n     * @dev Return index of the first element in array x with value v\n     * @return found set to true if found\n     * @return i index in the array\n     */\n    function indexOf(uint256[] memory x, uint256 v) internal pure returns (bool, uint256) {\n        for (uint256 i; i < x.length;) {\n            if (x[i] == v) {\n                return (true, i);\n            }\n\n            unchecked {\n                ++i;\n            }\n        }\n        return (false, 0);\n    }\n\n    /**\n     * @dev Compute sum of all elements\n     * @return s sum\n     */\n    function sum(uint256[] memory x) internal pure returns (uint256 s) {\n        require(x.length != 0);\n        // Variable to implement the overflow logic\n        uint256 j;\n        assembly {\n            // The Memory layout of input array looks like this\n            // It has Consequent slots of 32 bytes each\n            // {length of array}{x[0]}{x[1]}{x[2]}....\n\n            //Cache the pointer to end of the array to be used in for loop\n            //First param to add() is a memory pointer to start of the first element slot\n            //Second param to add() is a memory pointer to end of the last element slot\n            let end := add(add(x, 0x20), shl(5, mload(x)))\n\n            // iszero(eq()) is cheaper than lt(i,n)\n            // We increment i by 32 bytes\n            for { let i := add(x, 0x20) } iszero(eq(i, end)) { i := add(i, 0x20) } {\n                j := s\n                s := add(s, mload(i))\n                if lt(s, j) {\n                    // Storing the 4byte selector of error IntegerOverflow()\n                    // mstore()\n                    mstore(0x00, 0xa5bd5d7f)\n                    // revert(memory offset,size of return data)\n                    // revert(28,4)\n                    revert(0x1c, 0x04)\n                }\n            }\n        }\n    }\n\n    /**\n     * @dev return a new array that's the result of concatting a and b\n     */\n    function concat(uint256[] memory a, uint256[] memory b) internal pure returns (uint256[] memory y) {\n        y = new uint256[](a.length + b.length);\n        uint256 v;\n        uint256 i;\n        for (i; i < a.length;) {\n            y[v] = a[i];\n\n            unchecked {\n                ++i;\n                ++v;\n            }\n        }\n        for (i = 0; i < b.length;) {\n            y[v] = b[i];\n\n            unchecked {\n                ++i;\n                ++v;\n            }\n        }\n    }\n\n    /**\n     * @dev Populates array a with values from b\n     * @dev modifies array a in place.\n     */\n    function populate(uint256[] memory a, uint256[] memory b) internal pure {\n        for (uint256 i; i < a.length;) {\n            a[i] = b[i];\n\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    /**\n     * @dev return the element at index i\n     *      if i is positive, it's the same as requesting x[i]\n     *      if i is negative, return the value positioned at -i from the end\n     * @param i can be positive or negative\n     */\n    function at(uint256[] memory x, int256 i) internal pure returns (uint256) {\n        if (i >= 0) {\n            // will revert with out of bound error if i is too large\n            return x[uint256(i)];\n        } else {\n            // will revert with underflow error if i is too small\n            return x[x.length - uint256(-i)];\n        }\n    }\n\n    /**\n     * @dev return a new array y with y[i] = z - x[i]\n     */\n    function subEachFrom(uint256[] memory x, uint256 z) internal pure returns (int256[] memory y) {\n        y = new int256[](x.length);\n        int256 intZ = z.toInt256();\n        for (uint256 i; i < x.length;) {\n            y[i] = intZ - x[i].toInt256();\n\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    /**\n     * @dev return a new array y with y[i] = x[i] - z\n     */\n    function subEachBy(uint256[] memory x, uint256 z) internal pure returns (int256[] memory y) {\n        y = new int256[](x.length);\n        int256 intZ = z.toInt256();\n        for (uint256 i; i < x.length;) {\n            y[i] = x[i].toInt256() - intZ;\n\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    /**\n     * @dev return dot of 2 vectors\n     *      will revert if 2 vectors has different length\n     * @param a uint256 array\n     * @param b uint256 array\n     */\n    function dot(uint256[] memory a, uint256[] memory b) internal pure returns (uint256 s) {\n        for (uint256 i; i < a.length;) {\n            s += a[i] * b[i];\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    /**\n     * @dev return dot of 2 vectors\n     *      will revert if 2 vectors has different length\n     * @param a uint256 array\n     * @param b int256 array\n     */\n    function dot(uint256[] memory a, int256[] memory b) internal pure returns (int256 s) {\n        for (uint256 i; i < a.length;) {\n            s += int256(a[i]) * b[i];\n\n            unchecked {\n                ++i;\n            }\n        }\n    }\n}\n"
      },
      "src/libraries/AccountUtil.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n// cross margin types\nimport {CrossMarginDetail, Position} from \"../config/types.sol\";\n\nlibrary AccountUtil {\n    function append(CrossMarginDetail[] memory x, CrossMarginDetail memory v)\n        internal\n        pure\n        returns (CrossMarginDetail[] memory y)\n    {\n        y = new CrossMarginDetail[](x.length + 1);\n        uint256 i;\n        for (i; i < x.length;) {\n            y[i] = x[i];\n            unchecked {\n                ++i;\n            }\n        }\n        y[i] = v;\n    }\n\n    function append(Position[] memory x, Position memory v) internal pure returns (Position[] memory y) {\n        y = new Position[](x.length + 1);\n        uint256 i;\n        for (i; i < x.length;) {\n            y[i] = x[i];\n            unchecked {\n                ++i;\n            }\n        }\n        y[i] = v;\n    }\n\n    function concat(Position[] memory a, Position[] memory b) internal pure returns (Position[] memory y) {\n        y = new Position[](a.length + b.length);\n        uint256 v;\n        uint256 i;\n        for (i; i < a.length;) {\n            y[v] = a[i];\n            unchecked {\n                ++i;\n                ++v;\n            }\n        }\n        for (i = 0; i < b.length;) {\n            y[v] = b[i];\n            unchecked {\n                ++i;\n                ++v;\n            }\n        }\n    }\n\n    function find(Position[] memory x, uint256 v) internal pure returns (bool f, Position memory p, uint256 i) {\n        for (i; i < x.length;) {\n            if (x[i].tokenId == v) {\n                p = x[i];\n                f = true;\n                break;\n            }\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    function indexOf(Position[] memory x, uint256 v) internal pure returns (bool f, uint256 i) {\n        for (i; i < x.length;) {\n            if (x[i].tokenId == v) {\n                f = true;\n                break;\n            }\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    function isEmpty(Position[] memory x) internal pure returns (bool e) {\n        e = true;\n        for (uint256 i; i < x.length;) {\n            if (x[i].amount > 0) {\n                e = false;\n                break;\n            }\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    function removeAt(Position[] storage x, uint256 y) internal {\n        if (y >= x.length) return;\n        x[y] = x[x.length - 1];\n        x.pop();\n    }\n}\n"
      },
      "src/settled-physical/CrossMarginPhysicalMath.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport {SafeCast} from \"openzeppelin/utils/math/SafeCast.sol\";\nimport {UintArrayLib} from \"array-lib/UintArrayLib.sol\";\nimport {IntArrayLib} from \"array-lib/IntArrayLib.sol\";\nimport {QuickSort} from \"array-lib/sorting/QuickSort.sol\";\n\nimport {IPomace} from \"pomace/interfaces/IPomace.sol\";\n\n// shard libraries\nimport {NumberUtil} from \"pomace/libraries/NumberUtil.sol\";\nimport {ProductIdUtil} from \"pomace/libraries/ProductIdUtil.sol\";\nimport {TokenIdUtil} from \"pomace/libraries/TokenIdUtil.sol\";\nimport {BalanceUtil} from \"pomace/libraries/BalanceUtil.sol\";\nimport {BytesArrayUtil} from \"pomace/libraries/BytesArrayUtil.sol\";\n\n// cross margin libraries\nimport {AccountUtil} from \"../libraries/AccountUtil.sol\";\n\n// Cross margin types\nimport \"./types.sol\";\nimport \"../config/errors.sol\";\n\nimport {ProductDetails} from \"pomace/config/types.sol\";\nimport \"pomace/config/constants.sol\";\nimport \"pomace/config/enums.sol\";\nimport \"pomace/config/errors.sol\";\n\n/**\n * @title   CrossMarginPhysicalMath\n * @notice  this library is in charge of calculating the min collateral for a given cross margin account\n * @dev     deployed as a separate contract to save space\n */\nlibrary CrossMarginPhysicalMath {\n    using BalanceUtil for Balance[];\n    using AccountUtil for CrossMarginDetail[];\n    using AccountUtil for Position[];\n    using UintArrayLib for uint256[];\n    using IntArrayLib for int256[];\n    using QuickSort for uint256[];\n    using SafeCast for int256;\n    using SafeCast for uint256;\n    using TokenIdUtil for uint256;\n\n    /*///////////////////////////////////////////////////////////////\n                         Portfolio Margin Requirements\n    //////////////////////////////////////////////////////////////*/\n\n    /**\n     * @notice get minimum collateral for a given amount of shorts & longs\n     * @dev typically used for calculating a portfolios margin requirements\n     * @param pomace interface to query pomace contract\n     * @param shorts is array of Position structs\n     * @param longs is array of Position structs\n     * @return amounts is an array of Balance struct representing full collateralization\n     */\n    function getMinCollateralForPositions(IPomace pomace, Position[] calldata shorts, Position[] calldata longs)\n        external\n        view\n        returns (Balance[] memory amounts)\n    {\n        // groups shorts and longs by underlying + strike + collateral + expiry\n        CrossMarginDetail[] memory details = _getPositionDetails(pomace, shorts, longs);\n\n        // portfolio has no longs or shorts\n        if (details.length == 0) return amounts;\n\n        bool found;\n        uint256 index;\n\n        for (uint256 i; i < details.length;) {\n            CrossMarginDetail memory detail = details[i];\n\n            // checks that the combination has positions, otherwise skips\n            if (detail.callWeights.length != 0 || detail.putWeights.length != 0) {\n                // gets the amount of numeraire and underlying needed\n                (uint256 numeraireNeeded, uint256 underlyingNeeded) = getMinCollateral(detail);\n\n                if (numeraireNeeded > 0) {\n                    (found, index) = amounts.indexOf(detail.numeraireId);\n\n                    if (found) amounts[index].amount += numeraireNeeded.toUint80();\n                    else amounts = amounts.append(Balance(detail.numeraireId, numeraireNeeded.toUint80()));\n                }\n\n                if (underlyingNeeded > 0) {\n                    (found, index) = amounts.indexOf(detail.underlyingId);\n\n                    if (found) amounts[index].amount += underlyingNeeded.toUint80();\n                    else amounts = amounts.append(Balance(detail.underlyingId, underlyingNeeded.toUint80()));\n                }\n            }\n\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    /*///////////////////////////////////////////////////////////////\n                         Cross Margin Calculations\n    //////////////////////////////////////////////////////////////*/\n\n    /**\n     * @notice get minimum collateral\n     * @dev detail is composed of positions with the same underlying + strike + expiry\n     * @param _detail margin details\n     * @return numeraireNeeded with {numeraire asset's} decimals\n     * @return underlyingNeeded with {underlying asset's} decimals\n     */\n    function getMinCollateral(CrossMarginDetail memory _detail)\n        public\n        pure\n        returns (uint256 numeraireNeeded, uint256 underlyingNeeded)\n    {\n        _verifyInputs(_detail);\n\n        (uint256[] memory scenarios, int256[] memory payouts) = _getScenariosAndPayouts(_detail);\n\n        (numeraireNeeded, underlyingNeeded) = _getCollateralNeeds(_detail, scenarios, payouts);\n\n        // if options collateralized in underlying, forcing numeraire to be converted to underlying\n        // only applied to calls since puts cannot be collateralized in underlying\n        if (numeraireNeeded > 0 && _detail.putStrikes.length == 0) {\n            numeraireNeeded = 0;\n\n            underlyingNeeded = _convertCallNumeraireToUnderlying(scenarios, payouts, underlyingNeeded);\n        } else {\n            numeraireNeeded = NumberUtil.convertDecimals(numeraireNeeded, UNIT_DECIMALS, _detail.numeraireDecimals);\n        }\n\n        underlyingNeeded = NumberUtil.convertDecimals(underlyingNeeded, UNIT_DECIMALS, _detail.underlyingDecimals);\n    }\n\n    /**\n     * @notice checks inputs for calculating margin, reverts if bad inputs\n     * @param _detail margin details\n     */\n    function _verifyInputs(CrossMarginDetail memory _detail) internal pure {\n        if (_detail.callStrikes.length != _detail.callWeights.length) revert CMM_InvalidCallLengths();\n        if (_detail.putStrikes.length != _detail.putWeights.length) revert CMM_InvalidPutLengths();\n\n        uint256 i;\n        for (i; i < _detail.putWeights.length;) {\n            if (_detail.putWeights[i] == 0) revert CMM_InvalidPutWeight();\n\n            unchecked {\n                ++i;\n            }\n        }\n\n        for (i = 0; i < _detail.callWeights.length;) {\n            if (_detail.callWeights[i] == 0) revert CMM_InvalidCallWeight();\n\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    /**\n     * @notice setting up values needed to calculate margin requirements\n     * @param _detail margin details\n     * @return scenarios array of all the strikes\n     * @return payouts payouts for a given scenario\n     */\n    function _getScenariosAndPayouts(CrossMarginDetail memory _detail)\n        internal\n        pure\n        returns (uint256[] memory scenarios, int256[] memory payouts)\n    {\n        bool hasPuts = _detail.putStrikes.length > 0;\n        bool hasCalls = _detail.callStrikes.length > 0;\n\n        scenarios = _detail.putStrikes.concat(_detail.callStrikes);\n        scenarios.sort(); // sort in memory\n\n        // payouts at each scenario (strike)\n        payouts = new int256[](scenarios.length);\n\n        uint256 lastScenario;\n\n        for (uint256 i; i < scenarios.length;) {\n            // deduping scenarios, leaving payout as 0\n            if (scenarios[i] != lastScenario) {\n                if (hasPuts) {\n                    payouts[i] = _detail.putStrikes.subEachBy(scenarios[i]).maximum(0).dot(_detail.putWeights) / sUNIT;\n                }\n\n                if (hasCalls) {\n                    payouts[i] += _detail.callStrikes.subEachFrom(scenarios[i]).maximum(0).dot(_detail.callWeights) / sUNIT;\n                }\n\n                lastScenario = scenarios[i];\n            }\n\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    /**\n     * @notice get numeraire and underlying needed to fully collateralize\n     * @dev calculates left side and right side of the payout profile\n     * @param _detail margin details\n     * @param scenarios of all the options\n     * @param payouts are the payouts at a given scenario\n     * @return numeraireNeeded with {numeraire asset's} decimals\n     * @return underlyingNeeded with {underlying asset's} decimals\n     */\n    function _getCollateralNeeds(CrossMarginDetail memory _detail, uint256[] memory scenarios, int256[] memory payouts)\n        internal\n        pure\n        returns (uint256 numeraireNeeded, uint256 underlyingNeeded)\n    {\n        bool hasPuts = _detail.putStrikes.length > 0;\n        bool hasCalls = _detail.callStrikes.length > 0;\n\n        (int256 minPayout, uint256 minPayoutIndex) = payouts.minWithIndex();\n\n        // if put options exist, get amount of numeraire needed (left side of payout profile)\n        if (hasPuts) numeraireNeeded = _getNumeraireNeeded(minPayout, _detail.putStrikes, _detail.putWeights);\n\n        // if call options exist, get amount of underlying needed (right side of payout profile)\n        if (hasCalls) underlyingNeeded = _getUnderlyingNeeded(_detail.callWeights);\n\n        // crediting the numeraire if underlying has a positive payout\n        numeraireNeeded =\n            _getUnderlyingAdjustedNumeraireNeeded(scenarios, minPayout, minPayoutIndex, numeraireNeeded, underlyingNeeded);\n    }\n\n    /**\n     * @notice calculates the amount of numeraire is needed for put options\n     * @dev only called if there are put options, usually denominated in cash\n     * @param minPayout minimum payout across scenarios\n     * @param putStrikes put option strikes\n     * @param putWeights number of put options at a corresponding strike\n     * @return numeraireNeeded amount of numeraire asset needed\n     */\n    function _getNumeraireNeeded(int256 minPayout, uint256[] memory putStrikes, int256[] memory putWeights)\n        internal\n        pure\n        returns (uint256 numeraireNeeded)\n    {\n        int256 _numeraireNeeded = putStrikes.dot(putWeights) / sUNIT;\n\n        if (_numeraireNeeded > minPayout) _numeraireNeeded = minPayout;\n\n        if (_numeraireNeeded < 0) numeraireNeeded = uint256(-_numeraireNeeded);\n    }\n\n    /**\n     * @notice calculates the amount of underlying is needed for call options\n     * @dev only called if there are call options\n     * @param callWeights number of call options at a corresponding strike\n     * @return underlyingNeeded amount of underlying needed\n     */\n    function _getUnderlyingNeeded(int256[] memory callWeights) internal pure returns (uint256 underlyingNeeded) {\n        int256 totalCalls = callWeights.sum();\n\n        if (totalCalls < 0) underlyingNeeded = uint256(-totalCalls);\n    }\n\n    /**\n     * @notice crediting the numeraire if underlying has a positive payout\n     * @dev checks if subAccount has positive underlying value, if it does then cash requirements can be lowered\n     * @param scenarios of all the options\n     * @param minPayout minimum payout across scenarios\n     * @param minPayoutIndex minimum payout across scenarios index\n     * @param numeraireNeeded current numeraire needed\n     * @param underlyingNeeded underlying needed\n     * @return numeraireNeeded adjusted numeraire needed\n     */\n    function _getUnderlyingAdjustedNumeraireNeeded(\n        uint256[] memory scenarios,\n        int256 minPayout,\n        uint256 minPayoutIndex,\n        uint256 numeraireNeeded,\n        uint256 underlyingNeeded\n    ) internal pure returns (uint256) {\n        // negating to focus on negative payouts which require positive collateral\n        minPayout = -minPayout;\n\n        if (numeraireNeeded.toInt256() < minPayout) {\n            uint256 underlyingPayoutAtMinStrike = (scenarios[minPayoutIndex] * underlyingNeeded) / UNIT;\n\n            if (underlyingPayoutAtMinStrike.toInt256() > minPayout) {\n                numeraireNeeded = 0;\n            } else {\n                // check directly above means minPayout > underlyingPayoutAtMinStrike\n                numeraireNeeded = uint256(minPayout) - underlyingPayoutAtMinStrike;\n            }\n        }\n\n        return numeraireNeeded;\n    }\n\n    /**\n     * @notice converts numeraire needed entirely in underlying\n     * @dev only used if options collateralized in underlying\n     * @param scenarios of all the options\n     * @param payouts payouts at corresponding scenarios\n     * @param underlyingNeeded current underlying needed\n     * @return underlyingOnlyNeeded adjusted underlying needed\n     */\n    function _convertCallNumeraireToUnderlying(uint256[] memory scenarios, int256[] memory payouts, uint256 underlyingNeeded)\n        internal\n        pure\n        returns (uint256 underlyingOnlyNeeded)\n    {\n        int256 maxPayoutsOverScenarios;\n        int256[] memory payoutsOverScenarios = new int256[](scenarios.length);\n\n        for (uint256 i; i < scenarios.length;) {\n            payoutsOverScenarios[i] = (-payouts[i] * sUNIT) / int256(scenarios[i]);\n\n            if (payoutsOverScenarios[i] > maxPayoutsOverScenarios) maxPayoutsOverScenarios = payoutsOverScenarios[i];\n\n            unchecked {\n                ++i;\n            }\n        }\n\n        underlyingOnlyNeeded = underlyingNeeded;\n\n        if (maxPayoutsOverScenarios > 0) underlyingOnlyNeeded += uint256(maxPayoutsOverScenarios);\n    }\n\n    /*///////////////////////////////////////////////////////////////\n                         Setup CrossMarginDetail\n    //////////////////////////////////////////////////////////////*/\n\n    /**\n     * @notice  converts Position struct arrays to in-memory detail struct arrays\n     */\n    function _getPositionDetails(IPomace pomace, Position[] calldata shorts, Position[] calldata longs)\n        internal\n        view\n        returns (CrossMarginDetail[] memory details)\n    {\n        details = new CrossMarginDetail[](0);\n\n        // used to reference which detail struct should be updated for a given position\n        bytes32[] memory usceLookUp = new bytes32[](0);\n\n        Position[] memory positions = shorts.concat(longs);\n        uint256 shortLength = shorts.length;\n\n        // used to cache product detail during the loop to save gas when productIds are the same between iterations\n        ProductDetails memory product;\n        //  used to cache product id between loop iterations\n        //  default value of 0 is not a valid productId so the first run will always set the cache\n        uint32 lastUsedProductId;\n\n        for (uint256 i; i < positions.length;) {\n            (, uint32 productId, uint64 expiry,, uint64 exerciseWindow) = positions[i].tokenId.parseTokenId();\n\n            // skip expired long positions\n            if (i >= shortLength && expiry + exerciseWindow < block.timestamp) {\n                unchecked {\n                    ++i;\n                }\n\n                continue;\n            }\n\n            // cache product detail if a productId differs from a previous iteration\n            if (productId != lastUsedProductId) {\n                product = _getProductDetails(pomace, productId);\n\n                lastUsedProductId = productId;\n            }\n\n            bytes32 pos = keccak256(abi.encode(product.underlyingId, product.strikeId, expiry));\n\n            (bool found, uint256 index) = BytesArrayUtil.indexOf(usceLookUp, pos);\n\n            CrossMarginDetail memory detail;\n\n            if (found) {\n                detail = details[index];\n            } else {\n                usceLookUp = BytesArrayUtil.append(usceLookUp, pos);\n\n                detail.underlyingId = product.underlyingId;\n                detail.underlyingDecimals = product.underlyingDecimals;\n                detail.numeraireId = product.strikeId;\n                detail.numeraireDecimals = product.strikeDecimals;\n\n                detail.expiry = expiry;\n\n                details = details.append(detail);\n            }\n\n            int256 amount = int256(int64(positions[i].amount));\n\n            if (i < shortLength) amount = -amount;\n\n            _processDetailWithToken(detail, positions[i].tokenId, amount);\n\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    /**\n     * @notice merges option and amounts into the set\n     * @dev if weight turns into zero, we remove it from the set\n     */\n    function _processDetailWithToken(CrossMarginDetail memory detail, uint256 tokenId, int256 amount) internal pure {\n        (TokenType tokenType,,, uint64 strike,) = tokenId.parseTokenId();\n\n        bool found;\n        uint256 index;\n\n        // adjust or append to callStrikes array or callWeights array.\n        if (tokenType == TokenType.CALL) {\n            (found, index) = detail.callStrikes.indexOf(strike);\n\n            if (found) {\n                detail.callWeights[index] += amount;\n\n                if (detail.callWeights[index] == 0) {\n                    detail.callWeights = detail.callWeights.remove(index);\n                    detail.callStrikes = detail.callStrikes.remove(index);\n                }\n            } else {\n                detail.callStrikes = detail.callStrikes.append(strike);\n                detail.callWeights = detail.callWeights.append(amount);\n            }\n        } else if (tokenType == TokenType.PUT) {\n            // adjust or append to putStrikes array or putWeights array.\n            (found, index) = detail.putStrikes.indexOf(strike);\n\n            if (found) {\n                detail.putWeights[index] += amount;\n\n                if (detail.putWeights[index] == 0) {\n                    detail.putWeights = detail.putWeights.remove(index);\n                    detail.putStrikes = detail.putStrikes.remove(index);\n                }\n            } else {\n                detail.putStrikes = detail.putStrikes.append(strike);\n                detail.putWeights = detail.putWeights.append(amount);\n            }\n        }\n    }\n\n    /**\n     * @notice gets product asset specific details from pomace in one call\n     */\n    function _getProductDetails(IPomace pomace, uint32 productId) internal view returns (ProductDetails memory info) {\n        (, uint8 underlyingId, uint8 strikeId,) = ProductIdUtil.parseProductId(productId);\n\n        (, address underlying, uint8 underlyingDecimals, address strike, uint8 strikeDecimals,,) =\n            pomace.getDetailFromProductId(productId);\n\n        info.underlying = underlying;\n        info.underlyingId = underlyingId;\n        info.underlyingDecimals = underlyingDecimals;\n        info.strike = strike;\n        info.strikeId = strikeId;\n        info.strikeDecimals = strikeDecimals;\n    }\n}\n"
      },
      "src/settled-physical/CrossMarginPhysicalLib.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport {IPomace} from \"pomace/interfaces/IPomace.sol\";\nimport {IERC20} from \"openzeppelin/token/ERC20/IERC20.sol\";\nimport {UintArrayLib} from \"array-lib/UintArrayLib.sol\";\n\nimport {ICrossMarginEngine} from \"pomace/interfaces/ICrossMarginEngine.sol\";\n\nimport \"pomace/libraries/TokenIdUtil.sol\";\nimport \"pomace/libraries/BalanceUtil.sol\";\n\n// Cross Margin libraries and configs\nimport \"../libraries/AccountUtil.sol\";\n\nimport {CrossMarginAccount} from \"./types.sol\";\nimport \"../config/errors.sol\";\n\n/**\n * @title CrossMarginPhysicalLib\n * @dev   This library is in charge of updating the simple account struct and do validations\n */\nlibrary CrossMarginPhysicalLib {\n    using BalanceUtil for Balance[];\n    using AccountUtil for Position[];\n    using UintArrayLib for uint256[];\n    using TokenIdUtil for uint256;\n\n    /**\n     * @dev return true if the account has no short,long positions nor collateral\n     */\n    function isEmpty(CrossMarginAccount storage account) external view returns (bool) {\n        return account.shorts.isEmpty() && account.longs.isEmpty() && account.collaterals.isEmpty();\n    }\n\n    ///@dev Increase the collateral in the account\n    ///@param account CrossMarginAccount storage that will be updated\n    function addCollateral(CrossMarginAccount storage account, uint8 collateralId, uint80 amount) public {\n        if (amount == 0) return;\n\n        (bool found, uint256 index) = account.collaterals.indexOf(collateralId);\n\n        if (!found) {\n            account.collaterals.push(Balance(collateralId, amount));\n        } else {\n            account.collaterals[index].amount += amount;\n        }\n    }\n\n    ///@dev Reduce the collateral in the account\n    ///@param account CrossMarginAccount storage that will be updated\n    function removeCollateral(CrossMarginAccount storage account, uint8 collateralId, uint80 amount) public {\n        Balance[] memory collaterals = account.collaterals;\n\n        (bool found, uint256 index) = collaterals.indexOf(collateralId);\n\n        if (!found) revert CM_WrongCollateralId();\n\n        uint80 newAmount = collaterals[index].amount - amount;\n\n        if (newAmount == 0) {\n            account.collaterals.remove(index);\n        } else {\n            account.collaterals[index].amount = newAmount;\n        }\n    }\n\n    ///@dev Increase the amount of short call or put (debt) of the account\n    ///@param account CrossMarginAccount storage that will be updated\n    function mintOption(CrossMarginAccount storage account, uint256 tokenId, uint64 amount) external {\n        if (amount == 0) return;\n\n        TokenType optionType = tokenId.parseTokenType();\n\n        // engine only supports calls and puts\n        if (optionType != TokenType.CALL && optionType != TokenType.PUT) revert CM_UnsupportedTokenType();\n\n        (bool found, uint256 index) = account.shorts.indexOf(tokenId);\n        if (!found) {\n            account.shorts.push(Position(tokenId, amount));\n        } else {\n            account.shorts[index].amount += amount;\n        }\n    }\n\n    ///@dev Remove the amount of short call or put (debt) of the account\n    ///@param account CrossMarginAccount storage that will be updated in-place\n    function burnOption(CrossMarginAccount storage account, uint256 tokenId, uint64 amount) external {\n        (bool found, Position memory position, uint256 index) = account.shorts.find(tokenId);\n\n        if (!found) revert CM_InvalidToken();\n\n        uint64 newShortAmount = position.amount - amount;\n        if (newShortAmount == 0) {\n            account.shorts.removeAt(index);\n        } else {\n            account.shorts[index].amount = newShortAmount;\n        }\n    }\n\n    ///@dev Increase the amount of long call or put (debt) of the account\n    ///@param account CrossMarginAccount storage that will be updated\n    function addOption(CrossMarginAccount storage account, uint256 tokenId, uint64 amount) external {\n        if (amount == 0) return;\n\n        (bool found, uint256 index) = account.longs.indexOf(tokenId);\n\n        if (!found) {\n            account.longs.push(Position(tokenId, amount));\n        } else {\n            account.longs[index].amount += amount;\n        }\n    }\n\n    ///@dev Remove the amount of long call or put held by the account\n    ///@param account CrossMarginAccount storage that will be updated in-place\n    function removeOption(CrossMarginAccount storage account, uint256 tokenId, uint64 amount) external {\n        (bool found, Position memory position, uint256 index) = account.longs.find(tokenId);\n\n        if (!found) revert CM_InvalidToken();\n\n        uint64 newLongAmount = position.amount - amount;\n        if (newLongAmount == 0) {\n            account.longs.removeAt(index);\n        } else {\n            account.longs[index].amount = newLongAmount;\n        }\n    }\n\n    // ///@dev Settles the accounts longs and shorts\n    // ///@param account CrossMarginAccount storage that will be updated in-place\n    // function settleAtExpiry(CrossMarginAccount storage account, IPomace pomace)\n    //     external\n    //     returns (Balance[] memory longPayouts, Balance[] memory shortPayouts)\n    // {\n    //     // settling longs first as they can only increase collateral\n    //     _settleLongs(pomace, account);\n    //     // settling shorts last as they can only reduce collateral\n    //     _settleShorts(pomace, account);\n    // }\n\n    ///@dev Exercising long, adding and removing collateral to balances\n    ///@param account CrossMarginAccount memory that will be updated in-place\n    ///@param pomace interface to settle long options in a batch call\n    ///@param tokenId Option to exercise\n    ///@param amount amount of options\n    function exerciseToken(CrossMarginAccount storage account, IPomace pomace, uint256 tokenId, uint256 amount)\n        external\n        returns (Balance memory debt, Balance memory payout)\n    {\n        uint256 i;\n        bool tokenFound;\n\n        for (i; i < account.longs.length;) {\n            if (tokenId == account.longs[i].tokenId) {\n                (,, uint64 expiry,, uint64 exerciseWindow) = tokenId.parseTokenId();\n\n                if (expiry > block.timestamp) revert CML_NotExpired();\n\n                if (expiry + exerciseWindow < block.timestamp) {\n                    // worthless option, removing from account\n                    account.longs.removeAt(i);\n                } else {\n                    uint256 accountAmount = account.longs[i].amount;\n                    if (amount > accountAmount) revert CML_ExceedsAmount();\n\n                    if (amount == accountAmount) {\n                        account.longs.removeAt(i);\n                    } else {\n                        account.longs[i].amount -= uint64(amount);\n                    }\n                }\n\n                tokenFound = true;\n\n                break;\n            }\n\n            unchecked {\n                ++i;\n            }\n        }\n\n        if (tokenFound) {\n            (debt, payout) = pomace.settleOption(address(this), tokenId, amount);\n\n            // add the collateral in the account storage.\n            if (payout.amount > 0) addCollateral(account, payout.collateralId, payout.amount);\n\n            // remove the collateral in the account storage.\n            if (debt.amount > 0) removeCollateral(account, debt.collateralId, debt.amount);\n        }\n\n        // clean up worthless tokens\n        for (i = 0; i < account.longs.length;) {\n            (,, uint64 expiry,, uint64 exerciseWindow) = account.longs[i].tokenId.parseTokenId();\n\n            if (expiry + exerciseWindow < block.timestamp) {\n                account.longs.removeAt(i);\n            } else {\n                unchecked {\n                    ++i;\n                }\n            }\n        }\n    }\n\n    ///@dev Settles the accounts shorts, updating collateral for exercised options\n    ///@param account CrossMarginAccount memory that will be updated in-place\n    function settleShorts(CrossMarginAccount storage account)\n        external\n        returns (Balance[] memory debts, Balance[] memory payouts)\n    {\n        uint256 i;\n        uint256[] memory tokenIds;\n        uint256[] memory amounts;\n\n        for (i; i < account.shorts.length;) {\n            uint256 tokenId = account.shorts[i].tokenId;\n\n            (,, uint64 expiry,, uint64 exerciseWindow) = tokenId.parseTokenId();\n\n            // can only settle short options after the settlement window\n            if (expiry + exerciseWindow < block.timestamp) {\n                tokenIds = tokenIds.append(tokenId);\n                amounts = amounts.append(account.shorts[i].amount);\n                account.shorts.removeAt(i);\n            } else {\n                unchecked {\n                    ++i;\n                }\n            }\n        }\n\n        ICrossMarginEngine engine = ICrossMarginEngine(address(this));\n\n        if (tokenIds.length > 0) {\n            // the engine will socialized the debt and payout for settled options\n            (debts, payouts) = engine.getBatchSettlementForShorts(tokenIds, amounts);\n\n            // debts and payouts are equal length\n            for (i = 0; i < payouts.length;) {\n                // add to what is paid from exerciser\n                if (debts[i].amount > 0) addCollateral(account, debts[i].collateralId, debts[i].amount);\n\n                // remove the collateral in the account storage.\n                if (payouts[i].amount > 0) removeCollateral(account, payouts[i].collateralId, payouts[i].amount);\n\n                unchecked {\n                    ++i;\n                }\n            }\n        }\n\n        // clean up worthless tokens\n        for (i = 0; i < account.longs.length;) {\n            (,, uint64 expiry,, uint64 exerciseWindow) = account.longs[i].tokenId.parseTokenId();\n\n            if (expiry + exerciseWindow < block.timestamp) {\n                account.longs.removeAt(i);\n            } else {\n                unchecked {\n                    ++i;\n                }\n            }\n        }\n    }\n}\n"
      },
      "src/settled-physical/types.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"../config/types.sol\";\nimport {Balance} from \"pomace/config/types.sol\";\n\n/**\n * @dev base unit of cross margin account. This is the data stored in the state\n *      storage packing is utilized to save gas.\n * @param shorts an array of short positions\n * @param longs an array of long positions\n * @param collaterals an array of collateral balances\n */\nstruct CrossMarginAccount {\n    Position[] shorts;\n    Position[] longs;\n    Balance[] collaterals;\n}\n"
      },
      "src/config/errors.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/* --------------------- *\n *  Cross Margin Errors\n * --------------------- */\n\n/// @dev cross margin doesn't support this action\nerror CM_UnsupportedAction();\n\n/// @dev cannot override a non-empty subaccount id\nerror CM_AccountIsNotEmpty();\n\n/// @dev unsupported token type\nerror CM_UnsupportedTokenType();\n\n/// @dev can only add long tokens that are not expired\nerror CM_Token_Expired();\n\n/// @dev can only add long tokens from authorized engines\nerror CM_Not_Authorized_Engine();\n\n/// @dev collateral id is wrong: the id doesn't match the existing collateral\nerror CM_WrongCollateralId();\n\n/// @dev invalid collateral:\nerror CM_CannotMintOptionWithThisCollateral();\n\n/// @dev invalid tokenId specify to mint / burn actions\nerror CM_InvalidToken();\n\n//// @dev invalid signed message\nerror CM_InvalidSignature();\n\n/* -------------------------- *\n *  Cross Margin Math Errors\n * -------------------------- */\n\n/// @dev invalid put length given strikes\nerror CMM_InvalidPutLengths();\n\n/// @dev invalid call length given strikes\nerror CMM_InvalidCallLengths();\n\n/// @dev invalid put length of zero\nerror CMM_InvalidPutWeight();\n\n/// @dev invalid call length of zero\nerror CMM_InvalidCallWeight();\n\n/* ------------------------ *\n *  Cross Margin Lib Errors\n * ------------------------ */\n\n/// @dev token not yet expired\nerror CML_NotExpired();\n\nerror CML_ExceedsAmount();\n"
      },
      "lib/core-physical/src/config/types.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"./enums.sol\";\n\n/**\n * @dev struct representing the current balance for a given collateral\n * @param collateralId pomace asset id\n * @param amount amount the asset\n */\nstruct Balance {\n    uint8 collateralId;\n    uint80 amount;\n}\n\n/**\n * @dev struct containing assets detail for an product\n * @param underlying    underlying address\n * @param strike        strike address\n * @param collateral    collateral address\n * @param collateralDecimals collateral asset decimals\n */\nstruct ProductDetails {\n    address engine;\n    uint8 engineId;\n    address underlying;\n    uint8 underlyingId;\n    uint8 underlyingDecimals;\n    address strike;\n    uint8 strikeId;\n    uint8 strikeDecimals;\n    address collateral;\n    uint8 collateralId;\n    uint8 collateralDecimals;\n}\n\n// todo: update doc\nstruct ActionArgs {\n    ActionType action;\n    bytes data;\n}\n\nstruct BatchExecute {\n    address subAccount;\n    ActionArgs[] actions;\n}\n\n/**\n * @dev asset detail stored per asset id\n * @param addr address of the asset\n * @param decimals token decimals\n */\nstruct AssetDetail {\n    address addr;\n    uint8 decimals;\n}\n"
      },
      "lib/core-physical/src/config/enums.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nenum TokenType {\n    PUT,\n    CALL\n}\n\n/**\n * @dev common action types on margin engines\n */\nenum ActionType {\n    AddCollateral,\n    RemoveCollateral,\n    MintShort,\n    BurnShort,\n    AddLong,\n    RemoveLong,\n    ExerciseToken,\n    SettleAccount,\n    // actions that influence more than one subAccounts:\n    // These actions are defined in \"OptionTransferable\"\n    MintShortIntoAccount, // increase short (debt) position in one subAccount, increase long token directly to another subAccount\n    TransferCollateral, // transfer collateral directly to another subAccount\n    TransferLong, // transfer long directly to another subAccount\n    TransferShort, // transfer short directly to another subAccount\n    BurnShortInAccount // decreases short position in one subAccount, decreases long position in another\n\n}\n"
      },
      "lib/core-physical/src/config/constants.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n///@dev unit used for option amount and strike prices\nuint8 constant UNIT_DECIMALS = 6;\n\n///@dev unit scaled used to convert amounts.\nuint256 constant UNIT = 10 ** 6;\n\n///@dev int scaled used to convert amounts.\nint256 constant sUNIT = int256(10 ** 6);\n\n///@dev maximum dispute period for oracle\nuint256 constant MAX_DISPUTE_PERIOD = 6 hours;\n"
      },
      "lib/core-physical/src/config/errors.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/* ------------------------ *\n *      Shared Errors       *\n * -----------------------  */\n\nerror NoAccess();\n\n/* ------------------------ *\n *      Pomace Errors       *\n * -----------------------  */\n\n/// @dev asset already registered\nerror PM_AssetAlreadyRegistered();\n\n/// @dev margin engine already registered\nerror PM_EngineAlreadyRegistered();\n\n/// @dev amounts length specified to batch settle doesn't match with tokenIds\nerror PM_WrongArgumentLength();\n\n/// @dev cannot settle an unexpired option\nerror PM_NotExpired();\n\n/// @dev settlement price is not finalized yet\nerror PM_PriceNotFinalized();\n\n/// @dev cannot mint token after expiry\nerror PM_InvalidExpiry();\n\n/// @dev cannot mint token with zero settlement window\nerror PM_InvalidExerciseWindow();\n\n/// @dev cannot mint token with zero settlement window\nerror PM_InvalidCollateral();\n\n/// @dev burn or mint can only be called by corresponding engine.\nerror PM_Not_Authorized_Engine();\n\n/* ---------------------------- *\n *   Common BaseEngine Errors   *\n * ---------------------------  */\n\n/// @dev account is not healthy / account is underwater\nerror BM_AccountUnderwater();\n\n/// @dev msg.sender is not authorized to ask margin account to pull token from {from} address\nerror BM_InvalidFromAddress();\n"
      },
      "lib/entitlements/src/config/enums.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nenum Role {\n    Investor_MFFeederDomestic,\n    Investor_MFFeederInternational,\n    Investor_SDYFDomestic,\n    Investor_SDYFInternational,\n    Investor_LOFDomestic,\n    Investor_LOFInternational,\n    Investor_Reserve1,\n    Investor_Reserve2,\n    Investor_Reserve3,\n    Investor_Reserve4,\n    Investor_Reserve5,\n    Custodian_Centralized,\n    Custodian_Decentralized,\n    System_FundAdmin,\n    System_Token,\n    System_Vault,\n    System_Auction,\n    System_Teller,\n    System_Oracle,\n    System_MarginEngine,\n    LiquidityProvider_Options,\n    LiquidityProvider_Spot\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/interfaces/draft-IERC1822.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\n * proxy whose upgrades are fully controlled by the current implementation.\n */\ninterface IERC1822Proxiable {\n    /**\n     * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\n     * address.\n     *\n     * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n     * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n     * function revert if invoked through a proxy.\n     */\n    function proxiableUUID() external view returns (bytes32);\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/proxy/ERC1967/ERC1967Upgrade.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../beacon/IBeacon.sol\";\nimport \"../../interfaces/draft-IERC1822.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/StorageSlot.sol\";\n\n/**\n * @dev This abstract contract provides getters and event emitting update functions for\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\n *\n * _Available since v4.1._\n *\n * @custom:oz-upgrades-unsafe-allow delegatecall\n */\nabstract contract ERC1967Upgrade {\n    // This is the keccak-256 hash of \"eip1967.proxy.rollback\" subtracted by 1\n    bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\n\n    /**\n     * @dev Storage slot with the address of the current implementation.\n     * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1, and is\n     * validated in the constructor.\n     */\n    bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n    /**\n     * @dev Emitted when the implementation is upgraded.\n     */\n    event Upgraded(address indexed implementation);\n\n    /**\n     * @dev Returns the current implementation address.\n     */\n    function _getImplementation() internal view returns (address) {\n        return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n    }\n\n    /**\n     * @dev Stores a new address in the EIP1967 implementation slot.\n     */\n    function _setImplementation(address newImplementation) private {\n        require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n        StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n    }\n\n    /**\n     * @dev Perform implementation upgrade\n     *\n     * Emits an {Upgraded} event.\n     */\n    function _upgradeTo(address newImplementation) internal {\n        _setImplementation(newImplementation);\n        emit Upgraded(newImplementation);\n    }\n\n    /**\n     * @dev Perform implementation upgrade with additional setup call.\n     *\n     * Emits an {Upgraded} event.\n     */\n    function _upgradeToAndCall(\n        address newImplementation,\n        bytes memory data,\n        bool forceCall\n    ) internal {\n        _upgradeTo(newImplementation);\n        if (data.length > 0 || forceCall) {\n            Address.functionDelegateCall(newImplementation, data);\n        }\n    }\n\n    /**\n     * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\n     *\n     * Emits an {Upgraded} event.\n     */\n    function _upgradeToAndCallUUPS(\n        address newImplementation,\n        bytes memory data,\n        bool forceCall\n    ) internal {\n        // Upgrades from old implementations will perform a rollback test. This test requires the new\n        // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\n        // this special case will break upgrade paths from old UUPS implementation to new ones.\n        if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\n            _setImplementation(newImplementation);\n        } else {\n            try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\n                require(slot == _IMPLEMENTATION_SLOT, \"ERC1967Upgrade: unsupported proxiableUUID\");\n            } catch {\n                revert(\"ERC1967Upgrade: new implementation is not UUPS\");\n            }\n            _upgradeToAndCall(newImplementation, data, forceCall);\n        }\n    }\n\n    /**\n     * @dev Storage slot with the admin of the contract.\n     * This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1, and is\n     * validated in the constructor.\n     */\n    bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n    /**\n     * @dev Emitted when the admin account has changed.\n     */\n    event AdminChanged(address previousAdmin, address newAdmin);\n\n    /**\n     * @dev Returns the current admin.\n     */\n    function _getAdmin() internal view returns (address) {\n        return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\n    }\n\n    /**\n     * @dev Stores a new address in the EIP1967 admin slot.\n     */\n    function _setAdmin(address newAdmin) private {\n        require(newAdmin != address(0), \"ERC1967: new admin is the zero address\");\n        StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\n    }\n\n    /**\n     * @dev Changes the admin of the proxy.\n     *\n     * Emits an {AdminChanged} event.\n     */\n    function _changeAdmin(address newAdmin) internal {\n        emit AdminChanged(_getAdmin(), newAdmin);\n        _setAdmin(newAdmin);\n    }\n\n    /**\n     * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\n     * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\n     */\n    bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\n\n    /**\n     * @dev Emitted when the beacon is upgraded.\n     */\n    event BeaconUpgraded(address indexed beacon);\n\n    /**\n     * @dev Returns the current beacon.\n     */\n    function _getBeacon() internal view returns (address) {\n        return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\n    }\n\n    /**\n     * @dev Stores a new beacon in the EIP1967 beacon slot.\n     */\n    function _setBeacon(address newBeacon) private {\n        require(Address.isContract(newBeacon), \"ERC1967: new beacon is not a contract\");\n        require(\n            Address.isContract(IBeacon(newBeacon).implementation()),\n            \"ERC1967: beacon implementation is not a contract\"\n        );\n        StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\n    }\n\n    /**\n     * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\n     * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\n     *\n     * Emits a {BeaconUpgraded} event.\n     */\n    function _upgradeBeaconToAndCall(\n        address newBeacon,\n        bytes memory data,\n        bool forceCall\n    ) internal {\n        _setBeacon(newBeacon);\n        emit BeaconUpgraded(newBeacon);\n        if (data.length > 0 || forceCall) {\n            Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\n        }\n    }\n}\n"
      },
      "lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\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 ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\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    /**\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[50] private __gap;\n}\n"
      },
      "lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.1) (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 * ```\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\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"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-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    function safeTransfer(\n        IERC20 token,\n        address to,\n        uint256 value\n    ) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n    }\n\n    function safeTransferFrom(\n        IERC20 token,\n        address from,\n        address to,\n        uint256 value\n    ) 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(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) 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    function safeIncreaseAllowance(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        uint256 newAllowance = token.allowance(address(this), spender) + value;\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n    }\n\n    function safeDecreaseAllowance(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        unchecked {\n            uint256 oldAllowance = token.allowance(address(this), spender);\n            require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n            uint256 newAllowance = oldAllowance - value;\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n        }\n    }\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        if (returndata.length > 0) {\n            // Return data is optional\n            require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n        }\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.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(\n        address from,\n        address to,\n        uint256 amount\n    ) external returns (bool);\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/IERC1155.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC1155 compliant contract, as defined in the\n * https://eips.ethereum.org/EIPS/eip-1155[EIP].\n *\n * _Available since v3.1._\n */\ninterface IERC1155 is IERC165 {\n    /**\n     * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\n     */\n    event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\n\n    /**\n     * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\n     * transfers.\n     */\n    event TransferBatch(\n        address indexed operator,\n        address indexed from,\n        address indexed to,\n        uint256[] ids,\n        uint256[] values\n    );\n\n    /**\n     * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\n     * `approved`.\n     */\n    event ApprovalForAll(address indexed account, address indexed operator, bool approved);\n\n    /**\n     * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\n     *\n     * If an {URI} event was emitted for `id`, the standard\n     * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\n     * returned by {IERC1155MetadataURI-uri}.\n     */\n    event URI(string value, uint256 indexed id);\n\n    /**\n     * @dev Returns the amount of tokens of token type `id` owned by `account`.\n     *\n     * Requirements:\n     *\n     * - `account` cannot be the zero address.\n     */\n    function balanceOf(address account, uint256 id) external view returns (uint256);\n\n    /**\n     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\n     *\n     * Requirements:\n     *\n     * - `accounts` and `ids` must have the same length.\n     */\n    function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)\n        external\n        view\n        returns (uint256[] memory);\n\n    /**\n     * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\n     *\n     * Emits an {ApprovalForAll} event.\n     *\n     * Requirements:\n     *\n     * - `operator` cannot be the caller.\n     */\n    function setApprovalForAll(address operator, bool approved) external;\n\n    /**\n     * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\n     *\n     * See {setApprovalForAll}.\n     */\n    function isApprovedForAll(address account, address operator) external view returns (bool);\n\n    /**\n     * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\n     *\n     * Emits a {TransferSingle} event.\n     *\n     * Requirements:\n     *\n     * - `to` cannot be the zero address.\n     * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\n     * - `from` must have a balance of tokens of type `id` of at least `amount`.\n     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\n     * acceptance magic value.\n     */\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 id,\n        uint256 amount,\n        bytes calldata data\n    ) external;\n\n    /**\n     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\n     *\n     * Emits a {TransferBatch} event.\n     *\n     * Requirements:\n     *\n     * - `ids` and `amounts` must have the same length.\n     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\n     * acceptance magic value.\n     */\n    function safeBatchTransferFrom(\n        address from,\n        address to,\n        uint256[] calldata ids,\n        uint256[] calldata amounts,\n        bytes calldata data\n    ) external;\n}\n"
      },
      "lib/core-physical/src/interfaces/IPomace.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"../config/types.sol\";\nimport {IOracle} from \"./IOracle.sol\";\n\ninterface IPomace {\n    function oracle() external view returns (IOracle oracle);\n\n    function checkEngineAccess(uint256 _tokenId, address _engine) external view;\n\n    function checkEngineAccessAndTokenId(uint256 _tokenId, address _engine) external view;\n\n    function engineIds(address _engine) external view returns (uint8 id);\n\n    function assetIds(address _asset) external view returns (uint8 id);\n\n    function assets(uint8 _id) external view returns (address addr, uint8 decimals);\n\n    function engines(uint8 _id) external view returns (address engine);\n\n    function isCollateralizable(uint8 _asset0, uint8 _asset1) external view returns (bool);\n\n    function isCollateralizable(address _asset0, address _asset1) external view returns (bool);\n\n    function getDebtAndPayout(uint256 tokenId, uint64 amount)\n        external\n        view\n        returns (address engine, uint8 debtId, uint256 debt, uint8 payoutId, uint256 payout);\n\n    function batchGetDebtAndPayouts(uint256[] calldata tokenId, uint256[] calldata amount)\n        external\n        view\n        returns (Balance[] memory debts, Balance[] memory payouts);\n\n    function getProductId(address engine, address underlying, address strike, address collateral)\n        external\n        view\n        returns (uint32 id);\n\n    function getTokenId(TokenType tokenType, uint32 productId, uint256 expiry, uint256 strike, uint256 exerciseWindow)\n        external\n        view\n        returns (uint256 id);\n\n    function getDetailFromProductId(uint32 _productId)\n        external\n        view\n        returns (\n            address engine,\n            address underlying,\n            uint8 underlyingDecimals,\n            address strike,\n            uint8 strikeDecimals,\n            address collateral,\n            uint8 collateralDecimals\n        );\n\n    /**\n     * @notice burn option token and get out cash value at expiry\n     * @param _account who to settle for\n     * @param _tokenId  tokenId of option token to burn\n     * @param _amount   amount to settle\n     * @return debt amount collected\n     * @return payout amount paid out\n     */\n    function settleOption(address _account, uint256 _tokenId, uint256 _amount)\n        external\n        returns (Balance memory debt, Balance memory payout);\n\n    /**\n     * @notice burn array of option tokens and get out cash value at expiry\n     * @param _account who to settle for\n     * @param _tokenIds array of tokenIds to burn\n     * @param _amounts   array of amounts to burn\n     */\n    function batchSettleOptions(address _account, uint256[] memory _tokenIds, uint256[] memory _amounts) external;\n}\n"
      },
      "lib/core-physical/src/interfaces/IPhysicalOptionToken.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IPhysicalOptionToken {\n    /**\n     * @dev mint option token to an address. Can only be called by corresponding margin engine\n     * @param _recipient    where to mint token to\n     * @param _tokenId      tokenId to mint\n     * @param _amount       amount to mint\n     *\n     */\n    function mint(address _recipient, uint256 _tokenId, uint256 _amount) external;\n\n    /**\n     * @dev burn option token from an address. Can only be called by corresponding margin engine\n     * @param _from         account to burn from\n     * @param _tokenId      tokenId to burn\n     * @param _amount       amount to burn\n     *\n     */\n    function burn(address _from, uint256 _tokenId, uint256 _amount) external;\n\n    /**\n     * @dev burn option token from an address. Can only be called by pomace, used for settlement\n     * @param _from         account to burn from\n     * @param _tokenId      tokenId to burn\n     * @param _amount       amount to burn\n     *\n     */\n    function burnPomaceOnly(address _from, uint256 _tokenId, uint256 _amount) external;\n\n    /**\n     * @dev burn batch of option token from an address. Can only be called by pomace\n     * @param _from         account to burn from\n     * @param _ids          tokenId to burn\n     * @param _amounts      amount to burn\n     *\n     */\n    function batchBurnPomaceOnly(address _from, uint256[] memory _ids, uint256[] memory _amounts) external;\n}\n"
      },
      "src/config/types.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/**\n * @dev struct used in memory to represent a cross margin account's option set\n *      this is a grouping of like underlying, collateral, strike (asset), and expiry\n *      used to calculate margin requirements\n * @param putWeights            amount of put options held in account (shorts and longs)\n * @param putStrikes            strikes of put options held in account (shorts and longs)\n * @param callWeights           amount of call options held in account (shorts and longs)\n * @param callStrikes           strikes of call options held in account (shorts and longs)\n * @param underlyingId          pomace id for underlying asset\n * @param underlyingDecimals    decimal points of underlying asset\n * @param numeraireId           pomace id for numeraire (aka strike) asset\n * @param numeraireDecimals     decimal points of numeraire (aka strike) asset\n * @param expiry                expiry of the option\n */\nstruct CrossMarginDetail {\n    int256[] putWeights;\n    uint256[] putStrikes;\n    int256[] callWeights;\n    uint256[] callStrikes;\n    uint8 underlyingId;\n    uint8 underlyingDecimals;\n    uint8 numeraireId;\n    uint8 numeraireDecimals;\n    uint256 expiry;\n}\n\n/**\n * @dev an uncompressed Position struct, expanding tokenId to uint256\n * @param tokenId pomace option token id\n * @param amount number option tokens\n */\nstruct Position {\n    uint256 tokenId;\n    uint64 amount;\n}\n\nstruct SettlementTracker {\n    uint64 issued;\n    uint80 totalDebt;\n    uint80 totalPaid;\n}\n"
      },
      "lib/array-lib/src/IntArrayLib.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {SafeCast} from \"openzeppelin/utils/math/SafeCast.sol\";\n\nlibrary IntArrayLib {\n    using SafeCast for int256;\n    using SafeCast for uint256;\n\n    /**\n     * @dev returns min value of aray x\n     */\n    function min(int256[] memory x) internal pure returns (int256 m) {\n        m = x[0];\n        for (uint256 i = 1; i < x.length;) {\n            if (x[i] < m) {\n                m = x[i];\n            }\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    /**\n     * @dev Returns maximal element in array\n     */\n    function max(int256[] memory x) internal pure returns (int256 m) {\n        m = x[0];\n        for (uint256 i = 1; i < x.length;) {\n            if (x[i] > m) {\n                m = x[i];\n            }\n\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    /**\n     * @dev returns min value of aray x and its index\n     */\n    function minWithIndex(int256[] memory x) internal pure returns (int256 m, uint256 idx) {\n        m = x[0];\n        idx = 0;\n        for (uint256 i = 1; i < x.length;) {\n            if (x[i] < m) {\n                m = x[i];\n                idx = i;\n            }\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    /**\n     * @dev Returns maximal elements compared to value z\n     * @return y array\n     */\n    function maximum(int256[] memory x, int256 z) internal pure returns (int256[] memory y) {\n        y = new int256[](x.length);\n        for (uint256 i; i < x.length;) {\n            if (x[i] > z) y[i] = x[i];\n            else y[i] = z;\n\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    /**\n     * @dev Return a new array that removes element at index z.\n     * @return y new array\n     */\n    function remove(int256[] memory x, uint256 z) internal pure returns (int256[] memory y) {\n        if (z >= x.length) return x;\n        y = new int256[](x.length - 1);\n        for (uint256 i; i < x.length;) {\n            unchecked {\n                if (i < z) y[i] = x[i];\n                else if (i > z) y[i - 1] = x[i];\n                ++i;\n            }\n        }\n    }\n\n    /**\n     * @dev Returns index of element\n     * @return found\n     * @return index\n     */\n    function indexOf(int256[] memory x, int256 v) internal pure returns (bool, uint256) {\n        for (uint256 i; i < x.length;) {\n            if (x[i] == v) {\n                return (true, i);\n            }\n\n            unchecked {\n                ++i;\n            }\n        }\n        return (false, 0);\n    }\n\n    /**\n     * @dev Compute sum of all elements\n     */\n    function sum(int256[] memory x) internal pure returns (int256 s) {\n        for (uint256 i; i < x.length;) {\n            s += x[i];\n\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    /**\n     * @dev return a new array which is sorted by indexes array\n     * @param x original array\n     * @param idxs indexes to sort based on.\n     */\n    function sortByIndexes(int256[] memory x, uint256[] memory idxs) internal pure returns (int256[] memory y) {\n        y = new int256[](x.length);\n        for (uint256 i; i < x.length;) {\n            y[i] = x[idxs[i]];\n\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    /**\n     * @dev return a new array that append element v at the end of array x\n     */\n    function append(int256[] memory x, int256 v) internal pure returns (int256[] memory y) {\n        y = new int256[](x.length + 1);\n        uint256 i;\n        for (i; i < x.length;) {\n            y[i] = x[i];\n\n            unchecked {\n                ++i;\n            }\n        }\n        y[i] = v;\n    }\n\n    /**\n     * @dev return a new array that's the result of concatting a and b\n     */\n    function concat(int256[] memory a, int256[] memory b) internal pure returns (int256[] memory y) {\n        y = new int256[](a.length + b.length);\n        uint256 v;\n        uint256 i;\n        for (i; i < a.length;) {\n            y[v] = a[i];\n\n            unchecked {\n                ++i;\n                ++v;\n            }\n        }\n        for (i = 0; i < b.length;) {\n            y[v] = b[i];\n\n            unchecked {\n                ++i;\n                ++v;\n            }\n        }\n    }\n\n    /**\n     * @dev Fills array x with value v in place.\n     */\n    function fill(int256[] memory x, int256 v) internal pure {\n        for (uint256 i; i < x.length;) {\n            x[i] = v;\n\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    /**\n     * @dev modifies memory a IN PLACE. Populates a starting at index z with values from b.\n     */\n    function populate(int256[] memory a, int256[] memory b) internal pure {\n        for (uint256 i; i < a.length;) {\n            a[i] = b[i];\n\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    /**\n     * @dev return the element at index i\n     *      if i is positive, it's the same as requesting x[i]\n     *      if i is negative, return the value positioned at -i from the end\n     * @param i can be positive or negative\n     */\n    function at(int256[] memory x, int256 i) internal pure returns (int256) {\n        if (i >= 0) {\n            // will revert with out of bound error if i is too large\n            return x[uint256(i)];\n        } else {\n            // will revert with underflow error if i is too small\n            return x[x.length - uint256(-i)];\n        }\n    }\n\n    /**\n     * @dev return a new array contains the copy from x[start] to x[end]\n     *      if i is positive, it's the same as requesting x[i]\n     *      if i is negative, return the value positioned at -i from the end\n     * @param x array to copy\n     * @param _start starting index, can be negative\n     * @param _start ending index, can be negative\n     */\n    function slice(int256[] memory x, int256 _start, int256 _end) internal pure returns (int256[] memory a) {\n        int256 len = int256(x.length);\n        if (_start < 0) _start = len + _start;\n        if (_end <= 0) _end = len + _end;\n        if (_end < _start) return new int256[](0);\n\n        uint256 start = uint256(_start);\n        uint256 end = uint256(_end);\n\n        a = new int256[](end - start);\n        uint256 y;\n        for (uint256 i = start; i < end;) {\n            a[y] = x[i];\n\n            unchecked {\n                ++i;\n                ++y;\n            }\n        }\n    }\n\n    /**\n     * @dev return an array y as the sum of 2 same-length array\n     *      y[i] = a[i] + b[i]\n     */\n    function add(int256[] memory a, int256[] memory b) internal pure returns (int256[] memory y) {\n        y = new int256[](a.length);\n        for (uint256 i; i < a.length;) {\n            y[i] = a[i] + b[i];\n\n            unchecked {\n                i++;\n            }\n        }\n    }\n\n    /**\n     * @dev return an new array y with y[i] = x[i] + z\n     */\n    function addEachBy(int256[] memory x, int256 z) internal pure returns (int256[] memory y) {\n        y = new int256[](x.length);\n        for (uint256 i; i < x.length;) {\n            y[i] = x[i] + z;\n\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    /**\n     * @dev return a new array y with y[i] = x[i] - z\n     */\n    function subEachBy(int256[] memory x, int256 z) internal pure returns (int256[] memory y) {\n        y = new int256[](x.length);\n        for (uint256 i; i < x.length;) {\n            y[i] = x[i] - z;\n\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    /**\n     * @dev return dot of 2 vectors\n     *      will revert if 2 vectors have different length\n     */\n    function dot(int256[] memory a, int256[] memory b) internal pure returns (int256 s) {\n        for (uint256 i; i < a.length;) {\n            s += a[i] * b[i];\n\n            unchecked {\n                ++i;\n            }\n        }\n    }\n}\n"
      },
      "lib/array-lib/src/sorting/QuickSort.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"../IntArrayLib.sol\";\nimport \"../UintArrayLib.sol\";\n\n/**\n * @author dsshap\n */\nlibrary QuickSort {\n    /**\n     * ----------------------- **\n     *  |  Quick Sort For Int256[]  |\n     * ----------------------- *\n     */\n\n    /**\n     * @dev get a new sorted array and index order used to sort.\n     * @return y copy of x but sorted\n     * @return idxs indexes of input array used for sorting.\n     */\n    function argSort(int256[] memory x) internal pure returns (int256[] memory y, uint256[] memory idxs) {\n        idxs = new uint256[](x.length);\n        // fill in index array\n        for (uint256 i; i < x.length;) {\n            idxs[i] = i;\n            unchecked {\n                ++i;\n            }\n        }\n        // initialize copy of x\n        y = new int256[](x.length);\n        IntArrayLib.populate(y, x);\n        // sort\n        quickSort(y, int256(0), int256(y.length - 1), idxs);\n    }\n\n    /**\n     * @dev return a new sorted copy of array x\n     */\n    function getSorted(int256[] memory x) internal pure returns (int256[] memory y) {\n        y = new int256[](x.length);\n        IntArrayLib.populate(y, x);\n        quickSort(y, int256(0), int256(y.length - 1));\n    }\n\n    /**\n     * @dev sort array x in place with quick sort algorithm\n     */\n    function sort(int256[] memory x) internal pure {\n        quickSort(x, int256(0), int256(x.length - 1));\n    }\n\n    /**\n     * @dev sort arr[left:right] in place with quick sort algorithm\n     */\n    function quickSort(int256[] memory arr, int256 left, int256 right) internal pure {\n        if (left == right) return;\n        int256 i = left;\n        int256 j = right;\n        unchecked {\n            int256 pivot = arr[uint256((left + right) / 2)];\n\n            while (i <= j) {\n                while (arr[uint256(i)] < pivot) {\n                    ++i;\n                }\n                while (pivot < arr[uint256(j)]) {\n                    --j;\n                }\n                if (i <= j) {\n                    (arr[uint256(i)], arr[uint256(j)]) = (arr[uint256(j)], arr[uint256(i)]);\n                    ++i;\n                    --j;\n                }\n            }\n        }\n        if (left < j) quickSort(arr, left, j);\n        if (i < right) quickSort(arr, i, right);\n    }\n\n    /**\n     * @dev quicksort implementation with indexes, sorts arr and indexArray in place\n     */\n    function quickSort(int256[] memory arr, int256 left, int256 right, uint256[] memory indexArray) internal pure {\n        if (left == right) return;\n        int256 i = left;\n        int256 j = right;\n        unchecked {\n            int256 pivot = arr[uint256((left + right) / 2)];\n            while (i <= j) {\n                while (arr[uint256(i)] < pivot) {\n                    ++i;\n                }\n                while (pivot < arr[uint256(j)]) {\n                    --j;\n                }\n                if (i <= j) {\n                    (arr[uint256(i)], arr[uint256(j)]) = (arr[uint256(j)], arr[uint256(i)]);\n                    (indexArray[uint256(i)], indexArray[uint256(j)]) = (indexArray[uint256(j)], indexArray[uint256(i)]);\n                    ++i;\n                    --j;\n                }\n            }\n        }\n        if (left < j) quickSort(arr, left, j, indexArray);\n        if (i < right) quickSort(arr, i, right, indexArray);\n    }\n\n    /**\n     * ----------------------- **\n     *  |  Quick Sort For Uint256[] |\n     * ----------------------- *\n     */\n\n    /**\n     * @dev get a new sorted array and index order used to sort.\n     * @return y copy of x but sorted\n     * @return idxs indexes of input array used for sorting.\n     */\n    function argSort(uint256[] memory x) internal pure returns (uint256[] memory y, uint256[] memory idxs) {\n        idxs = new uint256[](x.length);\n        // fill in index array\n        for (uint256 i; i < x.length;) {\n            idxs[i] = i;\n            unchecked {\n                ++i;\n            }\n        }\n        // initialize copy of x\n        y = new uint256[](x.length);\n        UintArrayLib.populate(y, x);\n        // sort\n        quickSort(y, int256(0), int256(y.length - 1), idxs);\n    }\n\n    /**\n     * @dev return a new sorted copy of array x\n     */\n    function getSorted(uint256[] memory x) internal pure returns (uint256[] memory y) {\n        y = new uint256[](x.length);\n        UintArrayLib.populate(y, x);\n        quickSort(y, int256(0), int256(y.length - 1));\n    }\n\n    /**\n     * @dev sort array x in place with quick sort algorithm\n     */\n    function sort(uint256[] memory x) internal pure {\n        quickSort(x, int256(0), int256(x.length - 1));\n    }\n\n    /**\n     * @dev sort arr[left:right] in place with quick sort algorithm\n     */\n    function quickSort(uint256[] memory arr, int256 left, int256 right) internal pure {\n        if (left == right) return;\n        int256 i = left;\n        int256 j = right;\n        unchecked {\n            uint256 pivot = arr[uint256(left + right) / 2];\n            while (i <= j) {\n                while (arr[uint256(i)] < pivot) {\n                    ++i;\n                }\n                while (pivot < arr[uint256(j)]) {\n                    --j;\n                }\n                if (i <= j) {\n                    (arr[uint256(i)], arr[uint256(j)]) = (arr[uint256(j)], arr[uint256(i)]);\n                    ++i;\n                    --j;\n                }\n            }\n        }\n        if (left < j) quickSort(arr, left, j);\n        if (i < right) quickSort(arr, i, right);\n    }\n\n    /**\n     * @dev quicksort implementation with indexes, sorts input arr and indexArray IN PLACE\n     */\n    function quickSort(uint256[] memory arr, int256 left, int256 right, uint256[] memory indexArray) internal pure {\n        if (left == right) return;\n        int256 i = left;\n        int256 j = right;\n        unchecked {\n            uint256 pivot = arr[uint256((left + right) / 2)];\n            while (i <= j) {\n                while (arr[uint256(i)] < pivot) {\n                    ++i;\n                }\n                while (pivot < arr[uint256(j)]) {\n                    --j;\n                }\n                if (i <= j) {\n                    (arr[uint256(i)], arr[uint256(j)]) = (arr[uint256(j)], arr[uint256(i)]);\n                    (indexArray[uint256(i)], indexArray[uint256(j)]) = (indexArray[uint256(j)], indexArray[uint256(i)]);\n                    ++i;\n                    --j;\n                }\n            }\n            if (left < j) quickSort(arr, left, j, indexArray);\n            if (i < right) quickSort(arr, i, right, indexArray);\n        }\n    }\n}\n"
      },
      "lib/core-physical/src/libraries/NumberUtil.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nlibrary NumberUtil {\n    /**\n     * @dev use it in uncheck so overflow will still be checked.\n     */\n    function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store x * y in z for now.\n            z := mul(x, y)\n\n            // Equivalent to require(x == 0 || (x * y) / x == y)\n            if iszero(or(iszero(x), eq(div(z, x), y))) { revert(0, 0) }\n        }\n    }\n\n    /**\n     * @notice convert decimals of an amount\n     *\n     * @param  amount      number to convert\n     * @param fromDecimals the decimals amount has\n     * @param toDecimals   the target decimals\n     *\n     * @return newAmount number with toDecimals decimals\n     */\n    function convertDecimals(uint256 amount, uint8 fromDecimals, uint8 toDecimals) internal pure returns (uint256) {\n        if (fromDecimals == toDecimals) return amount;\n\n        if (fromDecimals > toDecimals) {\n            uint8 diff;\n            unchecked {\n                diff = fromDecimals - toDecimals;\n                // div cannot underflow because diff 10**diff != 0\n                return amount / (10 ** diff);\n            }\n        } else {\n            uint8 diff;\n            unchecked {\n                diff = toDecimals - fromDecimals;\n            }\n            return amount * (10 ** diff);\n        }\n    }\n}\n"
      },
      "lib/core-physical/src/libraries/BytesArrayUtil.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {SafeCast} from \"openzeppelin/utils/math/SafeCast.sol\";\n\nlibrary BytesArrayUtil {\n    function indexOf(bytes32[] memory x, bytes32 v) internal pure returns (bool, uint256) {\n        for (uint256 i; i < x.length;) {\n            if (x[i] == v) {\n                return (true, i);\n            }\n\n            unchecked {\n                ++i;\n            }\n        }\n        return (false, 0);\n    }\n\n    function append(bytes32[] memory x, bytes32 e) internal pure returns (bytes32[] memory y) {\n        y = new bytes32[](x.length + 1);\n        uint256 i;\n        for (i; i < x.length;) {\n            y[i] = x[i];\n\n            unchecked {\n                ++i;\n            }\n        }\n        y[i] = e;\n    }\n}\n"
      },
      "lib/core-physical/src/interfaces/ICrossMarginEngine.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {Balance} from \"../config/types.sol\";\n\ninterface ICrossMarginEngine {\n    /**\n     * how the short should be settled\n     */\n    function getBatchSettlementForShorts(uint256[] calldata _tokenIds, uint256[] calldata _amounts)\n        external\n        view\n        returns (Balance[] memory debts, Balance[] memory payouts);\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/proxy/beacon/IBeacon.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\n */\ninterface IBeacon {\n    /**\n     * @dev Must return an address that can be used as a delegate call target.\n     *\n     * {BeaconProxy} will check that this address is a contract.\n     */\n    function implementation() external view returns (address);\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/Address.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.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     *\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://diligence.consensys.net/posts/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.5.11/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(\n        address target,\n        bytes memory data,\n        uint256 value\n    ) 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"
      },
      "lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol)\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 * ```\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`, and `uint256`._\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    /**\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"
      },
      "lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.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     *\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://diligence.consensys.net/posts/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.5.11/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(\n        address target,\n        bytes memory data,\n        uint256 value\n    ) 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 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"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-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"
      },
      "lib/openzeppelin-contracts/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"
      }
    },
    "settings": {
      "remappings": [
        "solmate/=lib/solmate/src/",
        "forge-std/=lib/forge-std/src/",
        "openzeppelin/=lib/openzeppelin-contracts/contracts/",
        "openzeppelin-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
        "array-lib/=lib/array-lib/src/",
        "pomace/=lib/core-physical/src/",
        "grappa/=lib/core-cash/src/",
        "grappa-test/=lib/core-cash/test/",
        "pomace-test/=lib/core-physical/test/",
        "entitlements/=lib/entitlements/",
        "@openzeppelin/contracts-upgradeable/=lib/entitlements/lib/openzeppelin-contracts-upgradeable/contracts/",
        "@openzeppelin/contracts/=lib/entitlements/lib/openzeppelin-contracts/contracts/",
        "array-lib/=lib/array-lib/src/",
        "core-cash/=lib/core-cash/",
        "core-physical/=lib/core-physical/",
        "ds-test/=lib/forge-std/lib/ds-test/src/",
        "erc4626-tests/=lib/entitlements/lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/",
        "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
        "openzeppelin-contracts/=lib/openzeppelin-contracts/"
      ],
      "optimizer": {
        "enabled": true,
        "runs": 800
      },
      "metadata": {
        "useLiteralContent": false,
        "bytecodeHash": "ipfs"
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "evmVersion": "london",
      "viaIR": false,
      "libraries": {
        "src/settled-physical/CrossMarginPhysicalLib.sol": {
          "CrossMarginPhysicalLib": "0x0e6B762f45d412C13B975dB10001d467d6CAAA19"
        },
        "src/settled-physical/CrossMarginPhysicalMath.sol": {
          "CrossMarginPhysicalMath": "0x93cc687407ACFc75D8994d20A4fF70563Bcc4B42"
        }
      }
    }
  }}