diff --git a/contracts/src/matching/HyperdriveMatchingEngineV2.sol b/contracts/src/matching/HyperdriveMatchingEngineV2.sol
index 56a6c5029..63450143c 100644
--- a/contracts/src/matching/HyperdriveMatchingEngineV2.sol
+++ b/contracts/src/matching/HyperdriveMatchingEngineV2.sol
@@ -143,10 +143,10 @@ contract HyperdriveMatchingEngineV2 is
             }
 
             // Calculate costs and parameters.
-            (
-                uint256 maturityTime,
-                uint256 cost
-            ) = _calculateMintCost(hyperdrive, bondMatchAmount);
+            (uint256 maturityTime, uint256 cost) = _calculateMintCost(
+                hyperdrive,
+                bondMatchAmount
+            );
 
             // Check if the maturity time is within the range.
             if (
@@ -354,7 +354,7 @@ contract HyperdriveMatchingEngineV2 is
     ///        extraData: ""
     ///    }),
     ///    orderType: _takerOrderType, // Take from the user's input.
-    ///    // For closing positions, take maturity time from the user's input; 
+    ///    // For closing positions, take maturity time from the user's input;
     ///    // otherwise, use values from the maker order.
     ///    minMaturityTime: _closeOrderMaturityTime or _makerOrder.minMaturityTime,
     ///    maxMaturityTime: _closeOrderMaturityTime or _makerOrder.maxMaturityTime,
@@ -367,11 +367,15 @@ contract HyperdriveMatchingEngineV2 is
         OrderIntent calldata _takerOrder
     ) external nonReentrant {
         // Validate maker order and taker order.
-        bytes32 makerOrderHash = _validateOrdersWithTaker(_makerOrder, _takerOrder);
+        bytes32 makerOrderHash = _validateOrdersWithTaker(
+            _makerOrder,
+            _takerOrder
+        );
 
         // Calculates the amount of bonds that can be matched between two orders.
         OrderAmounts memory amountsMaker = orderAmountsUsed[makerOrderHash];
-        uint256 makerBondAmount = _makerOrder.bondAmount - amountsMaker.bondAmount;
+        uint256 makerBondAmount = _makerOrder.bondAmount -
+            amountsMaker.bondAmount;
         uint256 bondMatchAmount = makerBondAmount.min(_takerOrder.bondAmount);
 
         IHyperdrive hyperdrive = _makerOrder.hyperdrive;
@@ -385,7 +389,7 @@ contract HyperdriveMatchingEngineV2 is
         // Handle different maker order types.
         if (_makerOrder.orderType == OrderType.OpenLong) {
             if (_takerOrder.orderType == OrderType.OpenShort) {
-                // OpenLong + OpenShort: Use mint().
+                // OpenLong + OpenShort: _handleMint().
                 // Calculate the amount of fund tokens to transfer based on the
                 // bondMatchAmount using dynamic pricing. During a series of partial
                 // matching, the pricing requirements can go easier as needed for
@@ -398,22 +402,23 @@ contract HyperdriveMatchingEngineV2 is
                         (_makerOrder.bondAmount -
                             orderAmountsUsed[makerOrderHash].bondAmount)
                     );
-                
+
                 // Update order fund amount used.
                 _updateOrderAmount(makerOrderHash, fundTokenAmountMaker, false);
 
                 // Check if the fund amount used is greater than the order amount.
                 if (
-                    orderAmountsUsed[makerOrderHash].fundAmount > _makerOrder.fundAmount
+                    orderAmountsUsed[makerOrderHash].fundAmount >
+                    _makerOrder.fundAmount
                 ) {
                     revert InvalidFundAmount();
                 }
 
                 // Calculate costs and parameters.
-                (
-                    uint256 maturityTime,
-                    uint256 cost
-                ) = _calculateMintCost(hyperdrive, bondMatchAmount);
+                (uint256 maturityTime, uint256 cost) = _calculateMintCost(
+                    hyperdrive,
+                    bondMatchAmount
+                );
 
                 // Check if the maturity time is within the range.
                 if (
@@ -424,7 +429,10 @@ contract HyperdriveMatchingEngineV2 is
                 }
 
                 // Calculate the amount of fund tokens the taker needs to pay.
-                uint256 fundTokenAmountTaker = fundTokenAmountMaker > cost + TOKEN_AMOUNT_BUFFER ? 0 : cost + TOKEN_AMOUNT_BUFFER - fundTokenAmountMaker;
+                uint256 fundTokenAmountTaker = fundTokenAmountMaker >
+                    cost + TOKEN_AMOUNT_BUFFER
+                    ? 0
+                    : cost + TOKEN_AMOUNT_BUFFER - fundTokenAmountMaker;
 
                 // Mint the bonds.
                 uint256 bondAmount = _handleMint(
@@ -441,7 +449,7 @@ contract HyperdriveMatchingEngineV2 is
                 // Update order bond amount used.
                 _updateOrderAmount(makerOrderHash, bondAmount, true);
             } else if (_takerOrder.orderType == OrderType.CloseLong) {
-                // OpenLong + CloseLong: Transfer long position.
+                // OpenLong + CloseLong: _handleTransfer().
                 // Verify that the maturity time of the close order matches the
                 // open order's requirements.
                 if (
@@ -489,48 +497,313 @@ contract HyperdriveMatchingEngineV2 is
             } else {
                 revert InvalidOrderCombination();
             }
-        }
-        // else if (_makerOrder.orderType == OrderType.OpenShort) {
-        //     if (_takerOrderType == OrderType.OpenLong) {
-        //         // OpenShort + OpenLong: Use mint().
-        //         _handleMint(takerOrder, _makerOrder);
-        //     } else if (_takerOrderType == OrderType.CloseShort) {
-        //         // OpenShort + CloseShort: Transfer short position.
-        //         _handleTransfer(_makerOrder, takerOrder);
-        //     } else {
-        //         revert InvalidOrderCombination();
-        //     }
-        // }
-        // else if (_makerOrder.orderType == OrderType.CloseLong) {
-        //     if (_takerOrderType == OrderType.OpenLong) {
-        //         // CloseLong + OpenLong: Transfer long position.
-        //         _handleTransfer(takerOrder, _makerOrder);
-        //     } else if (_takerOrderType == OrderType.CloseShort) {
-        //         // CloseLong + CloseShort: Use burn().
-        //         _handleBurn(_makerOrder, takerOrder);
-        //     } else {
-        //         revert InvalidOrderCombination();
-        //     }
-        // }
-        // else if (_makerOrder.orderType == OrderType.CloseShort) {
-        //     if (_takerOrderType == OrderType.OpenShort) {
-        //         // CloseShort + OpenShort: Transfer short position.
-        //         _handleTransfer(takerOrder, _makerOrder);
-        //     } else if (_takerOrderType == OrderType.CloseLong) {
-        //         // CloseShort + CloseLong: Use burn().
-        //         _handleBurn(takerOrder, _makerOrder);
-        //     } else {
-        //         revert InvalidOrderCombination();
-        //     }
-        // }
-        else {
+        } else if (_makerOrder.orderType == OrderType.OpenShort) {
+            if (_takerOrder.orderType == OrderType.OpenLong) {
+                // OpenShort + OpenLong: _handleMint() but reverse the order.
+                // Calculate the amount of fund tokens to transfer based on the
+                // bondMatchAmount using dynamic pricing. During a series of partial
+                // matching, the pricing requirements can go easier as needed for
+                // each new match, hence increasing the match likelihood.
+                // NOTE: Round the required fund amount down to prevent overspending
+                //       and possible reverting at a later step.
+                uint256 fundTokenAmountMaker = (_makerOrder.fundAmount -
+                    orderAmountsUsed[makerOrderHash].fundAmount).mulDivDown(
+                        bondMatchAmount,
+                        (_makerOrder.bondAmount -
+                            orderAmountsUsed[makerOrderHash].bondAmount)
+                    );
+
+                // Update order fund amount used.
+                _updateOrderAmount(makerOrderHash, fundTokenAmountMaker, false);
+
+                // Check if the fund amount used is greater than the order amount.
+                if (
+                    orderAmountsUsed[makerOrderHash].fundAmount >
+                    _makerOrder.fundAmount
+                ) {
+                    revert InvalidFundAmount();
+                }
+
+                // Calculate costs and parameters.
+                (uint256 maturityTime, uint256 cost) = _calculateMintCost(
+                    hyperdrive,
+                    bondMatchAmount
+                );
+
+                // Check if the maturity time is within the range.
+                if (
+                    maturityTime < _makerOrder.minMaturityTime ||
+                    maturityTime > _makerOrder.maxMaturityTime
+                ) {
+                    revert InvalidMaturityTime();
+                }
+
+                // Calculate the amount of fund tokens the taker needs to pay.
+                uint256 fundTokenAmountTaker = fundTokenAmountMaker >
+                    cost + TOKEN_AMOUNT_BUFFER
+                    ? 0
+                    : cost + TOKEN_AMOUNT_BUFFER - fundTokenAmountMaker;
+
+                // Mint the bonds.
+                uint256 bondAmount = _handleMint(
+                    _takerOrder,
+                    _makerOrder,
+                    fundTokenAmountTaker,
+                    fundTokenAmountMaker,
+                    cost,
+                    bondMatchAmount,
+                    fundToken,
+                    hyperdrive
+                );
+
+                // Update order bond amount used.
+                _updateOrderAmount(makerOrderHash, bondAmount, true);
+            } else if (_takerOrder.orderType == OrderType.CloseShort) {
+                // OpenShort + CloseShort: _handleTransfer().
+                // Verify that the maturity time of the close order matches the
+                // open order's requirements.
+                if (
+                    _takerOrder.maxMaturityTime > _makerOrder.maxMaturityTime ||
+                    _takerOrder.maxMaturityTime < _makerOrder.minMaturityTime
+                ) {
+                    revert InvalidMaturityTime();
+                }
+
+                // Calculate the amount of fund tokens to transfer based on the
+                // bondMatchAmount using dynamic pricing. During a series of partial
+                // matching, the pricing requirements can go easier as needed for each
+                // new match, hence increasing the match likelihood.
+                // NOTE: Round the required fund amount down to prevent overspending
+                //       and possible reverting at a later step.
+                uint256 fundTokenAmountMaker = (_makerOrder.fundAmount -
+                    orderAmountsUsed[makerOrderHash].fundAmount).mulDivDown(
+                        bondMatchAmount,
+                        (_makerOrder.bondAmount -
+                            orderAmountsUsed[makerOrderHash].bondAmount)
+                    );
+
+                // The taker simply agrees with the maker's fund amount, and no
+                // additional donation nor validations need to be considered
+                uint256 minFundAmountTaker = fundTokenAmountMaker;
+
+                // Update order bond amount used.
+                // @dev After the update, there is no need to check if the bond
+                //      amount used is greater than the order amount, as the order
+                //      amount is already used to calculate the bondMatchAmount.
+                _updateOrderAmount(makerOrderHash, bondMatchAmount, true);
+
+                _handleTransfer(
+                    _makerOrder,
+                    _takerOrder,
+                    fundTokenAmountMaker,
+                    minFundAmountTaker,
+                    bondMatchAmount,
+                    fundToken,
+                    hyperdrive
+                );
+
+                // Update order fund amount used.
+                _updateOrderAmount(makerOrderHash, fundTokenAmountMaker, false);
+            } else {
+                revert InvalidOrderCombination();
+            }
+        } else if (_makerOrder.orderType == OrderType.CloseLong) {
+            if (_takerOrder.orderType == OrderType.OpenLong) {
+                // CloseLong + OpenLong: _handleTransfer() but reverse the order.
+                // Verify that the maturity time of the close order matches the
+                // open order's requirements.
+                if (
+                    _makerOrder.maxMaturityTime > _takerOrder.maxMaturityTime ||
+                    _makerOrder.maxMaturityTime < _takerOrder.minMaturityTime
+                ) {
+                    revert InvalidMaturityTime();
+                }
+
+                // Calculate the amount of fund tokens to transfer based on the
+                // bondMatchAmount using dynamic pricing. During a series of partial
+                // matching, the pricing requirements can go easier as needed for each
+                // new match, hence increasing the match likelihood.
+                // NOTE: Round the required fund amount down to prevent overspending
+                //       and possible reverting at a later step.
+                uint256 minFundAmountMaker = (_makerOrder.fundAmount -
+                    orderAmountsUsed[makerOrderHash].fundAmount).mulDivDown(
+                        bondMatchAmount,
+                        (_makerOrder.bondAmount -
+                            orderAmountsUsed[makerOrderHash].bondAmount)
+                    );
+
+                // The taker simply agrees with the maker's fund amount, and no
+                // additional donation nor validations need to be considered
+                uint256 fundTokenAmountTaker = minFundAmountMaker;
+
+                // Update order bond amount used.
+                // @dev After the update, there is no need to check if the bond
+                //      amount used is greater than the order amount, as the order
+                //      amount is already used to calculate the bondMatchAmount.
+                _updateOrderAmount(makerOrderHash, bondMatchAmount, true);
+
+                _handleTransfer(
+                    _takerOrder,
+                    _makerOrder,
+                    fundTokenAmountTaker,
+                    minFundAmountMaker,
+                    bondMatchAmount,
+                    fundToken,
+                    hyperdrive
+                );
+
+                // Update order fund amount used.
+                _updateOrderAmount(makerOrderHash, minFundAmountMaker, false);
+            } else if (_takerOrder.orderType == OrderType.CloseShort) {
+                // CloseLong + CloseShort: _handleBurn().
+                // Verify both orders have the same maturity time.
+                if (
+                    _makerOrder.maxMaturityTime != _takerOrder.maxMaturityTime
+                ) {
+                    revert InvalidMaturityTime();
+                }
+
+                // Get the min fund output according to the bondMatchAmount.
+                // NOTE: Round the required fund amount up to respect the order
+                //       specified min fund output.
+                uint256 minFundAmountMaker = (_makerOrder.fundAmount -
+                    orderAmountsUsed[makerOrderHash].fundAmount).mulDivUp(
+                        bondMatchAmount,
+                        (_makerOrder.bondAmount -
+                            orderAmountsUsed[makerOrderHash].bondAmount)
+                    );
+
+                // The taker takes whatever the leftover fund amount is.
+                // @dev The taker will not receive proceeds inside the _handleBurn(),
+                //      but will receive the leftover fund at the surplus distribution.
+                uint256 minFundAmountTaker = 0;
+
+                // Update order bond amount used.
+                // @dev After the update, there is no need to check if the bond
+                //      amount used is greater than the order amount, as the order
+                //      amount is already used to calculate the bondMatchAmount.
+                _updateOrderAmount(makerOrderHash, bondMatchAmount, true);
+
+                // Handle burn operation through helper function.
+                _handleBurn(
+                    _makerOrder,
+                    _takerOrder,
+                    minFundAmountMaker,
+                    minFundAmountTaker,
+                    bondMatchAmount,
+                    fundToken,
+                    hyperdrive
+                );
+
+                // Update order fund amount used.
+                _updateOrderAmount(makerOrderHash, minFundAmountMaker, false);
+            } else {
+                revert InvalidOrderCombination();
+            }
+        } else if (_makerOrder.orderType == OrderType.CloseShort) {
+            if (_takerOrder.orderType == OrderType.OpenShort) {
+                // CloseShort + OpenShort: _handleTransfer() but reverse the order.
+                // Verify that the maturity time of the close order matches the
+                // open order's requirements.
+                if (
+                    _makerOrder.maxMaturityTime > _takerOrder.maxMaturityTime ||
+                    _makerOrder.maxMaturityTime < _takerOrder.minMaturityTime
+                ) {
+                    revert InvalidMaturityTime();
+                }
+
+                // Calculate the amount of fund tokens to transfer based on the
+                // bondMatchAmount using dynamic pricing. During a series of partial
+                // matching, the pricing requirements can go easier as needed for each
+                // new match, hence increasing the match likelihood.
+                // NOTE: Round the required fund amount down to prevent overspending
+                //       and possible reverting at a later step.
+                uint256 minFundAmountMaker = (_makerOrder.fundAmount -
+                    orderAmountsUsed[makerOrderHash].fundAmount).mulDivDown(
+                        bondMatchAmount,
+                        (_makerOrder.bondAmount -
+                            orderAmountsUsed[makerOrderHash].bondAmount)
+                    );
+
+                // The taker simply agrees with the maker's fund amount, and no
+                // additional donation nor validations need to be considered
+                uint256 fundTokenAmountTaker = minFundAmountMaker;
+
+                // Update order bond amount used.
+                // @dev After the update, there is no need to check if the bond
+                //      amount used is greater than the order amount, as the order
+                //      amount is already used to calculate the bondMatchAmount.
+                _updateOrderAmount(makerOrderHash, bondMatchAmount, true);
+
+                _handleTransfer(
+                    _takerOrder,
+                    _makerOrder,
+                    fundTokenAmountTaker,
+                    minFundAmountMaker,
+                    bondMatchAmount,
+                    fundToken,
+                    hyperdrive
+                );
+
+                // Update order fund amount used.
+                _updateOrderAmount(makerOrderHash, minFundAmountMaker, false);
+            } else if (_takerOrder.orderType == OrderType.CloseLong) {
+                // CloseShort + CloseLong: _handleBurn() but reverse the order.
+                // Verify both orders have the same maturity time.
+                if (
+                    _makerOrder.maxMaturityTime != _takerOrder.maxMaturityTime
+                ) {
+                    revert InvalidMaturityTime();
+                }
+
+                // Get the min fund output according to the bondMatchAmount.
+                // NOTE: Round the required fund amount up to respect the order
+                //       specified min fund output.
+                uint256 minFundAmountMaker = (_makerOrder.fundAmount -
+                    orderAmountsUsed[makerOrderHash].fundAmount).mulDivUp(
+                        bondMatchAmount,
+                        (_makerOrder.bondAmount -
+                            orderAmountsUsed[makerOrderHash].bondAmount)
+                    );
+
+                // The taker takes whatever the leftover fund amount is.
+                // @dev The taker will not receive proceeds inside the _handleBurn(),
+                //      but will receive the leftover fund at the surplus distribution.
+                uint256 minFundAmountTaker = 0;
+
+                // Update order bond amount used.
+                // @dev After the update, there is no need to check if the bond
+                //      amount used is greater than the order amount, as the order
+                //      amount is already used to calculate the bondMatchAmount.
+                _updateOrderAmount(makerOrderHash, bondMatchAmount, true);
+
+                // Handle burn operation through helper function.
+                _handleBurn(
+                    _takerOrder,
+                    _makerOrder,
+                    minFundAmountTaker,
+                    minFundAmountMaker,
+                    bondMatchAmount,
+                    fundToken,
+                    hyperdrive
+                );
+
+                // Update order fund amount used.
+                _updateOrderAmount(makerOrderHash, minFundAmountMaker, false);
+            } else {
+                revert InvalidOrderCombination();
+            }
+        } else {
             revert InvalidOrderCombination();
         }
 
-        // Transfer the remaining fund tokens back to the taker's destination.
+        // Transfer any remaining fund tokens back to the taker's destination.
         uint256 remainingBalance = fundToken.balanceOf(address(this));
         if (remainingBalance > 0) {
-            fundToken.safeTransfer(_takerOrder.options.destination, remainingBalance);
+            fundToken.safeTransfer(
+                _takerOrder.options.destination,
+                remainingBalance
+            );
         }
 
         emit OrderFilled(
@@ -583,7 +856,7 @@ contract HyperdriveMatchingEngineV2 is
                         ORDER_INTENT_TYPEHASH,
                         _order.trader,
                         _order.counterparty,
-                        _order.feeRecipient,
+                        // _order.feeRecipient,
                         address(_order.hyperdrive),
                         _order.fundAmount,
                         _order.bondAmount,
@@ -769,8 +1042,10 @@ contract HyperdriveMatchingEngineV2 is
         }
 
         // Verify valid maturity time.
-        if (_makerOrder.minMaturityTime > _makerOrder.maxMaturityTime ||
-            _takerOrder.minMaturityTime > _takerOrder.maxMaturityTime) {
+        if (
+            _makerOrder.minMaturityTime > _makerOrder.maxMaturityTime ||
+            _takerOrder.minMaturityTime > _takerOrder.maxMaturityTime
+        ) {
             revert InvalidMaturityTime();
         }
 
@@ -793,8 +1068,10 @@ contract HyperdriveMatchingEngineV2 is
         }
 
         // Check that the destination is not the zero address.
-        if (_makerOrder.options.destination == address(0) ||
-            _takerOrder.options.destination == address(0)) {
+        if (
+            _makerOrder.options.destination == address(0) ||
+            _takerOrder.options.destination == address(0)
+        ) {
             revert InvalidDestination();
         }
 
@@ -803,8 +1080,10 @@ contract HyperdriveMatchingEngineV2 is
 
         // Check if the maker order is fully executed.
         if (
-            orderAmountsUsed[makerOrderHash].bondAmount >= _makerOrder.bondAmount ||
-            orderAmountsUsed[makerOrderHash].fundAmount >= _makerOrder.fundAmount
+            orderAmountsUsed[makerOrderHash].bondAmount >=
+            _makerOrder.bondAmount ||
+            orderAmountsUsed[makerOrderHash].fundAmount >=
+            _makerOrder.fundAmount
         ) {
             revert AlreadyFullyExecuted();
         }
@@ -816,7 +1095,11 @@ contract HyperdriveMatchingEngineV2 is
 
         // Verify the maker's signature.
         if (
-            !verifySignature(makerOrderHash, _makerOrder.signature, _makerOrder.trader)
+            !verifySignature(
+                makerOrderHash,
+                _makerOrder.signature,
+                _makerOrder.trader
+            )
         ) {
             revert InvalidSignature();
         }
@@ -1072,38 +1355,37 @@ contract HyperdriveMatchingEngineV2 is
     function _calculateMintCost(
         IHyperdrive _hyperdrive,
         uint256 _bondMatchAmount
-    ) internal view returns (
-        uint256 maturityTime,
-        uint256 cost
-    ) {
+    ) internal view returns (uint256 maturityTime, uint256 cost) {
         // Get pool configuration.
         IHyperdrive.PoolConfig memory config = _hyperdrive.getPoolConfig();
-        
+
         // Calculate checkpoint and maturity time.
         uint256 latestCheckpoint = _latestCheckpoint(config.checkpointDuration);
         maturityTime = latestCheckpoint + config.positionDuration;
-        
+
         // Get vault share prices.
         // @dev TODO: there is another way to get the info without calling
         //      getPoolInfo()?
         uint256 vaultSharePrice = _hyperdrive.getPoolInfo().vaultSharePrice;
-        uint256 openVaultSharePrice = _hyperdrive.getCheckpoint(latestCheckpoint).vaultSharePrice;
+        uint256 openVaultSharePrice = _hyperdrive
+            .getCheckpoint(latestCheckpoint)
+            .vaultSharePrice;
         if (openVaultSharePrice == 0) {
             openVaultSharePrice = vaultSharePrice;
         }
-        
+
         // Calculate the required fund amount.
         // NOTE: Round the required fund amount up to overestimate the cost.
         cost = _bondMatchAmount.mulDivUp(
             vaultSharePrice.max(openVaultSharePrice),
             openVaultSharePrice
         );
-        
+
         // Add flat fee.
         // NOTE: Round the flat fee calculation up to match other flows.
         uint256 flatFee = _bondMatchAmount.mulUp(config.fees.flat);
         cost += flatFee;
-        
+
         // Add governance fee.
         // NOTE: Round the governance fee calculation down to match other flows.
         uint256 governanceFee = 2 * flatFee.mulDown(config.fees.governanceLP);