Skip to content

Commit

Permalink
Merge branch 'master' of github.com:eth-infinitism/bundler into AA-45…
Browse files Browse the repository at this point in the history
…3-eip-7702-support
  • Loading branch information
forshtat committed Dec 11, 2024
2 parents 24a80f8 + 8bc5028 commit 915df43
Show file tree
Hide file tree
Showing 32 changed files with 439 additions and 231 deletions.
20 changes: 0 additions & 20 deletions packages/bundler/contracts/BundlerHelper.sol

This file was deleted.

5 changes: 3 additions & 2 deletions packages/bundler/localconfig/bundler.config.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"chainId": 1337,
"gasFactor": "1",
"port": "3000",
"privateApiPort": "3001",
Expand All @@ -8,8 +9,8 @@
"minBalance": "1",
"mnemonic": "./localconfig/mnemonic.txt",
"maxBundleGas": 5e6,
"minStake": "1" ,
"minUnstakeDelay": 0 ,
"minStake": "1",
"minUnstakeDelay": 0,
"autoBundleInterval": 3,
"autoBundleMempoolSize": 10,
"rip7560": false,
Expand Down
5 changes: 3 additions & 2 deletions packages/bundler/localconfig/bundler.rip7560.config.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"chainId": 1337,
"gasFactor": "1",
"port": "3000",
"privateApiPort": "3001",
Expand All @@ -8,8 +9,8 @@
"minBalance": "1",
"mnemonic": "./localconfig/mnemonic.txt",
"maxBundleGas": 30e6,
"minStake": "1" ,
"minUnstakeDelay": 0 ,
"minStake": "1",
"minUnstakeDelay": 0,
"autoBundleInterval": 3,
"autoBundleMempoolSize": 10,
"rip7560": true,
Expand Down
40 changes: 39 additions & 1 deletion packages/bundler/src/BundlerConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import ow from 'ow'
// RIP-7560 EntyPoint address
const MIN_UNSTAKE_DELAY = 86400
const MIN_STAKE_VALUE = 1e18.toString()

export interface BundlerConfig {
chainId: number
beneficiary: string
entryPoint: string
gasFactor: string
Expand All @@ -14,6 +16,7 @@ export interface BundlerConfig {
port: string
privateApiPort: string
unsafe: boolean
tracerRpcUrl?: string
debugRpc?: boolean
conditionalRpc: boolean

Expand All @@ -29,10 +32,20 @@ export interface BundlerConfig {
gethDevMode: boolean

eip7702Support: boolean
// Config overrides for PreVerificationGas calculation
fixedGasOverhead?: number
perUserOpGasOverhead?: number
perUserOpWordGasOverhead?: number
zeroByteGasCost?: number
nonZeroByteGasCost?: number
expectedBundleSize?: number
estimationSignatureSize?: number
estimationPaymasterDataSize?: number
}

// TODO: implement merging config (args -> config.js -> default) and runtime shape validation
export const BundlerConfigShape = {
chainId: ow.number,
beneficiary: ow.string,
entryPoint: ow.string,
gasFactor: ow.string,
Expand All @@ -42,6 +55,7 @@ export const BundlerConfigShape = {
port: ow.string,
privateApiPort: ow.string,
unsafe: ow.boolean,
tracerRpcUrl: ow.optional.string,
debugRpc: ow.optional.boolean,
conditionalRpc: ow.boolean,

Expand All @@ -55,7 +69,31 @@ export const BundlerConfigShape = {
rip7560: ow.boolean,
rip7560Mode: ow.string.oneOf(['PULL', 'PUSH']),
gethDevMode: ow.boolean,
eip7702Support: ow.boolean
eip7702Support: ow.boolean,

// Config overrides for PreVerificationGas calculation
fixedGasOverhead: ow.optional.number,
perUserOpGasOverhead: ow.optional.number,
perUserOpWordGasOverhead: ow.optional.number,
zeroByteGasCost: ow.optional.number,
nonZeroByteGasCost: ow.optional.number,
expectedBundleSize: ow.optional.number,
estimationSignatureSize: ow.optional.number,
estimationPaymasterDataSize: ow.optional.number
}

/**
* Only parameters in this object can be provided by a 'debug_bundler_setConfiguration' API.
*/
export const DebugBundlerConfigShape = {
fixedGasOverhead: ow.optional.number,
perUserOpGasOverhead: ow.optional.number,
perUserOpWordGasOverhead: ow.optional.number,
zeroByteGasCost: ow.optional.number,
nonZeroByteGasCost: ow.optional.number,
expectedBundleSize: ow.optional.number,
estimationSignatureSize: ow.optional.number,
estimationPaymasterDataSize: ow.optional.number
}

// TODO: consider if we want any default fields at all
Expand Down
9 changes: 8 additions & 1 deletion packages/bundler/src/BundlerServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,8 @@ export class BundlerServer {
} = reqItem
debug('>>', { jsonrpc, id, method, params })
try {
const result = deepHexlify(await this.handleMethod(method, params))
const handleResult = await this.handleMethod(method, params)
const result = deepHexlify(handleResult)
debug('sent', method, '-', result)
debug('<<', { jsonrpc, id, result })
return {
Expand Down Expand Up @@ -331,6 +332,12 @@ export class BundlerServer {
case 'debug_bundler_getStakeStatus':
result = await this.debugHandler.getStakeStatus(params[0], params[1])
break
case 'debug_bundler_setConfiguration': {
const pvgc = await this.debugHandler._setConfiguration(params[0])
this.methodHandler.preVerificationGasCalculator = pvgc
}
result = {}
break
default:
throw new RpcError(`Method ${method} is not supported`, -32601)
}
Expand Down
16 changes: 13 additions & 3 deletions packages/bundler/src/DebugMethodHandler.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
import ow from 'ow'

import { StakeInfo } from '@account-abstraction/utils'
import { PreVerificationGasCalculator } from '@account-abstraction/sdk'

import { BundlerConfig, DebugBundlerConfigShape } from './BundlerConfig'
import { EventsManager } from './modules/EventsManager'
import { ExecutionManager } from './modules/ExecutionManager'
import { ReputationDump, ReputationManager } from './modules/ReputationManager'
import { MempoolManager } from './modules/MempoolManager'
import { ReputationDump, ReputationManager } from './modules/ReputationManager'
import { SendBundleReturn } from './modules/BundleManager'
import { EventsManager } from './modules/EventsManager'
import { StakeInfo } from '@account-abstraction/utils'

export class DebugMethodHandler {
constructor (
Expand Down Expand Up @@ -76,4 +81,9 @@ export class DebugMethodHandler {
}> {
return await this.repManager.getStakeStatus(address, entryPoint)
}

async _setConfiguration (config: Partial<BundlerConfig>): Promise<PreVerificationGasCalculator> {
ow.object.exactShape(DebugBundlerConfigShape)
return await this.execManager._setConfiguration(config)
}
}
20 changes: 13 additions & 7 deletions packages/bundler/src/MethodHandlerERC4337.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import debug from 'debug'
import { BigNumber, BigNumberish, Signer } from 'ethers'
import { JsonRpcProvider, Log } from '@ethersproject/providers'
import { EventFragment } from '@ethersproject/abi'

import { MainnetConfig, PreVerificationGasCalculator } from '@account-abstraction/sdk'

import { BundlerConfig } from './BundlerConfig'
import {
AddressZero,
IEntryPoint,
Expand All @@ -22,10 +25,10 @@ import {
tostr,
unpackUserOp
} from '@account-abstraction/utils'
import { BundlerConfig } from './BundlerConfig'

import { ExecutionManager } from './modules/ExecutionManager'
import { StateOverride, UserOperationByHashResponse, UserOperationReceipt } from './RpcTypes'
import { calcPreVerificationGas } from '@account-abstraction/sdk'
import { EventFragment } from '@ethersproject/abi'

export const HEX_REGEX = /^0x[a-fA-F\d]*$/i

Expand Down Expand Up @@ -63,7 +66,8 @@ export class MethodHandlerERC4337 {
readonly provider: JsonRpcProvider,
readonly signer: Signer,
readonly config: BundlerConfig,
readonly entryPoint: IEntryPoint
readonly entryPoint: IEntryPoint,
public preVerificationGasCalculator: PreVerificationGasCalculator
) {
}

Expand Down Expand Up @@ -158,7 +162,7 @@ export class MethodHandlerERC4337 {
} = returnInfo

// todo: use simulateHandleOp for this too...
const callGasLimit = await this.provider.send(
let callGasLimit = await this.provider.send(
'eth_estimateGas', [
{
from: this.entryPoint.address,
Expand All @@ -172,8 +176,10 @@ export class MethodHandlerERC4337 {
const message = err.message.match(/reason="(.*?)"/)?.at(1) ?? 'execution reverted'
throw new RpcError(message, ValidationErrors.UserOperationReverted)
})
// Results from 'estimateGas' assume making a standalone transaction and paying 21'000 gas extra for it
callGasLimit -= MainnetConfig.transactionGasStipend

const preVerificationGas = calcPreVerificationGas(userOp)
const preVerificationGas = this.preVerificationGasCalculator.estimatePreVerificationGas(userOp)
const verificationGasLimit = BigNumber.from(preOpGas).toNumber()
return {
preVerificationGas,
Expand All @@ -190,7 +196,7 @@ export class MethodHandlerERC4337 {
}
await this._validateParameters(userOp, entryPointInput)

console.log(`UserOperation: Sender=${userOp.sender} Nonce=${tostr(userOp.nonce)} EntryPoint=${entryPointInput} Paymaster=${userOp.paymaster ?? ''} EIP-7702TuplesSize=${userOp.authorizationList.length}`)
debug(`UserOperation: Sender=${userOp.sender} Nonce=${tostr(userOp.nonce)} EntryPoint=${entryPointInput} Paymaster=${userOp.paymaster ?? ''} EIP-7702TuplesSize=${userOp.authorizationList.length}`)
await this.execManager.sendUserOperation(userOp, entryPointInput, false)
return await this.entryPoint.getUserOpHash(packUserOp(userOp))
}
Expand Down
10 changes: 3 additions & 7 deletions packages/bundler/src/modules/BundleManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,10 @@ import {
getEip7702AuthorizationSigner,
mergeStorageMap,
packUserOp,
runContractScript
getUserOpHash
} from '@account-abstraction/utils'

import { EventsManager } from './EventsManager'
import { GetUserOpHashes__factory } from '../types'
import { IBundleManager } from './IBundleManager'
import { MempoolEntry } from './MempoolEntry'
import { MempoolManager } from './MempoolManager'
Expand Down Expand Up @@ -467,11 +466,8 @@ export class BundleManager implements IBundleManager {

// helper function to get hashes of all UserOps
async getUserOpHashes (userOps: UserOperation[]): Promise<string[]> {
const { userOpHashes } = await runContractScript(this.entryPoint.provider,
new GetUserOpHashes__factory(),
[this.entryPoint.address, userOps.map(packUserOp)])

return userOpHashes
const network = await this.entryPoint.provider.getNetwork()
return userOps.map(it => getUserOpHash(it, this.entryPoint.address, network.chainId))
}

async getPaymasterBalance (paymaster: string): Promise<BigNumber> {
Expand Down
17 changes: 15 additions & 2 deletions packages/bundler/src/modules/ExecutionManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ import { ReputationManager } from './ReputationManager'
import { IBundleManager } from './IBundleManager'
import {
EmptyValidateUserOpResult,
IValidationManager
IValidationManager, ValidationManager
} from '@account-abstraction/validation-manager'
import { DepositManager } from './DepositManager'
import { BigNumberish, Signer } from 'ethers'
import { BundlerConfig } from '../BundlerConfig'
import { PreVerificationGasCalculator } from '@account-abstraction/sdk'

const debug = Debug('aa.exec')

Expand All @@ -30,7 +32,7 @@ export class ExecutionManager {
constructor (private readonly reputationManager: ReputationManager,
private readonly mempoolManager: MempoolManager,
private readonly bundleManager: IBundleManager,
private readonly validationManager: IValidationManager,
private validationManager: IValidationManager,
private readonly depositManager: DepositManager,
private readonly signer: Signer,
private readonly rip7560: boolean,
Expand Down Expand Up @@ -142,4 +144,15 @@ export class ExecutionManager {
): Promise<[OperationBase[], EIP7702Authorization[], StorageMap]> {
return await this.bundleManager.createBundle(minBaseFee, maxBundleGas, maxBundleSize)
}

async _setConfiguration (configOverrides: Partial<BundlerConfig>): Promise<PreVerificationGasCalculator> {
const { configuration, entryPoint, unsafe } = this.validationManager._getDebugConfiguration()
const pvgc = new PreVerificationGasCalculator(Object.assign({}, configuration, configOverrides))
this.validationManager = new ValidationManager(
entryPoint,
unsafe,
pvgc
)
return pvgc
}
}
10 changes: 7 additions & 3 deletions packages/bundler/src/modules/initServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,26 @@ import { BundleManagerRIP7560 } from './BundleManagerRIP7560'
import { IBundleManager } from './IBundleManager'
import { DepositManager } from './DepositManager'
import { IRip7560StakeManager__factory } from '@account-abstraction/utils/dist/src/types'
import { PreVerificationGasCalculator, ChainConfigs } from '@account-abstraction/sdk'

/**
* initialize server modules.
* returns the ExecutionManager and EventsManager (for handling events, to update reputation)
* @param config
* @param signer
*/
export function initServer (config: BundlerConfig, signer: Signer): [ExecutionManager, EventsManager, ReputationManager, MempoolManager] {
export function initServer (config: BundlerConfig, signer: Signer): [ExecutionManager, EventsManager, ReputationManager, MempoolManager, PreVerificationGasCalculator] {
const entryPoint = IEntryPoint__factory.connect(config.entryPoint, signer)
const reputationManager = new ReputationManager(getNetworkProvider(config.network), BundlerReputationParams, parseEther(config.minStake), config.minUnstakeDelay)
const mempoolManager = new MempoolManager(reputationManager)
const eventsManager = new EventsManager(entryPoint, mempoolManager, reputationManager)
const mergedPvgcConfig = Object.assign({}, ChainConfigs[config.chainId] ?? {}, config)
const preVerificationGasCalculator = new PreVerificationGasCalculator(mergedPvgcConfig)
let validationManager: IValidationManager
let bundleManager: IBundleManager
if (!config.rip7560) {
validationManager = new ValidationManager(entryPoint, config.unsafe)
const tracerProvider = config.tracerRpcUrl == null ? undefined : getNetworkProvider(config.tracerRpcUrl)
validationManager = new ValidationManager(entryPoint, config.unsafe, preVerificationGasCalculator, tracerProvider)
bundleManager = new BundleManager(entryPoint, entryPoint.provider as JsonRpcProvider, signer, eventsManager, mempoolManager, validationManager, reputationManager,
config.beneficiary, parseEther(config.minBalance), config.maxBundleGas, config.conditionalRpc)
} else {
Expand All @@ -52,5 +56,5 @@ export function initServer (config: BundlerConfig, signer: Signer): [ExecutionMa
if (config.rip7560 && config.rip7560Mode === 'PUSH') {
executionManager.setAutoBundler(config.autoBundleInterval, config.autoBundleMempoolSize)
}
return [executionManager, eventsManager, reputationManager, mempoolManager]
return [executionManager, eventsManager, reputationManager, mempoolManager, preVerificationGasCalculator]
}
Loading

0 comments on commit 915df43

Please sign in to comment.