Stage: PMM Selection & Failure Handling

📝 Overview The SELECT_PMM stage takes place after the MPC has confirmed the deposit. At this stage, the Solver is responsible for selecting the optimal PMM (Professional Market Maker) based on user RFQ constraints. If no valid PMM is matched before the scriptTimeout, the MPC will mark the trade as FAILURE.

Key responsibilities of the Solver during this phase:

  • Selecting the optimal PMM that offers a valid quote based on the user's RFQ (minAmountOut).

  • Verifying the PMM's quote is still valid (not expired) and corresponds to a valid pre-signed settlement.

  • Submitting proof (signed data) from both the selected PMM and the user to validate mutual agreement on trade terms.

  • Ensuring protocol and affiliate fees are within acceptable bounds and the final amount out meets user expectations.

Possible Scenarios

✅ Successful PMM Selection:

If the Solver provides a valid PMM quote and all signature verifications pass, the protocol:

  • Validates and stores the selected PMM's data.

  • Calculates and locks protocol/affiliate fees.

  • Emits a SelectedPMM event.

  • Advances the trade to the MAKE_PAYMENT stage.

❌ No Match / Timeout:

If no suitable PMM is selected before the timeout (scriptTimeout), the trade is considered stalled.

  • The MPC may later mark the trade as Failure, halting further progression.

  • After the full grace period (scriptTimeout), the trade becomes eligible for a refund.

  • No settlement or payment occurs, and user funds are returned through the protocol's refund path.

✅ On PMM match: selectPMM()

function selectPMM(bytes32 tradeId, PMMSelection calldata info) external;

🔐 Permissioned Execution

  • Can only be called through the Router contract.

  • The requester must be the same authorized Solver who originally submitted the trade.

  • Prevents unauthorized or malicious PMM selection attempts.

🔎 Trade Stage Validation

  • Ensures the trade is currently at the SELECT_PMM stage.

  • Prevents out-of-sequence execution and misuse of expired trade sessions.

  • Ensures the selected PMM exists within the pre-signed settlement data (settlementPresigns).

⏱️ Timeout & Expiry Checks

  • Confirms the trade has not already timed out (tradeTimeout).

  • Validates tradeTimeout and confirms it does not exceed the original scriptTimeout.

  • Verifies the PMM's signature has not expired (sigExpiry).

💸 Fee Validation

  • Calculates protocol (pFeeAmount) and affiliate (aFeeAmount) fees based on the quoted amountOut.

  • Ensures that amountOut - totalFeeAmount meets or exceeds the user-defined minAmountOut.

  • Reverts with InsufficientQuoteAmount if the quote is below expectations.

🔑 Signature Verification

  • Validates the selected PMM’s signature by hashing relevant fields and verifying against the PMM signer.

  • Checks that the selected PMM address matches the address in the pre-signed settlement proof.

  • Validates the user’s RFQ signature to confirm agreement on minAmountOut, tradeTimeout, and affiliate details.

🔁 Trade State Transition

  • Saves the calculated totalFeeAmount, pFeeAmount, and aFeeAmount in the trade’s fee record.

  • Records the selected PMM’s information on-chain.

  • Advances the trade to the next stage (e.g. MAKE_PAYMENT).

📢 Event Emission

  • Emits the SelectedPMM event which signals the successful PMM selection and allows off-chain systems to initiate payment processes.

❌ No PMM match & Timeout: report()

function report(bytes32 tradeId, bytes calldata msgError, bytes calldata signature) external;

📝 Note If no suitable PMM is selected before the timeout (scriptTimeout), the trade enters a finalized state. This failure scenario can be reported by the MPC once the timeout has been reached.

🔐 Permissioned Execution

  • Can only be called through the Router contract.

  • The requester must be an authorized MPC Node.

🔎 Constraints & Behavior

  • The trade must not already be finalized (COMPLETED, FAILURE, or REFUNDED).

  • This is the stage where reporting does strictly require a timeout delay (scriptTimeout).

⚠️ Valid Reasons to Report Failure

  • No valid PMM is selected within the allowed timeout window.

🔑 Signature Verification

  • The failure message is signed using EIP-712 format to ensure authenticity.

  • The signer must be a valid MPC signer for the relevant source chain.

🔁 Trade State Transition

  • Stores failure details, including msgError and the failed stage (SELECT_PMM).

  • The trade is immediately marked as FAILURE, halting any further progression.

🧾 Refund Behavior

  • Once the scriptTimeout elapses, the user’s funds are eligible for automatic refund.

📢 Event Emission

  • Emits a FailureReported event, including failed stage, error reference, which enables public inspection and monitoring of failed trades.

Queryable Trade Data

📝 Note After the pmm selection phase—whether the trade advances to MAKE_PAYMENT or transitions to FAILURE—several public view functions become available to query related data and track trade progress. These are essential for frontend rendering, auditability, and off-chain monitoring.

✅ On Successful PMM Selection

🔍 Get Trade Stage

function getCurrentStage(bytes32 tradeId) external view returns (uint256);

Returns the current stage of the trade (e.g., MAKE_PAYMENT).

🔍 Get PMM Selection

function getPMMSelection(bytes32 tradeId) external view returns (PMMSelection memory);

Returns a struct containing the user's RFQ and the selected PMM's quote.

❌ On No Matching PMM & Timeout

🔍 Get Trade Stage

function getCurrentStage(bytes32 tradeId) external view returns (uint256);

Returns the current stage of the trade (e.g., FAILURE).

🔍 Get Failure Details

function getFailureInfo(bytes32 tradeId) external view returns (FailureDetails memory)

Returns the error metadata associated with the failed trade, including the stage and reason for failure.