Fix - Use EIP-5792 sendCalls for dataSuffix attribution on Base App / Coinbase Wallet#42
Conversation
…inbase Wallet - Gate EIP-5792 path on wallet_getCapabilities (useCapabilities) so only wallets that advertise dataSuffix support take this path; MetaMask and other EOA wallets fall back to writeContractAsync + dataSuffix unchanged - Use useWalletClient (wallet provider transport) for waitForCallsStatus instead of useClient (PublicClient / mainnet.base.org) which rejected wallet_getCallsStatus with MethodNotFoundRpcError - Guard walletClient null-check before writeContractsAsync to prevent broadcasting a tx when the receipt cannot be retrieved - Add !capabilitiesPending guard to avoid silently falling through to EOA path while wallet_getCapabilities is still in-flight - Use !!chainCapabilities?.dataSuffix instead of "dataSuffix" in obj to avoid truthy match on null/false values - Remove dead hook scaffolding (useState id, useSendCalls, useCallsStatus, contractStatus effect) that was permanently disabled - Add 120s timeout to waitForCallsStatus to prevent infinite hang
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9fee8f60fe
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Review — EIP-5792 dataSuffix attributionReviewed via two independent passes (Claude + Codex), cross-checked against viem source ( Verdict: no P0 blocker — nothing here can silently lose funds on the happy path. But there are 4 P1 should-fixes, two of which are real money-moving risks on the failure paths. For a payments SDK I'd want #1 and #2 fixed before this ships to smart-wallet users. P1 — reverted batch is reported as a successful payment
Fix: gate on success before trusting the receipt, e.g. if (result.status !== 'success') throw new Error(`Batched call failed: ${result.status}`);
const hash = result.receipts?.[0]?.transactionHash;
if (!hash) throw new Error("No receipt from batched call");
return hash;(Per-receipt P1 — 120s timeout resets order to
|
- Updated `useWallets` to ensure mobile in-app browsers can connect to both EVM and Solana wallets. - Implemented fuzzy matching for `solanaConnectorName` in the mobile branch to allow seamless wallet selection. - Enhanced `ConnectorList` to initiate connections for both chains simultaneously, improving user experience on mobile devices.
…wser connection issues - Added guidance for non-Next.js / SPA apps on managing wallet connections without SSR. - Clarified the root cause and fix for the method picker issue in wallet in-app browsers. - Updated README to emphasize the need for cookie-persisted initial state for seamless wallet connections.
Review — EIP-5792 sendCalls for dataSuffix attribution on Base App / Coinbase WalletVerdict: APPROVE (no P0) — but two substantive P1s worth resolving before/right after shipping a payments release. I traced the fund-safety concerns (double-broadcast, null-check-before-broadcast, path exclusivity) and none can lose or double-spend funds within a single invocation:
P1 — should fix
P1 — verification hygiene
P2
No P0 blockers — approving per the no-P0 gate. Please still address P1 #1 (the |
shawnmuggle
left a comment
There was a problem hiding this comment.
Approved — no P0 blockers found. See the detailed review comment for P1/P2 follow-ups worth addressing.
Follow-up review — commit range
|
Summary
Base App and Coinbase Wallet use ERC-4337 smart contract accounts. The previous
writeContractAsync+dataSuffixapproach works for EOA wallets (MetaMask) but does not produce valid ERC-8021 attribution for ERC-4337 transactions — the suffix must be appended touserOp.callDatavia the EIP-5792wallet_sendCallspath.This PR gates the
writeContractsAsync(EIP-5792) path onwallet_getCapabilities— only wallets that advertisedataSuffixsupport (Base App, Coinbase Wallet) take this path. All other wallets fall back to the existingwriteContractAsync + dataSuffixpath unchanged.Changes Made
useCapabilities()to detect whether the connected wallet supports the EIP-5792dataSuffixcapability for the payment chainuseWalletClient()as the transport forwaitForCallsStatus— routeswallet_getCallsStatusthrough the wallet provider instead of the public RPC nodewriteContractsAsync(EIP-5792) path inpayWithTokenfor wallets that advertisedataSuffixcapability, with a 120s timeout guard!capabilitiesPendingto prevent a race where capabilities haven't resolved yet and a Base App user silently falls through to the EOA pathwalletClientnull-check beforewriteContractsAsyncto prevent broadcasting a transaction when the receipt can't be retrieveduseState id,useSendCalls,useCallsStatus,contractStatuseffect) that was permanently disabledHow to Test
dataSuffix/ builder code configured ingetDefaultConfig8021 Attributed ✅with your builder codeTesting Checklist
0xc13cae...)Reviewer Notes
waitForCallsStatusfromviem/actionsrequires a WalletClient (wallet provider transport), not a PublicClient. UsinguseClient()(PublicClient) was the original bug — it routedwallet_getCallsStatustomainnet.base.orgwhich rejected it withMethodNotFoundRpcError, identical to the MetaMask failure. Fixed by usinguseWalletClient().userOp.callData, not the outerhandleOpstx. Checking the Transaction hash on the attribution checker will show "Not attributed" — this is expected. Check the UserOperation (AA) hash instead.bc_mnipappearing alongside your builder code in on-chain data is Base App injecting its own attribution code — expected behavior, does not invalidate yours.Related