diff --git a/.idea/aa-bundler.iml b/.idea/aa-bundler.iml
new file mode 100644
index 00000000..678fa554
--- /dev/null
+++ b/.idea/aa-bundler.iml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 00000000..639900d1
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dockers/bundler/dbuild.sh b/dockers/bundler/dbuild.sh
index ef0604e7..62a6be77 100755
--- a/dockers/bundler/dbuild.sh
+++ b/dockers/bundler/dbuild.sh
@@ -4,7 +4,7 @@ cd `cd \`dirname $0\`;pwd`
#need to preprocess first to have the Version.js
test -z $NOBUILD && yarn preprocess
-test -z "$VERSION" && VERSION=`node -e "console.log(require('../../packages/common/dist/src/Version.js').erc4337RuntimeVersion)"`
+test -z "$VERSION" && VERSION=`jq -r .version ../../packages/utils/package.json`
echo version=$VERSION
IMAGE=accountabstraction/bundler
diff --git a/dockers/docker-compose.yml b/dockers/docker-compose.yml
index 7250bd2a..5efb77d4 100644
--- a/dockers/docker-compose.yml
+++ b/dockers/docker-compose.yml
@@ -40,7 +40,7 @@ services:
bundler:
container_name: bundler
ports: [ '3000:3000' ]
- image: accountabstraction/bundler:0.2.0
+ image: accountabstraction/bundler:0.2.1
restart: on-failure
volumes:
diff --git a/lerna.json b/lerna.json
index 505b232a..20bdbcb4 100644
--- a/lerna.json
+++ b/lerna.json
@@ -1,5 +1,5 @@
{
- "version": "0.2.0",
+ "version": "0.2.3",
"npmClient": "yarn",
"useWorkspaces": true
}
diff --git a/packages/bundler/package.json b/packages/bundler/package.json
index 0e680e7c..d3f8c4a8 100644
--- a/packages/bundler/package.json
+++ b/packages/bundler/package.json
@@ -1,6 +1,6 @@
{
"name": "@account-abstraction/bundler",
- "version": "0.2.0",
+ "version": "0.2.3",
"license": "MIT",
"private": true,
"files": [
@@ -25,7 +25,7 @@
},
"dependencies": {
"@account-abstraction/contracts": "^0.2.0",
- "@account-abstraction/utils": "^0.2.0",
+ "@account-abstraction/utils": "^0.2.3",
"@ethersproject/abi": "^5.7.0",
"@ethersproject/providers": "^5.7.0",
"@types/cors": "^2.8.12",
@@ -39,7 +39,7 @@
"source-map-support": "^0.5.21"
},
"devDependencies": {
- "@account-abstraction/sdk": "^0.2.0",
+ "@account-abstraction/sdk": "^0.2.3",
"@nomicfoundation/hardhat-chai-matchers": "^1.0.3",
"@nomicfoundation/hardhat-network-helpers": "^1.0.0",
"@nomicfoundation/hardhat-toolbox": "^1.0.2",
diff --git a/packages/bundler/src/BundlerServer.ts b/packages/bundler/src/BundlerServer.ts
index 02c1e226..9b002d84 100644
--- a/packages/bundler/src/BundlerServer.ts
+++ b/packages/bundler/src/BundlerServer.ts
@@ -1,7 +1,6 @@
import bodyParser from 'body-parser'
import cors from 'cors'
import express, { Express, Response, Request } from 'express'
-import { JsonRpcRequest } from 'hardhat/types'
import { Provider } from '@ethersproject/providers'
import { Wallet, utils } from 'ethers'
import { hexlify, parseEther } from 'ethers/lib/utils'
@@ -75,7 +74,7 @@ export class BundlerServer {
params,
jsonrpc,
id
- }: JsonRpcRequest = req.body
+ } = req.body
try {
const result = await this.handleMethod(method, params)
console.log('sent', method, '-', result)
diff --git a/packages/bundler/src/UserOpMethodHandler.ts b/packages/bundler/src/UserOpMethodHandler.ts
index 7e878e8b..61df535c 100644
--- a/packages/bundler/src/UserOpMethodHandler.ts
+++ b/packages/bundler/src/UserOpMethodHandler.ts
@@ -7,7 +7,7 @@ import { UserOperationStruct } from './types/contracts/BundlerHelper'
import { hexValue, resolveProperties } from 'ethers/lib/utils'
import { rethrowError } from '@account-abstraction/utils'
import { calcPreVerificationGas } from '@account-abstraction/sdk/dist/src/calcPreVerificationGas'
-import { postExecutionDump } from '@account-abstraction/utils/dist/src/postExecCheck'
+// import { postExecutionDump } from '@account-abstraction/utils/dist/src/postExecCheck'
export class UserOpMethodHandler {
constructor (
@@ -55,9 +55,10 @@ export class UserOpMethodHandler {
}
const gasLimit = undefined
+ console.log('using gasLimit=', gasLimit)
await this.entryPoint.handleOps([userOp], beneficiary, { gasLimit }).catch(rethrowError)
- await postExecutionDump(this.entryPoint, requestId)
+ // await postExecutionDump(this.entryPoint, requestId)
return requestId
}
}
diff --git a/packages/bundler/src/runner/runop.ts b/packages/bundler/src/runner/runop.ts
index 7ae390bc..ceeb31b0 100644
--- a/packages/bundler/src/runner/runop.ts
+++ b/packages/bundler/src/runner/runop.ts
@@ -40,7 +40,7 @@ class Runner {
}
async getAddress (): Promise {
- return await this.walletApi.getWalletAddress()
+ return await this.walletApi.getCreate2Address()
}
async init (deploymentSigner?: Signer): Promise {
@@ -88,7 +88,9 @@ class Runner {
data
})
try {
- await this.bundlerProvider.sendUserOpToBundler(userOp)
+ const requestId = await this.bundlerProvider.sendUserOpToBundler(userOp)
+ const txid = await this.walletApi.getUserOpReceipt(requestId)
+ console.log('reqId', requestId, 'txid=', txid)
} catch (e: any) {
throw this.parseExpectedGas(e)
}
@@ -110,9 +112,14 @@ async function main (): Promise {
let signer: Signer
const deployDeployer: boolean = opts.deployDeployer
if (opts.mnemonic != null) {
- signer = Wallet.fromMnemonic(fs.readFileSync(opts.mnemonic, 'ascii').trim())
+ signer = Wallet.fromMnemonic(fs.readFileSync(opts.mnemonic, 'ascii').trim()).connect(provider)
} else {
try {
+ const accounts = await provider.listAccounts()
+ if (accounts.length === 0) {
+ console.log('fatal: no account. use --mnemonic (needed to fund wallet)')
+ process.exit(1)
+ }
// for hardhat/node, use account[0]
signer = provider.getSigner()
// deployDeployer = true
@@ -120,7 +127,7 @@ async function main (): Promise {
throw new Error('must specify --mnemonic')
}
}
- const walletOwner = new Wallet('0x'.padEnd(66, '1'))
+ const walletOwner = new Wallet('0x'.padEnd(66, '7'))
const client = await new Runner(provider, opts.bundlerUrl, walletOwner).init(deployDeployer ? signer : undefined)
@@ -138,12 +145,14 @@ async function main (): Promise {
console.log('wallet address', addr, 'deployed=', await isDeployed(addr), 'bal=', formatEther(bal))
// TODO: actual required val
const requiredBalance = parseEther('0.1')
- if (bal.lt(requiredBalance)) {
+ if (bal.lt(requiredBalance.div(2))) {
console.log('funding wallet to', requiredBalance)
await signer.sendTransaction({
to: addr,
value: requiredBalance.sub(bal)
})
+ } else {
+ console.log('not funding wallet. balance is enough')
}
const dest = addr
diff --git a/packages/bundler/test/Flow.test.ts b/packages/bundler/test/Flow.test.ts
index 6612e6cd..14818ca7 100644
--- a/packages/bundler/test/Flow.test.ts
+++ b/packages/bundler/test/Flow.test.ts
@@ -34,10 +34,8 @@ describe('Flow', function () {
let entryPointAddress: string
let sampleRecipientAddress: string
let signer: Signer
- let chainId: number
before(async function () {
signer = await hre.ethers.provider.getSigner()
- chainId = await hre.ethers.provider.getNetwork().then(net => net.chainId)
const beneficiary = await signer.getAddress()
const sampleRecipientFactory = await ethers.getContractFactory('SampleRecipient')
@@ -80,8 +78,7 @@ describe('Flow', function () {
it('should send transaction and make profit', async function () {
const config: ClientConfig = {
entryPointAddress,
- bundlerUrl: 'http://localhost:5555/rpc',
- chainId
+ bundlerUrl: 'http://localhost:5555/rpc'
}
// use this as signer (instead of node's first account)
diff --git a/packages/bundler/test/UserOpMethodHandler.test.ts b/packages/bundler/test/UserOpMethodHandler.test.ts
index 232ed1ca..1f749e72 100644
--- a/packages/bundler/test/UserOpMethodHandler.test.ts
+++ b/packages/bundler/test/UserOpMethodHandler.test.ts
@@ -75,6 +75,7 @@ describe('UserOpMethodHandler', function () {
let walletDeployerAddress: string
before(async function () {
+ DeterministicDeployer.init(ethers.provider)
walletDeployerAddress = await DeterministicDeployer.deploy(SimpleWalletDeployer__factory.bytecode)
const smartWalletAPI = new SimpleWalletAPI({
diff --git a/packages/sdk/package.json b/packages/sdk/package.json
index 3b4a3cc4..ea0e5d42 100644
--- a/packages/sdk/package.json
+++ b/packages/sdk/package.json
@@ -1,6 +1,6 @@
{
"name": "@account-abstraction/sdk",
- "version": "0.2.0",
+ "version": "0.2.3",
"main": "./dist/src/index.js",
"license": "MIT",
"files": [
@@ -18,7 +18,7 @@
},
"dependencies": {
"@account-abstraction/contracts": "^0.2.0",
- "@account-abstraction/utils": "^0.2.0",
+ "@account-abstraction/utils": "^0.2.3",
"@ethersproject/abstract-provider": "^5.7.0",
"@ethersproject/abstract-signer": "^5.7.0",
"@ethersproject/networks": "^5.7.0",
diff --git a/packages/sdk/src/BaseWalletAPI.ts b/packages/sdk/src/BaseWalletAPI.ts
index d8b668be..9a4d8db5 100644
--- a/packages/sdk/src/BaseWalletAPI.ts
+++ b/packages/sdk/src/BaseWalletAPI.ts
@@ -19,6 +19,11 @@ export interface BaseApiParams {
paymasterAPI?: PaymasterAPI
}
+export interface UserOpResult {
+ transactionHash: string
+ success: boolean
+}
+
/**
* Base class for all Smart Wallet ERC-4337 Clients to implement.
* Subclass should inherit 5 methods to support a specific wallet contract:
@@ -249,7 +254,16 @@ export abstract class BaseWalletAPI {
maxPriorityFeePerGas
}
- partialUserOp.paymasterAndData = this.paymasterAPI == null ? '0x' : await this.paymasterAPI.getPaymasterAndData(partialUserOp)
+ let paymasterAndData: string | undefined
+ if (this.paymasterAPI != null) {
+ // fill (partial) preVerificationGas (all except the cost of the generated paymasterAndData)
+ const userOpForPm = {
+ ...partialUserOp,
+ preVerificationGas: this.getPreVerificationGas(partialUserOp)
+ }
+ paymasterAndData = await this.paymasterAPI.getPaymasterAndData(userOpForPm)
+ }
+ partialUserOp.paymasterAndData = paymasterAndData ?? '0x'
return {
...partialUserOp,
preVerificationGas: this.getPreVerificationGas(partialUserOp),
@@ -277,4 +291,23 @@ export abstract class BaseWalletAPI {
async createSignedUserOp (info: TransactionDetailsForUserOp): Promise {
return await this.signUserOp(await this.createUnsignedUserOp(info))
}
+
+ /**
+ * get the transaction that has this requestId mined, or null if not found
+ * @param requestId returned by sendUserOpToBundler (or by getRequestId..)
+ * @param timeout stop waiting after this timeout
+ * @param interval time to wait between polls.
+ * @return the transactionHash this userOp was mined, or null if not found.
+ */
+ async getUserOpReceipt (requestId: string, timeout = 30000, interval = 5000): Promise {
+ const endtime = Date.now() + timeout
+ while (Date.now() < endtime) {
+ const events = await this.entryPointView.queryFilter(this.entryPointView.filters.UserOperationEvent(requestId))
+ if (events.length > 0) {
+ return events[0].transactionHash
+ }
+ await new Promise(resolve => setTimeout(resolve, interval))
+ }
+ return null
+ }
}
diff --git a/packages/sdk/src/ClientConfig.ts b/packages/sdk/src/ClientConfig.ts
index 69bdd8ad..d90719a3 100644
--- a/packages/sdk/src/ClientConfig.ts
+++ b/packages/sdk/src/ClientConfig.ts
@@ -1,3 +1,5 @@
+import { PaymasterAPI } from './PaymasterAPI'
+
/**
* configuration params for wrapProvider
*/
@@ -10,10 +12,6 @@ export interface ClientConfig {
* url to the bundler
*/
bundlerUrl: string
- /**
- * chainId of current network. used to validate against the bundler's chainId
- */
- chainId: number
/**
* if set, use this pre-deployed wallet.
* (if not set, use getSigner().getAddress() to query the "counterfactual" address of wallet.
@@ -21,7 +19,7 @@ export interface ClientConfig {
*/
walletAddres?: string
/**
- * if set, use this paymaster
+ * if set, call just before signing.
*/
- paymasterAddress?: string
+ paymasterAPI?: PaymasterAPI
}
diff --git a/packages/sdk/src/DeterministicDeployer.ts b/packages/sdk/src/DeterministicDeployer.ts
index b5da9ae5..6e23db97 100644
--- a/packages/sdk/src/DeterministicDeployer.ts
+++ b/packages/sdk/src/DeterministicDeployer.ts
@@ -1,7 +1,7 @@
-import { ethers } from 'hardhat'
import { BigNumber, BigNumberish } from 'ethers'
import { hexConcat, hexlify, hexZeroPad, keccak256 } from 'ethers/lib/utils'
import { TransactionRequest } from '@ethersproject/abstract-provider'
+import { JsonRpcProvider } from '@ethersproject/providers'
/**
* wrapper class for Arachnid's deterministic deployer
@@ -34,7 +34,7 @@ export class DeterministicDeployer {
deploymentGasPrice = 100e9
deploymentGasLimit = 100000
- constructor (readonly provider = ethers.provider) {
+ constructor (readonly provider: JsonRpcProvider) {
}
async isContractDeployed (address: string): Promise {
@@ -98,5 +98,16 @@ export class DeterministicDeployer {
return addr
}
- static instance = new DeterministicDeployer()
+ private static _instance?: DeterministicDeployer
+
+ static init (provider: JsonRpcProvider): void {
+ this._instance = new DeterministicDeployer(provider)
+ }
+
+ static get instance (): DeterministicDeployer {
+ if (this._instance == null) {
+ throw new Error('must call "DeterministicDeployer.init(ethers.provider)" first')
+ }
+ return this._instance
+ }
}
diff --git a/packages/sdk/src/ERC4337EthersProvider.ts b/packages/sdk/src/ERC4337EthersProvider.ts
index b73793d0..6fa0c195 100644
--- a/packages/sdk/src/ERC4337EthersProvider.ts
+++ b/packages/sdk/src/ERC4337EthersProvider.ts
@@ -19,6 +19,7 @@ export class ERC4337EthersProvider extends BaseProvider {
readonly signer: ERC4337EthersSigner
constructor (
+ readonly chainId: number,
readonly config: ClientConfig,
readonly originalSigner: Signer,
readonly originalProvider: BaseProvider,
@@ -28,12 +29,17 @@ export class ERC4337EthersProvider extends BaseProvider {
) {
super({
name: 'ERC-4337 Custom Network',
- chainId: config.chainId
+ chainId
})
this.signer = new ERC4337EthersSigner(config, originalSigner, this, httpRpcClient, smartWalletAPI)
}
+ /**
+ * finish intializing the provider.
+ * MUST be called after construction, before using the provider.
+ */
async init (): Promise {
+ // await this.httpRpcClient.validateChainId()
this.initializedBlockNumber = await this.originalProvider.getBlockNumber()
await this.smartWalletAPI.init()
// await this.signer.init()
@@ -85,7 +91,7 @@ export class ERC4337EthersProvider extends BaseProvider {
// fabricate a response in a format usable by ethers users...
async constructUserOpTransactionResponse (userOp1: UserOperationStruct): Promise {
const userOp = await resolveProperties(userOp1)
- const requestId = getRequestId(userOp, this.config.entryPointAddress, this.config.chainId)
+ const requestId = getRequestId(userOp, this.config.entryPointAddress, this.chainId)
const waitPromise = new Promise((resolve, reject) => {
new UserOperationEventListener(
resolve, reject, this.entryPoint, userOp.sender, requestId, userOp.nonce
@@ -99,7 +105,7 @@ export class ERC4337EthersProvider extends BaseProvider {
gasLimit: BigNumber.from(userOp.callGasLimit), // ??
value: BigNumber.from(0),
data: hexValue(userOp.callData), // should extract the actual called method from this "execFromEntryPoint()" call
- chainId: this.config.chainId,
+ chainId: this.chainId,
wait: async (confirmations?: number): Promise => {
const transactionReceipt = await waitPromise
if (userOp.initCode.length !== 0) {
diff --git a/packages/sdk/src/HttpRpcClient.ts b/packages/sdk/src/HttpRpcClient.ts
index 245b9c72..f7412d92 100644
--- a/packages/sdk/src/HttpRpcClient.ts
+++ b/packages/sdk/src/HttpRpcClient.ts
@@ -32,7 +32,12 @@ export class HttpRpcClient {
}
}
- async sendUserOpToBundler (userOp1: UserOperationStruct): Promise {
+ /**
+ * send a UserOperation to the bundler
+ * @param userOp1
+ * @return requestId the id of this operation, for getUserOperationTransaction
+ */
+ async sendUserOpToBundler (userOp1: UserOperationStruct): Promise {
await this.initializing
const userOp = await resolveProperties(userOp1)
const hexifiedUserOp: any =
diff --git a/packages/sdk/src/PaymasterAPI.ts b/packages/sdk/src/PaymasterAPI.ts
index b2ed3fa6..d06c6651 100644
--- a/packages/sdk/src/PaymasterAPI.ts
+++ b/packages/sdk/src/PaymasterAPI.ts
@@ -1,7 +1,16 @@
import { UserOperationStruct } from '@account-abstraction/contracts'
+/**
+ * an API to external a UserOperation with paymaster info
+ */
export class PaymasterAPI {
- async getPaymasterAndData (userOp: Partial): Promise {
+ /**
+ * @param userOp a partially-filled UserOperation (without signature and paymasterAndData
+ * note that the "preVerificationGas" is incomplete: it can't account for the
+ * paymasterAndData value, which will only be returned by this method..
+ * @returns the value to put into the PaymasterAndData, undefined to leave it empty
+ */
+ async getPaymasterAndData (userOp: Partial): Promise {
return '0x'
}
}
diff --git a/packages/sdk/src/Provider.ts b/packages/sdk/src/Provider.ts
index 67a2ae9e..cb9ae44b 100644
--- a/packages/sdk/src/Provider.ts
+++ b/packages/sdk/src/Provider.ts
@@ -23,18 +23,22 @@ export async function wrapProvider (
config: ClientConfig,
originalSigner: Signer = originalProvider.getSigner()
): Promise {
- const entryPoint = new EntryPoint__factory().attach(config.entryPointAddress).connect(originalProvider)
+ const entryPoint = EntryPoint__factory.connect(config.entryPointAddress, originalProvider)
// Initial SimpleWallet instance is not deployed and exists just for the interface
- const simpleWalletDeployer = await DeterministicDeployer.deploy(SimpleWalletDeployer__factory.bytecode)
+ const detDeployer = new DeterministicDeployer(originalProvider)
+ const simpleWalletDeployer = await detDeployer.deterministicDeploy(SimpleWalletDeployer__factory.bytecode)
const smartWalletAPI = new SimpleWalletAPI({
provider: originalProvider,
entryPointAddress: entryPoint.address,
owner: originalSigner,
- factoryAddress: simpleWalletDeployer
+ factoryAddress: simpleWalletDeployer,
+ paymasterAPI: config.paymasterAPI
})
- const httpRpcClient = new HttpRpcClient(config.bundlerUrl, config.entryPointAddress, 31337)
debug('config=', config)
+ const chainId = await originalProvider.getNetwork().then(net => net.chainId)
+ const httpRpcClient = new HttpRpcClient(config.bundlerUrl, config.entryPointAddress, chainId)
return await new ERC4337EthersProvider(
+ chainId,
config,
originalSigner,
originalProvider,
diff --git a/packages/sdk/src/SimpleWalletAPI.ts b/packages/sdk/src/SimpleWalletAPI.ts
index 23abfc80..c3c15ef3 100644
--- a/packages/sdk/src/SimpleWalletAPI.ts
+++ b/packages/sdk/src/SimpleWalletAPI.ts
@@ -5,7 +5,7 @@ import {
SimpleWalletDeployer__factory
} from '@account-abstraction/contracts'
-import { arrayify, hexConcat } from 'ethers/lib/utils'
+import { arrayify, hexConcat, keccak256 } from 'ethers/lib/utils'
import { Signer } from '@ethersproject/abstract-signer'
import { BaseApiParams, BaseWalletAPI } from './BaseWalletAPI'
@@ -102,4 +102,25 @@ export class SimpleWalletAPI extends BaseWalletAPI {
async signRequestId (requestId: string): Promise {
return await this.owner.signMessage(arrayify(requestId))
}
+
+ /**
+ * calculate the wallet address even before it is deployed.
+ * We know our factory: it just calls CREATE2 to construct the wallet.
+ * NOTE: getWalletAddress works with any contract/factory (but only before creation)
+ * This method is tied to SimpleWallet implementation
+ */
+ async getCreate2Address (): Promise {
+ if (this.factoryAddress == null) {
+ throw new Error('can\'t calculate address: no factory')
+ }
+
+ const ctrWithParams = new SimpleWallet__factory(undefined).getDeployTransaction(this.entryPointAddress, await this.owner.getAddress()).data as any
+ const salt = '0x' + this.index.toString(16).padStart(64, '0')
+ const hash = keccak256(hexConcat([
+ '0xff', this.factoryAddress, salt, keccak256(ctrWithParams)
+ ]))
+ // hash is 32bytes, or 66 chars.
+ // address is last 40 chars, with '0x' prefix
+ return '0x' + hash.substring(66 - 40)
+ }
}
diff --git a/packages/sdk/test/0-deterministicDeployer.test.ts b/packages/sdk/test/0-deterministicDeployer.test.ts
index fb1b8d23..fd69eacd 100644
--- a/packages/sdk/test/0-deterministicDeployer.test.ts
+++ b/packages/sdk/test/0-deterministicDeployer.test.ts
@@ -4,7 +4,7 @@ import { ethers } from 'hardhat'
import { hexValue } from 'ethers/lib/utils'
import { DeterministicDeployer } from '../src/DeterministicDeployer'
-const deployer = DeterministicDeployer.instance
+const deployer = new DeterministicDeployer(ethers.provider)
describe('#deterministicDeployer', () => {
it('deploy deployer', async () => {
@@ -17,6 +17,7 @@ describe('#deterministicDeployer', () => {
})
it('should deploy at given address', async () => {
const ctr = hexValue(new SampleRecipient__factory(ethers.provider.getSigner()).getDeployTransaction().data!)
+ DeterministicDeployer.init(ethers.provider)
const addr = await DeterministicDeployer.getAddress(ctr)
expect(await deployer.isContractDeployed(addr)).to.equal(false)
await DeterministicDeployer.deploy(ctr)
diff --git a/packages/sdk/test/3-ERC4337EthersSigner.test.ts b/packages/sdk/test/3-ERC4337EthersSigner.test.ts
index 1102d057..2e1f9788 100644
--- a/packages/sdk/test/3-ERC4337EthersSigner.test.ts
+++ b/packages/sdk/test/3-ERC4337EthersSigner.test.ts
@@ -18,7 +18,6 @@ describe('ERC4337EthersSigner, Provider', function () {
const deployRecipient = await new SampleRecipient__factory(signer).deploy()
entryPoint = await new EntryPoint__factory(signer).deploy(1, 1)
const config: ClientConfig = {
- chainId: await provider.getNetwork().then(net => net.chainId),
entryPointAddress: entryPoint.address,
bundlerUrl: ''
}
@@ -38,6 +37,7 @@ describe('ERC4337EthersSigner, Provider', function () {
throw new Error(message)
})
}
+ return ''
}
recipient = deployRecipient.connect(aaProvider.getSigner())
})
diff --git a/packages/utils/package.json b/packages/utils/package.json
index afb02110..3cf2595a 100644
--- a/packages/utils/package.json
+++ b/packages/utils/package.json
@@ -1,6 +1,6 @@
{
"name": "@account-abstraction/utils",
- "version": "0.2.0",
+ "version": "0.2.3",
"main": "./dist/src/index.js",
"license": "MIT",
"files": [
diff --git a/packages/utils/src/postExecCheck.ts b/packages/utils/src/postExecCheck.ts
index d8de0692..58c91d78 100644
--- a/packages/utils/src/postExecCheck.ts
+++ b/packages/utils/src/postExecCheck.ts
@@ -24,6 +24,11 @@ export async function postExecutionCheck (entryPoint: EntryPoint, requestId: str
userOp: NotPromise
}> {
const req = await entryPoint.queryFilter(entryPoint.filters.UserOperationEvent(requestId))
+ if (req.length === 0) {
+ console.log('postExecutionCheck: failed to read event (not mined)')
+ // @ts-ignore
+ return { gasUsed: 0, gasPaid: 0, success: false, userOp: {} }
+ }
const transactionReceipt = await req[0].getTransactionReceipt()
const tx = await req[0].getTransaction()