Skip to content

Bundler does not validate incoming requests #786

@dnpotter

Description

@dnpotter

bundler v1.0.0
abstractjs v1.0.13

abstractjs (via viem and account-abstraction) formats outgoing requests to the bundler, encoding any numeric literals to hex strings. The bundler, on receiving a request, does not reverse the formatting, instead passing the user op unchecked to the request method handler. This can cause valid userOps to be misinterpreted by the application.

An example of this problem is when sending a transaction with a custom paymaster configured in abstractjs' createSmartAccountClient. The gas limits - numeric literals - returned by the paymaster's getPaymasterData method get converted to hex-strings before being sent to the bundler to estimate user operation gas. In the bundler, the gas estimator constructs the packed user op and in the process incorrectly converts the hex-string limits to ascii - huge numbers that cause gas estimation to incorrectly report insufficient funds.

Fortunately, custom paymasters have the option of returning pre-encoded paymasterAndData so this specific example can be worked around.


Detailed example:

Consider the following paymaster client and bundler log...

class PaymasterConfig {
  
  paymasterAddress: string;

  constructor(paymasterAddress: string) {
    this.paymasterAddress = paymasterAddress;
    this.getPaymasterData = this.getPaymasterData.bind(this);
    this.getPaymasterStubData = this.getPaymasterStubData.bind(this);
  }

  async getPaymasterData(params: GetPaymasterDataParameters): Promise<GetPaymasterDataReturnType> {
    return { 
      paymaster: this.paymasterAddress, 
      paymasterData: abiEncode(["address"], [this.paymasterAddress]),
      paymasterVerificationGasLimit: 500_000,
      paymasterPostOpGasLimit: 1_500_000, 
    } 
  }

  async getPaymasterStubData(): Promise<GetPaymasterDataReturnType> {
    return "0x";
  }
}
[10:33:52.110] INFO (54): EP v7 estimateUserOperationGas called, entryPointAddress: 0x0000000071727De22E5E9d8BAf0edAc6f37da032
    module: "api/v3/eth_estimateUserOperationGas/handler.ts"
    chainId: "137"
    requestId: 4
    apiKey: "my_apikey"
[10:33:52.111] INFO (54): userOp received: {"callData":"0xe9ae5c53000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000034f5715961c550fc497832063a98ea34673ad7c8160000000000000000000000000000000000000000000000000000000000000001000000000000000000000000","factory":"0xf0C1dab676AE40CFA72C85A4805B0E711A29827F","factoryData":"0xea6d13ac000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000280000000000000000000000000bd4c9e797a8dbbfdde9c77bc5a5b21acf611db8f0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000020441bede0300000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000000142DcC3C0c49Bf7c0b095F7B7cd7cef30e2c9279050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","nonce":"0xc2f1500000000000000000000000000000000000000000000000000000000000","paymaster":"0x1870F688591aD27Cb5506A3F1a6675294649668d","paymasterData":"0x0000000000000000000000001870f688591ad27cb5506a3f1a6675294649668d","paymasterPostOpGasLimit":"0x16e360","paymasterVerificationGasLimit":"0x7a120","sender":"0x5F38eB7AeC00C43Adc5ACb64EB417a9d192aE013","signature":"0x81d4b4981670cb18f99f0b4a66446df1bf5b204d24cfcb659bf38ba27a4359b5711649ec2423c5e1247245eba2964679b6a1dbb85c992ae40b9b00c6935b02ff1b"} on chainId: 137
    module: "src/common/simulation/BundlerSimulationService.v7.ts"
[10:33:52.111] INFO (54): userOp to be used for estimation: {"callData":"0xe9ae5c53000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000034f5715961c550fc497832063a98ea34673ad7c8160000000000000000000000000000000000000000000000000000000000000001000000000000000000000000","factory":"0xf0C1dab676AE40CFA72C85A4805B0E711A29827F","factoryData":"0xea6d13ac000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000280000000000000000000000000bd4c9e797a8dbbfdde9c77bc5a5b21acf611db8f0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000020441bede0300000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000000142DcC3C0c49Bf7c0b095F7B7cd7cef30e2c9279050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","nonce":"0xc2f1500000000000000000000000000000000000000000000000000000000000","paymaster":"0x1870F688591aD27Cb5506A3F1a6675294649668d","paymasterData":"0x0000000000000000000000001870f688591ad27cb5506a3f1a6675294649668d","paymasterPostOpGasLimit":"0x16e360","paymasterVerificationGasLimit":"0x7a120","sender":"0x5F38eB7AeC00C43Adc5ACb64EB417a9d192aE013","signature":"0x81d4b4981670cb18f99f0b4a66446df1bf5b204d24cfcb659bf38ba27a4359b5711649ec2423c5e1247245eba2964679b6a1dbb85c992ae40b9b00c6935b02ff1b","maxFeePerGas":"1","callGasLimit":"5000000","verificationGasLimit":"5000000","preVerificationGas":"5000000","maxPriorityFeePerGas":"1"} on chainId: 137
    module: "src/common/simulation/BundlerSimulationService.v7.ts"
[10:33:52.111] INFO (54): config:
    module: "src/common/simulation/BundlerSimulationService.v7.ts"
[10:33:52.111] INFO (54): getting baseFeePerGas from gasPriceService
    module: "src/common/simulation/BundlerSimulationService.v7.ts"
[10:33:52.111] INFO (54): GasPriceService.getBaseFeePerGas
    chainId: 137
    key: "BaseFeePerGas_137"
[10:33:52.111] INFO (54): RedisCacheService.get()
    module: "common/cache/redis/RedisCacheService.ts"
    key: "BaseFeePerGas_137"
[10:33:52.113] INFO (54): calling estimateUserOperationGas (v7) from entry-point-gas-estimations package
    module: "src/common/simulation/BundlerSimulationService.v7.ts"
[10:33:52.113] INFO (54): testing console.log 2
    module: "src/common/simulation/BundlerSimulationService.v7.ts"
[10:33:52.113] INFO (54): Estimating gas for user operation (v7)...
    module: "src/common/simulation/BundlerSimulationService.v7.ts"
[10:33:52.113] INFO (54): calling simulateHandleOp
    module: "src/common/simulation/BundlerSimulationService.v7.ts"
[10:33:52.114] INFO (54): Simulating handleOp...
    module: "src/common/simulation/BundlerSimulationService.v7.ts"
[10:33:52.114] INFO (54): Packed User Operation: {"sender":"0x5F38eB7AeC00C43Adc5ACb64EB417a9d192aE013","nonce":"0xc2f1500000000000000000000000000000000000000000000000000000000000","initCode":"0xf0C1dab676AE40CFA72C85A4805B0E711A29827Fea6d13ac000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000280000000000000000000000000bd4c9e797a8dbbfdde9c77bc5a5b21acf611db8f0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000020441bede0300000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000000142DcC3C0c49Bf7c0b095F7B7cd7cef30e2c9279050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","callData":"0xe9ae5c53000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000034f5715961c550fc497832063a98ea34673ad7c8160000000000000000000000000000000000000000000000000000000000000001000000000000000000000000","accountGasLimits":"0x000000000000000000000000004c4b40000000000000000000000000004c4b40","preVerificationGas":"5000000","gasFees":"0x0000000000000000000000000000000100000000000000000000000000000001","paymasterAndData":"0x1870F688591aD27Cb5506A3F1a6675294649668d00000000000000000030783761313230000000000000000030783136653336300000000000000000000000001870f688591ad27cb5506a3f1a6675294649668d","signature":"0x81d4b4981670cb18f99f0b4a66446df1bf5b204d24cfcb659bf38ba27a4359b5711649ec2423c5e1247245eba2964679b6a1dbb85c992ae40b9b00c6935b02ff1b"}
    module: "src/common/simulation/BundlerSimulationService.v7.ts"

The two paymaster gas limits in the 'userOp received' are 0x16e360 (1.5M) and 0x7a120 (500k). The 'Packed User Operation' contains:

"paymasterAndData":"0x1870F688591aD27Cb5506A3F1a6675294649668d00000000000000000030783761313230000000000000000030783136653336300000000000000000000000001870f688591ad27cb5506a3f1a6675294649668d"

with encoded limits of: 30783761313230 and 3078313665333630.

The encoded limits are in fact the ascii representations of the strings 0x7a120 and 0x16e360 respectively.

Cause:

The v3 handler, passes the userOp to the simulator unchecked. The simulator (BundlerSimulationServiceV07) expects the userOp to be type constrained, with the limits expected to be of BigInt type, not hex strings. The simulator uses a gas estimator from the entry-point-gas-estimations library, which packs the user operation using helper functions from it's utils. These helper functions treat all strings as text and convert the limits to ascii.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions