Sync/upstream 2026 07#79
Conversation
…xact_gasfree Add servers/multi-scheme: an Express resource server that accepts EVM exact, TRON exact, and TRON exact_gasfree payments on one endpoint. Wires the two existing facilitators (basic :4022, gasfree :4032); the resource server routes verify/settle by (network, scheme) via /supported from each. Adds dev script, README, and .env-multi-scheme.example.
…ACILITATOR_URL Use a comma-separated FACILITATOR_URL for all facilitators instead of two separate env vars; the resource server still routes by (network, scheme) via /supported from each.
Port 7 upstream commits from @x402/* to @bankofai/x402-*: 1. 04860337 — authorization_value_mismatch error (EVM + legacy) 2. a3ad102b — MCP cross-SDK interop: null field normalization + parsePaymentRequired 3. 59ac597d — dynamicInfoFields for extension echo validation 4. 4cba2622 — EVM wallet compatibility: strict signature verification (EOA/ERC-1271/ERC-6492/ERC-7702), counterfactual deposit support 5. f4c532e8 — validAfter time-window correction (EVM + Tron) 6. 8f22db34 — Retry-After regex fix 7. 266b19d2 — validateFacilitatorSupport hook + optional authorizerSigner (EVM + Tron) Tests: core 516/517 (1 pre-existing network failure), EVM 747/747, Tron 152/152, MCP 99/99, extensions 471/471.
Format 17 files across core, mcp, evm, tron packages to pass the format quality gate.
Format settle.ts, exact/server/scheme.ts, upto/server/scheme.ts to pass the format quality gate.
…ent examples The upto and batch-settlement facilitators were missing EVM_RPC_URL support that the exact facilitator already had, causing EVM verify/settle to fail with ECONNREFUSED when viem's default BSC testnet endpoint was unreachable.
SDK (tron package): - constants.ts: add Shasta to PERMIT2_ADDRESSES, X402_PERMIT2_PROXY_ADDRESSES, X402_UPTO_PERMIT2_PROXY_ADDRESSES - batch-settlement/constants.ts: add Shasta to BATCH_SETTLEMENT_ADDRESSES, ERC3009_DEPOSIT_COLLECTOR_ADDRESSES, PERMIT2_DEPOSIT_COLLECTOR_ADDRESSES - tokens.ts: set Shasta USDT to permit2 (was eip3009); update comments - tokens.test.ts: update Shasta assertions to match permit2 Examples: - Replace all hardcoded tron:0x... CAIP-2 IDs with SDK-exported TRON_NILE / TRON_MAINNET / TRON_SHASTA constants (28 files) - Add TRON_SHASTA to multi-network arrays (exact trio) - Make single-network scenarios env-switchable via TRON_NETWORK env var (upto, batch, gasfree, mcp, multi-scheme) - Convert flat TOKEN_ADDRESSES to nested by-network structure (upto, batch, mcp clients); add Shasta USDT entry - servers/express: tronAccepts() now dynamically lists tokens per network via getNetworkTokens() instead of hardcoding USDT+USDD - .env-*.example: document all available TRON networks (Nile/Shasta/Mainnet) and add TRON_NETWORK env var hint for single-network scenarios Tested on Shasta: exact, upto, batch-settlement scenarios all pass.
Replace hardcoded USDT+USDD with dynamic getNetworkTokens() lookup, matching the fix already applied to servers/express. Fixes 500 error on networks without USDD (e.g. Shasta).
Remove the external facilitator service-fee (feeConfig) configuration across exact/upto/gasfree schemes, along with the shared/fee.ts module and its FeeInfo/ExactTronFeeConfig exports. The GasFree provider-driven fees (transferFee, activateFee, relayer provider selection and provider-list validation) are preserved. BREAKING CHANGE: TronFacilitatorConfig.fee, TronGasFreeFacilitatorConfig.fee, the upto facilitator feeConfig constructor parameter, and the FeeInfo / ExactTronFeeConfig type exports are removed. Upgrade requires a major version.
filterAffordableRequirements only checked req.amount, but GasFree deducts amount + maxFee (transferFee + activateFee). Add an optional estimateCost method to BalanceCheckable; the GasFree client implements it by reusing computeMaxFee so options whose balance covers amount but not amount + fee are excluded before selection instead of failing later in createPaymentPayload. Also applies prettier formatting to the fee-removal files flagged by CI.
matrix-agent116
left a comment
There was a problem hiding this comment.
Summary
This is a substantial upstream synchronization with useful interoperability, wallet-compatibility, and TRON network updates. However, the new counterfactual batch-deposit verification can accept reverted simulations, and the example network-selection changes contain regressions, so I’m requesting changes before merge.
Required improvements
- Blocker: Inspect the results returned by the counterfactual ERC-6492 batch-deposit multicall.
tryAggregate(false, ...)reports individual reverts as failure entries rather than throwing, so the current function returns success even when deployment or deposit simulation failed. - Blocker: Key custom GasFree API URLs by the selected
TRON_NETWORKin both the client and facilitator. The current Nile-only map replaces the complete defaults map and leaves Shasta/mainnet without a configured client when an override is supplied. - Blocker: Preserve documented family-prefix targets such as
tron@USDTandeip155@USDC, or remove those shortcuts from the documentation. The new network-indexed lookup currently leaves such symbols unresolved in the batch-settlement, MCP, and upto clients. - Add regression coverage for failed multicall entries, non-Nile GasFree overrides, and family-prefix token targets.
- Remove the newly introduced unused imports and provide the PR’s test/lint results in the description before the next review.
| callData: depositCallData, | ||
| }, | ||
| ]); | ||
| return true; |
There was a problem hiding this comment.
[blocker] Please check both results returned by multicall before returning success. The helper calls tryAggregate(false, ...), so a reverted factory deployment or deposit is returned as { status: "failure" } without rejecting the promise; as written, any normally returned result array reaches return true, allowing an invalid counterfactual deposit to pass verify. Require successful deployment and deposit entries, and add tests for each failure case.
| ? { schemeOptions: { apiBaseUrls: { "tron:0xcd8690dc": process.env.GASFREE_API_URL } } } | ||
| ? { | ||
| schemeOptions: { | ||
| apiBaseUrls: { [TRON_NILE]: process.env.GASFREE_API_URL }, |
There was a problem hiding this comment.
[blocker] This override must be keyed by TRON_NETWORK, not always TRON_NILE. Supplying GASFREE_API_URL replaces the SDK’s complete default URL map with this one-entry map; when TRON_NETWORK selects Shasta or mainnet, getApiClient therefore has no entry for the payment network. The facilitator has the same issue in its apiBaseUrls override and should be updated together.
| function resolveToken(token: string): string { | ||
| return TOKEN_ADDRESSES[token.toUpperCase()] ?? token; | ||
| function resolveToken(prefix: string, token: string): string { | ||
| return TOKEN_ADDRESSES[prefix]?.[token.toUpperCase()] ?? token; |
There was a problem hiding this comment.
[blocker] The documented family shortcuts no longer work when a token symbol is included. For example, tron@USDT looks up TOKEN_ADDRESSES["tron"], falls back to the literal string USDT, and later compares that string with an advertised asset address, so no option matches. Please resolve a family prefix against the matching configured networks (with ambiguity handled explicitly), or require a full network whenever a symbol is supplied and update the documentation. The same new lookup appears in the MCP and upto clients.
| import { getAddress, encodeFunctionData } from "viem"; | ||
| import { parseErc6492Signature, isAddressEqual } from "viem"; | ||
| import { FacilitatorEvmSigner } from "../../signer"; | ||
| import { verifyTypedDataSignature } from "../../shared/verifySignature"; |
There was a problem hiding this comment.
[nit] verifyTypedDataSignature is imported here but is not referenced in this file; isContractRevert on line 19 is also unused. Please remove both imports because this package’s ESLint configuration treats unused variables/imports as errors.
upto is permit2-only (no EIP-3009 path), so facilitatorAddress and permit2FacilitatorAddress were always identical. Remove the redundant field and its fallback reads across facilitator/client/server; keep only permit2FacilitatorAddress.
Resolve fee-removal conflicts by taking ours (full GasFree fee removal). Adopt main's requirementsWithoutFee fee-stripping in exact/upto servers, advisory-fee-removal tests, README/changeset fixes, and signer-wallet naming. Fix README and changeset to reflect GasFree fee also removed.
- Check multicall results in counterfactual ERC-6492 deposit simulation: tryAggregate(false) returns failure entries without throwing, so verify each result is successful instead of unconditionally returning true - Key GASFREE_API_URL override by TRON_NETWORK instead of hardcoded TRON_NILE in both client and facilitator, so non-Nile networks resolve - Require full CAIP-2 network when a token symbol is specified in PAY_TARGETS across batch-settlement, upto, mcp, and fetch clients; family prefixes (e.g. tron@USDT) now error with a clear message - Remove unused verifyTypedDataSignature and isContractRevert imports

Description
Tests
Checklist