Road to 4337: Understanding Entrypoint and UserOp Calldata

Pre-Reeds (<5 min)

Aditya Agarwal
JiffyLabs
4 min readMay 17, 2023

--

If you’re new to Account Abstraction or 4337, I recommend reading these first:

I assume you know what smart contracts are and how an EOA triggers a smart contract function.

Introduction

Since Eth Denver in Feb’23, crypto Twitter has gone gaga over Account Abstraction and EIP-4337’s impact on the EVM ecosystem.

After talking with multiple web3 devs and mentoring teams at ETH Tokyo Hackathon, we realized it’s taking a good chunk of time and effort to grasp the basic concepts of 4337, causing delays in people getting their hands dirty.
We’re here to create easy-to-grasp material, with no fluff or annoying tech jargon, at least not without clarifying it in an easy-to-understand manner.

So let’s get started.

Overview

Anyone wishing to build on 4337, first needs to understand the actual data submitted for a 4337 transaction. This post is dedicated to achieving the same.

The tutorial is basically split into two sections:

  1. Understanding the data fields representing an individual User Operations (UserOp)
  2. Understanding the metadata (bundle) representing the actual on-chain transaction

Sample Reference Transaction

We will refer to the transaction (aka bundle) 0x7ed2…204 submitted to the Polygon chain on 15th May. We chose this bundle as it has more than 1 userOp and paymasters are used.
Explore it on PolyScan or On JiffyScan.

  1. 0xfa44f8d690560a97b5dac43487ce98773a11c26dce6fd5fb3891ba6251d553e5
  2. 0xd44c9f908422e79552878f25121a8801dcbdf0819a761d269ee337954d1debc9

The two UserOp Hashes in the bundle are:

Now let me show you how to understand a 4337 transaction.

Breaking down Calldata

The calldata, in simple terms, is the input parameters of a blockchain transaction. UserOp is an abstract transaction, i.e., it is not natively understood by the EVM chain. Rather certain sub-fields passed in the actual blockchain transaction are recognized as UserOps by the entrypoint smart contract and smart contract wallets (SCWs).

A single blockchain transaction to the entrypoint contract can contain 1 or more UserOps. Each UserOp is independent of the others in a transaction and its success or failure doesn’t depend on the ones preceding it or the ones after it.

A simplified flow of an UserOp in 4337

Thus, it would be fair to say that a UserOp is the atomic unit of 4337. Now, let's dissect it further.

UserOp Fields

UserOp is the individual operation a smart contract wallet executes. We’ll first understand its fields and their purpose and then see the value from actual UserOperations.

In the latest release of 4337 ( v0.6), the entrypoint requires a UserOperation with the following fields:

struct UserOperation {
address sender;
uint256 nonce;
bytes initCode;
bytes callData;
uint256 callGasLimit;
uint256 verificationGasLimit;
uint256 preVerificationGas;
uint256 maxFeePerGas;
uint256 maxPriorityFeePerGas;
bytes paymasterAndData;
bytes signature;
}

The fields are officially defined in EIP-4337. Though we’ll like to represent them again here in slightly more friendly terms:

Description of UserOp Fields in 4337 (v0.6)
Description of UserOp Fields in 4337 (v0.6)

You can see the calldata values for each UserOp on the JiffyScan Explorer by going down to the developer details and expanding the row:

Calldata for UserOp Hash 0xfa4…3e5

Understanding Bundle

The Bundle represents a single on-chain transaction, containing one or more UserOps. It is a typical on-chain EVM transaction invoking the handleOps() function of the entrypoint smart contract and is usually triggered by EOA. A bundler generally does this, in order to first validate the correctness of a UserOp, and to package multiple UserOps from different users into one to save gas costs. Though it could be as simple as an EOA invoking the function directly with the required calldata.

As the 4337 matures & picks up adoption, the bundler is expected to sponsor gas on behalf of multiple UserOps in a single bundle. During the execution of a bundle, the entrypoint contract collects the promised gas fee from SCW or sponsoring paymaster and holds it during execution of the bundle. At the end of the bundle, all the gas fee collected from the UserOps is transferred to an address the bundler specifies.

parameters for handleOps() function of the entrypoint
The calldata fields for a Bundle

Let’s see what happened in our reference bundle above:

4337 Bundle Internal Txns as shown on polyscan
4337 Bundle Internal Txns as shown on polyscan

Here, there are two UserOps, both successful shown by the first two transfer calls of 0.2 MATIC and 0.18 MATIC respectively. Then there’s a third internal transaction transferring 0.17699 MATIC to the beneficiary, which, in this case, is the Stackup’s bundler itself.

What’s Next

Try submitting a UserOp yourself. Resources listed at awesome-account-abstraction can help you explore further.

Remember you can use the JiffyScan interface to share your UserOps with your friends and community.

Also, if you need real-time data on 4337, do check out our leading API.

We will be releasing more deep dives, walkthroughs, and quickstart tutorials for 4337 regularly in the coming weeks. Follow me on Twitter or JiffyScan to stay updated.

Originally published at https://docs.jiffyscan.xyz on May 17, 2023.

--

--