@vultisig/core-chain 2.26.0 → 2.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. package/CHANGELOG.md +129 -0
  2. package/dist/chains/cosmos/account/getCosmosAccountInfo.d.ts +1 -0
  3. package/dist/chains/cosmos/account/getCosmosAccountInfo.d.ts.map +1 -1
  4. package/dist/chains/cosmos/account/getCosmosAccountInfo.js +112 -30
  5. package/dist/chains/cosmos/account/getCosmosAccountInfo.js.map +1 -1
  6. package/dist/chains/cosmos/parseUint64.d.ts +6 -0
  7. package/dist/chains/cosmos/parseUint64.d.ts.map +1 -0
  8. package/dist/chains/cosmos/parseUint64.js +12 -0
  9. package/dist/chains/cosmos/parseUint64.js.map +1 -0
  10. package/dist/chains/cosmos/qbtc/claim/broadcastClaimTx.d.ts.map +1 -1
  11. package/dist/chains/cosmos/qbtc/claim/broadcastClaimTx.js +3 -28
  12. package/dist/chains/cosmos/qbtc/claim/broadcastClaimTx.js.map +1 -1
  13. package/dist/chains/cosmos/qbtc/getQbtcAccountInfo.d.ts.map +1 -1
  14. package/dist/chains/cosmos/qbtc/getQbtcAccountInfo.js +11 -13
  15. package/dist/chains/cosmos/qbtc/getQbtcAccountInfo.js.map +1 -1
  16. package/dist/chains/cosmos/qbtc/waitForQbtcTxInclusion.d.ts +32 -0
  17. package/dist/chains/cosmos/qbtc/waitForQbtcTxInclusion.d.ts.map +1 -0
  18. package/dist/chains/cosmos/qbtc/waitForQbtcTxInclusion.js +33 -0
  19. package/dist/chains/cosmos/qbtc/waitForQbtcTxInclusion.js.map +1 -0
  20. package/dist/coin/balance/getEvmChainBalances.d.ts +6 -0
  21. package/dist/coin/balance/getEvmChainBalances.d.ts.map +1 -1
  22. package/dist/coin/balance/getEvmChainBalances.js +11 -5
  23. package/dist/coin/balance/getEvmChainBalances.js.map +1 -1
  24. package/dist/coin/price/resolveTokenPriceId.d.ts +8 -10
  25. package/dist/coin/price/resolveTokenPriceId.d.ts.map +1 -1
  26. package/dist/coin/price/resolveTokenPriceId.js +21 -14
  27. package/dist/coin/price/resolveTokenPriceId.js.map +1 -1
  28. package/dist/swap/general/GeneralSwapQuote.d.ts +19 -3
  29. package/dist/swap/general/GeneralSwapQuote.d.ts.map +1 -1
  30. package/dist/swap/general/cowswap/sign/buildCowSwapOrderTypedData.d.ts +0 -9
  31. package/dist/swap/general/cowswap/sign/buildCowSwapOrderTypedData.d.ts.map +1 -1
  32. package/dist/swap/general/cowswap/sign/buildCowSwapOrderTypedData.js +52 -22
  33. package/dist/swap/general/cowswap/sign/buildCowSwapOrderTypedData.js.map +1 -1
  34. package/dist/swap/general/knownAggregatorRouters.d.ts +59 -2
  35. package/dist/swap/general/knownAggregatorRouters.d.ts.map +1 -1
  36. package/dist/swap/general/knownAggregatorRouters.js +118 -12
  37. package/dist/swap/general/knownAggregatorRouters.js.map +1 -1
  38. package/dist/swap/general/kyber/chains.d.ts +1 -1
  39. package/dist/swap/general/kyber/chains.d.ts.map +1 -1
  40. package/dist/swap/general/kyber/chains.js +5 -2
  41. package/dist/swap/general/kyber/chains.js.map +1 -1
  42. package/dist/swap/general/lifi/api/getLifiSwapQuote.d.ts +2 -9
  43. package/dist/swap/general/lifi/api/getLifiSwapQuote.d.ts.map +1 -1
  44. package/dist/swap/general/lifi/api/getLifiSwapQuote.js +29 -81
  45. package/dist/swap/general/lifi/api/getLifiSwapQuote.js.map +1 -1
  46. package/dist/swap/general/lifi/api/lifiSlippage.d.ts +25 -0
  47. package/dist/swap/general/lifi/api/lifiSlippage.d.ts.map +1 -0
  48. package/dist/swap/general/lifi/api/lifiSlippage.js +51 -0
  49. package/dist/swap/general/lifi/api/lifiSlippage.js.map +1 -0
  50. package/dist/swap/general/oneInch/api/getOneInchSwapQuote.d.ts.map +1 -1
  51. package/dist/swap/general/oneInch/api/getOneInchSwapQuote.js +8 -0
  52. package/dist/swap/general/oneInch/api/getOneInchSwapQuote.js.map +1 -1
  53. package/dist/swap/general/swapkit/api/getSwapKitQuote.d.ts.map +1 -1
  54. package/dist/swap/general/swapkit/api/getSwapKitQuote.js +23 -2
  55. package/dist/swap/general/swapkit/api/getSwapKitQuote.js.map +1 -1
  56. package/dist/swap/general/swapkit/getSwapKitTrackerUrl.d.ts +43 -0
  57. package/dist/swap/general/swapkit/getSwapKitTrackerUrl.d.ts.map +1 -0
  58. package/dist/swap/general/swapkit/getSwapKitTrackerUrl.js +47 -0
  59. package/dist/swap/general/swapkit/getSwapKitTrackerUrl.js.map +1 -0
  60. package/dist/swap/native/NativeSwapChain.d.ts +4 -0
  61. package/dist/swap/native/NativeSwapChain.d.ts.map +1 -1
  62. package/dist/swap/native/NativeSwapChain.js +4 -0
  63. package/dist/swap/native/NativeSwapChain.js.map +1 -1
  64. package/dist/swap/native/asset/toNativeSwapAsset.d.ts.map +1 -1
  65. package/dist/swap/native/asset/toNativeSwapAsset.js +2 -5
  66. package/dist/swap/native/asset/toNativeSwapAsset.js.map +1 -1
  67. package/dist/swap/native/halts/getNativeSwapTradingHalt.d.ts.map +1 -1
  68. package/dist/swap/native/halts/getNativeSwapTradingHalt.js +2 -2
  69. package/dist/swap/native/halts/getNativeSwapTradingHalt.js.map +1 -1
  70. package/dist/swap/native/limitSwapAvailability.d.ts +21 -0
  71. package/dist/swap/native/limitSwapAvailability.d.ts.map +1 -0
  72. package/dist/swap/native/limitSwapAvailability.js +32 -0
  73. package/dist/swap/native/limitSwapAvailability.js.map +1 -0
  74. package/dist/swap/native/limitSwapInbound.d.ts +53 -0
  75. package/dist/swap/native/limitSwapInbound.d.ts.map +1 -0
  76. package/dist/swap/native/limitSwapInbound.js +73 -0
  77. package/dist/swap/native/limitSwapInbound.js.map +1 -0
  78. package/dist/swap/native/limitSwapMemo.d.ts +19 -0
  79. package/dist/swap/native/limitSwapMemo.d.ts.map +1 -1
  80. package/dist/swap/native/limitSwapMemo.js +56 -25
  81. package/dist/swap/native/limitSwapMemo.js.map +1 -1
  82. package/dist/swap/native/minimum/getNativeSwapMinAmountIn.d.ts.map +1 -1
  83. package/dist/swap/native/minimum/getNativeSwapMinAmountIn.js +9 -3
  84. package/dist/swap/native/minimum/getNativeSwapMinAmountIn.js.map +1 -1
  85. package/dist/swap/native/thorchainMemoAsset.d.ts +76 -0
  86. package/dist/swap/native/thorchainMemoAsset.d.ts.map +1 -0
  87. package/dist/swap/native/thorchainMemoAsset.js +126 -0
  88. package/dist/swap/native/thorchainMemoAsset.js.map +1 -0
  89. package/dist/swap/quote/findSwapQuote.d.ts.map +1 -1
  90. package/dist/swap/quote/findSwapQuote.js +6 -1
  91. package/dist/swap/quote/findSwapQuote.js.map +1 -1
  92. package/dist/swap/swapEnabledChains.d.ts.map +1 -1
  93. package/dist/swap/swapEnabledChains.js +12 -0
  94. package/dist/swap/swapEnabledChains.js.map +1 -1
  95. package/dist/swap/utils/getSwapExplorerUrl/index.d.ts +10 -7
  96. package/dist/swap/utils/getSwapExplorerUrl/index.d.ts.map +1 -1
  97. package/dist/swap/utils/getSwapExplorerUrl/index.js +13 -12
  98. package/dist/swap/utils/getSwapExplorerUrl/index.js.map +1 -1
  99. package/dist/tx/broadcast/resolvers/bittensor.d.ts.map +1 -1
  100. package/dist/tx/broadcast/resolvers/bittensor.js +21 -15
  101. package/dist/tx/broadcast/resolvers/bittensor.js.map +1 -1
  102. package/dist/tx/broadcast/resolvers/cosmos.d.ts +1 -0
  103. package/dist/tx/broadcast/resolvers/cosmos.d.ts.map +1 -1
  104. package/dist/tx/broadcast/resolvers/cosmos.js +30 -2
  105. package/dist/tx/broadcast/resolvers/cosmos.js.map +1 -1
  106. package/dist/tx/broadcast/resolvers/polkadot.d.ts.map +1 -1
  107. package/dist/tx/broadcast/resolvers/polkadot.js +3 -36
  108. package/dist/tx/broadcast/resolvers/polkadot.js.map +1 -1
  109. package/dist/tx/broadcast/resolvers/qbtc.d.ts.map +1 -1
  110. package/dist/tx/broadcast/resolvers/qbtc.js +37 -7
  111. package/dist/tx/broadcast/resolvers/qbtc.js.map +1 -1
  112. package/dist/tx/broadcast/resolvers/substrate.d.ts +8 -0
  113. package/dist/tx/broadcast/resolvers/substrate.d.ts.map +1 -0
  114. package/dist/tx/broadcast/resolvers/substrate.js +15 -0
  115. package/dist/tx/broadcast/resolvers/substrate.js.map +1 -0
  116. package/dist/tx/broadcast/resolvers/sui.d.ts +8 -0
  117. package/dist/tx/broadcast/resolvers/sui.d.ts.map +1 -1
  118. package/dist/tx/broadcast/resolvers/sui.js +33 -7
  119. package/dist/tx/broadcast/resolvers/sui.js.map +1 -1
  120. package/dist/tx/broadcast/transientRetry.d.ts +17 -0
  121. package/dist/tx/broadcast/transientRetry.d.ts.map +1 -1
  122. package/dist/tx/broadcast/transientRetry.js +23 -0
  123. package/dist/tx/broadcast/transientRetry.js.map +1 -1
  124. package/dist/tx/broadcast/verifyBroadcastByHash.d.ts +8 -4
  125. package/dist/tx/broadcast/verifyBroadcastByHash.d.ts.map +1 -1
  126. package/dist/tx/broadcast/verifyBroadcastByHash.js +33 -11
  127. package/dist/tx/broadcast/verifyBroadcastByHash.js.map +1 -1
  128. package/dist/tx/status/resolvers/cardano.d.ts.map +1 -1
  129. package/dist/tx/status/resolvers/cardano.js +19 -3
  130. package/dist/tx/status/resolvers/cardano.js.map +1 -1
  131. package/dist/tx/status/resolvers/tron.d.ts.map +1 -1
  132. package/dist/tx/status/resolvers/tron.js +35 -6
  133. package/dist/tx/status/resolvers/tron.js.map +1 -1
  134. package/package.json +42 -2
@@ -1,4 +1,6 @@
1
+ import { isOneOf } from '@vultisig/lib-utils/array/isOneOf';
1
2
  import { Chain } from '../../Chain.js';
3
+ import { COW_VAULT_RELAYER_ADDRESS, cowSwapSupportedChains } from './cowswap/config.js';
2
4
  /**
3
5
  * Fund-safety allowlist for the general-purpose EVM swap aggregators (AGG-02, round-2
4
6
  * spec-level fund-safety audit, 2026-07-08).
@@ -18,6 +20,12 @@ import { Chain } from '../../Chain.js';
18
20
  * stable, deterministically-deployed constant on almost every chain — verified against each
19
21
  * provider's OWN live quote API (not just docs/explorers), chain by chain, on 2026-07-08.
20
22
  *
23
+ * CowSwap is ALSO enforced (sdk#1457): unlike 1inch/Kyber it doesn't route to a swap router at
24
+ * all - orders settle off-chain via solvers, and the on-chain leg (both the swap-leg address AND
25
+ * the ERC-20 approval spender) is always the same fixed GPv2VaultRelayer contract across every
26
+ * supported chain (see build.ts / getSwapDestinationAddress.ts). That determinism makes it just
27
+ * as allow-listable as 1inch/Kyber's routers.
28
+ *
21
29
  * CHAIN-SCOPING MATTERS (codex review, PR #1079): 1inch's V6 router is NOT the same address
22
30
  * on zkSync Era — confirmed live (a real 200 response from a real quote request returned a
23
31
  * DIFFERENT contract there). This is exactly the caveat chains/evm/contract/knownContracts.ts
@@ -30,7 +38,10 @@ import { Chain } from '../../Chain.js';
30
38
  * bridge/DEX contracts by design (diamond routing, multi-hop, chain-specific deployments),
31
39
  * so a hard allowlist would false-block legitimate routes. Those two are logged (never
32
40
  * thrown) via logUnenforcedAggregatorDestination so an anomaly is queryable, and so a future
33
- * allowlist has real usage data to build from if a pattern emerges.
41
+ * allowlist has real usage data to build from if a pattern emerges. sdk#1457: because they are
42
+ * the only genuinely unenforceable-by-address providers, they are the one residual gap
43
+ * assertKnownAggregatorRouterOnSigningPath's provider-string closed-list still can't structurally
44
+ * close - see that function's doc comment.
34
45
  */
35
46
  // 1inch Aggregation Router V5 (legacy). Same address as
36
47
  // chains/evm/contract/knownContracts.ts's display-only registry; kept separate here since
@@ -45,15 +56,100 @@ const ONE_INCH_V6_STANDARD_ROUTER = '0x111111125421ca6dc452d289314280a0f8842a65'
45
56
  // V6 on zkSync Era ONLY — live-confirmed 2026-07-08 via a real api.vultisig.com/1inch
46
57
  // v6.0 quote request returning this address (NOT the standard one above).
47
58
  const ONE_INCH_V6_ZKSYNC_ROUTER = '0x6fd4383cb451173d5f9304f041c7bcbf27d561ff';
48
- // KyberSwap MetaAggregationRouterV2 — same address confirmed live 2026-07-08 on every chain
49
- // that returned a response through aggregator-api.kyberswap.com's /routes (Ethereum, BSC,
50
- // Arbitrum, Optimism, Avalanche, Base, Polygon — 7 of 9 kyberSwapEnabledChains chains).
51
- // zkSync/Blast 404'd on this exact API path during verification — that looks like those two
52
- // chains aren't actually live through this aggregator endpoint today (a pre-existing,
53
- // separate question from this fix — kyberSwapEnabledChains may be ahead of what the live API
54
- // serves), not evidence of a differing router address. No chain-scoping needed unless that
55
- // changes.
59
+ // KyberSwap MetaAggregationRouterV2 — same address confirmed live 2026-07-08 on every
60
+ // kyberSwapEnabledChains chain through aggregator-api.kyberswap.com's /routes
61
+ // (Ethereum, BSC, Arbitrum, Optimism, Avalanche, Base, Polygon).
56
62
  const KYBER_STANDARD_ROUTER = '0x6131b5fae19ea4f9d964eac0408e4408b66337b5';
63
+ const ENFORCED_ROUTER_PROVIDERS = new Set(['1inch', 'kyber', 'cowswap']);
64
+ // sdk#1457: the small, closed set of provider values the codebase legitimately produces for a
65
+ // route that is genuinely NOT address-allow-listable. `li.fi`/`swapkit` route through many
66
+ // different bridge/DEX contracts by design (see the file doc comment). `''` is NOT an attacker
67
+ // label - it is the documented fallback mapSwapPayload.ts (and getKeysignSwapPayload's own
68
+ // callers) use for pre-provider-field mobile captures, proven by real golden fixtures
69
+ // (mobileFixtures.golden.test.ts's arb.json/lifiswap.json) that still carry an unset provider.
70
+ // This is a CLOSED list, not "everything not enforced": a `provider` string outside BOTH this
71
+ // set and ENFORCED_ROUTER_PROVIDERS is unrecognized and rejected below, instead of silently logged.
72
+ const RECOGNIZED_UNENFORCED_PROVIDERS = new Set(['li.fi', 'swapkit', '']);
73
+ /**
74
+ * Signing-path re-assert (sdk#1358): the same allow-list check as {@link assertKnownAggregatorRouter},
75
+ * but keyed off an arbitrary provider STRING (the value carried in KeysignSwapPayload.general.provider,
76
+ * which is a plain `string`). Enforced providers (1inch/kyber/cowswap) fail closed; the small closed set
77
+ * of genuinely unenforceable providers (li.fi/swapkit, plus the legacy `''` unattributed provider - see
78
+ * RECOGNIZED_UNENFORCED_PROVIDERS) fall through to the same log-only path they take at quote construction;
79
+ * anything else is rejected outright (sdk#1457, see below).
80
+ *
81
+ * WHY THIS EXISTS SEPARATELY FROM quote construction: a compromised initiator (or server composing the
82
+ * intent) can hand a co-signer a KeysignPayload whose swapPayload.quote.tx.to was NEVER run through the
83
+ * quote-time check - every co-signer independently rebuilds the signing input from that payload, so the
84
+ * guard has to run HERE too, on the signing-input path, or a co-signer (e.g. VultiServer in a 2-of-2)
85
+ * signs a destination it never validated. Mirrors the Ripple resolver's in-resolver fail-closed binding.
86
+ *
87
+ * THREAT MODEL / TRUST OF `provider` (CodeRabbit security review; sdk#1457): `provider` here is the free
88
+ * `provider` STRING on the OneInchSwapPayload proto (the `oneinchSwapPayload` oneof case carries
89
+ * 1inch/li.fi/cowswap/kyber with only this string to tell them apart; swapkit's dedicated transfer route
90
+ * is the one general provider that has its own oneof case - see getKeysignSwapPayload.ts). It is
91
+ * therefore part of the attacker-influenceable payload, NOT a trusted oneof discriminant, and a payload
92
+ * whose `provider` disagrees with its actual executing shape (an attacker relabeling to dodge
93
+ * enforcement) is a real, closable gap - not just a theoretical one.
94
+ *
95
+ * sdk#1457 FIX: two structural improvements that need no proto change. (1) CowSwap is now enforced -
96
+ * unlike li.fi/swapkit it settles through ONE fixed, deterministic contract (the GPv2VaultRelayer, see
97
+ * assertKnownAggregatorRouter), so its destination is exactly as allow-listable as 1inch/Kyber's; a
98
+ * payload can no longer relabel itself 'cowswap' to dodge a router check the way it previously could. (2)
99
+ * the log-only fallback is now a CLOSED list of the provider values the codebase legitimately produces
100
+ * (li.fi/swapkit, plus the legacy `''` unattributed provider) - a `provider` string outside every known
101
+ * value (enforced or unenforced) is unrecognized and REJECTED, not silently passed through. Together
102
+ * these shrink "relabel to escape enforcement" from "any string at all" down to exactly li.fi, swapkit,
103
+ * and the legacy `''`, which remain unenforceable by address because they legitimately route through
104
+ * many different contracts by design (see the file doc comment) - closing that residual gap needs the
105
+ * provider identity to be a trusted wire discriminant instead of a free string, i.e. a proto oneof case
106
+ * per provider (tracked in sdk#1457, not attempted here: a schema change on the shared commondata proto
107
+ * is a cross-repo, cross-consumer change every native client (iOS/Android/Windows) also builds against).
108
+ *
109
+ * This guard remains MONOTONIC beyond that residual gap: it only ever THROWS (rejects) or no-ops - it
110
+ * never makes anything signable that wasn't already.
111
+ */
112
+ export function assertKnownAggregatorRouterOnSigningPath(provider, address, chain) {
113
+ if (ENFORCED_ROUTER_PROVIDERS.has(provider)) {
114
+ // assertKnownAggregatorRouter fails closed on an unrecognized address, INCLUDING an empty/missing
115
+ // one - an enforced-provider swap with no destination is itself a malformed intent we won't sign.
116
+ assertKnownAggregatorRouter(provider, address, chain);
117
+ return;
118
+ }
119
+ if (!RECOGNIZED_UNENFORCED_PROVIDERS.has(provider)) {
120
+ throw new Error(`Unrecognized swap provider "${provider}" on the co-signer signing path - refusing to sign a swap ` +
121
+ 'whose provider label does not match any known aggregator (enforced or unenforced).');
122
+ }
123
+ // Unenforced (li.fi/swapkit): log-only, and log the ACTUAL provider so the usage dataset the future
124
+ // allow-list is built from isn't poisoned by a coerced label. Skip a genuinely empty address.
125
+ if (address) {
126
+ logUnenforcedAggregatorDestination(provider, address);
127
+ }
128
+ }
129
+ /**
130
+ * Signing-path approval-spender bind (sdk#1358 review follow-up, requested by neavra). The
131
+ * follow-on to {@link assertKnownAggregatorRouterOnSigningPath}: that guard validates the swap-leg
132
+ * destination (`quote.tx.to`), but a general swap that needs an allowance also carries a SEPARATE,
133
+ * independent wire field - `erc20ApprovePayload.spender` - which the approve resolver (erc20.ts)
134
+ * reads verbatim and nothing binds to `quote.tx.to`. So a payload can pass the router check with a
135
+ * genuine 1inch/kyber `tx.to` yet still carry an approve granting an ATTACKER an allowance over the
136
+ * user's token (a classic approval-drain the co-signer would otherwise sign blind).
137
+ *
138
+ * On the initiator these coincide by construction (build.ts sets the approve spender to
139
+ * `getSwapDestinationAddress` === `tx.to`), so this only ever fires on a hand-built/tampered payload.
140
+ * Enforced providers (1inch/kyber/cowswap) MUST have `spender === routerDestination`; unenforced
141
+ * providers (li.fi/swapkit) are NOT bound. CowSwap's spender IS its `tx.to` (both are the fixed
142
+ * GPv2VaultRelayer - see getSwapDestinationAddress.ts), so it binds the same way 1inch/kyber do. Like
143
+ * its sibling this is a MONOTONIC gate: it only throws or no-ops, never changes the signed bytes.
144
+ */
145
+ export function assertEnforcedSwapApprovalSpenderBound(provider, spender, routerDestination, chain) {
146
+ if (!ENFORCED_ROUTER_PROVIDERS.has(provider)) {
147
+ return;
148
+ }
149
+ if (spender.toLowerCase() !== routerDestination.toLowerCase()) {
150
+ throw new Error(`${provider} swap approval spender (${spender}) does not match the verified swap router (${routerDestination}) on ${chain} — refusing to sign an approval to an unbound spender.`);
151
+ }
152
+ }
57
153
  /**
58
154
  * Throws if `address` isn't the known router for `provider` on `chain`. Call this at quote
59
155
  * construction, before a GeneralSwapQuote carrying `address` as `tx.evm.to` can exist.
@@ -62,9 +158,19 @@ export function assertKnownAggregatorRouter(provider, address, chain) {
62
158
  const normalized = address.toLowerCase();
63
159
  const isKnown = provider === 'kyber'
64
160
  ? normalized === KYBER_STANDARD_ROUTER
65
- : chain === Chain.Zksync
66
- ? normalized === ONE_INCH_V6_ZKSYNC_ROUTER
67
- : normalized === ONE_INCH_V5_ROUTER || normalized === ONE_INCH_V6_STANDARD_ROUTER;
161
+ : provider === 'cowswap'
162
+ ? // CHAIN-SCOPED, same reason the 1inch arm is: the relayer is a deterministic address, so it
163
+ // resolves on EVERY EVM chain, but CoW has only deployed the GPv2 stack on
164
+ // cowSwapSupportedChains (findSwapQuote gates quotes to exactly those). Accepting it
165
+ // chain-agnostically would let a tampered payload relabelled 'cowswap' on e.g. CronosChain /
166
+ // Zksync / Blast — where eth_getCode at this address is literally `0x`, verified 2026-07-21 —
167
+ // pass BOTH this guard and assertEnforcedSwapApprovalSpenderBound, so the co-signer would
168
+ // sign an ERC-20 approve to a codeless address anyone can later claim via the deterministic
169
+ // deployment proxy. Fail closed off the supported set.
170
+ isOneOf(chain, cowSwapSupportedChains) && normalized === COW_VAULT_RELAYER_ADDRESS.toLowerCase()
171
+ : chain === Chain.Zksync
172
+ ? normalized === ONE_INCH_V6_ZKSYNC_ROUTER
173
+ : normalized === ONE_INCH_V5_ROUTER || normalized === ONE_INCH_V6_STANDARD_ROUTER;
68
174
  if (!isKnown) {
69
175
  throw new Error(`${provider} swap quote returned an unrecognized router address (${address}) on ${chain} — refusing to build a signable transaction against it.`);
70
176
  }
@@ -1 +1 @@
1
- {"version":3,"file":"knownAggregatorRouters.js","sourceRoot":"","sources":["../../../../../../packages/core/chain/swap/general/knownAggregatorRouters.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAEnC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,wDAAwD;AACxD,0FAA0F;AAC1F,4FAA4F;AAC5F,wFAAwF;AACxF,qFAAqF;AACrF,oDAAoD;AACpD,MAAM,kBAAkB,GAAG,4CAA4C,CAAA;AAEvE,sFAAsF;AACtF,yEAAyE;AACzE,MAAM,2BAA2B,GAAG,4CAA4C,CAAA;AAEhF,sFAAsF;AACtF,0EAA0E;AAC1E,MAAM,yBAAyB,GAAG,4CAA4C,CAAA;AAE9E,4FAA4F;AAC5F,0FAA0F;AAC1F,wFAAwF;AACxF,4FAA4F;AAC5F,sFAAsF;AACtF,6FAA6F;AAC7F,2FAA2F;AAC3F,WAAW;AACX,MAAM,qBAAqB,GAAG,4CAA4C,CAAA;AAI1E;;;GAGG;AACH,MAAM,UAAU,2BAA2B,CAAC,QAAgC,EAAE,OAAe,EAAE,KAAY;IACzG,MAAM,UAAU,GAAG,OAAO,CAAC,WAAW,EAAE,CAAA;IACxC,MAAM,OAAO,GACX,QAAQ,KAAK,OAAO;QAClB,CAAC,CAAC,UAAU,KAAK,qBAAqB;QACtC,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,MAAM;YACtB,CAAC,CAAC,UAAU,KAAK,yBAAyB;YAC1C,CAAC,CAAC,UAAU,KAAK,kBAAkB,IAAI,UAAU,KAAK,2BAA2B,CAAA;IAEvF,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,GAAG,QAAQ,wDAAwD,OAAO,QAAQ,KAAK,yDAAyD,CACjJ,CAAA;IACH,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kCAAkC,CAAC,QAA6B,EAAE,OAAe;IAC/F,OAAO,CAAC,IAAI,CAAC,8FAA8F,EAAE;QAC3G,QAAQ;QACR,OAAO;KACR,CAAC,CAAA;AACJ,CAAC"}
1
+ {"version":3,"file":"knownAggregatorRouters.js","sourceRoot":"","sources":["../../../../../../packages/core/chain/swap/general/knownAggregatorRouters.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,3 @@
1
- export declare const kyberSwapEnabledChains: readonly ["Ethereum", "BSC", "Arbitrum", "Polygon", "Optimism", "Avalanche", "Base", "Zksync", "Blast"];
1
+ export declare const kyberSwapEnabledChains: readonly ["Ethereum", "BSC", "Arbitrum", "Polygon", "Optimism", "Avalanche", "Base"];
2
2
  export type KyberSwapEnabledChain = (typeof kyberSwapEnabledChains)[number];
3
3
  //# sourceMappingURL=chains.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"chains.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/swap/general/kyber/chains.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,sBAAsB,yGAUzB,CAAA;AAEV,MAAM,MAAM,qBAAqB,GAAG,CAAC,OAAO,sBAAsB,CAAC,CAAC,MAAM,CAAC,CAAA"}
1
+ {"version":3,"file":"chains.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/swap/general/kyber/chains.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,sBAAsB,sFAQzB,CAAA;AAEV,MAAM,MAAM,qBAAqB,GAAG,CAAC,OAAO,sBAAsB,CAAC,CAAC,MAAM,CAAC,CAAA"}
@@ -1,4 +1,9 @@
1
1
  import { Chain } from '@vultisig/core-chain/Chain';
2
+ // Zksync and Blast are intentionally absent (sdk#1151): Kyber's
3
+ // aggregator-api.kyberswap.com /routes endpoint 404s on both (verified
4
+ // 2026-07-08, see knownAggregatorRouters.ts) — listing them only burned a
5
+ // doomed fetch + timeout slot per quote on those chains. Re-add if Kyber's
6
+ // API starts serving them.
2
7
  export const kyberSwapEnabledChains = [
3
8
  Chain.Ethereum,
4
9
  Chain.BSC,
@@ -7,7 +12,5 @@ export const kyberSwapEnabledChains = [
7
12
  Chain.Optimism,
8
13
  Chain.Avalanche,
9
14
  Chain.Base,
10
- Chain.Zksync,
11
- Chain.Blast,
12
15
  ];
13
16
  //# sourceMappingURL=chains.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"chains.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/swap/general/kyber/chains.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAA;AAElD,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,KAAK,CAAC,QAAQ;IACd,KAAK,CAAC,GAAG;IACT,KAAK,CAAC,QAAQ;IACd,KAAK,CAAC,OAAO;IACb,KAAK,CAAC,QAAQ;IACd,KAAK,CAAC,SAAS;IACf,KAAK,CAAC,IAAI;IACV,KAAK,CAAC,MAAM;IACZ,KAAK,CAAC,KAAK;CACH,CAAA"}
1
+ {"version":3,"file":"chains.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/swap/general/kyber/chains.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAA;AAElD,gEAAgE;AAChE,uEAAuE;AACvE,0EAA0E;AAC1E,2EAA2E;AAC3E,2BAA2B;AAC3B,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,KAAK,CAAC,QAAQ;IACd,KAAK,CAAC,GAAG;IACT,KAAK,CAAC,QAAQ;IACd,KAAK,CAAC,OAAO;IACb,KAAK,CAAC,QAAQ;IACd,KAAK,CAAC,SAAS;IACf,KAAK,CAAC,IAAI;CACF,CAAA"}
@@ -15,14 +15,7 @@ type Input = Record<TransferDirection, AccountCoinKey<LifiSwapEnabledChain> & {
15
15
  * back to the stable/non-stable pair default. */
16
16
  slippage?: number;
17
17
  };
18
- /** @internal exported for unit tests only */
19
- export declare const STABLE_TICKERS: ReadonlySet<string>;
20
- /** @internal exported for unit tests only */
21
- export declare const isStablePair: (from: {
22
- ticker?: string;
23
- }, to: {
24
- ticker?: string;
25
- }) => boolean;
18
+ /** @internal re-exported for unit tests only — source of truth is ./lifiSlippage. */
19
+ export { isStablePair, STABLE_TICKERS } from './lifiSlippage.js';
26
20
  export declare const getLifiSwapQuote: ({ amount, affiliateBps, lifiAffiliateConfig, slippage: slippageOverride, ...transfer }: Input) => Promise<GeneralSwapQuote>;
27
- export {};
28
21
  //# sourceMappingURL=getLifiSwapQuote.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"getLifiSwapQuote.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/chain/swap/general/lifi/api/getLifiSwapQuote.ts"],"names":[],"mappings":"AAIA,OAAO,EAEL,mBAAmB,EAGpB,MAAM,+CAA+C,CAAA;AACtD,OAAO,EAAmB,oBAAoB,EAAE,MAAM,8DAA8D,CAAA;AAKpH,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAA;AAEzE,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAA;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AAIzD,KAAK,KAAK,GAAG,MAAM,CAAC,iBAAiB,EAAE,cAAc,CAAC,oBAAoB,CAAC,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG;IACnG,MAAM,EAAE,MAAM,CAAA;IACd,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;4EACwE;IACxE,mBAAmB,CAAC,EAAE,mBAAmB,CAAA;IACzC;qDACiD;IACjD,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,CAAA;AAKD,6CAA6C;AAC7C,eAAO,MAAM,cAAc,EAAE,WAAW,CAAC,MAAM,CAa7C,CAAA;AAKF,6CAA6C;AAC7C,eAAO,MAAM,YAAY,GAAI,MAAM;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,IAAI;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,KAAG,OACxB,CAAA;AAkG1D,eAAO,MAAM,gBAAgB,GAAU,wFAMpC,KAAK,KAAG,OAAO,CAAC,gBAAgB,CAuLlC,CAAA"}
1
+ {"version":3,"file":"getLifiSwapQuote.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/chain/swap/general/lifi/api/getLifiSwapQuote.ts"],"names":[],"mappings":"AAIA,OAAO,EAEL,mBAAmB,EAGpB,MAAM,+CAA+C,CAAA;AACtD,OAAO,EAAmB,oBAAoB,EAAE,MAAM,8DAA8D,CAAA;AAKpH,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAA;AAEzE,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAA;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AAKzD,KAAK,KAAK,GAAG,MAAM,CAAC,iBAAiB,EAAE,cAAc,CAAC,oBAAoB,CAAC,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG;IACnG,MAAM,EAAE,MAAM,CAAA;IACd,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;4EACwE;IACxE,mBAAmB,CAAC,EAAE,mBAAmB,CAAA;IACzC;qDACiD;IACjD,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,qFAAqF;AACrF,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AA2C7D,eAAO,MAAM,gBAAgB,GAAU,wFAMpC,KAAK,KAAG,OAAO,CAAC,gBAAgB,CA0MlC,CAAA"}
@@ -10,27 +10,9 @@ import { memoize } from '@vultisig/lib-utils/memoize';
10
10
  import { mirrorRecord } from '@vultisig/lib-utils/record/mirrorRecord';
11
11
  import { logUnenforcedAggregatorDestination } from '../../knownAggregatorRouters.js';
12
12
  import { injectSolanaAtaIfMissing } from './injectSolanaAtaIfMissing.js';
13
- // Stable-pair detection: tickers that commonly trade within a tight peg.
14
- // DAI is included because on most DEXs DAI/USDC depth is comparable to
15
- // USDC/USDT and the 0.3% ceiling is still safe headroom for MPC latency.
16
- /** @internal exported for unit tests only */
17
- export const STABLE_TICKERS = new Set([
18
- 'USDC',
19
- 'USDT',
20
- 'DAI',
21
- 'BUSD',
22
- 'TUSD',
23
- 'FRAX',
24
- 'USDP',
25
- 'GUSD',
26
- 'LUSD',
27
- 'USDD',
28
- 'FDUSD',
29
- 'PYUSD',
30
- ]);
31
- const isStableTicker = (ticker) => ticker !== undefined && STABLE_TICKERS.has(ticker.toUpperCase());
32
- /** @internal exported for unit tests only */
33
- export const isStablePair = (from, to) => isStableTicker(from.ticker) && isStableTicker(to.ticker);
13
+ import { MAX_COMBINED_COST_BPS, resolveLifiSlippage } from './lifiSlippage.js';
14
+ /** @internal re-exported for unit tests only source of truth is ./lifiSlippage. */
15
+ export { isStablePair, STABLE_TICKERS } from './lifiSlippage.js';
34
16
  /** Lazy bootstrap for callers that never invoked the public `setupLifi`
35
17
  * — uses whatever defaults sit on `lifiConfig` (vultisig-0 + no apiUrl
36
18
  * unless a consumer mutated them at module load). The public `setupLifi`
@@ -39,64 +21,10 @@ export const isStablePair = (from, to) => isStableTicker(from.ticker) && isStabl
39
21
  const ensureLifiConfigured = memoize(() => {
40
22
  setupLifi();
41
23
  });
42
- // Slippage tolerance baked into the LiFi-prebuilt swap tx. The
43
- // returned `transactionRequest.data` is a fully-formed Solana / EVM
44
- // transaction that encodes a minAmountOut floor at quote time
45
- // the underlying AMM (Raydium / Orca / Meteora on Solana; Uniswap /
46
- // 1inch on EVM) reverts if simulation-time output drops below the
47
- // floor. Default LiFi slippage is 0.005 (0.5%), which is far too
48
- // tight for MPC-signed flows where the keysign ceremony adds
49
- // 30-90s of clock drift between quote and broadcast and the price
50
- // routinely moves more than 0.5% on volatile pairs (SOL/USDC,
51
- // SOL/anything memecoin). Production repro (2026-05-22):
52
- // SOL→USDC simulation failed with `-32002: custom program error:
53
- // 0x32` (Raydium AMM error 50 = AmountExceedsMaximum / slippage
54
- // exceeded). Bump to 1% — covers the typical ceremony drift while
55
- // staying well inside the user's pre-sign card's risk surface
56
- // (typical realised slippage on these aggregators is <0.1%, so
57
- // the 1% is a ceiling, not the expected price hit).
58
- //
59
- // EVM is less time-sensitive — the model dispatches and the user
60
- // signs in seconds, but the same 1% bump still helps cover block
61
- // time variance during mempool pending (~12s on ETH, ~2s on L2s).
62
- // On WalletConnect / injected signers the dapp typically re-fetches
63
- // the quote at MetaMask/Rainbow signing time, so quote staleness from
64
- // user pause on the pre-sign card is NOT the failure mode — block-
65
- // time variance during pending is. (NeOMakinG #513 round 1 CR
66
- // `should-fix` 1 — comment was misleading pre-fix.)
67
- //
68
- // **Cross-chain bridge+swap caveat (NeOMakinG #513 round 1
69
- // `preferably-blocking`).** This 1% slippage applies to the FINAL
70
- // destination amount only. LiFi cross-chain routes (Stargate, Across,
71
- // Hop + destination AMM swap) have TWO slippage points: (1) bridge
72
- // liquidity pool exit on the source chain, (2) destination AMM swap.
73
- // Intermediate bridge slippage is managed by bridge protocols' own
74
- // limits and is NOT covered by this 1% floor — so total realised
75
- // slippage on a SOL→ETH→USDC route could be 2-3% even when this
76
- // constant says "1%". Document the bridge cost explicitly to users
77
- // when surfacing cross-chain quote previews; don't rely on this
78
- // constant as the single source of truth for cross-chain slippage.
79
- //
80
- // Hoisted to module scope so the planned per-pair / per-call
81
- // override (forwarding `execute_swap.slippage_tolerance_percent`
82
- // through the resolver, tracked at vultisig/vultisig-sdk#NEW — TODO
83
- // open) lands as a clean diff rather than reshaping the function
84
- // body. Codex Round 1b review feedback (vultisig-sdk#513 r1).
85
- //
86
- // Two tiers (vultisig-sdk#524):
87
- // - stable pairs (USDC/USDT/DAI/...): 0.3% — well above typical
88
- // concentrated-liquidity spread (0.02-0.05%) but avoids the 1%
89
- // MEV surface on tight-peg operations.
90
- // - volatile pairs: 1% — covers MPC ceremony latency (30-90s) where
91
- // price can move >0.5% on thin pairs. See full rationale above.
92
- const DEFAULT_LIFI_SLIPPAGE_TOLERANCE = 0.01;
93
- const STABLE_PAIR_LIFI_SLIPPAGE_TOLERANCE = 0.003;
94
- // Combined affiliate + slippage ceiling. Defensive guard so a high
95
- // affiliateBps + the 1% slippage don't silently combine into a >3%
96
- // effective cost on the user without anyone noticing. Logged-only,
97
- // not a hard reject — getQuote will still dispatch. NeOMakinG #513
98
- // round 1 `suggestion` 1.
99
- const MAX_COMBINED_COST_BPS = 300;
24
+ // Slippage tolerance (baked into the LiFi-prebuilt tx's minAmountOut floor) is resolved by
25
+ // ./lifiSlippage the shared source of truth for the two tiers + combined-cost ceiling, so the RN
26
+ // override resolves it identically. See that module for the full rationale (MPC ceremony drift, the
27
+ // stable/volatile split, and the cross-chain bridge-slippage caveat).
100
28
  // Resolve a LiFi fee-token `chainId` back to a Vultisig `LifiSwapEnabledChain`.
101
29
  //
102
30
  // `mirrorRecord(lifiSwapChainId)` is a closed, build-time map of LI.FI source
@@ -128,8 +56,7 @@ export const getLifiSwapQuote = async ({ amount, affiliateBps, lifiAffiliateConf
128
56
  const [fromChain, toChain] = [transfer.from, transfer.to].map(({ chain }) => lifiSwapChainId[chain]);
129
57
  const [fromToken, toToken] = [transfer.from, transfer.to].map(({ id, chain }) => id ?? chainFeeCoin[chain].ticker);
130
58
  const [fromAddress, toAddress] = [transfer.from, transfer.to].map(({ address }) => address);
131
- const slippage = slippageOverride ??
132
- (isStablePair(transfer.from, transfer.to) ? STABLE_PAIR_LIFI_SLIPPAGE_TOLERANCE : DEFAULT_LIFI_SLIPPAGE_TOLERANCE);
59
+ const slippage = resolveLifiSlippage({ slippageOverride, from: transfer.from, to: transfer.to });
133
60
  // Defensive: log when affiliate + slippage combined cost crosses the
134
61
  // 3% ceiling. Today affiliateBps is typically 0 and slippage is 1%,
135
62
  // so 100bps total — well under the ceiling — but a future bump to
@@ -254,6 +181,21 @@ export const getLifiSwapQuote = async ({ amount, affiliateBps, lifiAffiliateConf
254
181
  const swapFeeAssetId = swapFee &&
255
182
  ([fromToken, toToken].find(token => token.toLowerCase() === swapFeeAddress) ||
256
183
  chainFeeCoin[transfer.from.chain].id);
184
+ // LI.FI `estimate.approvalAddress` is the address that will call
185
+ // `transferFrom` on the input ERC-20. It can differ from `to` (the
186
+ // Diamond / router) when an inner executor (e.g. 1inch
187
+ // AggregationExecutor) pulls the token directly. The field is always
188
+ // present in the LiFi API response (`Estimate.approvalAddress: string`)
189
+ // but may be the zero address or equal to `to` for native-token routes.
190
+ // Pass it through so mcp-ts (and other consumers) can approve the
191
+ // correct spender instead of the Diamond.
192
+ //
193
+ // On-chain proof: tx 0xa3aadf17 (Ethereum, block 25415989) reverted
194
+ // with "ERC20: transfer amount exceeds allowance". Vault had 9.41 USDC
195
+ // approved to Diamond (0x9025B8ff…, = `to`) — sufficient. Inner 1inch
196
+ // executor (0x7f51c134…, = `approvalAddress`) had zero allowance — the
197
+ // actual transferFrom caller → revert.
198
+ const approvalAddr = estimate.approvalAddress;
257
199
  const evmTo = shouldBePresent(to);
258
200
  // AGG-02: LiFi routes through many different bridge/DEX contracts by design
259
201
  // (diamond routing, multi-hop, chain-specific deployments) — a hard allowlist
@@ -267,6 +209,12 @@ export const getLifiSwapQuote = async ({ amount, affiliateBps, lifiAffiliateConf
267
209
  data: shouldBePresent(data),
268
210
  value: BigInt(shouldBePresent(value)).toString(),
269
211
  gasLimit: gasLimit ? BigInt(gasLimit) : undefined,
212
+ // Include approvalAddress when it is present and non-zero so the
213
+ // consumer can approve the right spender. Omit for the zero address
214
+ // (native-only routes) to avoid a spurious zero-address approval.
215
+ ...(approvalAddr && approvalAddr !== '0x0000000000000000000000000000000000000000'
216
+ ? { approvalAddress: approvalAddr }
217
+ : {}),
270
218
  ...(swapFee
271
219
  ? {
272
220
  affiliateFee: {
@@ -1 +1 @@
1
- {"version":3,"file":"getLifiSwapQuote.js","sourceRoot":"","sources":["../../../../../../../../packages/core/chain/swap/general/lifi/api/getLifiSwapQuote.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"getLifiSwapQuote.js","sourceRoot":"","sources":["../../../../../../../../packages/core/chain/swap/general/lifi/api/getLifiSwapQuote.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ export declare const DEFAULT_LIFI_SLIPPAGE_TOLERANCE = 0.01;
2
+ export declare const STABLE_PAIR_LIFI_SLIPPAGE_TOLERANCE = 0.003;
3
+ export declare const MAX_COMBINED_COST_BPS = 300;
4
+ export declare const STABLE_TICKERS: ReadonlySet<string>;
5
+ export declare const isStablePair: (from: {
6
+ ticker?: string;
7
+ }, to: {
8
+ ticker?: string;
9
+ }) => boolean;
10
+ /**
11
+ * Resolve the LiFi slippage fraction: honor an explicit consumer override, else pick the tier by
12
+ * pair type. `slippageOverride` is a fraction (0.01 = 1%). This is what gets baked into the
13
+ * LiFi-prebuilt tx's `minAmountOut` floor, so dropping the override silently widens the user's
14
+ * slippage on an explicit tight-tolerance request.
15
+ */
16
+ export declare const resolveLifiSlippage: ({ slippageOverride, from, to, }: {
17
+ slippageOverride: number | undefined;
18
+ from: {
19
+ ticker?: string;
20
+ };
21
+ to: {
22
+ ticker?: string;
23
+ };
24
+ }) => number;
25
+ //# sourceMappingURL=lifiSlippage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lifiSlippage.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/chain/swap/general/lifi/api/lifiSlippage.ts"],"names":[],"mappings":"AAqBA,eAAO,MAAM,+BAA+B,OAAO,CAAA;AACnD,eAAO,MAAM,mCAAmC,QAAQ,CAAA;AAIxD,eAAO,MAAM,qBAAqB,MAAM,CAAA;AAIxC,eAAO,MAAM,cAAc,EAAE,WAAW,CAAC,MAAM,CAa7C,CAAA;AAKF,eAAO,MAAM,YAAY,GAAI,MAAM;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,IAAI;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,KAAG,OACxB,CAAA;AAE1D;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,GAAI,iCAIjC;IACD,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAA;IACpC,IAAI,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IACzB,EAAE,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CACxB,KAAG,MACkH,CAAA"}
@@ -0,0 +1,51 @@
1
+ // Shared LiFi slippage-tier logic, extracted so the core `getLifiSwapQuote` AND its RN override
2
+ // (platforms/react-native/overrides/getLifiSwapQuote.ts — a SEPARATE build target that rollup
3
+ // redirects core's module to, see rollup.platforms.config.js) resolve slippage identically. The
4
+ // override cannot import from core's `getLifiSwapQuote` (that path redirects back to itself), so
5
+ // this sibling module is the single source of truth for the stable-pair set + the two tiers.
6
+ // The slippage fraction is baked into the LiFi-prebuilt tx's `minAmountOut` floor at quote time
7
+ // (the underlying AMM reverts if simulation-time output drops below it). LiFi's default 0.5% is too
8
+ // tight for MPC-signed flows: the keysign ceremony adds 30-90s of drift between quote and broadcast.
9
+ // Production repro (2026-05-22): a SOL→USDC route failed simulation with Raydium AMM error 50
10
+ // (AmountExceedsMaximum / slippage exceeded) at 0.5%.
11
+ //
12
+ // Two tiers (vultisig-sdk#524):
13
+ // - stable pairs (USDC/USDT/DAI/...): 0.3% — well above typical concentrated-liquidity spread
14
+ // (0.02-0.05%) but avoids the 1% MEV surface on tight-peg operations.
15
+ // - volatile pairs: 1% — covers the ceremony drift; typical realised slippage is <0.1%, so this is
16
+ // a ceiling, not the expected hit.
17
+ //
18
+ // Cross-chain caveat (NeOMakinG #513): this fraction applies to the FINAL destination amount only.
19
+ // LiFi bridge+swap routes have a SECOND slippage point at the bridge pool exit that bridge protocols
20
+ // manage themselves — total realised slippage on a cross-chain route can exceed this floor.
21
+ export const DEFAULT_LIFI_SLIPPAGE_TOLERANCE = 0.01;
22
+ export const STABLE_PAIR_LIFI_SLIPPAGE_TOLERANCE = 0.003;
23
+ // Defensive combined affiliate + slippage ceiling (logged, never thrown): a high affiliateBps must
24
+ // not silently combine with slippage into a >3% effective cost without anyone noticing.
25
+ export const MAX_COMBINED_COST_BPS = 300;
26
+ // Stable-pair detection: tickers that commonly trade within a tight peg. DAI is included because on
27
+ // most DEXs DAI/USDC depth is comparable to USDC/USDT and the 0.3% ceiling is still safe headroom.
28
+ export const STABLE_TICKERS = new Set([
29
+ 'USDC',
30
+ 'USDT',
31
+ 'DAI',
32
+ 'BUSD',
33
+ 'TUSD',
34
+ 'FRAX',
35
+ 'USDP',
36
+ 'GUSD',
37
+ 'LUSD',
38
+ 'USDD',
39
+ 'FDUSD',
40
+ 'PYUSD',
41
+ ]);
42
+ const isStableTicker = (ticker) => ticker !== undefined && STABLE_TICKERS.has(ticker.toUpperCase());
43
+ export const isStablePair = (from, to) => isStableTicker(from.ticker) && isStableTicker(to.ticker);
44
+ /**
45
+ * Resolve the LiFi slippage fraction: honor an explicit consumer override, else pick the tier by
46
+ * pair type. `slippageOverride` is a fraction (0.01 = 1%). This is what gets baked into the
47
+ * LiFi-prebuilt tx's `minAmountOut` floor, so dropping the override silently widens the user's
48
+ * slippage on an explicit tight-tolerance request.
49
+ */
50
+ export const resolveLifiSlippage = ({ slippageOverride, from, to, }) => slippageOverride ?? (isStablePair(from, to) ? STABLE_PAIR_LIFI_SLIPPAGE_TOLERANCE : DEFAULT_LIFI_SLIPPAGE_TOLERANCE);
51
+ //# sourceMappingURL=lifiSlippage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lifiSlippage.js","sourceRoot":"","sources":["../../../../../../../../packages/core/chain/swap/general/lifi/api/lifiSlippage.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAChG,8FAA8F;AAC9F,gGAAgG;AAChG,iGAAiG;AACjG,6FAA6F;AAE7F,gGAAgG;AAChG,oGAAoG;AACpG,qGAAqG;AACrG,8FAA8F;AAC9F,sDAAsD;AACtD,EAAE;AACF,gCAAgC;AAChC,8FAA8F;AAC9F,wEAAwE;AACxE,mGAAmG;AACnG,qCAAqC;AACrC,EAAE;AACF,mGAAmG;AACnG,qGAAqG;AACrG,4FAA4F;AAC5F,MAAM,CAAC,MAAM,+BAA+B,GAAG,IAAI,CAAA;AACnD,MAAM,CAAC,MAAM,mCAAmC,GAAG,KAAK,CAAA;AAExD,mGAAmG;AACnG,wFAAwF;AACxF,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAAG,CAAA;AAExC,oGAAoG;AACpG,mGAAmG;AACnG,MAAM,CAAC,MAAM,cAAc,GAAwB,IAAI,GAAG,CAAC;IACzD,MAAM;IACN,MAAM;IACN,KAAK;IACL,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,OAAO;IACP,OAAO;CACR,CAAC,CAAA;AAEF,MAAM,cAAc,GAAG,CAAC,MAA0B,EAAW,EAAE,CAC7D,MAAM,KAAK,SAAS,IAAI,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CAAA;AAElE,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,IAAyB,EAAE,EAAuB,EAAW,EAAE,CAC1F,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,cAAc,CAAC,EAAE,CAAC,MAAM,CAAC,CAAA;AAE1D;;;;;GAKG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,EAClC,gBAAgB,EAChB,IAAI,EACJ,EAAE,GAKH,EAAU,EAAE,CACX,gBAAgB,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,mCAAmC,CAAC,CAAC,CAAC,+BAA+B,CAAC,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"getOneInchSwapQuote.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/chain/swap/general/oneInch/api/getOneInchSwapQuote.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAA;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAA;AAEhE,OAAO,EAAE,WAAW,EAAE,MAAM,uCAAuC,CAAA;AAEnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,oDAAoD,CAAA;AAGrF,OAAO,EAAE,sBAAsB,EAAE,MAAM,kEAAkE,CAAA;AASzG,MAAM,MAAM,sBAAsB,GAAG,OAAO,sBAAsB,CAAA;AAElE,KAAK,KAAK,GAAG;IACX,OAAO,EAAE,YAAY,CAAA;IACrB;;+FAE2F;IAC3F,UAAU,EAAE,MAAM,GAAG,SAAS,CAAA;IAC9B,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAA;IAC5B;mEAC+D;IAC/D,EAAE,CAAC,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAA;IAC1B,MAAM,EAAE,MAAM,CAAA;IACd,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,aAAa,CAAC,EAAE,sBAAsB,CAAA;IACtC,wEAAwE;IACxE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,CAAA;AAuCD,eAAO,MAAM,mBAAmB,GAAU,uFASvC,KAAK,KAAG,OAAO,CAAC,gBAAgB,CAwClC,CAAA"}
1
+ {"version":3,"file":"getOneInchSwapQuote.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/chain/swap/general/oneInch/api/getOneInchSwapQuote.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAA;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAA;AAEhE,OAAO,EAAE,WAAW,EAAE,MAAM,uCAAuC,CAAA;AAEnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,oDAAoD,CAAA;AAGrF,OAAO,EAAE,sBAAsB,EAAE,MAAM,kEAAkE,CAAA;AASzG,MAAM,MAAM,sBAAsB,GAAG,OAAO,sBAAsB,CAAA;AAElE,KAAK,KAAK,GAAG;IACX,OAAO,EAAE,YAAY,CAAA;IACrB;;+FAE2F;IAC3F,UAAU,EAAE,MAAM,GAAG,SAAS,CAAA;IAC9B,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAA;IAC5B;mEAC+D;IAC/D,EAAE,CAAC,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAA;IAC1B,MAAM,EAAE,MAAM,CAAA;IACd,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,aAAa,CAAC,EAAE,sBAAsB,CAAA;IACtC,wEAAwE;IACxE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,CAAA;AAuCD,eAAO,MAAM,mBAAmB,GAAU,uFASvC,KAAK,KAAG,OAAO,CAAC,gBAAgB,CAmDlC,CAAA"}
@@ -54,6 +54,14 @@ export const getOneInchSwapQuote = async ({ account, fromCoinId, toCoinId, to, a
54
54
  // response can become a signable GeneralSwapQuote. Chain-scoped: 1inch's router differs
55
55
  // on zkSync Era. See knownAggregatorRouters.ts.
56
56
  assertKnownAggregatorRouter('1inch', tx.to, chain);
57
+ // Fund-safety: 1inch's `tx.value` flows through from the untrusted response VERBATIM (spread
58
+ // below), unlike Kyber which constructs `value` itself. For a TOKEN-source swap the sell token is
59
+ // pulled via ERC-20 allowance (approve/transferFrom), so `value` MUST be 0 — a non-zero value
60
+ // would move native chain gas-coin the user never authorized alongside the swap. A native-source
61
+ // swap (no `fromCoinId`) legitimately carries `value` == the sell amount, so only guard tokens.
62
+ if (!isFeeCoin({ id: fromCoinId, chain }) && tx.value && tx.value !== '0') {
63
+ throw new Error(`1inch quote returned a non-zero tx.value (${tx.value}) for a token-source swap on ${chain} — a token swap pulls the sell token via allowance and must not move native value; refusing to sign.`);
64
+ }
57
65
  return {
58
66
  dstAmount,
59
67
  provider: '1inch',
@@ -1 +1 @@
1
- {"version":3,"file":"getOneInchSwapQuote.js","sourceRoot":"","sources":["../../../../../../../../packages/core/chain/swap/general/oneInch/api/getOneInchSwapQuote.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"getOneInchSwapQuote.js","sourceRoot":"","sources":["../../../../../../../../packages/core/chain/swap/general/oneInch/api/getOneInchSwapQuote.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"getSwapKitQuote.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/chain/swap/general/swapkit/api/getSwapKitQuote.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,uCAAuC,CAAA;AAEnE,OAAO,EAAE,gBAAgB,EAAiB,MAAM,oDAAoD,CAAA;AAGpG,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,gEAAgE,CAAA;AAYxH,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAA;AAGzE,KAAK,KAAK,GAAG,MAAM,CAAC,iBAAiB,EAAE,WAAW,CAAC,mBAAmB,CAAC,CAAC,GAAG;IACzE,IAAI,EAAE,WAAW,CAAC,kBAAkB,CAAC,CAAA;IACrC,MAAM,EAAE,MAAM,CAAA;IACd,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,CAAA;AAurBD,eAAO,MAAM,eAAe,GAAU,+CAMnC,KAAK,KAAG,OAAO,CAAC,gBAAgB,CAiDlC,CAAA"}
1
+ {"version":3,"file":"getSwapKitQuote.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/chain/swap/general/swapkit/api/getSwapKitQuote.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,uCAAuC,CAAA;AAEnE,OAAO,EAAE,gBAAgB,EAAiB,MAAM,oDAAoD,CAAA;AAGpG,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,gEAAgE,CAAA;AAYxH,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAA;AAGzE,KAAK,KAAK,GAAG,MAAM,CAAC,iBAAiB,EAAE,WAAW,CAAC,mBAAmB,CAAC,CAAC,GAAG;IACzE,IAAI,EAAE,WAAW,CAAC,kBAAkB,CAAC,CAAA;IACrC,MAAM,EAAE,MAAM,CAAA;IACd,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,CAAA;AA2tBD,eAAO,MAAM,eAAe,GAAU,+CAMnC,KAAK,KAAG,OAAO,CAAC,gBAAgB,CAiDlC,CAAA"}
@@ -210,7 +210,23 @@ const safeBigInt = (value) => {
210
210
  }
211
211
  return BigInt(value);
212
212
  };
213
- const buildEvmTx = (tx, fromAddress) => {
213
+ // Decode the spender from a SwapKit-provided approve() calldata
214
+ // (approve(address spender, uint256 amount) — selector 0x095ea7b3). Returns the
215
+ // 20-byte spender address, or undefined if the calldata is missing/not an approve.
216
+ const decodeApproveSpender = (data) => {
217
+ if (typeof data !== 'string' || !data.startsWith('0x095ea7b3') || data.length < 74) {
218
+ return undefined;
219
+ }
220
+ const spender = `0x${data.slice(34, 74)}`;
221
+ if (!/^0x[0-9a-fA-F]{40}$/.test(spender)) {
222
+ return undefined;
223
+ }
224
+ // Mirror LiFi's zero-address omit: an approve() to the zero address is never
225
+ // a real allowance target, so surface nothing and let the consumer keep the
226
+ // tx.to fallback instead of emitting a spurious zero-address approval.
227
+ return spender === '0x0000000000000000000000000000000000000000' ? undefined : spender;
228
+ };
229
+ const buildEvmTx = (tx, fromAddress, approvalTx) => {
214
230
  if (!isRecord(tx)) {
215
231
  throw new Error('SwapKit EVM route did not return a transaction object.');
216
232
  }
@@ -223,6 +239,10 @@ const buildEvmTx = (tx, fromAddress) => {
223
239
  // false-block legitimate routes, so log (never throw). See knownAggregatorRouters.ts.
224
240
  logUnenforcedAggregatorDestination('swapkit', evmTx.to);
225
241
  const gas = evmTx.gasLimit ?? evmTx.gas;
242
+ // When SwapKit hands back a ready-made approve tx, its spender is the REAL
243
+ // allowance target (often an inner executor != tx.to). Surface it so the
244
+ // consumer approves the correct contract instead of the router.
245
+ const approvalAddress = decodeApproveSpender(approvalTx?.data);
226
246
  return {
227
247
  evm: {
228
248
  from: evmTx.from ?? fromAddress,
@@ -230,6 +250,7 @@ const buildEvmTx = (tx, fromAddress) => {
230
250
  data: evmTx.data ?? '0x',
231
251
  value: bigintString(evmTx.value),
232
252
  gasLimit: safeBigInt(gas),
253
+ ...(approvalAddress ? { approvalAddress } : {}),
233
254
  },
234
255
  };
235
256
  };
@@ -390,7 +411,7 @@ const buildSwapKitTx = (response, from, amount) => {
390
411
  if (shouldUseTransferTx(from.chain)) {
391
412
  return buildTransferTx(response, from, amount);
392
413
  }
393
- return buildEvmTx(response.tx, from.address);
414
+ return buildEvmTx(response.tx, from.address, response.approvalTx);
394
415
  };
395
416
  const routeExpectedBuyAmount = (route, decimals) => {
396
417
  if (!route.expectedBuyAmount) {