Skip to content

ERC4337 Integration with SBC

What is ERC4337?

ERC4337 is the Account Abstraction standard for Ethereum that enables smart contract wallets to function like EOAs (Externally Owned Accounts) without requiring changes to the Ethereum protocol. This standard introduces several key components:

  • UserOperation: A data structure that represents a user's intent to perform an action
  • Bundler: A service that bundles multiple UserOperations and submits them to the blockchain
  • Paymaster: A contract that can sponsor gas fees for users
  • EntryPoint: A singleton contract that verifies and executes UserOperations

SBC's Custom Implementation

Stable Coin Inc has developed a custom bundler and paymaster implementation optimized for the Base network. Our implementation enables:

  1. Gasless Transactions: Users can perform transactions without having ETH for gas
  2. Batch Transactions: Multiple actions can be combined into a single transaction
  3. Account Abstraction: Smart contract wallets can be used as primary accounts

Architecture

See Architecture

SBC Bundler

Our custom bundler service:

  • Accepts UserOperations from clients
  • Validates operations according to ERC4337 specification
  • Bundles compatible operations together
  • Submits bundles to the EntryPoint contract on-chain (v0.7)

SBC Paymaster

Our custom paymaster:

  • Verifies that operations meet SBC's criteria for sponsorship
  • Signs operations that qualify for gasless execution
  • Manages gas sponsorship for different use cases

Integration Quickstart

Here's the fastest way to integrate with our ERC4337 infrastructure, using viem and permissionless.

Basic usage using SimpleAccount:

import { Address, createWalletClient, custom, http, Chain, PublicClient } from 'viem';
import { base, baseSepolia } from "viem/chains";
import { entryPoint07Address, UserOperation, createPaymasterClient } from "viem/account-abstraction";
import { toSimpleSmartAccount } from "permissionless/accounts";
import { createSmartAccountClient } from "permissionless";
 
// create a client for your connected wallet
const owner = createWalletClient({
  account: "0x..." as Address, // your wallet address
  chain: base, 
  transport: custom((window as any).ethereum),
});
 
// create a public client for reading onchain
const publicClient = createPublicClient({
  chain: base,
  transport: http("https://base-rpc.publicnode.com"), // or your custom rpc
}) as PublicClient;
 
// Create a SimpleAccount with your wallet as owner
const simpleAccount = await toSimpleSmartAccount({
  client: publicClient,
  owner: owner,
  entryPoint: {
    address: entryPoint07Address,
    version: "0.7",
  },
});
 
function getAccountAbstractionApiUrl(chain: Chain) {
  switch (chain.id) {
    case base.id:
      // Reach out to us on Telegram for the Paymaster API Key
      return `https://api.aa.stablecoin.xyz/rpc/v1/base/${SBC_PAYMASTER_API_KEY}`;
    default:
      return `chain ${chain.name} not supported`;
  }
}
 
// Create a Paymaster client from the SBC Paymaster
const paymaster = createPaymasterClient({
  transport: http(getAccountAbstractionApiUrl(base)), 
});
 
// Package it into one Smart Account Client
const smartAccountClient = createSmartAccountClient({
  account: simpleAccount,
  chain: base,
  bundlerTransport: http(getAccountAbstractionApiUrl(base)),
  paymaster,
  userOperation: {
    estimateFeesPerGas: async () => {
      return {
        maxFeePerGas: 10n,
        maxPriorityFeePerGas: 10n,
      };
    },
  },
});
 
// Encode your User operation
// ...
// const calls = [
//   {
//     to: "0x..." as Address,     // your target contract or EOA address
//     data: <yourEncodedCallData> as Hex // encoded data of your user op
//   },
//   {
//     to: "0x..." as Address,
//     data: <yourEncodedCallData> as Hex
//   }
// ];
 
// Send the user operation with your Smart Account Client
const userOpHash = await smartAccountClient.sendUserOperation({ calls });
const receipt = await smartAccountClient.waitForUserOperationReceipt({
  hash: userOpHash,
});
 
console.log(`Your user op hash: ${receipt.userOpHash}`);

For more examples, see Smart Account Implementations.

Next Steps

  • Reach out to us on Telegram to get your Bundler and Paymaster URL, as well as some SBC on testnet to try our demos.
  • Try our use cases: