Are you confident in accurately reporting cryptocurrency earnings on your tax returns?

From Envelope to Letter: Recovering Intent in ERC-4337

Share article

ERC-4337 changes how transactions appear on-chain. Learn how we decode UserOperations, unwrap smart wallet calls, and recover the real DeFi action.

From Envelope to Letter: Recovering Intent in ERC-4337

If you’ve looked at a block explorer lately and thought, “why does every transaction interact with EntryPoint?” Same. If you use Coinbase Wallet, you’re already using a smart contract wallet. (New to this? See the key terms in the appendix below.)

ERC-4337 routes wallet actions through a shared EntryPoint. That shift hides the real DeFi call one layer deeper, so we rebuilt our pipeline to peel back the envelope and recover the actual intent.

This post is the story of how we stopped staring at the envelope and started reading the letter.

The day our dashboards went quiet

Nothing was down, but something was off. As Coinbase Smart Wallet users made up a larger share of our transaction volume, we noticed something strange. We had always thought the top-level transaction pointed to the DeFi contract the user wanted to interact with. Suddenly, everything connected to the EntryPoint, and the actual swap or borrow happened one layer deeper.

Transactions that used to point straight at a DeFi smart contract now pointed at EntryPoint.handleOps. Inside were a bundle of UserOperations [1] the chain had faithfully executed, but only after a smart wallet forwarded the real call somewhere else.

We no longer saw the actual protocol interaction at the top level.

To get ahead of it, we started by asking ourselves:

What would it take to reliably recover the user’s actual intent at scale and why does it matter? Without the answer, we'd be showing users "EntryPoint interaction" on their tax report instead of "swap" and calculating cost basis against the wrong transaction.

Evolving from key pairs to smart contract execution with ERC-4337

An Ethereum wallet is, at its core, a private key and the addresses it controls. For most of Ethereum's history, that has been the whole story: one signer per address, one transaction per action, gas paid in ETH. The native account model does not support recovery, spending limits, or third-party fee sponsorship. This is not a design flaw so much as a constraint of how accounts were originally built, and it has quietly kept the barrier to entry high.

That constraint now has a name for its solution: account abstraction. The core idea is to decouple transaction execution from the private key itself, allowing the account to define its own rules for validation, gas payment, and call routing. In practice, this means wallets can support biometric authentication, batch multiple actions into a single transaction, and let apps sponsor transaction fees on behalf of users.

ERC-4337 is one of the standards that formalizes how this works on-chain. Instead of signing a transaction that interacts directly with a DeFi contract, users now sign a UserOperation [1], which is a structured request describing their intended action. A bundler [3], which submits UserOperations on-chain, picks up the request and sends it to a shared EntryPoint [2] contract. This is the single entry point for all ERC-4337 transactions. The EntryPoint checks the request and calls the user’s smart contract account (SCA) [5], a wallet designed as a smart contract that handles actions internally. The SCA then forwards the actual call to the destination, for example a swap on Uniswap. Users can also engage an optional Paymaster [4], a contract that can cover or collect gas fees. This allows users to pay fees in ERC-20 tokens or not pay anything at all.

Here’s why this is important for analytics:

  • The real actions are hidden. The chain only indicates that “EntryPoint was called.” What we really want to know is, “Uniswap swapped token A for token B.”
  • Batches are common. One UserOperation can include multiple calls. If you collapse them, you lose important details.
  • Gas fees have become more flexible. Paymasters can cover gas or allow users to pay in ERC-20 tokens, but the EntryPoint still settles in ETH. If you treat those flows as regular transfers, your profit and loss can quickly become confusing.

1) Top-level vs. underlying interaction: taking the letter out of the envelope

What changes on-chain

With ERC-4337, the visible transaction hits the EntryPoint. The user’s intent lives in each UserOperation’s callData (the fourth argument). Smart contract accounts then forward that intent to other contracts, commonly through execute or executeBatch patterns. Exact calls vary by implementation.

Example:

A user wants to swap USDC → WETH.

  1. The user signs a UserOperation with that intent.
  2. A bundler submits it to the EntryPoint.
  3. The EntryPoint validates and executes the UserOperation against the smart wallet.
  4. The wallet forwards the real call to the actual DeFi contract, for example Uniswap's router.

The important part is not the EntryPoint transaction. It is the downstream call or calls that reflect what the user actually wanted to do.

How we handle it

We see the EntryPoint as an envelope and read the letter inside. We find out which UserOperations belong to the wallet we are examining, unwrap the forwarded calls, decode each one’s function, and classify the action (swap, borrow, repay, etc.).

TL;DR: instead of saying “EntryPoint was called,” our metadata shows “Swap USDC to WETH on Router X.” This allows CoinTracker to properly classify this as a USDC disposal and a WETH acquisition, with the right cost basis, which is important for tax purposes.

Diagram: end-to-end flow

End-to-end flow diagram

2) Batches: extracting the primary action

What changes on-chain

Batches are common. A UserOperation can forward multiple calls in sequence. For example, a swap typically requires an approval followed by the actual swap call. Smart contract accounts implement different forwarding patterns. Examples include execute(address, value, bytes) for single calls, executeBatch(address[], value[], bytes[]) for multiple calls, and various module-based patterns.

How we handle it

Primary action heuristic

When a UserOperation includes several forwarded calls [6], the internal calls the smart wallet makes to execute the user's intent, we identify the call that best reflects the user’s desired outcome. In most wallet setups today, this is the last forwarded call, since earlier calls usually involve setup or preparation steps. Using the final call’s destination contract and function, we categorize the overall action as a swap, add liquidity, borrow, repay, or another DeFi primitive.

Limitations

This approach works well for the majority of current patterns, but it is not perfect. Some smart wallets interleave logic or batch actions that do not neatly separate into “setup” and “primary” steps. In those cases, relying solely on the final call can oversimplify the underlying flow. A more granular approach is on our radar as the ecosystem matures.

Visual: one transaction, multiple UserOps and calls:

3) From “you pay ETH” to “who pays, with what?”

What changes on-chain

Before ERC-4337, gas on EVM chains was simple. For every transaction, the sender paid in the native token (ETH, POL, etc.) and needed that balance up front.

Execution still settles in ETH, but it changes the experience. A Paymaster can sponsor or front the cost, so fees become a policy decision.

  • Who pays? The user, the dapp, the wallet, or a third-party sponsor.
  • What do they “pay” with? Potentially an ERC-20 the user already holds, or $0 to the user if it is fully sponsored.

In practice, the Paymaster handles ETH settlement with the EntryPoint and may bill the user in tokens, apply credits or coupons, or absorb the cost for a promotion.

Aside: Why this matters for product and UX

Coinbase Wallet currently accounts for about 60% of all ERC-4337 activations. Since they are such a large player, this standard is now a reality for many mainstream users, making it essential to support. Users do not need to hold ETH to get started. They can pay fees with tokens they already have or avoid fees altogether when a dapp covers the transaction costs. This also opens up opportunities for builders, such as gas-free promotions, metered sponsorships for frequent users, and B2B workflows where an employer handles the expenses.

How we handle it

To correctly attribute value flows, we treat EntryPoint and Paymaster interactions as fees, not transfers. We record the asset that actually left the user’s wallet, whether that is USDC, ETH, or another ERC-20, while keeping the underlying ETH settlement visible at the protocol layer.

In practice, this looks like:

  • In-app representation:
    • “Fee: 10 USDC” (user pays the Paymaster in USDC), or
    • “Fee: 0.001 ETH” (user pays natively).
  • On-chain reality: The EntryPoint still settles in ETH.
  • Our modeling: We tag Paymaster and EntryPoint flows as fees and keep the user-facing fee asset accurate.

Diagram: fee flow

Parting thoughts

Once you peel back the envelope and model batches and fees correctly, you get back to the same core questions:

What did the user do, where did the assets move, and how much did it cost?

ERC-4337 will not be the last protocol shift that reshapes how transactions look on the surface. We are already thinking about what comes next.

Appendix: Key Terms

[1] UserOperation

A structured request containing a user’s intended action. It does not appear on-chain directly but determines what the wallet will execute internally.

[2] EntryPoint

The shared contract that processes UserOperations. Almost every ERC-4337 transaction appears as a call to this contract, which hides the actual DeFi call under it.

[3] Bundler

The actor that submits UserOperations on-chain. Bundling means many actions share a single top-level EntryPoint transaction.

[4] Paymaster

An optional component that sponsors or charges for gas. It shifts fee flows away from the simple “sender pays ETH” model.

[5] Smart contract account (SCA)

A wallet implemented as a smart contract. Since SCAs route actions internally, the top-level transaction no longer points to the final destination contract.

[6] Forwarded calls

The internal calls the smart contract wallet performs to carry out the user’s intent. These are the calls your analytics need to extract and interpret.

Related posts