Add transparent refund address for shielded Zcash Maya swaps - #459
Conversation
d550dc3 to
67bbce0
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 67bbce0. Configure here.
67bbce0 to
dfd5a7a
Compare
| // memo in the shielded note (not the transparent memo), which is not bound | ||
| // by that limit, so inject the refund into the memo here, after the quote | ||
| // was fetched without it. | ||
| if (refundAddress != null) { |
There was a problem hiding this comment.
This blob is pretty ugly. The memo is created by the quote/swap endpoint and it accepts a refund address argument so let's pass it to taht and use the memo they return.
There was a problem hiding this comment.
Passing the refund address to the quote/swap endpoint is what the original PR did, and it breaks every ZEC swap. Given refund_address, Maya builds the same DESTADDR/REFUNDADDR memo and then rejects the quote because the result overflows the source chain's memo limit. Reproduced live today against mayanode:
- BTC->ETH with refund:
generated memo too long for source chain: =:e:0x742d...f44e/bc1q...5mdq::ej:75 (96/80) - ZEC->DASH with refund is 86/80 (captured live in the prior run's window when ZEC trading was open).
The reason it still works on-chain is that the shielded ZEC send carries the memo in the encrypted note (512 bytes), which is not bound by the 80-char transparent-memo limit that Maya's quote endpoint pre-validates against. So the endpoint cannot return a usable memo for a shielded ZEC source; the refund has to be appended client-side after the quote is fetched without it.
I've addressed the readability concern: the inline blob is now a single call to a named, documented helper appendMayaRefundAddress (src/swap/defi/thorchain/thorchainCommon.ts), with the endpoint/80-char rationale on its docstring, plus unit tests in test/thorchain.test.ts pinning the exact memo output. Leaving this thread open for your call on the approach.
Maya cannot refund a shielded Zcash source and rejects the refund with "can't refund ZEC from shielded source without a refund address". Add the wallet's transparent (t-address) refund address to the Maya swap memo as DESTADDR/REFUNDADDR so Maya can process refunds. The refund is injected into the memo client-side rather than passed to the quote endpoint. Appending it to the quote request overflows Zcash's 80-char transparent-memo limit and the quote endpoint rejects the swap. The ZEC swap carries its memo in the shielded note, which is not bound by that limit, so the refund is added after the quote is fetched. Non-Zcash sources are unchanged and continue to default to the sending address.
dfd5a7a to
4a473d9
Compare
4a473d9 to
b55835f
Compare






CHANGELOG
Does this branch warrant an entry to the CHANGELOG?
Dependencies
none
Description
Asana: https://app.asana.com/0/1215088146871429/1214541361005860
Problem. When Edge sends a shielded-Zcash swap to Maya, the swap memo carries no refund address. Maya cannot refund a shielded source and rejects the refund:
For every chain except Zcash, Maya defaults the refund to the sending address, which is correct. A shielded ZEC source has no transparent sending address to refund to, so the integrator must supply a transparent (t-address) refund address in the swap memo.
Fix. In the shared Thorchain/Maya common code, when the source wallet is Zcash, fetch the wallet's transparent address (
getAddress(fromWallet, 'transparentAddress'), the same helper already used for the ZEC receive side) and append it to the swap memo's destination field asDESTADDR/REFUNDADDRper the Maya memo spec, via the new documented helperappendMayaRefundAddress.The refund address is deliberately NOT passed to the
quote/swapendpoint. Given arefund_address, Maya builds that sameDESTADDR/REFUNDADDRmemo and then rejects the quote because the result overflows the source chain's memo limit (e.g. ZEC to DASH is 86/80). The shielded ZEC send instead carries the memo in the encrypted note (512 bytes), which is not bound by the 80-char transparent-memo limit that the quote endpoint pre-validates against, so the refund is injected client-side after the quote is fetched without it. Non-Zcash sources are untouched and keep defaulting to the sending address (their quote requests and memos are unchanged).The change lives entirely in the dependency; no gui-side wiring is required.
Verification.
tsc --noEmit, eslint, and the mocha suite all pass (viaverify-repo.sh, which also runs the webpack build).test/thorchain.test.tspinappendMayaRefundAddress's output to the exact memo shape (=:d:DEST/REFUND:0/1/1:ej:75) and cover the no-destination-field edge case.mayanode.mayachain.info) confirms why the endpoint cannot build the memo: BTC to ETH withrefund_addressreturnsgenerated memo too long for source chain: ...(96/80); the same request without it returns a valid 53-char memo.HALTZECTRADING=1,trading is halted, can't process swap) at the protocol level, and a swap during the halt fails at the quote before the refund injection runs, so it would not exercise this code anyway. Re-run the in-app smoke once Maya resumes ZEC trading.Note
Medium Risk
Changes Maya swap memo construction for Zcash-only sources and affects refund routing on failure; scope is narrow and covered by tests, but incorrect memo shape would break refunds or swaps.
Overview
Shielded Zcash swaps through Maya now embed a transparent (t-address) refund in the swap memo so Maya can refund when trading halts or the swap fails—shielded sources have no transparent send address Maya can default to.
After quoting without
refund_address(passing it makes Mayanode reject quotes that exceed Zcash’s 80-character transparent-memo limit), the client fetches the wallet’s transparent address and appends it to memo field 2 asDESTADDR/REFUNDADDRviaappendMayaRefundAddress, then carries that memo in the shielded ZIP-321 note (512-byte limit). Non-Zcash sources and Thorchain behavior are unchanged.Debug ZIP-321 logging is removed; unit tests cover the memo transformation.
Reviewed by Cursor Bugbot for commit b55835f. Bugbot is set up for automated code reviews on this repo. Configure here.