Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions gator-sidebar.js
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ const sidebar = {
items: [
'troubleshooting/error-codes',
'troubleshooting/invalid-delegate',
'troubleshooting/aa21-prefund',
],
},
],
Expand Down
100 changes: 100 additions & 0 deletions smart-accounts-kit/troubleshooting/aa21-prefund.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
---
description: How to resolve the AA21 didn't pay prefund error when submitting user operations.
sidebar_label: AA21 didn't pay prefund
keywords: [AA21, pay prefund, user operation, troubleshooting]
---

import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";

# AA21 didn't pay prefund

The `EntryPoint` contract reverts with `AA21 didn't pay prefund` when a smart account doesn't
have enough native token balance to cover the gas cost of the user operation.

Before executing a user operation, the `EntryPoint` requires the sender account to prefund the
expected gas cost. If the account's balance is lower than the required prefund, the `EntryPoint`
reverts the operation.

## Solution

### Fund the smart account

Fund the smart account with enough native tokens to cover the required prefund.
Use Viem's [`estimateUserOperationGas`](https://viem.sh/account-abstraction/actions/bundler/estimateUserOperationGas)
to get the gas estimates from your bundler, then calculate the required prefund based on the
`EntryPoint` version.

<Tabs>
<TabItem value="v0.7" label="EntryPoint v0.7">

```typescript
import { formatEther } from "viem";

const gasEstimate = await bundlerClient.estimateUserOperationGas({
account: smartAccount,
calls: [{ to: "0x...", value: 0n }],
});

const { maxFeePerGas } = await publicClient.estimateFeesPerGas();

const requiredGas =
gasEstimate.verificationGasLimit +
gasEstimate.callGasLimit +
(gasEstimate.paymasterVerificationGasLimit ?? 0n) +
(gasEstimate.paymasterPostOpGasLimit ?? 0n) +
gasEstimate.preVerificationGas;

const requiredPrefund = requiredGas * maxFeePerGas;

const balance = await publicClient.getBalance({
address: smartAccount.address,
});

if (balance < requiredPrefund) {
console.log(
`Insufficient balance: account has ${formatEther(balance)} ETH, ` +
`but needs ${formatEther(requiredPrefund)} ETH`
);
}
```

</TabItem>
<TabItem value="v0.6" label="EntryPoint v0.6">

```typescript
import { formatEther } from "viem";

const gasEstimate = await bundlerClient.estimateUserOperationGas({
account: smartAccount,
calls: [{ to: "0x...", value: 0n }],
});

const { maxFeePerGas } = await publicClient.estimateFeesPerGas();

const requiredGas =
gasEstimate.callGasLimit +
gasEstimate.verificationGasLimit +
gasEstimate.preVerificationGas;

const requiredPrefund = requiredGas * maxFeePerGas;

const balance = await publicClient.getBalance({
address: smartAccount.address,
});

if (balance < requiredPrefund) {
console.log(
`Insufficient balance: account has ${formatEther(balance)} ETH, ` +
`but needs ${formatEther(requiredPrefund)} ETH`
);
}
```

</TabItem>
</Tabs>

### Use a paymaster

You can use a paymaster to sponsor the gas fees for the smart account, so the account doesn't
need to hold native tokens. For more information about configuring a paymaster, see [send a gasless transaction](../guides/smart-accounts/send-gasless-transaction.md).
1 change: 0 additions & 1 deletion smart-accounts-kit/troubleshooting/invalid-delegate.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ keywords: [InvalidDelegate, error code, delegation, troubleshooting]

The Delegation Manager reverts with `InvalidDelegate()` in the following two cases.


## Account is not the delegate

The account redeeming the delegation is not the delegate specified in the delegation.
Expand Down
Loading