Integrate MegaFuel with an ERC-4337 Wallet
Integrate MegaFuel with an ERC-4337 Wallet
This guide shows the wallet-side sequence for a MegaFuel-sponsored UserOperation. MegaFuel signs the paymaster authorization; the wallet still builds the UserOperation and creates the smart-account signature.
Endpoints
# Mainnet (chain ID 56 / 0x38)
PAYMASTER_URL=https://bsc-megafuel.nodereal.io/4337/paymaster
BUNDLER_URL=https://bsc-megafuel.nodereal.io/4337/bundler
# Testnet (chain ID 97 / 0x61)
PAYMASTER_URL=https://bsc-megafuel-testnet.nodereal.io/4337/paymaster
BUNDLER_URL=https://bsc-megafuel-testnet.nodereal.io/4337/bundlerAll requests are JSON-RPC 2.0 HTTPS POST requests with Content-Type: application/json.
Integration sequence
- Choose one EntryPoint returned by
eth_supportedEntryPoints. - Build the UserOperation with the sender, nonce, account call, fee fields, and factory information if the account is counterfactual.
- Call
pm_getPaymasterStubData. - Put the returned stub paymaster fields into the operation and attach a structurally valid dummy account signature for estimation.
- Call
eth_estimateUserOperationGason MegaFuel's Bundler and use its gas limits. - Call
pm_getPaymasterDatawith the final gas fields. It performs the policy check and returns short-lived, signed paymaster data. - Put the final paymaster fields into the operation, calculate the EntryPoint-specific UserOperation hash, and obtain the account signature according to your account's
validateUserOprules. - Submit the final operation with
eth_sendUserOperation. - Poll
eth_getUserOperationReceiptandnr_getUserOperationStatusuntil a terminal result is known.
Do not alter fields covered by the account or paymaster authorization after the final paymaster response. If a field changes, restart at paymaster-data requesting and sign the new UserOperation hash.
1. Discover supported EntryPoints
{
"jsonrpc": "2.0",
"id": 1,
"method": "eth_supportedEntryPoints",
"params": []
}Send this request to BUNDLER_URL. The returned address determines the version and JSON encoding to use.
2. Build the v0.7 / v0.8 operation
For v0.7 and v0.8, use the packed-family JSON fields. All quantities are hex-encoded quantities and all byte arrays are 0x-prefixed hex.
{
"sender": "0x<SMART_ACCOUNT>",
"nonce": "0x0",
"factory": "0x<FACTORY>",
"factoryData": "0x<CREATE_ACCOUNT_CALLDATA>",
"callData": "0x<SMART_ACCOUNT_EXECUTE_OR_EXECUTE_BATCH_CALLDATA>",
"maxFeePerGas": "0x<MAX_FEE_PER_GAS>",
"maxPriorityFeePerGas": "0x<MAX_PRIORITY_FEE_PER_GAS>",
"signature": "0x<DUMMY_OR_FINAL_ACCOUNT_SIGNATURE>"
}Omit factory and factoryData for an already deployed account. This is the recommended pre-estimation shape: omit the three account gas fields and use the returned estimates later. Do not send 0x0 as a final gas limit.
v0.6: use a distinct unpacked operation
EntryPoint v0.6 does not use the v0.7/v0.8 packed-family fields. Its Bundler operation must use this classic, unpacked shape:
{
"sender": "0x<SMART_ACCOUNT>",
"nonce": "0x0",
"initCode": "0x<20_BYTE_FACTORY_ADDRESS><CREATE_ACCOUNT_CALLDATA>",
"callData": "0x<SMART_ACCOUNT_EXECUTE_CALLDATA>",
"maxFeePerGas": "0x<MAX_FEE_PER_GAS>",
"maxPriorityFeePerGas": "0x<MAX_PRIORITY_FEE_PER_GAS>",
"paymasterAndData": "0x<20_BYTE_PAYMASTER_ADDRESS><PAYMASTER_DATA>",
"signature": "0x<DUMMY_OR_FINAL_ACCOUNT_SIGNATURE>"
}For an already deployed account, set initCode to 0x. initCode is the factory address followed immediately by the factory calldata; it is not the separate factory / factoryData representation used by v0.7/v0.8.
Use the normal MegaFuel paymaster RPC calls to obtain stub and final paymaster data. When a counterfactual v0.6 account needs deployment, provide the equivalent factory and factoryData values to those paymaster calls. For the v0.6 Bundler calls, convert them back to initCode as shown above.
For eth_estimateUserOperationGas and eth_sendUserOperation, build paymasterAndData exactly as:
paymasterAndData = paymaster (20 bytes) || paymasterDataUse stub paymasterData for estimation and final paymasterData for submission. Do not include v0.7/v0.8's two 16-byte paymaster gas-limit fields in v0.6 paymasterAndData; those fields do not exist in EntryPoint v0.6. Compute the UserOperation hash with the v0.6 EntryPoint over this unpacked tuple, then sign it using the signature scheme required by the selected account implementation.
Batch call encoding
For a standard SimpleAccount batch, use exactly:
executeBatch(address[] targets, uint256[] values, bytes[] calldatas)The arrays are aligned by index. MegaFuel decodes each inner target and calldata;
all inner calls must satisfy the same one public policy. A batch cannot combine
permissions from multiple policies.
3. Obtain stub paymaster data
Call the paymaster endpoint before estimating gas:
{
"jsonrpc": "2.0",
"id": 2,
"method": "pm_getPaymasterStubData",
"params": [
{
"sender": "0x<SMART_ACCOUNT>",
"nonce": "0x0",
"callData": "0x<ACCOUNT_CALLDATA>",
"maxFeePerGas": "0x<MAX_FEE_PER_GAS>",
"maxPriorityFeePerGas": "0x<MAX_PRIORITY_FEE_PER_GAS>",
"signature": "0x<DUMMY_ACCOUNT_SIGNATURE>"
},
"0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108",
"0x38",
{}
]
}For Testnet, use chain ID 0x61. Replace the EntryPoint with the selected v0.7 or v0.6 address as applicable.
The response has this shape:
{
"paymaster": "0x<MEGAFUEL_PAYMASTER>",
"paymasterData": "0x<STUB_DATA>",
"paymasterVerificationGasLimit": "0x...",
"paymasterPostOpGasLimit": "0x..."
}For v0.7/v0.8, copy the response to the matching separate operation fields. The stub is only for simulation/estimation; it is not a usable sponsorship authorization.
4. Estimate gas
Submit the stub-filled operation to the Bundler:
{
"jsonrpc": "2.0",
"id": 3,
"method": "eth_estimateUserOperationGas",
"params": [
{
"sender": "0x<SMART_ACCOUNT>",
"nonce": "0x0",
"callData": "0x<ACCOUNT_CALLDATA>",
"maxFeePerGas": "0x<MAX_FEE_PER_GAS>",
"maxPriorityFeePerGas": "0x<MAX_PRIORITY_FEE_PER_GAS>",
"paymaster": "0x<MEGAFUEL_PAYMASTER>",
"paymasterVerificationGasLimit": "0x<STUB_PM_VERIFICATION_GAS>",
"paymasterPostOpGasLimit": "0x<STUB_PM_POSTOP_GAS>",
"paymasterData": "0x<STUB_DATA>",
"signature": "0x<DUMMY_ACCOUNT_SIGNATURE>"
},
"0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108"
]
}Use the returned callGasLimit, verificationGasLimit, and preVerificationGas. Also use returned paymaster gas limits when present. The service signs the final paymaster authorization over the relevant operation fields, so do not substitute arbitrary larger limits after the final request.
5. Obtain final paymaster data
Call pm_getPaymasterData with the estimated gas fields and the same selected EntryPoint and chain ID.
{
"jsonrpc": "2.0",
"id": 4,
"method": "pm_getPaymasterData",
"params": [
{
"sender": "0x<SMART_ACCOUNT>",
"nonce": "0x0",
"callData": "0x<ACCOUNT_CALLDATA>",
"callGasLimit": "0x<ESTIMATED_CALL_GAS>",
"verificationGasLimit": "0x<ESTIMATED_VERIFICATION_GAS>",
"preVerificationGas": "0x<ESTIMATED_PREVERIFICATION_GAS>",
"maxFeePerGas": "0x<MAX_FEE_PER_GAS>",
"maxPriorityFeePerGas": "0x<MAX_PRIORITY_FEE_PER_GAS>",
"paymasterVerificationGasLimit": "0x<ESTIMATED_PM_VERIFICATION_GAS>",
"paymasterPostOpGasLimit": "0x<ESTIMATED_PM_POSTOP_GAS>",
"signature": "0x<DUMMY_ACCOUNT_SIGNATURE>"
},
"0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108",
"0x38",
{}
]
}Success returns paymaster, final paymasterData, and the two paymaster gas limits. An error means MegaFuel will not sponsor the operation; nothing has been sent to the chain. Show a useful error to the user or use an alternative, user-paid path when your product supports one.
6. Sign and send
Set the final paymaster fields, calculate getUserOpHash using the selected EntryPoint's exact version, and obtain the account signature. Do not use a generic signing method unless that is precisely what your smart account's validateUserOp expects.
Then call:
{
"jsonrpc": "2.0",
"id": 5,
"method": "eth_sendUserOperation",
"params": [
{ "...": "complete signed UserOperation" },
"0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108"
]
}The result is a userOpHash, not an Ethereum transaction hash. Store it with the user action so that the wallet can recover status later.
Account-signature compatibility matrix
The EntryPoint computes a version-specific UserOperation hash, but it does not
dictate the smart-account signature encoding. validateUserOp on the selected
account contract is authoritative.
| Reference setup | EntryPoint family | Signature over the UserOperation hash | Scope |
|---|---|---|---|
| MegaFuel MiniAccount test fixture | v0.8 | raw secp256k1 signature | Test fixture only |
| MegaFuel reference SimpleAccount test setup | v0.6, v0.7 | EIP-191 personal_sign style signature of the 32-byte hash | Reference setup only |
| Third-party account | any | Whatever its validateUserOp verifies | Must be verified on Testnet |
Do not infer a third-party account's signing method from its EntryPoint version.
The SimpleAccount reference client
makes the choice explicit as SIGNATURE_MODE=raw or SIGNATURE_MODE=eip191.
Use the mode that your deployed account verifies, then prove it with a Testnet
submission before production.
7. Track completion
Poll the Bundler endpoint:
{
"jsonrpc": "2.0",
"id": 6,
"method": "eth_getUserOperationReceipt",
"params": ["0x<USER_OP_HASH>"]
}null means the UserOperation is not yet included, but cannot by itself distinguish queued work from a terminal non-inclusion. Query nr_getUserOperationStatus at the same time. A non-null receipt includes the transactionHash, blockNumber, success, actualGasCost, sender, and paymaster. Use eth_getUserOperationByHash when you need the full submitted operation and its current outer transaction reference.
Multi-operation nonce handling
Use the EntryPoint's UserOperation nonce—not the owner EOA's transaction nonce. For multiple pending operations from one smart account and nonce key, query MegaFuel's optional nr_getPendingUserOperationNonce extension, then submit promptly. The returned value is a point-in-time queue view, not a reservation; handle a conflict by re-querying and rebuilding the UserOperation. See the RPC reference.
Updated 17 days ago

