MEDIUM severity: The vulnerability in the Position Manager contract's `mint` function allows an attacker to permanent. The vulnerability in the Position Manager contract's `mint` function allows an attacker to permanently lock a user's position data by providing a strike that is not exactly the same as the current strike maintained by the contract. This can occur when a user attempts to mint a new position using the...

Vulnerable code:
```\nfunction mint(\n    IPositionManager.MintParams calldata params\n) external override returns (uint256 tokenId, uint256 premium) {\n    IDVP dvp = IDVP(params.dvpAddr);\n\n    if (params.tokenId!= 0) {\n        tokenId = params.tokenId;\n        ManagedPosition storage position = _positions[tokenId];\n\n        if (ownerOf(tokenId)!= msg.sender) {\n            revert NotOwner();\n        }\n        // Check token compatibility:\n        if (position.dvpAddr!= params.dvpAddr || position.strike!= params.strike) {\n            revert InvalidTokenID();\n        }\n        Epoch memory epoch = dvp.getEpoch();\n        if (position.expiry!= epoch.current) {\n            revert PositionExpired();\n        }\n    }\n    if ((params.notionalUp > 0 && params.notionalDown > 0) && (params.notionalUp!= params.notionalDown)) {\n        // If amount is a smile, it must be balanced:\n        revert AsymmetricAmount();\n    }\n\n    uint256 obtainedPremium;\n    uint256 fee;\n    (obtainedPremium, fee) = dvp.premium(params.strike, params.notionalUp, params.notionalDown);\n\n    // Transfer premium:\n    // NOTE: The PositionManager is just a middleman between the user and the DVP\n    IERC20 baseToken = IERC20(dvp.baseToken());\n    baseToken.safeTransferFrom(msg.sender, address(this), obtainedPremium);\n\n    // Premium already include fee\n    baseToken.safeApprove(params.dvpAddr, obtainedPremium);\n\n    premium = dvp.mint(\n        address(this),\n        params.strike,\n        params.notionalUp,\n        params.notionalDown,\n        params.expectedPremium,\n        params.maxSlippage,\n        params.nftAccessTokenId\n    );\n}\n```\n```\nfunction mint(\n    address recipient,\n    uint256 strike,\n    uint256 amountUp,\n    uint256 amountDown,\n    uint256 expectedPremium,\n    uint256 maxSlippage,\n    uint256 nftAccessTokenId\n) external override returns (uint256 premium_) {\n    strike;\n    _checkNFTAccess(nftAccessTokenId, recipient, amountUp + amountDown);\n    Amount memory amount_ = Amount({up: amountUp, down: amountDown});\n\n    premium_ = _mint(recipient, financeParameters.currentStrike, amount_, expectedPremium, maxSlippage);\n}\n```\n```\nfunction mint(\n    IPositionManager.MintParams calldata params\n) external override returns (uint256 tokenId, uint256 premium) {\n    if (obtainedPremium > premium) {\n        baseToken.safeTransferFrom(address(this), msg.sender, obtainedPremium - premium);\n    }\n\n    if (params.tokenId == 0) {\n        tokenId = _nextId++;\n        _mint(params.recipient, tokenId);\n\n        Epoch memory epoch = dvp.getEpoch();\n\n        _positions[tokenId] = ManagedPosition({\n            dvpAddr: params.dvpAddr,\n            strike: params.strike,\n            expiry: epoch.current,\n            premium: premium,\n            leverage: (params.notionalUp + params.notionalDown) / premium,\n            notionalUp: params.notionalUp,\n            notionalDown: params.notionalDown,\n            cumulatedPayoff: 0\n        });\n    } else {\n        ManagedPosition storage position = _positions[tokenId];\n        position.premium += premium;\n        position.notionalUp += params.notionalUp;\n        position.notionalDown += params.notionalDown;\n        position.leverage = (position.notionalUp + position.notionalDown) / position.premium;\n    }\n\n    emit BuyDVP(tokenId, _positions[tokenId].expiry, params.notionalUp + params.notionalDown);\n    emit Buy(params.dvpAddr, _positions[tokenId].expiry, premium, params.recipient);\n}\n```\n```\nfunction testMintAndBurnFail() public {\n    (uint256 tokenId,) = initAndMint();\n    bytes4 PositionNotFound = bytes4(keccak256("PositionNotFound()"));\n\n    vm.prank(alice);\n    vm.expectRevert(PositionNotFound);\n    pm.sell(\n        IPositionManager.SellParams({\n            tokenId: tokenId,\n            notionalUp: 10 ether,\n            notionalDown: 0,\n            expectedMarketValue: 0,\n            maxSlippage: 0.1e18\n        })\n    );\n}\n```\n```\nfunction initAndMint() private returns (uint256 tokenId, IG ig) {\n    vm.startPrank(admin);\n\n    ig = new IG(address(vault), address(ap));\n    ig.grantRole(ig.ROLE_ADMIN(), admin);\n    ig.grantRole(ig.ROLE_EPOCH_ROLLER(), admin);\n    vault.grantRole(vault.ROLE_ADMIN(), admin);\n    vault.setAllowedDVP(address(ig));\n\n    MarketOracle mo = MarketOracle(ap.marketOracle());\n\n    mo.setDelay(ig.baseToken(), ig.sideToken(), ig.getEpoch().frequency, 0, true);\n\n    Utils.skipDay(true, vm);\n    ig.rollEpoch();\n    vm.stopPrank();\n\n    uint256 strike = ig.currentStrike();\n\n    (uint256 expectedMarketValue,) = ig.premium(0, 10 ether, 0);\n    TokenUtils.provideApprovedTokens(admin, ig.baseToken(), DEFAULT_SENDER, address(pm), expectedMarketValue, vm);\n\n    vm.prank(DEFAULT_SENDER);\n    (tokenId,) = pm.mint(\n        IPositionManager.MintParams({\n            dvpAddr: address(ig),\n            notionalUp: 10 ether,\n            notionalDown: 0,\n            strike: strike + 1,\n            recipient: alice,\n            tokenId: 0,\n            expectedPremium: expectedMarketValue,\n            maxSlippage: 0.1e18,\n            nftAccessTokenId: 0\n        })\n    );\n    assertGe(1, tokenId);\n    assertGe(1, pm.totalSupply());\n}\n```\n```\nforge test --match-contract PositionManagerTest --match-test testMintAndBurnFail -vvv\n```