Skip to content

evm: Gassless relay race. #3572

@JoeGruffins

Description

@JoeGruffins

Gasless Relay Redeem Race Condition

Summary

When the maker redeems via the gasless relay, the on-chain redemption
is visible before the server receives the deferred relay notification.
The taker's FindRedemption detects the on-chain spend and attempts to
redeem + notify the server, but the server rejects because it thinks
the maker hasn't redeemed yet. The trade ultimately completes but with
errors and a match revocation.

Timeline (from taker's log)

08:51:41 - Taker broadcasts polygon swap
08:51:12 - Maker submits gasless relay redeem (from maker's log)
08:52:15 - Relay redeem confirmed on-chain, maker sends deferred notification to server
08:52:25 - Taker sees its polygon swap contract is spent on-chain
08:52:55 - Taker finds maker's redemption via FindRedemption, extracts secret
08:53:10 - Taker broadcasts DCR redeem
08:53:10 - ERROR: "expected other party to act" - server rejects taker's redeem notification
08:53:10 - Match revoked while redeem tx was being broadcast
08:53:10 - SettlementSequenceError starts match status resolution
08:53:19 - Server finally notifies taker of maker's redemption
08:53:19 - Taker re-broadcasts redeem from cache (fast-path)
08:53:19 - Match marked complete (but also revoked)

Root Cause

The gasless relay flow has a gap between on-chain visibility and server
awareness:

  1. Maker signs a relay redeem, relay submits it on-chain
  2. The transaction is mined and visible to the taker's RPC providers
  3. BUT the server doesn't know about the redeem until the relay confirms
    and the maker sends the deferred redeem notification
  4. In this window, the taker's FindRedemption sees the spend, extracts
    the secret, redeems its side, and tries to notify the server
  5. Server rejects with "expected other party to act" (error code 26)
    because from its perspective, it's still the maker's turn

Impact

  • Funds are safe - both sides redeem successfully
  • Match gets revoked during the race, but redeems are already broadcast
  • Error log spam and match status resolution attempts
  • The "Redemption Resubmitted" warning on the maker side suggests the
    relay notification path may also have hiccups

Possible Fixes

  1. Server: accept taker redeem when maker hasn't reported yet - If
    the taker provides a valid secret in its redeem, the server could
    accept it and infer the maker redeemed, rather than rejecting with
    "expected other party to act"

  2. Client: delay FindRedemption reporting - If the taker finds the
    redemption on-chain but the server hasn't notified them of the
    maker's redeem, wait briefly for the server notification before
    sending the redeem request

  3. Relay: notify server directly - Instead of the maker client
    sending a deferred notification after relay confirmation, have the
    relay notify the server directly (would require relay-server
    integration)

  4. Server: don't revoke during relay window - Add tolerance for
    the deferred notification delay in the match state machine

Observed On

  • Mainnet, DCR-POLYGON market
  • Match 0bcaf4a6fea9a44385047c0bb244486cae5e121759c9529155176d6f82925ebf
  • v1.1.0-rc1 client and server, relay running on Polygon chain 137

Files

  • client/core/core.go - match tick processing, FindRedemption handling
  • client/asset/eth/eth.go - gaslessRedeem, relay status checking
  • server/swap/swap.go - match state machine, redeem validation
  • evmrelay/cmd/evmrelay/ - relay task lifecycle

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions