Repository navigation
fix(sdk-coin-atom): normalize memo-suffixed recipients in verifyTrans… - #10113
yashvanthbl137-crypto wants to merge 1 commit into
Conversation
|
|
9620337 to
cd31fd8
Compare
There was a problem hiding this comment.
Claude Code Review
This repository is configured for manual code reviews. Comment @claude review for a one-time review, or @claude review always to subscribe this PR to a review on every future push.
Tip: disable this comment in your organization's Code Review settings.
|
@claude review |
|
Claude finished @yashvanthbl137-crypto's task in 25s —— View job Review of #10113: normalize memo-suffixed recipients in
|
CosmosCoin.verifyTransaction compared txParams.recipients addresses as raw strings against explained outputs, which report the plain on-chain address plus a tx-level memo. Cosmos destinations represent their memo in more than one way across clients: the enterprise UI and wallet APIs fold it into the address as address?memoId=X, while the retail UI sends a plain address plus a tx-level memo param. The base class failed for the combined form (every withdrawal to a memo-required destination failed with 'Tx outputs does not match with expected txParams recipients', COINS-2285) while silently ignoring memo mismatches in every other form. Normalize both sides in sdk-coin-atom before comparing. A recipient's memo may be declared via the address ?memoId suffix, a recipient.memo field, or the tx-level txParams.memo.value; all declared sources must agree, and empty strings count as absent. A declared memo must match the transaction memo exactly; when no memo is declared anywhere, the transaction must not carry one either — a memo the user never approved is a prebuild-integrity failure. To keep the strict check intact on re-signs, resolveEffectiveTxParams now propagates the persisted intent.memo into effective txParams when the caller supplies none: signing paths that carry no txParams (pendingApproval.approve() -> recreateTxRequest() -> signTxRequest()) otherwise reached the coin verifier with a memo-less txParams while the prebuilt transaction carried the memo approved at send time. Ports the per-coin fix precedent from sdk-coin-tia (COINS-1760) and sdk-coin-zeta (CSHLD-1780) and declares the lodash dependency they use. Ticket: COINS-2285
cd31fd8 to
b817bf9
Compare
|
@claude re-review |
|
Claude finished @yashvanthbl137-crypto's task in 34s —— View job Re-review of #10113The blocking issue from my earlier inline review is fixed. I read the new code and the added tests, but I didn't run the test suites.
Earlier finding: resolved. Side effects of the
Remaining minor points (none blocking)
Verdict: No blocking issues remain. Once point 1 is confirmed, this looks good to merge. |
Summary
Cosmos-family withdrawals to memo-required destinations fail verification with
Tx outputs does not match with expected txParams recipients.CosmosCoin.verifyTransactioncomparestxParams.recipients[].addressas raw strings against explained outputs. Cosmos destinations represent their memo in more than one way across clients: the enterprise UI and wallet APIs fold it into the address ascosmos1...?memoId=X, while the retail UI sends a plain address plus a tx-level memo param.explainTransaction()reports the plain on-chain address plus a tx-levelmemofield — so the comparison always fails for combined-form recipients, even when the transaction was built correctly. Withdrawals from ATOM wallets to memo-required destinations were effectively impossible.Fix
Two parts:
sdk-coin-atom— overrideverifyTransaction(Atom/Tatom) and normalize both sides to{address, amount, memo?}before comparing. A recipient's memo may be declared via the?memoId=address suffix, arecipient.memofield, or the tx-leveltxParams.memo.value; all declared sources must agree, and empty strings are treated as absent. A declared memo must match the transaction memo exactly; when no memo is declared anywhere, the transaction must not carry one either — a memo the user never approved is a prebuild-integrity failure.sdk-core(resolveEffectiveTxParams) — propagate the persistedintent.memointo effectivetxParamswhen the caller supplies none. Signing paths that carry no txParams (pendingApproval.approve() -> recreateTxRequest() -> signTxRequest()) otherwise reached the coin verifier with a memo-less txParams while the prebuilt transaction carried the memo approved at send time, which would have made the strict check reject legitimate re-signs.Ports the per-coin precedent from
sdk-coin-tia(c2725f263b, COINS-1760) andsdk-coin-zeta(51d997c5d7, CSHLD-1780); also declares thelodashdependency those modules already use.Testing
sdk-coin-atom: memo-suffixed recipient verifies; wrong/missing memo rejected; tx-level and recipient-level memo accepted; conflicting memo declarations rejected; empty tx-level memo with a memo-less tx verifies; a memo transaction re-signed from a persisted intent verifies throughresolveEffectiveTxParams; a re-sign with a mismatched intent memo is rejected; malformed memo suffix rejected withInvalidAddressError.sdk-core:intent.memopropagated when txParams carries none; caller-supplied memo not overwritten; absent/empty intent memo stays undefined.sdk-coin-atomsuite: 90 passing;sdk-corerecipientUtilssuite: 44 passing.tatomUI withdrawal) and verified the exact error before this fix.Ticket: COINS-2285