Stage: Make Payment & Failure Handling

📝 Overview After a PMM is selected, the trade progresses to the MAKE_PAYMENT stage. In this phase, the selected PMM is responsible for fulfilling the trade by transferring the committed payment to the user and submitting the associated paymentTxId. The submission can be performed by either the Solver or the selected PMM, ensuring transparent on-chain tracking and auditability. If the PMM fails to make the payment before scriptTimeout, the MPC may mark the trade as FAILURE.

Key responsibilities of the Solver during this phase:

  • The Solver acts as a coordinator during this stage, with responsibilities that include:

    • Initiating Payment Submission (Optional): While the selected PMM is primarily responsible for making the payment, the Solver may assist by submitting it if necessary.

    • Monitoring PMM Activity: Tracks the PMM’s behavior to ensure payment is submitted within the designated timeframe.

Key responsibilities of the PMM during this phase:

  • The selected PMM is the main executor during this stage, responsible for:

    • Fulfilling the Payment: Transfers the committed funds to the user using an approved settlement method.

    • Submitting paymentTxId: Publicly announces the payment by submitting a verifiable transaction ID.

    • Signature Authentication: Signs the payment bundle with a valid cryptographic signature to guarantee authenticity and integrity.

    • Acting Within tradeTimeout: Must complete the payment before the user-defined deadline. Delays beyond this threshold may result in rejection by the MPC and potential fund loss.

    • Retrying After Warning: If the payment is marked as failed (e.g., trade is set to WARNING), the PMM can resubmit a corrected payment to recover the trade and avoid penalties.

✅ Successful Payment Submission

  • The selected PMM (or Solver) submits a valid paymentTxId within the permitted window (scriptTimeout).

  • The trade advances to the next stage (e.g. CONFIRM_PAYMENT).

  • A MadePayment event is emitted for traceability.

  • Multiple submissions are allowed within the valid timeframe.

  • Any previous failure state (e.g., WARNING) is cleared.

⚠️ Important: The PMM is responsible for submitting a valid payment before the user-defined deadline (tradeTimeout). While this deadline is not strictly enforced—due to factors like network congestion—a slight delay may be tolerated if it falls within a "safety buffer" agreed upon by the Solver and MPC. However, if the MPC deems the payment too delayed, it may reject confirmation, resulting in permanent loss for the PMM—even if payment was technically fulfilled.

❌ Failure: No Payment Submitted & Timeout

  • If the PMM fails to submit a valid paymentTxId before scriptTimeout, the trade is considered stalled.

  • The MPC node may invoke the report() function to formally mark the trade as failed.

✅ On Successful Make Payment: makePayment()

function makePayment(BundlePayment memory bundle)

🔐 Permissioned Execution

  • Can only be called through the Router contract.

  • The requester must be either the authorized Solver or the selected PMM of the trade.

  • Prevents unauthorized entities from injecting invalid payment data.

🔎 Trade Stage Validation

  • Ensures the trade is currently in the MAKE_PAYMENT or CONFIRM_PAYMENT stage.

  • Prevents duplicate or late submissions after progression or failure.

  • Clears previous failure records if it's a valid retry.

⏱️ Timeout & Expiry Checks

  • Validates the trade has not passed its scriptTimeout.

  • Ensures the signedAt timestamp is newer than any previous payment submission.

🔑 Signature Verification

  • Confirms the authenticity of the PMM's signature over the bundle.

  • Verifies the signer is authorized for the selected PMM.

🔁 Trade State Transition

  • Advances the trade to the CONFIRM_PAYMENT stage.

  • Records the paymentTxId and other bundle metadata for MPC verification.

  • Logs the submission time for replay protection.

📢 Event Emission

  • Emits a MadePayment event containing trade metadata, paymentTxId, and bundle information.

  • Facilitates monitoring and validation by off-chain services and the MPC.

❌ No Payment & Timeout: report()

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

📝 Note If the PMM fails to make the payment 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

  • Ensures the trade is still in a valid stage (MAKE_PAYMENT) for reporting.

  • Prevents reporting if the trade is already 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 payment submitted by the PMM 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 (MAKE_PAYMENT).

  • Marks the trade as FAILURE, blocking any further updates.

🧾 Refund Behavior

  • Once scriptTimeout elapses and the trade is marked as FAILURE, the user becomes eligible for a refund.

📢 Event Emission

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

Queryable Trade Data

📝 Note After the make payment phase—regardless of whether the trade proceeds to CONFIRM_PAYMENT or transitions to FAILURE—several public view functions become available to query related data and monitor trade progress. These are essential for frontend rendering, auditability, and off-chain monitoring.

✅ On Successful Make Payment

🔍 Get Trade Stage

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

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

🔍 Get Trade Finalization

function getTradeFinalization(bytes32 tradeId) external view returns (TradeFinalization memory);

Returns finalization details for the trade, including the paymentTxId and other relevant information used for MPC validation and future audits.

❌ No Payment & 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.