Skip to content

fix(swap): forward tolerance_bps on mayachain quotes (zero-slippage fund-loss)#597

Draft
gomesalexandre wants to merge 1 commit into
mainfrom
fix_mayachain_swap_slippage_protection
Draft

fix(swap): forward tolerance_bps on mayachain quotes (zero-slippage fund-loss)#597
gomesalexandre wants to merge 1 commit into
mainfrom
fix_mayachain_swap_slippage_protection

Conversation

@gomesalexandre

Copy link
Copy Markdown
Contributor

what — MayaChain swaps ship with zero slippage protection (MEV / fund-loss)

MayachainProvider.GetQuote (sdk/swap/mayachain.go) builds the Mayanode /quote/swap request from from_asset, to_asset, amount, destination, streaming_interval, streaming_quantity — but never sets tolerance_bps, unlike its sibling THORChainProvider.GetQuote (same file) which does.

An omitted tolerance_bps makes Mayanode return a market-order memo (=:c:maya1..., no LIM field), so the swap executes with zero slippage protection — full MEV/sandwich exposure on the entire amount — regardless of the slippage_tolerance_percent the caller threaded down into QuoteRequest.ToleranceBps. The value is correctly plumbed by the consumers (the Go MCP's build_swap_tx/execute_swap, agent-backend-ts) and silently dropped only inside this provider.

live verification (production Mayanode)

# no tolerance_bps → market order, no limit
GET /mayachain/quote/swap?from_asset=BTC.BTC&to_asset=MAYA.CACAO&amount=100000000&destination=maya1qqq…
  → "memo": "=:c:maya1qqq…"                              # NO limit

# with tolerance_bps → LIM present, and the API enforces it
GET …&tolerance_bps=9000  → "memo": "=:c:maya1qqq…:559503548616120"
GET …&tolerance_bps=100   → {"error":"… emit asset … less than price limit …"}

how

Mirror THORChainProvider.GetQuote exactly — same 2500 bps default, same 0-10000 bound, same params.Set("tolerance_bps", …). This is a straight parity fix; mayachain.go otherwise mirrors thorchain.go function-for-function. Added mayachain_tolerance_test.go (httptest captures the outgoing query) asserting tolerance_bps is forwarded (explicit value + the 2500 default when omitted).

risk

Low, strictly corrective — the only prior behavior was "no slippage floor." Isolated to the MayaChain provider.

note

The separate question of whether the shared 2500 bps (25%) default is itself too loose vs. 1inch/Jupiter's 1% (it applies to both THORChain and MayaChain today) is a broader design decision, not addressed here — this PR just brings Maya to parity so a floor exists at all.

receipts

Live-verified against the production Mayanode API (curls above). Regression test passes under the go.mod toolchain (GOTOOLCHAIN=go1.24.2 go test ./sdk/swap/ -run TestMayachainGetQuoteForwardsToleranceBps — the package's test binary doesn't link on Go ≥1.24 due to a pinned bytedance/sonic/go:linkname incompatibility, unrelated to this change; go build ./sdk/swap/ + go vet are clean on the default toolchain). Found by a fund-safety audit of the Go MCP swap builders that consume this provider.

…und-loss)

MayachainProvider.GetQuote built the Mayanode /quote/swap request from
from_asset, to_asset, amount, destination, streaming_interval,
streaming_quantity — but never set tolerance_bps, unlike its sibling
THORChainProvider.GetQuote which does. An omitted tolerance_bps makes
Mayanode return a market-order memo (=:c:maya1..., no LIM field), so the
swap executes with ZERO slippage protection — full MEV/sandwich exposure
on the entire amount — regardless of the slippage_tolerance_percent the
caller (agent-backend-ts / the Go MCP build_swap_tx / execute_swap)
threaded down into QuoteRequest.ToleranceBps. The value was silently
dropped only inside this provider.

Live-confirmed against production Mayanode: without tolerance_bps the memo
is '=:c:maya1...' (no limit); with tolerance_bps it carries
'=:c:maya1...:<LIM>' and the API rejects quotes that would violate it.

Mirror THORChainProvider exactly (same 2500bps default + 0-10000 bound) —
a straight parity fix, not a design change. Added a regression test
capturing the outgoing query to assert tolerance_bps is forwarded
(explicit + 2500 default).

Co-Authored-By: Claude <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 859b0268-a88c-4fce-b5fe-d5ca95022fcb

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix_mayachain_swap_slippage_protection

Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant