Skip to content

fix(swap-service): correct Mayachain affiliate fee asset (CACAO) and value by native precision#47

Merged
kaladinlight merged 6 commits into
developfrom
fix/mayachain-affiliate-fee-asset
Jul 1, 2026
Merged

fix(swap-service): correct Mayachain affiliate fee asset (CACAO) and value by native precision#47
kaladinlight merged 6 commits into
developfrom
fix/mayachain-affiliate-fee-asset

Conversation

@kaladinlight

@kaladinlight kaladinlight commented Jun 30, 2026

Copy link
Copy Markdown
Member

Description

MayaChain collects the affiliate fee in its native asset CACAO (like THORChain collects RUNE), but the fee-asset strategy mapped Mayachain to 'sell_asset'. So swaps stored affiliateFeeAssetId = the sell asset while actualAffiliateFeeAmountCryptoBaseUnit held a CACAO amount. resolveActualFeeUsd then priced that CACAO amount with the sell asset's price/precision, producing wildly wrong USD fees — observed $39,020 on a $100 swap (and a $57,712 row), which fed straight into the affiliate /stats totals and would have driven an erroneous payout.

Changes:

  • Fee asset: map Mayachain → mayachainAssetId (CACAO), mirroring Thorchain → thorchainAssetId (RUNE).
  • Read path: resolveActualFeeUsd now has explicit cases for the native fee assets — RUNE (precision 8) and CACAO (precision 10) — pricing the on-chain amount via affiliateAssetUsd (previously a fetched-but-unused column). Implemented as a switch on affiliateFeeAssetId.
  • Verifier: the shared Midgard verifier reports amounts in 1e8, so it now scales the stored affiliate fee to the fee asset's native precision (RUNE 8 = no-op, CACAO 10 = ×100), keeping storage consistent with the read path.
  • Historical data: the existing mislabeled rows on the develop DB were corrected by a one-off backfill (relabel → CACAO, native-precision amount, and historical CACAO/USD derived from the Maya ETH.USDC pool at each swap's block height). The script was applied and then removed.

Note: THORChain now values its actual RUNE fee instead of falling back to bps-implied — more accurate, but existing THORChain /stats numbers will shift slightly.

Linear: https://linear.app/shapeshift-dao/issue/SS-5709/mayachain-fee-inconsistent (SS-5709)

Closes #46

Testing

  • Full swap-service Jest suite green (58 tests); updated the maya verifier fee assertion to native precision (423777900000).
  • Validated end-to-end against the develop DB through the real calculateFeeForSwap: the $39,020 and $57,712 garbage rows collapse to ~$0.40 / ~$0.60, and every backfilled actual fee lands within <0.25% of its bps-implied value (well inside the payout deviation guard).
  • Backfill applied to the develop DB; re-run reports 0 mislabeled MayaChain swaps remaining (11 relabeled, 6 priced).

Summary by CodeRabbit

  • Bug Fixes
    • Improved affiliate fee calculations for swaps on Thorchain and Mayachain to use the correct native fee asset precision.
    • Updated Mayachain affiliate fee resolution to use the chain’s native fee asset rather than deriving it from sell-asset logic.
    • Refined swap verification so affiliate fee amounts are only reported when fee output data is present, preventing incorrect/missing fee values.
  • Tests
    • Updated the Mayachain verification test expectations to reflect the corrected CACAO fee scaling.

kaladinlight and others added 4 commits June 30, 2026 15:47
…sset

MayaChain, like Thorchain, collects the affiliate fee in its native asset
(CACAO), reported by the shared Midgard verifier as feeOut.coins[0].amount.
The fee-asset strategy mapped Mayachain to 'sell_asset', so the stored
affiliateFeeAssetId was the sell asset while the amount was CACAO base units.
resolveActualFeeUsd then priced the CACAO amount with the sell asset's price
and precision, producing wildly wrong USD fees (observed $39,020 on a $100
swap, which flowed into /stats and would have driven a ~$29k erroneous payout).

Map Mayachain to mayachainAssetId, mirroring Thorchain's thorchainAssetId. New
Maya swaps now fall back to the bps-implied fee (CACAO is neither sell nor buy,
so precision is unknown) exactly like Thorchain — bounded and correct.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Drafted one-off backfill to correct pre-fix MayaChain swaps whose
affiliateFeeAssetId was set to the sell asset instead of CACAO. For each swap
it reads the Midgard action (block height + CACAO affiliate fee out), fetches
the ETH.USDC pool at that height for historical CACAO/USD, and writes:
  affiliateFeeAssetId                    = CACAO
  actualAffiliateFeeAmountCryptoBaseUnit = Midgard 1e8 amount → CACAO native 1e10
  affiliateAssetUsd                      = historical CACAO/USD

Dry-run by default; --apply to write. Not yet applied. The backfilled
affiliateAssetUsd/amount are correct but remain unused until resolveActualFeeUsd
resolves the native fee-asset precision (deferred); until then Maya fees fall
back to the bps-implied value, which is bounded and correct.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
resolveActualFeeUsd previously returned null when the affiliate fee asset was
neither the sell nor buy asset, so the actual on-chain fee for Thorchain (RUNE)
and Maya (CACAO) was never valued — affiliateAssetUsd was a fetched-but-dead
column. Add explicit cases for thorchainAssetId (precision 8) and mayachainAssetId
(precision 10), pricing the stored amount with affiliateAssetUsd.

The stored amount must be in native base units for those precisions. Midgard
reports in 1e8, so the shared verifier now scales the affiliate fee to the fee
asset's native precision (RUNE 8 = no-op, CACAO 10 = x100). Historical Maya rows
are corrected by scripts/backfill-maya-fee-asset.ts.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The Maya fee-asset backfill has been applied; the one-off script (and its yarn
entry / tsconfig include) is no longer needed. Also reformats verifyThorchain
config formatting in the Midgard verifier.

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

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d8d8d99c-e04f-4df0-8e85-bf7dd9b03316

📥 Commits

Reviewing files that changed from the base of the PR and between 972069e and d745a80.

📒 Files selected for processing (1)
  • apps/swap-service/src/verification/swap-verification.service.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/swap-service/src/verification/swap-verification.service.ts

📝 Walkthrough

Walkthrough

This PR updates Mayachain affiliate fee asset resolution, fee USD calculation for native THORChain/Mayachain assets, and Midgard fee amount conversion so affiliate fee values use chain-specific precision.

Changes

Affiliate fee precision fix

Layer / File(s) Summary
Mayachain affiliate fee asset strategy
apps/swap-service/src/utils/affiliateFeeAsset.ts
SWAPPER_FEE_STRATEGY for Mayachain now resolves to mayachainAssetId directly instead of using the 'sell_asset' strategy.
Fee USD resolution for native chain assets
apps/swap-service/src/swaps/utils.ts
Adds thorchainAssetId/mayachainAssetId imports and RUNE_PRECISION/CACAO_PRECISION constants; replaces the sell/buy if/else in resolveActualFeeUsd with a switch that handles native THORChain/Mayachain affiliate fee assets, defaulting to null precision otherwise.
Midgard fee amount precision conversion
apps/swap-service/src/verification/swap-verification.service.ts, apps/swap-service/src/verification/__tests__/maya.test.ts
Passes feeAssetPrecision (8 for Thorchain, 10 for Maya) into verifyMidgardSwap; actualAffiliateFeeAmountCryptoBaseUnit is now computed via thorchainToNativePrecision guarded by affiliate/fee-output presence; updates the corresponding Maya test expectation.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant SwapVerificationService
  participant verifyMidgardSwap
  participant thorchainToNativePrecision
  participant resolveActualFeeUsd

  SwapVerificationService->>verifyMidgardSwap: verify swap (feeAssetPrecision=8/10)
  verifyMidgardSwap->>thorchainToNativePrecision: convert feeOut coin amount
  thorchainToNativePrecision-->>verifyMidgardSwap: actualAffiliateFeeAmountCryptoBaseUnit
  verifyMidgardSwap-->>SwapVerificationService: verification result with fee amount

  SwapVerificationService->>resolveActualFeeUsd: resolve affiliate fee USD
  resolveActualFeeUsd->>resolveActualFeeUsd: switch on affiliateFeeAssetId
  resolveActualFeeUsd-->>SwapVerificationService: fee USD (with correct precision)
Loading

Possibly related PRs

Poem

A rabbit hopped on moonlit beams,
With RUNE and CACAO in tidy streams.
No fee got lost, no math went astray,
Precision kept the wolves at bay.
Hop, hop — the swap math shines today 🐇

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately summarizes the main Mayachain CACAO/native-precision fix.
Linked Issues check ✅ Passed The changes address the inconsistent MayaChain fee values by using CACAO/native precision end-to-end in read and verification paths.
Out of Scope Changes check ✅ Passed No clearly unrelated code changes stand out; the Thorchain precision updates are tied to the shared affiliate-fee handling path.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/mayachain-affiliate-fee-asset

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install failed. For unrecoverable errors, disable the tool in CodeRabbit configuration.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/swap-service/src/verification/swap-verification.service.ts`:
- Around line 393-396: `verifySwap()` in `swap-verification.service.ts` should
preserve the missing-coin guard when computing
`actualAffiliateFeeAmountCryptoBaseUnit`; the current `feeOut.coins[0].amount`
access can throw if `feeOut` has no first coin. Update the affiliate-fee mapping
so it only calls `thorchainToNativePrecision` when `hasAffiliate`, `feeOut`, and
`feeOut.coins[0]` are all present, otherwise leave the field `undefined`. Use
the existing `verifySwap` affiliate-fee block and
`feeOut`/`thorchainToNativePrecision` symbols to locate the change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1174e7b6-9fb6-4197-a1b9-5cfd74a46e5d

📥 Commits

Reviewing files that changed from the base of the PR and between 0422a84 and 972069e.

📒 Files selected for processing (4)
  • apps/swap-service/src/swaps/utils.ts
  • apps/swap-service/src/utils/affiliateFeeAsset.ts
  • apps/swap-service/src/verification/__tests__/maya.test.ts
  • apps/swap-service/src/verification/swap-verification.service.ts

Comment thread apps/swap-service/src/verification/swap-verification.service.ts
kaladinlight and others added 2 commits July 1, 2026 10:43
Coins array is non-empty per Midgard types, but guard against an empty
array defensively so a malformed affiliate out leaves the fee amount
undefined instead of throwing and dropping the swap to PENDING.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@kaladinlight kaladinlight merged commit 8b24430 into develop Jul 1, 2026
2 checks passed
@kaladinlight kaladinlight deleted the fix/mayachain-affiliate-fee-asset branch July 1, 2026 20:33
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.

Mayachain Fee inconsistent

1 participant