Skip to content

Commit

Permalink
AA-227: Define JSON schema for the alt-mempool configuration (#238)
Browse files Browse the repository at this point in the history
* AA-227: Rewrite erc7562 parser and define JSON schema for the alt-mempool configuration
  • Loading branch information
forshtat authored Jan 21, 2025
1 parent 907adcb commit 715ff28
Show file tree
Hide file tree
Showing 22 changed files with 1,171 additions and 160 deletions.
3 changes: 3 additions & 0 deletions packages/bundler/src/BundlerConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export interface BundlerConfig {
chainId: number
beneficiary: string
entryPoint: string
senderCreator: string
gasFactor: string
minBalance: string
mnemonic: string
Expand Down Expand Up @@ -48,6 +49,7 @@ export const BundlerConfigShape = {
chainId: ow.number,
beneficiary: ow.string,
entryPoint: ow.string,
senderCreator: ow.string,
gasFactor: ow.string,
minBalance: ow.string,
mnemonic: ow.string,
Expand Down Expand Up @@ -102,6 +104,7 @@ export const bundlerConfigDefault: Partial<BundlerConfig> = {
port: '3000',
privateApiPort: '3001',
entryPoint: '0x0000000071727De22E5E9d8BAf0edAc6f37da032',
senderCreator: '0xefc2c1444ebcc4db75e7613d20c6a62ff67a167c',
unsafe: false,
conditionalRpc: false,
minStake: MIN_STAKE_VALUE,
Expand Down
8 changes: 6 additions & 2 deletions packages/bundler/src/modules/ExecutionManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { DepositManager } from './DepositManager'
import { BigNumberish, Signer } from 'ethers'
import { BundlerConfig } from '../BundlerConfig'
import { PreVerificationGasCalculator } from '@account-abstraction/sdk'
import { ERC7562Parser } from '@account-abstraction/validation-manager/dist/src/ERC7562Parser'

const debug = Debug('aa.exec')

Expand Down Expand Up @@ -147,11 +148,14 @@ export class ExecutionManager {

async _setConfiguration (configOverrides: Partial<BundlerConfig>): Promise<PreVerificationGasCalculator> {
const { configuration, entryPoint, unsafe } = this.validationManager._getDebugConfiguration()
const pvgc = new PreVerificationGasCalculator(Object.assign({}, configuration, configOverrides))
const mergedConfiguration = Object.assign({}, configuration, configOverrides)
const pvgc = new PreVerificationGasCalculator(mergedConfiguration)
const erc7562Parser = new ERC7562Parser(entryPoint.address, mergedConfiguration.senderCreator ?? '')
this.validationManager = new ValidationManager(
entryPoint,
unsafe,
pvgc
pvgc,
erc7562Parser
)
return pvgc
}
Expand Down
15 changes: 11 additions & 4 deletions packages/bundler/src/modules/initServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,13 @@ import { BundlerReputationParams, ReputationManager } from './ReputationManager'
import { MempoolManager } from './MempoolManager'
import { BundleManager } from './BundleManager'
import {
AA_ENTRY_POINT,
AA_NONCE_MANAGER,
AA_SENDER_CREATOR,
AA_STAKE_MANAGER,
IValidationManager,
ValidationManager,
ValidationManagerRIP7560,
IValidationManager, AA_STAKE_MANAGER
ValidationManagerRIP7560
} from '@account-abstraction/validation-manager'
import { BundlerConfig } from '../BundlerConfig'
import { EventsManager } from './EventsManager'
Expand All @@ -21,6 +25,7 @@ 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'
import { ERC7562Parser } from '@account-abstraction/validation-manager/dist/src/ERC7562Parser'

/**
* initialize server modules.
Expand All @@ -38,13 +43,15 @@ export function initServer (config: BundlerConfig, signer: Signer): [ExecutionMa
let validationManager: IValidationManager
let bundleManager: IBundleManager
if (!config.rip7560) {
const erc7562Parser = new ERC7562Parser(entryPoint.address, config.senderCreator)
const tracerProvider = config.tracerRpcUrl == null ? undefined : getNetworkProvider(config.tracerRpcUrl)
validationManager = new ValidationManager(entryPoint, config.unsafe, preVerificationGasCalculator, tracerProvider)
validationManager = new ValidationManager(entryPoint, config.unsafe, preVerificationGasCalculator, erc7562Parser, tracerProvider)
bundleManager = new BundleManager(entryPoint, entryPoint.provider as JsonRpcProvider, signer, eventsManager, mempoolManager, validationManager, reputationManager,
config.beneficiary, parseEther(config.minBalance), config.maxBundleGas, config.conditionalRpc)
} else {
const erc7562Parser = new ERC7562Parser(AA_ENTRY_POINT, AA_SENDER_CREATOR, AA_NONCE_MANAGER)
const stakeManager = IRip7560StakeManager__factory.connect(AA_STAKE_MANAGER, signer)
validationManager = new ValidationManagerRIP7560(stakeManager, entryPoint.provider as JsonRpcProvider, config.unsafe)
validationManager = new ValidationManagerRIP7560(stakeManager, entryPoint.provider as JsonRpcProvider, erc7562Parser, config.unsafe)
bundleManager = new BundleManagerRIP7560(entryPoint.provider as JsonRpcProvider, signer, eventsManager, mempoolManager, validationManager, reputationManager,
config.beneficiary, parseEther(config.minBalance), config.maxBundleGas, config.conditionalRpc, false)
}
Expand Down
9 changes: 7 additions & 2 deletions packages/bundler/test/BundlerManager.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { ExecutionManager } from '../src/modules/ExecutionManager'
import { EventsManager } from '../src/modules/EventsManager'
import { createSigner } from './testUtils'
import { DepositManager } from '../src/modules/DepositManager'
import { ERC7562Parser } from '@account-abstraction/validation-manager/dist/src/ERC7562Parser'

describe('#BundlerManager', () => {
let bm: BundleManager
Expand All @@ -40,6 +41,7 @@ describe('#BundlerManager', () => {
chainId: 1337,
beneficiary: await signer.getAddress(),
entryPoint: entryPoint.address,
senderCreator: '0xefc2c1444ebcc4db75e7613d20c6a62ff67a167c',
gasFactor: '0.2',
minBalance: '0',
mnemonic: '',
Expand All @@ -63,7 +65,8 @@ describe('#BundlerManager', () => {
const repMgr = new ReputationManager(provider, BundlerReputationParams, parseEther(config.minStake), config.minUnstakeDelay)
const mempoolMgr = new MempoolManager(repMgr)
const preVerificationGasCalculator = new PreVerificationGasCalculator(MainnetConfig)
const validMgr = new ValidationManager(entryPoint, config.unsafe, preVerificationGasCalculator)
const erc7562Parser = new ERC7562Parser(entryPoint.address, config.senderCreator)
const validMgr = new ValidationManager(entryPoint, config.unsafe, preVerificationGasCalculator, erc7562Parser)
const evMgr = new EventsManager(entryPoint, mempoolMgr, repMgr)
bm = new BundleManager(entryPoint, entryPoint.provider as JsonRpcProvider, entryPoint.signer, evMgr, mempoolMgr, validMgr, repMgr, config.beneficiary, parseEther(config.minBalance), config.maxBundleGas, config.conditionalRpc)
})
Expand Down Expand Up @@ -97,6 +100,7 @@ describe('#BundlerManager', () => {
chainId: 1337,
beneficiary: await bundlerSigner.getAddress(),
entryPoint: _entryPoint.address,
senderCreator: '0xefc2c1444ebcc4db75e7613d20c6a62ff67a167c',
gasFactor: '0.2',
minBalance: '0',
mnemonic: '',
Expand All @@ -119,7 +123,8 @@ describe('#BundlerManager', () => {
const repMgr = new ReputationManager(provider, BundlerReputationParams, parseEther(config.minStake), config.minUnstakeDelay)
const mempoolMgr = new MempoolManager(repMgr)
const preVerificationGasCalculator = new PreVerificationGasCalculator(MainnetConfig)
const validMgr = new ValidationManager(_entryPoint, config.unsafe, preVerificationGasCalculator)
const erc7562Parser = new ERC7562Parser(entryPoint.address, config.senderCreator)
const validMgr = new ValidationManager(_entryPoint, config.unsafe, preVerificationGasCalculator, erc7562Parser)
const evMgr = new EventsManager(_entryPoint, mempoolMgr, repMgr)
bundleMgr = new BundleManager(_entryPoint, _entryPoint.provider as JsonRpcProvider, _entryPoint.signer, evMgr, mempoolMgr, validMgr, repMgr, config.beneficiary, parseEther(config.minBalance), config.maxBundleGas, false)
const depositManager = new DepositManager(entryPoint, mempoolMgr, bundleMgr)
Expand Down
5 changes: 4 additions & 1 deletion packages/bundler/test/BundlerServer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { ExecutionManager } from '../src/modules/ExecutionManager'
import { MethodHandlerERC4337 } from '../src/MethodHandlerERC4337'
import { BundlerConfig } from '../src/BundlerConfig'
import { DepositManager } from '../src/modules/DepositManager'
import { ERC7562Parser } from '@account-abstraction/validation-manager/dist/src/ERC7562Parser'

describe('BundleServer', function () {
let entryPoint: IEntryPoint
Expand All @@ -36,6 +37,7 @@ describe('BundleServer', function () {
chainId: 1337,
beneficiary: await signer.getAddress(),
entryPoint: entryPoint.address,
senderCreator: '0xefc2c1444ebcc4db75e7613d20c6a62ff67a167c',
gasFactor: '0.2',
minBalance: '0',
mnemonic: '',
Expand All @@ -59,7 +61,8 @@ describe('BundleServer', function () {
const repMgr = new ReputationManager(provider, BundlerReputationParams, parseEther(config.minStake), config.minUnstakeDelay)
const mempoolMgr = new MempoolManager(repMgr)
const preVerificationGasCalculator = new PreVerificationGasCalculator(MainnetConfig)
const validMgr = new ValidationManager(entryPoint, config.unsafe, preVerificationGasCalculator)
const erc7562Parser = new ERC7562Parser(entryPoint.address, config.senderCreator)
const validMgr = new ValidationManager(entryPoint, config.unsafe, preVerificationGasCalculator, erc7562Parser)
const evMgr = new EventsManager(entryPoint, mempoolMgr, repMgr)
const bundleMgr = new BundleManager(entryPoint, entryPoint.provider as JsonRpcProvider, entryPoint.signer, evMgr, mempoolMgr, validMgr, repMgr, config.beneficiary, parseEther(config.minBalance), config.maxBundleGas, false)
const depositManager = new DepositManager(entryPoint, mempoolMgr, bundleMgr)
Expand Down
5 changes: 4 additions & 1 deletion packages/bundler/test/DebugMethodHandler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { MethodHandlerERC4337 } from '../src/MethodHandlerERC4337'
import { createSigner } from './testUtils'
import { EventsManager } from '../src/modules/EventsManager'
import { DepositManager } from '../src/modules/DepositManager'
import { ERC7562Parser } from '@account-abstraction/validation-manager/dist/src/ERC7562Parser'

const provider = ethers.provider

Expand All @@ -46,6 +47,7 @@ describe('#DebugMethodHandler', () => {
chainId: 1337,
beneficiary: await signer.getAddress(),
entryPoint: entryPoint.address,
senderCreator: '0xefc2c1444ebcc4db75e7613d20c6a62ff67a167c',
gasFactor: '0.2',
minBalance: '0',
mnemonic: '',
Expand All @@ -69,7 +71,8 @@ describe('#DebugMethodHandler', () => {
const repMgr = new ReputationManager(provider, BundlerReputationParams, parseEther(config.minStake), config.minUnstakeDelay)
const mempoolMgr = new MempoolManager(repMgr)
const preVerificationGasCalculator = new PreVerificationGasCalculator(MainnetConfig)
const validMgr = new ValidationManager(entryPoint, config.unsafe, preVerificationGasCalculator)
const erc7562Parser = new ERC7562Parser(entryPoint.address, config.senderCreator)
const validMgr = new ValidationManager(entryPoint, config.unsafe, preVerificationGasCalculator, erc7562Parser)
const eventsManager = new EventsManager(entryPoint, mempoolMgr, repMgr)
const bundleMgr = new BundleManager(entryPoint, entryPoint.provider as JsonRpcProvider, entryPoint.signer, eventsManager, mempoolMgr, validMgr, repMgr,
config.beneficiary, parseEther(config.minBalance), config.maxBundleGas, false)
Expand Down
5 changes: 4 additions & 1 deletion packages/bundler/test/UserOpMethodHandler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import { ethers } from 'hardhat'
import { createSigner } from './testUtils'
import { EventsManager } from '../src/modules/EventsManager'
import { DepositManager } from '../src/modules/DepositManager'
import { ERC7562Parser } from '@account-abstraction/validation-manager/dist/src/ERC7562Parser'

describe('UserOpMethodHandler', function () {
const helloWorld = 'hello world'
Expand Down Expand Up @@ -64,6 +65,7 @@ describe('UserOpMethodHandler', function () {
chainId: 1337,
beneficiary: await signer.getAddress(),
entryPoint: entryPoint.address,
senderCreator: '0xefc2c1444ebcc4db75e7613d20c6a62ff67a167c',
gasFactor: '0.2',
minBalance: '0',
mnemonic: '',
Expand All @@ -87,7 +89,8 @@ describe('UserOpMethodHandler', function () {
const repMgr = new ReputationManager(provider, BundlerReputationParams, parseEther(config.minStake), config.minUnstakeDelay)
mempoolMgr = new MempoolManager(repMgr)
const preVerificationGasCalculator = new PreVerificationGasCalculator(MainnetConfig)
const validMgr = new ValidationManager(entryPoint, config.unsafe, preVerificationGasCalculator)
const erc7562Parser = new ERC7562Parser(entryPoint.address, config.senderCreator)
const validMgr = new ValidationManager(entryPoint, config.unsafe, preVerificationGasCalculator, erc7562Parser)
const evMgr = new EventsManager(entryPoint, mempoolMgr, repMgr)
const bundleMgr = new BundleManager(entryPoint, entryPoint.provider as JsonRpcProvider, entryPoint.signer, evMgr, mempoolMgr, validMgr, repMgr, config.beneficiary, parseEther(config.minBalance), config.maxBundleGas, false)
const depositManager = new DepositManager(entryPoint, mempoolMgr, bundleMgr)
Expand Down
6 changes: 5 additions & 1 deletion packages/bundler/test/ValidateManager.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import {
TestTimeRangeAccountFactory,
TestTimeRangeAccountFactory__factory
} from '../src/types'
import { ERC7562Parser } from '@account-abstraction/validation-manager/dist/src/ERC7562Parser'

const cEmptyUserOp: UserOperation = {
sender: AddressZero,
Expand Down Expand Up @@ -154,7 +155,10 @@ describe('#ValidationManager', () => {

const unsafe = !await supportsDebugTraceCall(provider, false)
const preVerificationGasCalculator = new PreVerificationGasCalculator(MainnetConfig)
vm = new ValidationManager(entryPoint, unsafe, preVerificationGasCalculator)

const senderCreator = '0xefc2c1444ebcc4db75e7613d20c6a62ff67a167c'
const erc7562Parser = new ERC7562Parser(entryPoint.address, senderCreator)
vm = new ValidationManager(entryPoint, unsafe, preVerificationGasCalculator, erc7562Parser)

if (!await supportsDebugTraceCall(ethers.provider, false)) {
console.log('WARNING: opcode banning tests can only run with geth')
Expand Down
2 changes: 0 additions & 2 deletions packages/utils/src/interfaces/OperationBase.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { BigNumberish, BytesLike } from 'ethers'

import { EIP7702Authorization } from './EIP7702Authorization'

/**
* The operation interface that is shared by ERC-4337 and RIP-7560 types.
*/
Expand Down
3 changes: 2 additions & 1 deletion packages/validation-manager/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
"@ethersproject/properties": "^5.7.0",
"@ethersproject/providers": "^5.7.0",
"debug": "^4.3.4",
"ethers": "^5.7.0"
"ethers": "^5.7.0",
"ow": "^0.28.1"
},
"devDependencies": {}
}
11 changes: 11 additions & 0 deletions packages/validation-manager/src/AccountAbstractionEntity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export enum AccountAbstractionEntity {
account = 'account',
paymaster = 'paymaster',
factory = 'factory',
aggregator = 'aggregator',
senderCreator = 'SenderCreator',
entryPoint = 'EntryPoint',
nativeEntryPoint = 'NativeEntryPoint',
nativeNonceManager = 'NativeNonceManager',
none = 'none'
}
14 changes: 9 additions & 5 deletions packages/validation-manager/src/BundlerCollectorTracer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,17 @@ export interface ExitInfo {
data: string
}

export interface StorageAccessInfos { [address: string]: AccessInfo }
export interface OpcodeInfos { [address: string]: number }
export interface ContractSizes { [address: string]: ContractSizeInfo }
export interface ExtCodeAccessInfos { [address: string]: string }

export interface TopLevelCallInfo {
// topLevelMethodSig: string
topLevelTargetAddress: string
opcodes: { [opcode: string]: number }
access: { [address: string]: AccessInfo }
contractSize: { [addr: string]: ContractSizeInfo }
extCodeAccessInfo: { [addr: string]: string }
opcodes: OpcodeInfos
access: StorageAccessInfos
contractSize: ContractSizes
extCodeAccessInfo: ExtCodeAccessInfos
oog?: boolean
calls?: []
type?: string
Expand Down
31 changes: 31 additions & 0 deletions packages/validation-manager/src/ERC7562BannedOpcodes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* [OP-011] the opcodes banned for all entities.
*/
export const bannedOpCodes = new Set(
[
'BASEFEE',
'BLOCKHASH',
'COINBASE',
'DIFFICULTY',
'GAS',
'GASLIMIT',
'GASPRICE',
'INVALID',
'NUMBER',
'ORIGIN',
'PREVRANDAO',
'RANDOM',
'SELFDESTRUCT',
'TIMESTAMP'
]
)

/**
* [OP-080] the opcodes allowed in staked entities.
*/
export const opcodesOnlyInStakedEntities = new Set(
[
'BALANCE',
'SELFBALANCE'
]
)
76 changes: 76 additions & 0 deletions packages/validation-manager/src/ERC7562Call.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import ow from 'ow'

export interface ContractSize {
contractSize: number
opcode: number
}

export interface AccessedSlots {
reads?: Record<string, string[]>
transientReads?: Record<string, unknown>
transientWrites?: Record<string, unknown>
writes?: Record<string, number>
}

export interface ERC7562Call {
accessedSlots: AccessedSlots
contractSize: Record<string, ContractSize>
error?: string
extCodeAccessInfo: string[]
from: string
gas: string
gasUsed: string
input: string
outOfGas: boolean
output?: string
to: string
type: string
usedOpcodes: Record<number, number>
value?: string
calls?: ERC7562Call[]
keccak?: string[]
}

const contractSizeSchema = ow.object.exactShape({
contractSize: ow.number,
opcode: ow.number
})

const accessedSlotsSchema = ow.object.exactShape({
reads: ow.object.valuesOfType(ow.array.ofType(ow.string)),
transientReads: ow.object,
transientWrites: ow.object,
writes: ow.object.valuesOfType(ow.number)
})

const erc7562CallSchema = ow.object.exactShape({
accessedSlots: accessedSlotsSchema,
contractSize: ow.object.valuesOfType(contractSizeSchema),
error: ow.optional.string,
extCodeAccessInfo: ow.array.ofType(ow.string),
from: ow.string,
gas: ow.string,
gasUsed: ow.string,
input: ow.string,
outOfGas: ow.boolean,
output: ow.optional.string,
to: ow.string,
type: ow.string,
usedOpcodes: ow.object.valuesOfType(ow.number),
value: ow.optional.string,
calls: ow.optional.array,
keccak: ow.optional.array.ofType(ow.string)
})

/**
* Recursively check the calls ow schema.
*/
export function validateERC7562Call (value: ERC7562Call): void {
ow(value, erc7562CallSchema)

if (value.calls != null) {
for (const call of value.calls) {
validateERC7562Call(call)
}
}
}
Loading

0 comments on commit 715ff28

Please sign in to comment.