diff --git a/config/default.json b/config/default.json
index 57a08476..45033f5b 100644
--- a/config/default.json
+++ b/config/default.json
@@ -16,7 +16,9 @@
     196, 2810, 997, 713715, 3799, 167009, 80084, 5845, 167000, 1328, 1329, 995,
     28882, 288, 920637907288165, 1740, 1750, 4202, 1135, 2818
   ],
-  "supportedNetworksV07": [84532, 8453, 10, 11155420],
+  "supportedNetworksV07": [
+    84532, 8453, 10, 11155420, 56, 42161, 137, 100, 80084
+  ],
   "EIP1559SupportedNetworks": [
     1, 137, 42161, 10, 43114, 43113, 8453, 59144, 204, 5611, 421614, 11155111,
     84532, 168587773, 81457, 42170, 169, 56400, 11155420, 80002, 27827, 4653,
@@ -32,7 +34,7 @@
     "supportedNetworks": [1, 11155111],
     "confidenceLevel": 99
   },
-  "supportsDebugTraceCall": [1, 11155111],
+  "supportsDebugTraceCall": [],
   "supportedTransactionType": {
     "1": ["BUNDLER"],
     "137": ["BUNDLER"],
@@ -1023,7 +1025,9 @@
   },
   "entryPointV07Data": {
     "0x0000000071727De22E5E9d8BAf0edAc6f37da032": {
-      "supportedChainIds": [84532, 8453, 10, 11155420]
+      "supportedChainIds": [
+        84532, 8453, 10, 11155420, 42161, 56, 42161, 137, 100, 80084
+      ]
     }
   },
   "zeroAddress": "0x0000000000000000000000000000000000000000",
diff --git a/package.json b/package.json
index 7fb8f687..7a141e8c 100644
--- a/package.json
+++ b/package.json
@@ -13,6 +13,7 @@
   },
   "dependencies": {
     "@arbitrum/sdk": "^3.1.3",
+    "@biconomy/gas-estimations": "0.2.51",
     "@slack/web-api": "^6.8.0",
     "@types/config": "^3.3.3",
     "@types/crypto-js": "^4.1.1",
@@ -33,7 +34,6 @@
     "crypto-js": "^4.1.1",
     "dd-trace": "^4.17.0",
     "dotenv": "^16.0.3",
-    "entry-point-gas-estimations": "1.0.2",
     "ethereumjs-util": "^7.1.5",
     "express": "^4.18.2",
     "express-handlebars": "^6.0.6",
@@ -59,11 +59,13 @@
     "rest-api-errors": "^1.2.5",
     "serialize-error": "8.1.0",
     "typescript": "^5.3.3",
-    "viem": "^2.21.28"
+    "viem": "^2.21.49"
   },
   "devDependencies": {
     "@biconomy/account": "^4.5.7",
+    "@biconomy/sdk": "^0.0.19",
     "@eslint/js": "^9.13.0",
+    "@rhinestone/module-sdk": "^0.1.32",
     "@types/amqplib": "^0.8.2",
     "@types/big.js": "^6.1.5",
     "@types/consolidate": "^0.14.1",
diff --git a/src/admin-scripts/getRequiredPrefund.ts b/src/admin-scripts/getRequiredPrefund.ts
index 1b1d1349..34f7d3a6 100644
--- a/src/admin-scripts/getRequiredPrefund.ts
+++ b/src/admin-scripts/getRequiredPrefund.ts
@@ -1,5 +1,6 @@
- 
-function getRequiredPrefund(userOp: {
+import { formatEther } from "viem";
+
+export function getRequiredPrefund(userOp: {
   paymasterAndData: string;
   callGasLimit: bigint;
   verificationGasLimit: bigint;
@@ -17,11 +18,13 @@ function getRequiredPrefund(userOp: {
 }
 
 const prefund = getRequiredPrefund({
-  paymasterAndData: "0x",
-  callGasLimit: 651983n,
-  verificationGasLimit: 1459741n,
-  preVerificationGas: 313507n,
-  maxFeePerGas: 15796905452n,
+  paymasterAndData:
+    "0x00000f79b7faf42eebadba19acc07cd08af447890000000000000000000000005430eac2228c12577ed5179a4dee3aaa56a238a600000000000000000000000000000000000000000000000000000000676469c800000000000000000000000000000000000000000000000000000000676462c0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000413824432901286f0f7794774baa5b55728fdccee0a7884049992c7f82471299477f978db2c8ce464433153e134f39af1a265406475b104bef19aa9cd2758e90da1c00000000000000000000000000000000000000000000000000000000000000",
+  callGasLimit: 24276n,
+  verificationGasLimit: 297166n,
+  preVerificationGas: 493353887n,
+  maxFeePerGas: 16261619n,
 });
 
-console.log(`Required prefund: ${prefund} wei`);
+console.log(`Required prefund: ${formatEther(prefund)} ETH`);
+// old pvg: 523923235734
diff --git a/src/common/constants/index.ts b/src/common/constants/index.ts
index db28d69a..31e10d0a 100644
--- a/src/common/constants/index.ts
+++ b/src/common/constants/index.ts
@@ -50,6 +50,7 @@ export enum BLOCKCHAINS {
   MORPH_MAINNET = 2818,
   MORPH_HOLESKY_TESTNET = 2810,
   FIRECHAIN_TESTNET = 997,
+  FIRECHAIN_MAINNET = 995,
   SEI_DEVNET_ARCTIC_1 = 713715,
   SEI_TESTNET_ATLANTIC_2 = 1328,
   SEI_MAINNET = 1329,
@@ -63,4 +64,7 @@ export enum BLOCKCHAINS {
   METAL_L2_MAINNET = 1750,
   LISK_TESTNET = 4202,
   LISK_MAINNET = 1135,
+  BOBA_SEPOLIA_TESTNET = 28882,
+  BOBA_MAINNET = 288,
+  MOONBEAM_MAINNET = 1284,
 }
diff --git a/src/common/service-manager/index.ts b/src/common/service-manager/index.ts
index e33db589..522b8fcd 100644
--- a/src/common/service-manager/index.ts
+++ b/src/common/service-manager/index.ts
@@ -1,7 +1,6 @@
 import nodeconfig from "config";
 import { getContract, parseEther } from "viem";
 import { chain } from "lodash";
-import { ENTRY_POINT_ABI } from "entry-point-gas-estimations/dist/gas-estimator/entry-point-v6";
 import { config } from "../../config";
 import { EVMAccount, IEVMAccount } from "../../relayer/account";
 import { BundlerConsumer } from "../../relayer/consumer";
@@ -45,8 +44,9 @@ import { UserOperationStateDAO } from "../db/dao/UserOperationStateDAO";
 import { customJSONStringify, parseError } from "../utils";
 import { GasPriceService } from "../gas-price";
 import { CacheFeesJob } from "../gas-price/jobs/CacheFees";
-import { ENTRY_POINT_V07_ABI } from "../entrypoint-v7/abiv7";
 import { FlashbotsClient } from "../network/FlashbotsClient";
+import { ENTRYPOINT_V6_ABI } from "@biconomy/gas-estimations";
+import { ENTRYPOINT_V7_ABI } from "@biconomy/gas-estimations";
 
 const log = logger.child({
   module: module.filename.split("/").slice(-4).join("/"),
@@ -358,7 +358,7 @@ async function setupNetwork(
       entryPointMap[chainId].push({
         address: entryPointAddress,
         entryPointContract: getContract({
-          abi: ENTRY_POINT_ABI,
+          abi: ENTRYPOINT_V6_ABI,
           address: entryPointAddress as `0x${string}`,
           client: {
             public: networkService.provider,
@@ -376,7 +376,7 @@ async function setupNetwork(
       entryPointMapV07[chainId].push({
         address: entryPointAddress,
         entryPointContract: getContract({
-          abi: ENTRY_POINT_V07_ABI,
+          abi: ENTRYPOINT_V7_ABI,
           address: entryPointAddress as `0x${string}`,
           client: {
             public: networkService.provider,
diff --git a/src/common/simulation/BundlerSimulationService.test.ts b/src/common/simulation/BundlerSimulationService.test.ts
deleted file mode 100644
index c633cf25..00000000
--- a/src/common/simulation/BundlerSimulationService.test.ts
+++ /dev/null
@@ -1,157 +0,0 @@
-it.todo("fixme");
-// import { GasEstimator } from "entry-point-gas-estimations/dist/gas-estimator/entry-point-v6/GasEstimator/GasEstimator";
-// import { config } from "../../config";
-// import { GasPriceService } from "../gas-price";
-// import { EVMNetworkService } from "../network";
-// import { UserOperationType } from "../types";
-// import { BundlerSimulationService } from "./BundlerSimulationService";
-// import RpcError from "../utils/rpc-error";
-
-// describe("BundlerSimulationService", () => {
-//   const networkService = new EVMNetworkService({
-//     chainId: 137,
-//     rpcUrl: "https://random-rpc-url.com",
-//   });
-//   const gasPriceService = {} as unknown as GasPriceService;
-//   const bundlerSimulationService = new BundlerSimulationService(
-//     networkService,
-//     gasPriceService,
-//   );
-
-//   describe("user op rejection", () => {
-//     it("user op has insufficient max priority fee per gas", async () => {
-//       bundlerSimulationService.gasEstimator = {
-//         calculatePreVerificationGas: jest.fn().mockResolvedValue(50000n),
-//       } as unknown as GasEstimator;
-//       bundlerSimulationService.gasPriceService = {
-//         getBaseFeePerGas: jest.fn().mockResolvedValue(50000n),
-//       } as unknown as GasPriceService;
-//       const networkMaxFeePerGas = 10n;
-//       const networkMaxPriorityFeePerGas = 10n;
-
-//       const userOp: UserOperationType = {
-//         sender: "0xabc",
-//         nonce: 1n,
-//         initCode: "0x",
-//         callData: "0xdef",
-//         paymasterAndData: "0x",
-//         callGasLimit: 5000n,
-//         verificationGasLimit: 5000n,
-//         preVerificationGas: 5000n,
-//         maxPriorityFeePerGas: 1n,
-//         maxFeePerGas: 10n,
-//         signature: "0xsignature",
-//       };
-
-//       try {
-//         await bundlerSimulationService.checkUserOperationForRejection({
-//           userOp,
-//           networkMaxFeePerGas,
-//           networkMaxPriorityFeePerGas,
-//         });
-//       } catch (error) {
-//         expect((error as RpcError).message).toEqual(
-//           `maxPriorityFeePerGas in userOp: ${userOp.maxPriorityFeePerGas} is lower than expected maxPriorityFeePerGas: ${Number(networkMaxPriorityFeePerGas) * config.maxPriorityFeePerGasThresholdPercentage}`,
-//         );
-//       }
-//     });
-
-//     it("user op has insufficient max fee per gas", async () => {
-//       bundlerSimulationService.gasEstimator = {
-//         calculatePreVerificationGas: jest.fn().mockResolvedValue(50000n),
-//       } as unknown as GasEstimator;
-
-//       const networkMaxFeePerGas = 10n;
-//       const networkMaxPriorityFeePerGas = 10n;
-
-//       const userOp: UserOperationType = {
-//         sender: "0xabc",
-//         nonce: 1n,
-//         initCode: "0x",
-//         callData: "0xdef",
-//         paymasterAndData: "0x",
-//         callGasLimit: 5000n,
-//         verificationGasLimit: 5000n,
-//         preVerificationGas: 5000n,
-//         maxPriorityFeePerGas: 20n,
-//         maxFeePerGas: 1n,
-//         signature: "0xsignature",
-//       };
-//       try {
-//         await bundlerSimulationService.checkUserOperationForRejection({
-//           userOp,
-//           networkMaxFeePerGas,
-//           networkMaxPriorityFeePerGas,
-//         });
-//       } catch (error) {
-//         expect((error as RpcError).message).toEqual(
-//           `maxFeePerGas in userOp: ${userOp.maxFeePerGas} is lower than expected maxFeePerGas: ${Number(networkMaxFeePerGas) * config.maxFeePerGasThresholdPercentage}`,
-//         );
-//       }
-//     });
-
-//     it("user op has insufficient preVerificationGas", async () => {
-//       bundlerSimulationService.gasEstimator = {
-//         calculatePreVerificationGas: jest.fn().mockResolvedValue(50000n),
-//       } as unknown as GasEstimator;
-
-//       const networkMaxFeePerGas = 1n;
-//       const networkMaxPriorityFeePerGas = 1n;
-
-//       const userOp: UserOperationType = {
-//         sender: "0xabc",
-//         nonce: 1n,
-//         initCode: "0x",
-//         callData: "0xdef",
-//         paymasterAndData: "0x",
-//         callGasLimit: 5000n,
-//         verificationGasLimit: 5000n,
-//         preVerificationGas: 5000n,
-//         maxPriorityFeePerGas: 10n,
-//         maxFeePerGas: 10n,
-//         signature: "0xsignature",
-//       };
-//       try {
-//         bundlerSimulationService.checkUserOperationForRejection({
-//           userOp,
-//           networkMaxFeePerGas,
-//           networkMaxPriorityFeePerGas,
-//         });
-//       } catch (error) {
-//         expect((error as RpcError).message).toEqual(
-//           `preVerificationGas in userOp: ${userOp.preVerificationGas} is lower than expected preVerificationGas: ${50000 * config.preVerificationGasThresholdPercentage}`,
-//         );
-//       }
-//     });
-
-//     it("user op has sufficient max fee values and preVerificationGas", async () => {
-//       bundlerSimulationService.gasEstimator = {
-//         calculatePreVerificationGas: jest.fn().mockResolvedValue(5n),
-//       } as unknown as GasEstimator;
-
-//       const networkMaxFeePerGas = 1n;
-//       const networkMaxPriorityFeePerGas = 1n;
-
-//       const userOp: UserOperationType = {
-//         sender: "0xabc",
-//         nonce: 1n,
-//         initCode: "0x",
-//         callData: "0xdef",
-//         paymasterAndData: "0x",
-//         callGasLimit: 5000n,
-//         verificationGasLimit: 5000n,
-//         preVerificationGas: 5000n,
-//         maxPriorityFeePerGas: 10n,
-//         maxFeePerGas: 10n,
-//         signature: "0xsignature",
-//       };
-//       const response =
-//         await bundlerSimulationService.checkUserOperationForRejection({
-//           userOp,
-//           networkMaxFeePerGas,
-//           networkMaxPriorityFeePerGas,
-//         });
-//       expect(response).toBe(true);
-//     });
-//   });
-// });
diff --git a/src/common/simulation/BundlerSimulationService.ts b/src/common/simulation/BundlerSimulationService.ts
index 87969166..bafa953b 100644
--- a/src/common/simulation/BundlerSimulationService.ts
+++ b/src/common/simulation/BundlerSimulationService.ts
@@ -1,18 +1,15 @@
 /* eslint-disable @typescript-eslint/no-explicit-any */
 /* eslint-disable prefer-const */
 import {
-  Address,
   decodeErrorResult,
   encodeAbiParameters,
   encodeFunctionData,
-  Hex,
   keccak256,
   parseAbiParameters,
   toHex,
   zeroAddress,
 } from "viem";
 import nodeconfig from "config";
-import { IGasEstimator } from "entry-point-gas-estimations/dist/gas-estimator/entry-point-v6";
 import { config } from "../../config";
 import { IEVMAccount } from "../../relayer/account";
 import {
@@ -40,7 +37,11 @@ import {
 } from "./types";
 import { BLOCKCHAINS } from "../constants";
 import { IGasPriceService } from "../gas-price";
-import { GasEstimationsAdapter } from "./GasEstimationsWrapper";
+import { UserOperationV6 } from "@biconomy/gas-estimations";
+import { GasEstimator } from "@biconomy/gas-estimations";
+import { createGasEstimator } from "@biconomy/gas-estimations";
+import { isEstimateUserOperationGasResultV6 } from "@biconomy/gas-estimations";
+import { CallTracerResult, findErrorsInTrace } from "./trace";
 
 const log = logger.child({
   module: module.filename.split("/").slice(-4).join("/"),
@@ -73,9 +74,9 @@ export class BundlerSimulationService {
   constructor({
     networkService,
     gasPriceService,
-    gasEstimator = new GasEstimationsAdapter({
+    gasEstimator = createGasEstimator({
       chainId: networkService.chainId,
-      rpcUrl: networkService.rpcUrl,
+      rpc: networkService.provider,
     }),
   }: IBundlerSimulationServiceOptions) {
     this.networkService = networkService;
@@ -87,14 +88,17 @@ export class BundlerSimulationService {
    * Used for pretty printing the service configuration
    * @returns JSON stringified object with API keys removed
    */
-  toJSON(): Omit<IBundlerSimulationServiceOptions, "gasPriceService"> {
+  toJSON(): Omit<
+    IBundlerSimulationServiceOptions,
+    "gasPriceService" | "newGasEstimator"
+  > {
     return {
       networkService: this.networkService,
       gasEstimator: this.gasEstimator,
-      // TODO: add the gasPriceService after you write it's toJSON method
     };
   }
 
+  // TODO: Add option to pass an entrypoint address to the new gas estimator
   async estimateUserOperationGas(
     estimateUserOperationGasData: EstimateUserOperationGasDataType,
   ): Promise<EstimateUserOperationGasReturnType> {
@@ -102,8 +106,6 @@ export class BundlerSimulationService {
       const { userOp, entryPointContract, chainId, stateOverrideSet } =
         estimateUserOperationGasData;
 
-      this.gasEstimator.setEntryPointAddress(entryPointContract.address);
-
       const start = performance.now();
       log.info(
         `userOp received: ${customJSONStringify(
@@ -123,55 +125,14 @@ export class BundlerSimulationService {
           "0x73c3ac716c487ca34bb858247b5ccf1dc354fbaabdd089af3b2ac8e78ba85a4959a2d76250325bd67c11771c31fccda87c33ceec17cc0de912690521bb95ffcb1b";
       }
 
-      // for userOp completeness
-      if (
-        !userOp.maxFeePerGas ||
-        userOp.maxFeePerGas === BigInt(0) ||
-        (userOp.maxFeePerGas as unknown as string) === "0x" ||
-        (userOp.maxFeePerGas as unknown as string) === "0"
-      ) {
-        // setting a non zero value as division with maxFeePerGas will happen
-        userOp.maxFeePerGas = BigInt(1);
-        if (
-          config.optimismNetworks.includes(chainId) ||
-          config.mantleNetworks.includes(chainId)
-        ) {
-          const gasPrice = await this.gasPriceService.getGasPrice();
-          if (typeof gasPrice === "bigint") {
-            userOp.maxFeePerGas = gasPrice;
-          } else {
-            const { maxFeePerGas } = gasPrice;
-            userOp.maxFeePerGas = maxFeePerGas;
-          }
-        }
-      }
-
-      // for userOp completeness
-      userOp.callGasLimit = BigInt(20000000);
-      userOp.verificationGasLimit = BigInt(10000000);
-      userOp.preVerificationGas = BigInt(100000);
-
-      // for userOp completeness
-      if (
-        !userOp.maxPriorityFeePerGas ||
-        userOp.maxPriorityFeePerGas === BigInt(0) ||
-        (userOp.maxPriorityFeePerGas as unknown as string) === "0x" ||
-        (userOp.maxPriorityFeePerGas as unknown as string) === "0"
-      ) {
-        // setting a non zero value as division with maxPriorityFeePerGas will happen
-        userOp.maxPriorityFeePerGas = BigInt(1);
-        if (
-          config.optimismNetworks.includes(chainId) ||
-          config.mantleNetworks.includes(chainId)
-        ) {
-          const gasPrice = await this.gasPriceService.getGasPrice();
-          if (typeof gasPrice === "bigint") {
-            userOp.maxPriorityFeePerGas = gasPrice;
-          } else {
-            const { maxPriorityFeePerGas } = gasPrice;
-            userOp.maxPriorityFeePerGas = maxPriorityFeePerGas;
-          }
-        }
+      const gasPrice = await this.gasPriceService.getGasPrice();
+      if (typeof gasPrice === "bigint") {
+        userOp.maxFeePerGas = gasPrice;
+        userOp.maxPriorityFeePerGas = gasPrice;
+      } else {
+        const { maxFeePerGas } = gasPrice;
+        userOp.maxFeePerGas = maxFeePerGas;
+        userOp.maxPriorityFeePerGas = maxFeePerGas;
       }
 
       log.info(
@@ -180,22 +141,6 @@ export class BundlerSimulationService {
         )} on chainId: ${chainId}`,
       );
 
-      let supportsEthCallStateOverride = true;
-      let supportsEthCallByteCodeOverride = true;
-      if (config.networksNotSupportingEthCallStateOverrides.includes(chainId)) {
-        supportsEthCallStateOverride = false;
-      } else if (
-        config.networksNotSupportingEthCallBytecodeStateOverrides.includes(
-          chainId,
-        )
-      ) {
-        supportsEthCallByteCodeOverride = false;
-      }
-
-      if (userOp.initCode !== "0x") {
-        supportsEthCallByteCodeOverride = false;
-      }
-
       let baseFeePerGas = await this.gasPriceService.getBaseFeePerGas();
       if (chainId === BLOCKCHAINS.OP_BNB_MAINNET && baseFeePerGas === 0n) {
         baseFeePerGas = BigInt(
@@ -204,18 +149,25 @@ export class BundlerSimulationService {
       }
 
       const response = await this.gasEstimator.estimateUserOperationGas({
-        userOperation: userOp,
-        stateOverrideSet,
-        supportsEthCallByteCodeOverride,
-        supportsEthCallStateOverride,
+        unEstimatedUserOperation: userOp,
         baseFeePerGas,
+        stateOverrides: stateOverrideSet,
+        partialOptions: {
+          entryPointAddress: entryPointContract.address,
+        },
       });
+
       log.info(
-        `estimation respone from gas estimation package: ${customJSONStringify(
-          response,
-        )} on chainId: ${chainId}`,
+        { chainId },
+        `estimateUserOperationGas: ${customJSONStringify(response)}`,
       );
 
+      if (!isEstimateUserOperationGasResultV6(response)) {
+        throw new Error(
+          "Invalid response from the gas estimator. Expected a V6 response.",
+        );
+      }
+
       const { validAfter, validUntil } = response;
       let { verificationGasLimit, callGasLimit, preVerificationGas } = response;
 
@@ -258,6 +210,7 @@ export class BundlerSimulationService {
         callGasLimit +
         BigInt(verificationGasLimitMultiplier) * verificationGasLimit +
         preVerificationGas;
+
       log.info(`totalGas: ${totalGas} on chainId: ${chainId}`);
 
       const pvgMarkUp = config.pvgMarkUp[chainId] || 0.1; // setting default pvgMarkUp to 10% incase the value for a given chainId is not set
@@ -507,6 +460,8 @@ export class BundlerSimulationService {
     validationData: ValidationData,
     entryPointContract: EntryPointContractType,
   ): Promise<boolean> {
+    // TODO: Check if balance >= required prefund if wallet deployment because we can't simulate deployment tx's
+
     const { userOp, networkMaxFeePerGas, networkMaxPriorityFeePerGas } =
       validationData;
 
@@ -575,22 +530,27 @@ export class BundlerSimulationService {
       );
     }
 
-    // Check the user operation for validation and execution errors (if debug_traceCall is supported)
-    if (
-      nodeconfig.has("supportsDebugTraceCall") &&
-      nodeconfig
-        .get<number[]>("supportsDebugTraceCall")
-        .includes(this.networkService.chainId)
-    ) {
-      await this.validateUserOperation(entryPointContract, userOp);
-    }
-
     if (!config.disableFeeValidation.includes(this.networkService.chainId)) {
-      const { preVerificationGas: networkPreVerificationGas } =
-        await this.gasEstimator.calculatePreVerificationGas({
-          userOperation: userOp,
-          baseFeePerGas,
-        });
+      const userOperation: UserOperationV6 = {
+        sender: userOp.sender,
+        nonce: userOp.nonce,
+        initCode: userOp.initCode,
+        paymasterAndData: userOp.paymasterAndData,
+        signature: userOp.signature,
+        maxFeePerGas: BigInt(maxFeePerGas),
+        maxPriorityFeePerGas: BigInt(maxPriorityFeePerGas),
+        callData: userOp.callData,
+        callGasLimit: BigInt(userOp.callGasLimit),
+        verificationGasLimit: BigInt(userOp.verificationGasLimit),
+        preVerificationGas: BigInt(preVerificationGas),
+      };
+
+      const networkPreVerificationGas =
+        await this.gasEstimator.estimatePreVerificationGas(
+          userOperation,
+          BigInt(baseFeePerGas),
+        );
+
       log.info(`networkPreVerificationGas: ${networkPreVerificationGas}`);
 
       const minimumAcceptablePreVerificationGas =
@@ -608,99 +568,58 @@ export class BundlerSimulationService {
       }
     }
 
-    log.info(
-      `maxFeePerGas, maxPriorityFeePerGas and preVerification are within acceptable limits`,
-    );
-    return true;
-  }
-
-  /**
-   * Simulation checks for validation and execution errors when submitting a user operation to the EntryPoint contract
-   * @param entryPointContract EntryPoint contract to simulate against
-   * @param userOp User operation to simulate
-   */
-  private async validateUserOperation(
-    entryPointContract: EntryPointContractType,
-    userOp: UserOperationType,
-  ) {
-    try {
-      // We call debug_traceCall to simulation stack trace
-      const traceResult = await this.debugTraceCall(entryPointContract, userOp);
+    // Check the user operation for validation and execution errors (if debug_traceCall is supported)
+    if (
+      // we can't simulate deployment transactions, they will fail because of insufficient entrypoint deposit
+      userOp.initCode === "0x" &&
+      nodeconfig.has("supportsDebugTraceCall") &&
+      nodeconfig
+        .get<number[]>("supportsDebugTraceCall")
+        .includes(this.networkService.chainId)
+    ) {
+      const traceStart = performance.now();
+
+      const traceResult: CallTracerResult =
+        await this.networkService.provider.request({
+          method: "debug_traceCall" as any, // coalesce so viem doesn't complain
+          params: [
+            {
+              from: zeroAddress, // so we don't get balance errors
+              to: entryPointContract.address,
+              data: encodeFunctionData({
+                abi: entryPointContract.abi,
+                functionName: "handleOps",
+                args: [[userOp], "0xc75Bb3956c596efc6DB663cd3e2f64929d6AB0fc"],
+              }),
+            },
+            "latest",
+            {
+              tracer: "callTracer",
+              tracerConfig: {
+                onlyTopCall: false, // we need deep traces
+                disableStack: false, // and we want the stack
+                enableReturnData: true, // and the return data so we can decode the error
+              },
+            },
+          ],
+        });
+      const traceEnd = performance.now();
 
-      // simulateValidationShould always return a revert, otherwise something is terribly wrong 😱
-      if (!isReverted(traceResult)) {
-        logger.error(
-          `simulateValidation: didn't revert, traceResult: ${customJSONStringify(traceResult)}`,
-        );
-        throw new RpcError(
-          "Simulation failed",
-          BUNDLER_ERROR_CODES.INTERNAL_SERVER_ERROR,
-        );
-      }
+      log.info(`debug_traceCall took ${traceEnd - traceStart} milliseconds`);
 
-      // we try to decode the error message against the EP contract ABI
-      const { errorName, args } = decodeErrorResult({
-        abi: entryPointContract.abi,
-        data: traceResult.output,
-      });
+      const errors = findErrorsInTrace(traceResult, []);
 
-      // When simulation is successfull it returns {errorName: ValidationResult, args: [...]},
-      // and (for example) this is what a signature error looks like: { errorName: FailedOp, args: [0,AA23 reverted (or OOG)] }
-      if (errorName !== "ValidationResult") {
-        logger.warn(
-          `simulateValidation: errorName: ${errorName}, args: ${customJSONStringify(args)}`,
-        );
-        throw new RpcError(
-          `${errorName}: ${args[1]}`,
-          BUNDLER_ERROR_CODES.WALLET_TRANSACTION_REVERTED,
-        );
+      if (errors.length > 0) {
+        log.info(`Errors found in trace: ${customJSONStringify(errors)}`);
+        log.info(customJSONStringify(traceResult));
+        throw new Error(errors.join(", "));
       }
-    } catch (error: any) {
-      // this is a sanity check, in case debug_traceCall fails for whatever reason
-      logger.error(
-        { error: customJSONStringify(error) },
-        `simulateUserOp failed`,
-      );
-      throw new Error(error);
     }
-  }
 
-  /**
-   * Calls the debug_traceCall RPC method to simulate the validation of a user operation.
-   * See the following links for more information:
-   * - https://geth.ethereum.org/docs/interacting-with-geth/rpc/ns-debug#javascript-based-tracing
-   * - https://docs.chainstack.com/reference/ethereum-tracecall
-   * @param entryPointContract The entry point contract
-   * @param userOp The user operation to be traced
-   * @returns CallTracerResult
-   */
-  private async debugTraceCall(
-    entryPointContract: EntryPointContractType,
-    userOp: UserOperationType,
-  ): Promise<CallTracerResult> {
-    return this.networkService.provider.request({
-      method: "debug_traceCall" as any, // coalesce so viem doesn't complain
-      params: [
-        {
-          from: zeroAddress, // so we don't get balance errors
-          to: entryPointContract.address,
-          data: encodeFunctionData({
-            abi: entryPointContract.abi,
-            functionName: "simulateValidation",
-            args: [userOp] as any,
-          }),
-        },
-        "latest",
-        {
-          tracer: "callTracer",
-          tracerConfig: {
-            onlyTopCall: true, // don't need deep traces
-            disableStack: false, // but we want the stack
-            enableReturnData: true, // and the return data so we can decode the error
-          },
-        },
-      ],
-    });
+    log.info(
+      `maxFeePerGas, maxPriorityFeePerGas and preVerification are within acceptable limits`,
+    );
+    return true;
   }
 
   removeSpecialCharacters(input: string): string {
@@ -736,15 +655,6 @@ export class BundlerSimulationService {
   }
 }
 
-/**
- * Checks if the trace result is reverted
- * @param traceResult The result of the trace call
- * @returns true if the trace result is reverted
- */
-function isReverted(traceResult: CallTracerResult) {
-  return traceResult.error.toLowerCase().includes("reverted");
-}
-
 // The following are the dependencies of the BundlerSimulationService class
 
 // 💡 TIP: Always pick only the required fields from the interface
@@ -755,20 +665,6 @@ export type SimulationNetworkService = Pick<
 >;
 
 export type SimulationGasEstimator = Pick<
-  IGasEstimator,
-  | "estimateUserOperationGas"
-  | "setEntryPointAddress"
-  | "calculatePreVerificationGas"
+  GasEstimator,
+  "estimateUserOperationGas" | "estimatePreVerificationGas"
 >;
-
-interface CallTracerResult {
-  from: Address;
-  gas: Hex;
-  gasUsed: Hex;
-  to: Address;
-  input: Hex;
-  output: Hex;
-  value: Hex;
-  type: string;
-  error: string;
-}
diff --git a/src/common/simulation/BundlerSimulationService.v7.ts b/src/common/simulation/BundlerSimulationService.v7.ts
index d21c4b07..ec6186f4 100644
--- a/src/common/simulation/BundlerSimulationService.v7.ts
+++ b/src/common/simulation/BundlerSimulationService.v7.ts
@@ -1,12 +1,11 @@
 /* eslint-disable @typescript-eslint/no-explicit-any */
 /* eslint-disable prefer-const */
-import { decodeErrorResult, encodeFunctionData, toHex } from "viem";
 import {
-  createGasEstimator,
-  createOptimismGasEstimator,
-  EstimateUserOperationGas,
-  IGasEstimator,
-} from "entry-point-gas-estimations/dist/gas-estimator/entry-point-v7";
+  decodeErrorResult,
+  encodeFunctionData,
+  toHex,
+  zeroAddress,
+} from "viem";
 import { config } from "../../config";
 import { IEVMAccount } from "../../relayer/account";
 import {
@@ -15,7 +14,11 @@ import {
 } from "../../server/api/shared/middleware";
 import { logger } from "../logger";
 import { INetworkService } from "../network";
-import { EVMRawTransactionType, UserOperationType } from "../types";
+import {
+  EntryPointV07ContractType,
+  EVMRawTransactionType,
+  UserOperationType,
+} from "../types";
 import { customJSONStringify, parseError } from "../utils";
 import RpcError from "../utils/rpc-error";
 import {
@@ -30,6 +33,16 @@ import {
   getUserOpHash,
   packUserOperation,
 } from "../entrypoint-v7/PackedUserOperation";
+import { GasEstimator } from "@biconomy/gas-estimations";
+import { createGasEstimator } from "@biconomy/gas-estimations";
+import {
+  EstimateUserOperationGasResult,
+  isEstimateUserOperationGasResultV7,
+} from "@biconomy/gas-estimations";
+import nodeconfig from "config";
+import { CallTracerResult, findErrorsInTrace } from "./trace";
+import { toPackedUserOperation } from "@biconomy/gas-estimations";
+import { ZodError } from "zod";
 
 const log = logger.child({
   module: module.filename.split("/").slice(-4).join("/"),
@@ -41,7 +54,7 @@ export class BundlerSimulationServiceV07 {
 
   gasPriceService: IGasPriceService;
 
-  gasEstimator: IGasEstimator;
+  gasEstimator: GasEstimator;
 
   constructor(
     networkService: INetworkService<IEVMAccount, EVMRawTransactionType>,
@@ -50,16 +63,9 @@ export class BundlerSimulationServiceV07 {
     this.networkService = networkService;
     this.gasPriceService = gasPriceService;
     this.gasEstimator = createGasEstimator({
-      rpcUrl: this.networkService.rpcUrl,
-      chainId: this.networkService.chainId,
+      chainId: networkService.chainId,
+      rpc: networkService.provider,
     });
-
-    if (config.optimismNetworks.includes(this.networkService.chainId)) {
-      this.gasEstimator = createOptimismGasEstimator({
-        rpcUrl: this.networkService.rpcUrl,
-        chainId: this.networkService.chainId,
-      });
-    }
   }
 
   async estimateUserOperationGas(
@@ -69,8 +75,6 @@ export class BundlerSimulationServiceV07 {
       const { userOp, entryPointContract, chainId, stateOverrideSet } =
         estimateUserOperationGasData;
 
-      this.gasEstimator.setEntryPointAddress(entryPointContract.address);
-
       const start = performance.now();
       log.info(
         `userOp received: ${customJSONStringify(
@@ -78,58 +82,23 @@ export class BundlerSimulationServiceV07 {
         )} on chainId: ${chainId}`,
       );
 
-      // for userOp completeness
-      if (
-        !userOp.maxFeePerGas ||
-        userOp.maxFeePerGas === BigInt(0) ||
-        (userOp.maxFeePerGas as unknown as string) === "0x" ||
-        (userOp.maxFeePerGas as unknown as string) === "0"
-      ) {
-        // setting a non zero value as division with maxFeePerGas will happen
-        userOp.maxFeePerGas = BigInt(1);
-        if (
-          config.optimismNetworks.includes(chainId) ||
-          config.mantleNetworks.includes(chainId)
-        ) {
-          const gasPrice = await this.gasPriceService.getGasPrice();
-          if (typeof gasPrice === "bigint") {
-            userOp.maxFeePerGas = gasPrice;
-          } else {
-            const { maxFeePerGas } = gasPrice;
-            userOp.maxFeePerGas = maxFeePerGas;
-          }
-        }
+      const gasPrice = await this.gasPriceService.getGasPrice();
+      if (typeof gasPrice === "bigint") {
+        userOp.maxFeePerGas = gasPrice;
+        userOp.maxPriorityFeePerGas = gasPrice;
+      } else {
+        const { maxFeePerGas } = gasPrice;
+        userOp.maxFeePerGas = maxFeePerGas;
+        userOp.maxPriorityFeePerGas = maxFeePerGas;
       }
 
       // for userOp completeness
       userOp.callGasLimit = BigInt(5000000);
       userOp.verificationGasLimit = BigInt(5000000);
       userOp.preVerificationGas = BigInt(5000000);
-      userOp.maxPriorityFeePerGas = BigInt(userOp.maxPriorityFeePerGas);
-      userOp.maxFeePerGas = BigInt(userOp.maxFeePerGas);
 
-      // for userOp completeness
-      if (
-        !userOp.maxPriorityFeePerGas ||
-        userOp.maxPriorityFeePerGas === BigInt(0) ||
-        (userOp.maxPriorityFeePerGas as unknown as string) === "0x" ||
-        (userOp.maxPriorityFeePerGas as unknown as string) === "0"
-      ) {
-        // setting a non zero value as division with maxPriorityFeePerGas will happen
-        userOp.maxPriorityFeePerGas = BigInt(1);
-        if (
-          config.optimismNetworks.includes(chainId) ||
-          config.mantleNetworks.includes(chainId)
-        ) {
-          const gasPrice = await this.gasPriceService.getGasPrice();
-          if (typeof gasPrice === "bigint") {
-            userOp.maxPriorityFeePerGas = gasPrice;
-          } else {
-            const { maxPriorityFeePerGas } = gasPrice;
-            userOp.maxPriorityFeePerGas = maxPriorityFeePerGas;
-          }
-        }
-      }
+      userOp.factory = userOp.factory ?? "0x";
+      userOp.factoryData = userOp.factoryData ?? "0x";
 
       log.info(
         `userOp to be used for estimation: ${customJSONStringify(
@@ -137,40 +106,32 @@ export class BundlerSimulationServiceV07 {
         )} on chainId: ${chainId}`,
       );
 
-      let supportsEthCallStateOverride = true;
-      let supportsEthCallByteCodeOverride = true;
-      if (config.networksNotSupportingEthCallStateOverrides.includes(chainId)) {
-        supportsEthCallStateOverride = false;
-      } else if (
-        config.networksNotSupportingEthCallBytecodeStateOverrides.includes(
-          chainId,
-        )
-      ) {
-        supportsEthCallByteCodeOverride = false;
-      }
-
-      let response: EstimateUserOperationGas;
       const baseFeePerGas = await this.gasPriceService.getBaseFeePerGas();
 
+      let response: EstimateUserOperationGasResult;
       try {
         response = await this.gasEstimator.estimateUserOperationGas({
-          userOperation: userOp,
-          stateOverrideSet,
-          supportsEthCallByteCodeOverride,
-          supportsEthCallStateOverride,
+          unEstimatedUserOperation: userOp,
           baseFeePerGas,
+          stateOverrides: stateOverrideSet,
+          partialOptions: {
+            entryPointAddress: entryPointContract.address,
+          },
         });
-
-        log.info(
-          `estimation response from gas estimation package: ${customJSONStringify(
-            response,
-          )} on chainId: ${chainId}`,
-        );
       } catch (error: any) {
+        let errorMessage: string = error.message;
+
         log.error(
-          `[entry-point-gas-estimations] package threw an error: ${error.message}`,
+          { chainId },
+          `[@biconomy/gas-estimations] package threw an error: ${errorMessage}`,
+        );
+        throw errorMessage;
+      }
+
+      if (!isEstimateUserOperationGasResultV7(response)) {
+        throw new Error(
+          "Invalid response from the gas estimator. Expected a V7 response.",
         );
-        throw error;
       }
 
       let {
@@ -181,6 +142,11 @@ export class BundlerSimulationServiceV07 {
         paymasterVerificationGasLimit,
       } = response;
 
+      log.info(
+        { chainId },
+        `estimateUserOperationGas: ${customJSONStringify(response)}`,
+      );
+
       callGasLimit += BigInt(Math.ceil(Number(callGasLimit) * 0.1));
       verificationGasLimit += BigInt(
         Math.ceil(Number(verificationGasLimit) * 0.1),
@@ -192,17 +158,20 @@ export class BundlerSimulationServiceV07 {
         Math.ceil(Number(paymasterVerificationGasLimit) * 0.1),
       );
 
-      const verificationGasLimitMultiplier = userOp.paymaster === "0x" ? 1 : 3;
-      const totalGas =
+      const requiredGas =
+        verificationGasLimit +
         callGasLimit +
-        BigInt(verificationGasLimitMultiplier) * verificationGasLimit +
+        preVerificationGas +
+        paymasterVerificationGasLimit +
+        paymasterPostOpGasLimit +
         preVerificationGas;
-      log.info(`totalGas: ${totalGas} on chainId: ${chainId}`);
+
+      log.info({ chainId }, `requiredGas: ${requiredGas}`);
 
       const pvgMarkUp = config.pvgMarkUp[chainId] || 0.1; // setting default pvgMarkUp to 10% incase the value for a given chainId is not set
 
       preVerificationGas += BigInt(
-        Math.ceil(Number(toHex(totalGas)) * pvgMarkUp),
+        Math.ceil(Number(toHex(requiredGas)) * pvgMarkUp),
       );
 
       log.info(
@@ -254,6 +223,10 @@ export class BundlerSimulationServiceV07 {
     try {
       const { userOp, entryPointContract, chainId } = simulateValidationData;
 
+      // for userOp completeness
+      userOp.factory = userOp.factory ?? "0x";
+      userOp.factoryData = userOp.factoryData ?? "0x";
+
       log.info(
         `userOp received: ${customJSONStringify(
           userOp,
@@ -264,11 +237,14 @@ export class BundlerSimulationServiceV07 {
         await this.gasPriceService.get1559GasPrice();
       let gasPrice = Math.ceil(Number(maxFeePerGas) * 2).toString(16);
 
-      await this.checkUserOperationForRejection({
-        userOp,
-        networkMaxPriorityFeePerGas: maxPriorityFeePerGas,
-        networkMaxFeePerGas: maxFeePerGas,
-      });
+      await this.checkUserOperationForRejection(
+        {
+          userOp,
+          networkMaxPriorityFeePerGas: maxPriorityFeePerGas,
+          networkMaxFeePerGas: maxFeePerGas,
+        },
+        entryPointContract,
+      );
 
       const packed = packUserOperation(userOp);
       const data = encodeFunctionData({
@@ -444,7 +420,10 @@ export class BundlerSimulationServiceV07 {
    */
   async checkUserOperationForRejection(
     validationData: ValidationDataV07,
+    entryPointContract: EntryPointV07ContractType,
   ): Promise<boolean> {
+    // TODO: Check if balance >= required prefund if wallet deployment because we can't simulate deployment tx's
+
     const { userOp, networkMaxFeePerGas, networkMaxPriorityFeePerGas } =
       validationData;
 
@@ -499,11 +478,11 @@ export class BundlerSimulationServiceV07 {
 
     const baseFeePerGas = await this.gasPriceService.getBaseFeePerGas();
 
-    const { preVerificationGas: networkPreVerificationGas } =
-      await this.gasEstimator.calculatePreVerificationGas({
-        userOperation: userOp,
-        baseFeePerGas,
-      });
+    const networkPreVerificationGas =
+      await this.gasEstimator.estimatePreVerificationGas(
+        userOp,
+        BigInt(baseFeePerGas),
+      );
     log.info(`networkPreVerificationGas: ${networkPreVerificationGas}`);
 
     const minimumAcceptablePreVerificationGas =
@@ -519,6 +498,64 @@ export class BundlerSimulationServiceV07 {
       );
     }
 
+    // Check the user operation for validation and execution errors (if debug_traceCall is supported)
+    if (
+      // we can't simulate deployment transactions, they will fail because of insufficient entrypoint deposit
+      userOp.factory === "0x" &&
+      userOp.factoryData === "0x" &&
+      nodeconfig.has("supportsDebugTraceCall") &&
+      nodeconfig
+        .get<number[]>("supportsDebugTraceCall")
+        .includes(this.networkService.chainId)
+    ) {
+      const traceStart = performance.now();
+
+      const packedUserOperation = toPackedUserOperation(userOp);
+
+      log.info(
+        { chainId: this.networkService.chainId },
+        `packedUserOperation: ${customJSONStringify(packedUserOperation)}`,
+      );
+      const traceResult: CallTracerResult =
+        await this.networkService.provider.request({
+          method: "debug_traceCall" as any, // coalesce so viem doesn't complain
+          params: [
+            {
+              from: zeroAddress, // so we don't get balance errors
+              to: entryPointContract.address,
+              data: encodeFunctionData({
+                abi: entryPointContract.abi,
+                functionName: "handleOps",
+                args: [
+                  [packedUserOperation],
+                  "0xc75Bb3956c596efc6DB663cd3e2f64929d6AB0fc",
+                ],
+              }),
+            },
+            "latest",
+            {
+              tracer: "callTracer",
+              tracerConfig: {
+                onlyTopCall: false, // we need deep traces
+                disableStack: false, // and we want the stack
+                enableReturnData: true, // and the return data so we can decode the error
+              },
+            },
+          ],
+        });
+      const traceEnd = performance.now();
+
+      log.info(`debug_traceCall took ${traceEnd - traceStart} milliseconds`);
+
+      const errors = findErrorsInTrace(traceResult, []);
+
+      if (errors.length > 0) {
+        log.info(`Errors found in trace: ${customJSONStringify(errors)}`);
+        log.info(customJSONStringify(traceResult));
+        throw new Error(errors.join(", "));
+      }
+    }
+
     log.info(
       `maxFeePerGas, maxPriorityFeePerGas and preVerification are within acceptable limits`,
     );
diff --git a/src/common/simulation/GasEstimationsWrapper.ts b/src/common/simulation/GasEstimationsWrapper.ts
deleted file mode 100644
index 0c842b3b..00000000
--- a/src/common/simulation/GasEstimationsWrapper.ts
+++ /dev/null
@@ -1,175 +0,0 @@
-import {
-  CalculatePreVerificationGas,
-  CalculatePreVerificationGasParams,
-  createArbitrumGasEstimator,
-  createGasEstimator,
-  createKakarotGasEstimator,
-  createMantleGasEstimator,
-  createMorphGasEstimator,
-  createOptimismGasEstimator,
-  createScrollGasEstimator,
-  createSeiGasEstimator,
-  EstimateUserOperationGas,
-  EstimateUserOperationGasParams,
-} from "entry-point-gas-estimations/dist/gas-estimator/entry-point-v6";
-import { SimulationGasEstimator } from "./BundlerSimulationService";
-import config from "config";
-import { hideRpcUrlApiKey } from "../network/utils";
-
-/**
- * The following is the adapter for the gas estimations class exposed by the entry-point-gas-estimations package.
- * Because the original class is not designed properly, we wrap it with this adapter to make it more usable.
- */
-export class GasEstimationsAdapter implements SimulationGasEstimator {
-  public readonly chainId: number;
-  public readonly rpcUrl: string;
-
-  private wrappedGasEstimator: {
-    estimator: SimulationGasEstimator;
-    type: estimatorTypeChoices;
-  };
-
-  constructor({
-    chainId,
-    rpcUrl,
-    gasEstimator = factoryCreateGasEstimator({ chainId, rpcUrl }),
-  }: IGasEstimationsAdapterOptions) {
-    this.chainId = chainId;
-    this.rpcUrl = rpcUrl;
-    this.wrappedGasEstimator = gasEstimator;
-  }
-
-  /**
-   * Used for pretty printing the service configuration
-   * @returns JSON stringified object with API keys removed
-   */
-  toJSON(): Omit<IGasEstimationsAdapterOptions, "gasEstimator"> & {
-    type: estimatorTypeChoices;
-  } {
-    return {
-      chainId: this.chainId,
-      rpcUrl: hideRpcUrlApiKey(this.rpcUrl),
-      type: this.wrappedGasEstimator.type,
-    };
-  }
-
-  setEntryPointAddress(entryPointAddress: `0x${string}`): void {
-    return this.wrappedGasEstimator.estimator.setEntryPointAddress(
-      entryPointAddress,
-    );
-  }
-
-  estimateUserOperationGas(
-    params: EstimateUserOperationGasParams,
-  ): Promise<EstimateUserOperationGas> {
-    return this.wrappedGasEstimator.estimator.estimateUserOperationGas(params);
-  }
-
-  calculatePreVerificationGas(
-    params: CalculatePreVerificationGasParams,
-  ): Promise<CalculatePreVerificationGas> {
-    return this.wrappedGasEstimator.estimator.calculatePreVerificationGas(
-      params,
-    );
-  }
-}
-
-/**
- * A Factory Method for creating the nested gas estimators based on the chainId
- */
-const factoryCreateGasEstimator = ({
-  chainId,
-  rpcUrl,
-}: IGasEstimationsAdapterOptions): {
-  estimator: SimulationGasEstimator;
-  type: estimatorTypeChoices;
-} => {
-  if (config.get<number[]>("optimismNetworks").includes(chainId)) {
-    return {
-      estimator: createOptimismGasEstimator({
-        rpcUrl,
-      }),
-      type: "optimism",
-    };
-  }
-
-  if (config.get<number[]>("arbitrumNetworks").includes(chainId)) {
-    return {
-      estimator: createArbitrumGasEstimator({
-        rpcUrl,
-      }),
-      type: "arbitrum",
-    };
-  }
-
-  if (config.get<number[]>("mantleNetworks").includes(chainId)) {
-    return {
-      estimator: createMantleGasEstimator({
-        rpcUrl,
-      }),
-      type: "mantle",
-    };
-  }
-
-  if (config.get<number[]>("scrollNetworks").includes(chainId)) {
-    return {
-      estimator: createScrollGasEstimator({
-        rpcUrl,
-      }),
-      type: "scroll",
-    };
-  }
-
-  if (config.get<number[]>("morphNetworks").includes(chainId)) {
-    return {
-      estimator: createMorphGasEstimator({
-        rpcUrl,
-      }),
-      type: "morph",
-    };
-  }
-
-  if (config.get<number[]>("seiNetworks").includes(chainId)) {
-    return {
-      estimator: createSeiGasEstimator({
-        rpcUrl,
-      }),
-      type: "sei",
-    };
-  }
-
-  if (config.get<number[]>("kakarotNetworks").includes(chainId)) {
-    return {
-      estimator: createKakarotGasEstimator({
-        rpcUrl,
-      }),
-      type: "kakarot",
-    };
-  }
-
-  return {
-    estimator: createGasEstimator({
-      rpcUrl,
-    }),
-    type: "regular",
-  };
-};
-
-interface IGasEstimationsAdapterOptions {
-  chainId: number;
-  rpcUrl: string;
-  gasEstimator?: {
-    estimator: SimulationGasEstimator;
-    type: estimatorTypeChoices;
-  };
-}
-
-type estimatorTypeChoices =
-  | "regular"
-  | "optimism"
-  | "arbitrum"
-  | "mantle"
-  | "scroll"
-  | "morph"
-  | "sei"
-  | "kakarot";
diff --git a/src/common/simulation/trace.ts b/src/common/simulation/trace.ts
new file mode 100644
index 00000000..191509d9
--- /dev/null
+++ b/src/common/simulation/trace.ts
@@ -0,0 +1,49 @@
+import { Address, Hex } from "viem";
+
+export interface CallTracerResult {
+  from: Address;
+  gas: Hex;
+  gasUsed: Hex;
+  to: Address;
+  input: Hex;
+  output: Hex;
+  value: Hex;
+  type: string;
+  error: string;
+}
+
+export interface TraceCall {
+  from: string;
+  gas: string;
+  gasUsed: string;
+  to: string;
+  input: string;
+  output?: string;
+  error?: string;
+  calls?: TraceCall[];
+  value?: string;
+  type: string;
+}
+
+/**
+ * Recursively checks if any nested call contains errors and returns all errors.
+ * @param trace The top-level trace call object.
+ * @returns An array of errors (if found)
+ */
+export function findErrorsInTrace(
+  trace: TraceCall,
+  errors: string[],
+): string[] {
+  if (trace.error) {
+    errors.push(trace.error);
+  }
+
+  // If there are nested calls, check them recursively
+  if (trace.calls && trace.calls.length > 0) {
+    for (const nestedCall of trace.calls) {
+      findErrorsInTrace(nestedCall, errors);
+    }
+  }
+
+  return errors;
+}
diff --git a/src/common/types/index.ts b/src/common/types/index.ts
index 94696971..415fc702 100644
--- a/src/common/types/index.ts
+++ b/src/common/types/index.ts
@@ -1,8 +1,8 @@
 /* eslint-disable @typescript-eslint/no-explicit-any */
-import { ENTRY_POINT_ABI } from "entry-point-gas-estimations/dist/gas-estimator/entry-point-v6";
 import { GetContractReturnType, Hex } from "viem";
 import { ENTRY_POINT_V07_ABI } from "../entrypoint-v7/abiv7";
 import { EVMAccountInfo } from "../../relayer/account";
+import { ENTRYPOINT_V6_ABI } from "@biconomy/gas-estimations";
 
 export enum TransactionType {
   FUNDING = "FUNDING",
@@ -232,7 +232,7 @@ export type UpdateRequestDataType = {
 };
 
 export type EntryPointContractType = GetContractReturnType<
-  typeof ENTRY_POINT_ABI
+  typeof ENTRYPOINT_V6_ABI
 >;
 
 export type EntryPointV07ContractType = GetContractReturnType<
diff --git a/src/relayer/consumer/BundlerConsumer.ts b/src/relayer/consumer/BundlerConsumer.ts
index ce52f201..a149c98c 100644
--- a/src/relayer/consumer/BundlerConsumer.ts
+++ b/src/relayer/consumer/BundlerConsumer.ts
@@ -1,6 +1,5 @@
 import { ConsumeMessage } from "amqplib";
 import { encodeFunctionData } from "viem";
-import { ENTRY_POINT_ABI } from "entry-point-gas-estimations/dist/gas-estimator/entry-point-v6";
 import { ICacheService } from "../../common/cache";
 import { logger } from "../../common/logger";
 import { IQueue } from "../../common/queue";
@@ -25,6 +24,7 @@ import {
   isUserOpV06,
   packUserOperation,
 } from "../../common/entrypoint-v7/PackedUserOperation";
+import { ENTRYPOINT_V6_ABI } from "@biconomy/gas-estimations";
 
 const log = logger.child({
   module: module.filename.split("/").slice(-4).join("/"),
@@ -88,7 +88,7 @@ export class BundlerConsumer
           let data;
           if (isV06) {
             data = encodeFunctionData({
-              abi: ENTRY_POINT_ABI,
+              abi: ENTRYPOINT_V6_ABI,
               functionName: "handleOps",
               args: [[userOp], activeRelayer.getPublicKey() as `0x${string}`],
             });
diff --git a/src/relayer/transaction-service/EVMTransactionService.ts b/src/relayer/transaction-service/EVMTransactionService.ts
index ec8a2b9d..f32850f2 100644
--- a/src/relayer/transaction-service/EVMTransactionService.ts
+++ b/src/relayer/transaction-service/EVMTransactionService.ts
@@ -1,7 +1,6 @@
 import { Mutex } from "async-mutex";
 import { Hex, TransactionReceipt, decodeFunctionData, toHex } from "viem";
 import { estimateGas } from "viem/linea";
-import { ENTRY_POINT_ABI } from "entry-point-gas-estimations/dist/gas-estimator/entry-point-v6";
 import { ICacheService } from "../../common/cache";
 import { IGasPriceService } from "../../common/gas-price";
 import { logger } from "../../common/logger";
@@ -45,6 +44,7 @@ import { IUserOperationStateDAO } from "../../common/db";
 import { GasPriceType } from "../../common/gas-price/types";
 import { BLOCKCHAINS } from "../../common/constants";
 import pino from "pino";
+import { ENTRYPOINT_V6_ABI } from "@biconomy/gas-estimations";
 
 const log = logger.child({
   module: module.filename.split("/").slice(-4).join("/"),
@@ -573,7 +573,7 @@ export class EVMTransactionService
     let gasLimitOverhead = 50000n;
 
     // Now we need the verificationGasLimit and callGasLimit from the user op.
-    const decodedData = decodeFunctionData({ abi: ENTRY_POINT_ABI, data });
+    const decodedData = decodeFunctionData({ abi: ENTRYPOINT_V6_ABI, data });
     const firstArg = decodedData.args[0];
 
     if (Array.isArray(firstArg) && firstArg.length > 0) {
diff --git a/src/server/api/v2/biconomy_getGasFeeValues/handler.ts b/src/server/api/v2/biconomy_getGasFeeValues/handler.ts
index 32216d60..8522836c 100644
--- a/src/server/api/v2/biconomy_getGasFeeValues/handler.ts
+++ b/src/server/api/v2/biconomy_getGasFeeValues/handler.ts
@@ -3,15 +3,12 @@ import { BUNDLER_ERROR_CODES, STATUSES } from "../../shared/middleware";
 import { logger } from "../../../../common/logger";
 import { gasPriceServiceMap } from "../../../../common/service-manager";
 import { customJSONStringify, parseError } from "../../../../common/utils";
-// import { updateRequest } from '../../auth/UpdateRequest';
 
 const log = logger.child({
   module: module.filename.split("/").slice(-4).join("/"),
 });
 
 export const getGasFeeValues = async (req: Request, res: Response) => {
-  // const bundlerRequestId = req.body.params[6];
-
   try {
     const { id } = req.body;
     const { chainId /* apiKey */ } = req.params;
@@ -25,26 +22,6 @@ export const getGasFeeValues = async (req: Request, res: Response) => {
         )}`,
       );
 
-      // updateRequest({
-      //   chainId: parseInt(chainId, 10),
-      //   apiKey,
-      //   bundlerRequestId,
-      //   rawResponse: {
-      //     jsonrpc: '2.0',
-      //     id: id || 1,
-      //     result: {
-      //       callGasLimit,
-      //       verificationGasLimit,
-      //       preVerificationGas,
-      //       validUntil,
-      //       validAfter,
-      //       maxPriorityFeePerGas: gasPrice?.maxPriorityFeePerGas,
-      //       maxFeePerGas: gasPrice?.maxFeePerGas,
-      //     },
-      //   },
-      //   httpResponseCode: STATUSES.SUCCESS,
-      // });
-
       return res.status(STATUSES.SUCCESS).json({
         jsonrpc: "2.0",
         id: id || 1,
@@ -55,26 +32,6 @@ export const getGasFeeValues = async (req: Request, res: Response) => {
       });
     }
 
-    // updateRequest({
-    //   chainId: parseInt(chainId, 10),
-    //   apiKey,
-    //   bundlerRequestId,
-    //   rawResponse: {
-    //     jsonrpc: '2.0',
-    //     id: id || 1,
-    //     result: {
-    //       callGasLimit,
-    //       verificationGasLimit,
-    //       preVerificationGas,
-    //       validUntil,
-    //       validAfter,
-    //       maxPriorityFeePerGas: gasPrice,
-    //       maxFeePerGas: gasPrice,
-    //     },
-    //   },
-    //   httpResponseCode: STATUSES.SUCCESS,
-    // });
-
     return res.status(STATUSES.SUCCESS).json({
       jsonrpc: "2.0",
       id: id || 1,
@@ -87,20 +44,6 @@ export const getGasFeeValues = async (req: Request, res: Response) => {
     log.error(`Error in getGasFeeValues handler ${parseError(error)}`);
     const { id } = req.body;
 
-    // updateRequest({
-    //   chainId: parseInt(chainId, 10),
-    //   apiKey,
-    //   bundlerRequestId,
-    //   rawResponse: {
-    //     jsonrpc: '2.0',
-    //     id: id || 1,
-    //     error: {
-    //       code: BUNDLER_ERROR_CODES.INTERNAL_SERVER_ERROR,
-    //       message: `Internal Server error: ${parseError(error)}`,
-    //     },
-    //   },
-    //   httpResponseCode: STATUSES.INTERNAL_SERVER_ERROR,
-    // });
     return res.status(STATUSES.INTERNAL_SERVER_ERROR).json({
       jsonrpc: "2.0",
       id: id || 1,
diff --git a/src/server/api/v3/biconomy_getGasFeeValues/handler.ts b/src/server/api/v3/biconomy_getGasFeeValues/handler.ts
index e13d0657..44d9ab49 100644
--- a/src/server/api/v3/biconomy_getGasFeeValues/handler.ts
+++ b/src/server/api/v3/biconomy_getGasFeeValues/handler.ts
@@ -4,120 +4,56 @@ import { BUNDLER_ERROR_CODES, STATUSES } from "../../shared/middleware";
 import { logger } from "../../../../common/logger";
 import { gasPriceServiceMap } from "../../../../common/service-manager";
 import { customJSONStringify, parseError } from "../../../../common/utils";
-// import { updateRequest } from '../../auth/UpdateRequest';
 
 const log = logger.child({
   module: module.filename.split("/").slice(-4).join("/"),
 });
 
 export const getGasFeeValues = async (req: Request, res: Response) => {
-  // const bundlerRequestId = req.body.params[6];
-
   try {
     const { id } = req.body;
     const { chainId /* apiKey */ } = req.params;
 
     const gasPrice = await gasPriceServiceMap[Number(chainId)]?.getGasPrice();
 
+    let maxFeePerGas: bigint;
+    let maxPriorityFeePerGas: bigint;
+
     if (typeof gasPrice !== "bigint") {
       log.info(
         `Gas price for chainId: ${chainId} is: ${customJSONStringify(
           gasPrice,
         )}`,
       );
-
-      // updateRequest({
-      //   chainId: parseInt(chainId, 10),
-      //   apiKey,
-      //   bundlerRequestId,
-      //   rawResponse: {
-      //     jsonrpc: '2.0',
-      //     id: id || 1,
-      //     result: {
-      //       callGasLimit,
-      //       verificationGasLimit,
-      //       preVerificationGas,
-      //       validUntil,
-      //       validAfter,
-      //       maxPriorityFeePerGas: gasPrice?.maxPriorityFeePerGas,
-      //       maxFeePerGas: gasPrice?.maxFeePerGas,
-      //     },
-      //   },
-      //   httpResponseCode: STATUSES.SUCCESS,
-      // });
-
-      return res.status(STATUSES.SUCCESS).json({
-        jsonrpc: "2.0",
-        id: id || 1,
-        result: {
-          slow: {
-            maxPriorityFeePerGas: toHex(
-              gasPrice?.maxPriorityFeePerGas,
-            )?.toString(),
-            maxFeePerGas: toHex(gasPrice?.maxFeePerGas)?.toString(),
-          },
-          standard: {
-            maxPriorityFeePerGas: toHex(
-              gasPrice?.maxPriorityFeePerGas,
-            )?.toString(),
-            maxFeePerGas: toHex(gasPrice?.maxFeePerGas)?.toString(),
-          },
-          fast: {
-            maxPriorityFeePerGas: toHex(
-              gasPrice?.maxPriorityFeePerGas,
-            )?.toString(),
-            maxFeePerGas: toHex(gasPrice?.maxFeePerGas)?.toString(),
-          },
-        },
-      });
+      maxFeePerGas = gasPrice?.maxFeePerGas || 1n;
+      maxPriorityFeePerGas = gasPrice?.maxPriorityFeePerGas || 1n;
+    } else {
+      maxFeePerGas = gasPrice;
+      maxPriorityFeePerGas = gasPrice;
     }
 
-    // updateRequest({
-    //   chainId: parseInt(chainId, 10),
-    //   apiKey,
-    //   bundlerRequestId,
-    //   rawResponse: {
-    //     jsonrpc: '2.0',
-    //     id: id || 1,
-    //     result: {
-    //       callGasLimit,
-    //       verificationGasLimit,
-    //       preVerificationGas,
-    //       validUntil,
-    //       validAfter,
-    //       maxPriorityFeePerGas: gasPrice,
-    //       maxFeePerGas: gasPrice,
-    //     },
-    //   },
-    //   httpResponseCode: STATUSES.SUCCESS,
-    // });
-
     return res.status(STATUSES.SUCCESS).json({
       jsonrpc: "2.0",
       id: id || 1,
       result: {
-        maxPriorityFeePerGas: gasPrice.toString(),
-        maxFeePerGas: gasPrice.toString(),
+        slow: {
+          maxPriorityFeePerGas: toHex(maxPriorityFeePerGas)?.toString(),
+          maxFeePerGas: toHex(maxFeePerGas)?.toString(),
+        },
+        standard: {
+          maxPriorityFeePerGas: toHex(maxPriorityFeePerGas)?.toString(),
+          maxFeePerGas: toHex(maxFeePerGas)?.toString(),
+        },
+        fast: {
+          maxPriorityFeePerGas: toHex(maxPriorityFeePerGas)?.toString(),
+          maxFeePerGas: toHex(maxFeePerGas)?.toString(),
+        },
       },
     });
   } catch (error) {
     log.error(`Error in getGasFeeValues handler ${parseError(error)}`);
     const { id } = req.body;
 
-    // updateRequest({
-    //   chainId: parseInt(chainId, 10),
-    //   apiKey,
-    //   bundlerRequestId,
-    //   rawResponse: {
-    //     jsonrpc: '2.0',
-    //     id: id || 1,
-    //     error: {
-    //       code: BUNDLER_ERROR_CODES.INTERNAL_SERVER_ERROR,
-    //       message: `Internal Server error: ${parseError(error)}`,
-    //     },
-    //   },
-    //   httpResponseCode: STATUSES.INTERNAL_SERVER_ERROR,
-    // });
     return res.status(STATUSES.INTERNAL_SERVER_ERROR).json({
       jsonrpc: "2.0",
       id: id || 1,
diff --git a/src/test/e2e/nativeTransfer.test.ts b/src/test/e2e/nativeTransfer.test.ts
index a0ca9f07..9d987e91 100644
--- a/src/test/e2e/nativeTransfer.test.ts
+++ b/src/test/e2e/nativeTransfer.test.ts
@@ -1,11 +1,26 @@
-import { Chain, createWalletClient, http, PrivateKeyAccount } from "viem";
+import {
+  createWalletClient,
+  http,
+  PrivateKeyAccount,
+  publicActions,
+} from "viem";
 import { privateKeyToAccount } from "viem/accounts";
-import { base, avalanche, optimism, polygon, bsc, arbitrum } from "viem/chains";
+import {
+  base,
+  avalanche,
+  optimism,
+  polygon,
+  bsc,
+  arbitrum,
+  gnosis,
+} from "viem/chains";
 import {
   BiconomySmartAccountV2,
   createSmartAccountClient,
-  PaymasterMode,
+  UserOperationStruct,
 } from "@biconomy/account";
+import { createNexusClient } from "@biconomy/sdk";
+import axios, { AxiosError } from "axios";
 
 /**
  * This file contains end-to-end tests that can run against a local or production bundler instance.
@@ -31,6 +46,11 @@ import {
  * 🔥 Don't commit un-skipped e2e tests so someone doesn't run them by accident 🔥
  */
 describe("e2e", () => {
+  // eslint-disable-next-line @typescript-eslint/no-explicit-any
+  (BigInt.prototype as any).toJSON = function () {
+    return this.toString();
+  };
+
   const privateKey = process.env.PRIVATE_KEY;
   if (!privateKey) {
     throw new Error("PRIVATE_KEY is not defined");
@@ -42,248 +62,942 @@ describe("e2e", () => {
 
   const valueToSend = 1n; // send only 1 wei
 
-  describe.skip("base-mainnet", () => {
-    const chainId = 8453;
-    const bundlerUrl = `${bundlerHostname}/api/v2/${chainId}/test`;
+  const stubPaymasterAndData =
+    "0x00000f79b7faf42eebadba19acc07cd08af4478900000000000000000000000029c3e9456c0eca5beb1f78763204bac6c682407700000000000000000000000000000000000000000000000000000000676410e60000000000000000000000000000000000000000000000000000000067640fba0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000004170f9cfb3f7a4204e0a497c8d19a98e2157b0df2740019ba2250a4c73de30539f14ea86cc47e0c96c16fd61b4b2f7ef777cf2c306974a03d56bdcc9313040242b1c00000000000000000000000000000000000000000000000000000000000000";
 
-    const paymasterUrl = process.env.BASE_MAINNET_PAYMASTER_URL;
-    if (!paymasterUrl) {
-      throw new Error("BASE_MAINNET_PAYMASTER_URL is not defined");
-    }
+  describe("base-mainnet", () => {
+    const account = privateKeyToAccount(`0x${privateKey}`);
+
+    describe("EntryPoint v0.6.0", () => {
+      const bundlerUrl = `${bundlerHostname}/api/v2/${base.id}/test`;
 
-    it("should perform a native transfer using a paymaster", async () => {
-      const account = privateKeyToAccount(`0x${privateKey}`);
+      const paymasterUrl = process.env.BASE_MAINNET_PAYMASTER_URL;
 
-      logConfig(bundlerUrl, paymasterUrl, account);
+      logConfig(base.id, bundlerUrl, account, paymasterUrl);
 
-      const smartAccount = await buildSmartAccount(
-        base,
+      const signer = createWalletClient({
         account,
-        bundlerUrl,
-        paymasterUrl,
-        valueToSend,
-      );
+        chain: base,
+        transport: http(),
+      }).extend(publicActions);
 
-      const receipt = await sendUserOperation(account, smartAccount);
-      console.log(receipt);
+      let smartAccount: BiconomySmartAccountV2;
 
-      expect(receipt.success).toBe("true");
+      const tx = {
+        to: account.address,
+        value: 1n,
+      };
+
+      beforeAll(async () => {
+        smartAccount = await createSmartAccountClient({
+          signer: signer,
+          bundlerUrl,
+          paymasterUrl,
+        });
+        await requireBalance(smartAccount, valueToSend);
+      });
+
+      it("should perform a native transfer without a paymaster", async () => {
+        // const receipt = await sendUserOperation(account, smartAccount, false);
+        const userOpResponse = await smartAccount.sendTransaction(tx);
+
+        const receipt = await userOpResponse.wait();
+
+        console.log(receipt);
+
+        expect(receipt.success).toBe("true");
+      });
+
+      if (paymasterUrl) {
+        it("should perform a native transfer using a paymaster", async () => {
+          if (!paymasterUrl) {
+            throw new Error("BASE_MAINNET_PAYMASTER_URL is not defined");
+          }
+
+          const unestimatedUserOperation: Partial<UserOperationStruct> =
+            await smartAccount.signUserOp({
+              sender: await smartAccount.getAccountAddress(),
+              nonce: await smartAccount.getNonce(),
+              initCode: "0x",
+              callData: await smartAccount.encodeExecute(tx.to, tx.value, "0x"),
+              callGasLimit: 1n,
+              verificationGasLimit: 1n,
+              preVerificationGas: 1n,
+              maxFeePerGas: 1n,
+              maxPriorityFeePerGas: 1n,
+              paymasterAndData: stubPaymasterAndData,
+            });
+
+          const gasEstimate = await smartAccount.bundler?.estimateUserOpGas(
+            unestimatedUserOperation,
+          );
+
+          const {
+            callGasLimit,
+            verificationGasLimit,
+            preVerificationGas,
+            maxFeePerGas,
+            maxPriorityFeePerGas,
+          } = gasEstimate!;
+
+          let estimatedUserOperation = await smartAccount.signUserOp({
+            ...unestimatedUserOperation,
+            callGasLimit: BigInt(callGasLimit),
+            verificationGasLimit: BigInt(verificationGasLimit),
+            preVerificationGas: BigInt(preVerificationGas),
+            maxFeePerGas: BigInt(maxFeePerGas),
+            maxPriorityFeePerGas: BigInt(maxPriorityFeePerGas),
+          });
+
+          estimatedUserOperation.paymasterAndData = await sponsorUserOperation(
+            paymasterUrl,
+            estimatedUserOperation,
+          );
+
+          estimatedUserOperation = await smartAccount.signUserOp(
+            estimatedUserOperation,
+          );
+
+          const response = await smartAccount.bundler!.sendUserOp(
+            estimatedUserOperation,
+          );
+
+          const receipt = await response.wait();
+
+          console.log(receipt);
+
+          expect(receipt.success).toBe("true");
+        });
+      }
     });
-  });
 
-  describe.skip("optimism-mainnet", () => {
-    const chainId = 10;
+    describe("EntryPoint v0.7.0", () => {
+      const bundlerUrl = `${bundlerHostname}/api/v3/${base.id}/test`;
 
-    const bundlerUrl = `${bundlerHostname}/api/v2/${chainId}/test`;
+      logConfig(base.id, bundlerUrl, account, "");
 
-    const paymasterUrl = process.env.OPTIMISM_MAINNET_PAYMASTER_URL;
-    if (!paymasterUrl) {
-      throw new Error("OPTIMISM_MAINNET_PAYMASTER_URL is not defined");
-    }
+      it("should perform a native transfer without a paymaster", async () => {
+        const nexusClient = await createNexusClient({
+          signer: account,
+          chain: base,
+          transport: http(),
+          bundlerTransport: http(bundlerUrl),
+        });
 
-    it("should perform a native transfer using a paymaster", async () => {
-      const account = privateKeyToAccount(`0x${privateKey}`);
+        const smartAccountAddress = nexusClient.account.address;
+        console.log(`Nexus address: ${smartAccountAddress}`);
 
-      logConfig(bundlerUrl, paymasterUrl, account);
+        const hash = await nexusClient.sendTransaction({
+          calls: [
+            {
+              to: smartAccountAddress,
+              value: 1n,
+            },
+          ],
+        });
 
-      const smartAccount = await buildSmartAccount(
-        optimism,
-        account,
-        bundlerUrl,
-        paymasterUrl,
-        valueToSend,
-      );
+        const receipt = await nexusClient.waitForTransactionReceipt({ hash });
 
-      const receipt = await sendUserOperation(account, smartAccount);
-      console.log(receipt);
+        console.log(receipt);
 
-      expect(receipt.success).toBe("true");
+        expect(receipt.status).toBe("success");
+      });
     });
   });
 
-  describe.skip("avalanche-mainnet", () => {
-    const chainId = 43114;
-
-    const bundlerUrl = `${bundlerHostname}/api/v2/${chainId}/test`;
+  describe("optimism-mainnet", () => {
+    const account = privateKeyToAccount(`0x${privateKey}`);
 
-    const paymasterUrl = process.env.AVALANCHE_MAINNET_PAYMASTER_URL;
-    if (!paymasterUrl) {
-      throw new Error("AVALANCHE_MAINNET_PAYMASTER_URL is not defined");
-    }
+    describe("EntryPoint v0.6.0", () => {
+      const bundlerUrl = `${bundlerHostname}/api/v2/${optimism.id}/test`;
 
-    it("should perform a native transfer using a paymaster", async () => {
-      const account = privateKeyToAccount(`0x${privateKey}`);
+      const paymasterUrl = process.env.OPTIMISM_MAINNET_PAYMASTER_URL;
 
-      logConfig(bundlerUrl, paymasterUrl, account);
+      logConfig(optimism.id, bundlerUrl, account, paymasterUrl);
 
-      const smartAccount = await buildSmartAccount(
-        avalanche,
+      const client = createWalletClient({
         account,
-        bundlerUrl,
-        paymasterUrl,
-        valueToSend,
-      );
+        chain: optimism,
+        transport: http(),
+      });
 
-      const receipt = await sendUserOperation(account, smartAccount);
-      console.log(receipt);
+      let smartAccount: BiconomySmartAccountV2;
 
-      expect(receipt.success).toBe("true");
+      const tx = {
+        to: account.address,
+        value: 1n,
+      };
+
+      beforeAll(async () => {
+        smartAccount = await createSmartAccountClient({
+          signer: client,
+          bundlerUrl,
+          paymasterUrl,
+        });
+        await requireBalance(smartAccount, valueToSend);
+      });
+
+      it("should perform a native transfer without a paymaster", async () => {
+        // const receipt = await sendUserOperation(account, smartAccount, false);
+        const userOpResponse = await smartAccount.sendTransaction(tx);
+
+        const receipt = await userOpResponse.wait();
+
+        console.log(receipt);
+
+        expect(receipt.success).toBe("true");
+      });
+
+      if (paymasterUrl) {
+        it("should perform a native transfer using a paymaster", async () => {
+          if (!paymasterUrl) {
+            throw new Error("OPTIMISM_MAINNET_PAYMASTER_URL is not defined");
+          }
+
+          const unestimatedUserOperation: Partial<UserOperationStruct> =
+            await smartAccount.signUserOp({
+              sender: await smartAccount.getAccountAddress(),
+              nonce: await smartAccount.getNonce(),
+              initCode: "0x",
+              callData: await smartAccount.encodeExecute(tx.to, tx.value, "0x"),
+              callGasLimit: 1n,
+              verificationGasLimit: 1n,
+              preVerificationGas: 1n,
+              maxFeePerGas: 1n,
+              maxPriorityFeePerGas: 1n,
+              paymasterAndData: stubPaymasterAndData,
+            });
+
+          const gasEstimate = await smartAccount.bundler?.estimateUserOpGas(
+            unestimatedUserOperation,
+          );
+
+          const {
+            callGasLimit,
+            verificationGasLimit,
+            preVerificationGas,
+            maxFeePerGas,
+            maxPriorityFeePerGas,
+          } = gasEstimate!;
+
+          let estimatedUserOperation = await smartAccount.signUserOp({
+            ...unestimatedUserOperation,
+            callGasLimit: BigInt(callGasLimit),
+            verificationGasLimit: BigInt(verificationGasLimit),
+            preVerificationGas: BigInt(preVerificationGas),
+            maxFeePerGas: BigInt(maxFeePerGas),
+            maxPriorityFeePerGas: BigInt(maxPriorityFeePerGas),
+          });
+
+          estimatedUserOperation.paymasterAndData = await sponsorUserOperation(
+            paymasterUrl,
+            estimatedUserOperation,
+          );
+
+          estimatedUserOperation = await smartAccount.signUserOp(
+            estimatedUserOperation,
+          );
+
+          const response = await smartAccount.bundler!.sendUserOp(
+            estimatedUserOperation,
+          );
+
+          const receipt = await response.wait();
+
+          console.log(receipt);
+
+          expect(receipt.success).toBe("true");
+        });
+      }
+    });
+
+    describe("EntryPoint v0.7.0", () => {
+      const bundlerUrl = `${bundlerHostname}/api/v3/${optimism.id}/test`;
+
+      logConfig(optimism.id, bundlerUrl, account, "");
+
+      it("should perform a native transfer without a paymaster", async () => {
+        const nexusClient = await createNexusClient({
+          signer: account,
+          chain: optimism,
+          transport: http(),
+          bundlerTransport: http(bundlerUrl),
+        });
+
+        const smartAccountAddress = nexusClient.account.address;
+        console.log(`Nexus address: ${smartAccountAddress}`);
+
+        const hash = await nexusClient.sendTransaction({
+          calls: [
+            {
+              to: smartAccountAddress,
+              value: 1n,
+            },
+          ],
+        });
+
+        const receipt = await nexusClient.waitForTransactionReceipt({ hash });
+        console.log(receipt);
+        expect(receipt.status).toBe("success");
+      });
     });
   });
 
-  describe.skip("polygon-mainnet", () => {
-    const chainId = 137;
+  describe("avalanche-mainnet", () => {
+    const bundlerUrl = `${bundlerHostname}/api/v2/${avalanche.id}/test`;
+    const account = privateKeyToAccount(`0x${privateKey}`);
 
-    const bundlerUrl = `${bundlerHostname}/api/v2/${chainId}/test`;
+    const paymasterUrl = process.env.AVALANCHE_MAINNET_PAYMASTER_URL;
 
-    const paymasterUrl = process.env.POLYGON_MAINNET_PAYMASTER_URL;
-    if (!paymasterUrl) {
-      throw new Error("POLYGON_MAINNET_PAYMASTER_URL is not defined");
-    }
+    logConfig(avalanche.id, bundlerUrl, account, paymasterUrl);
 
-    it("should perform a native transfer using a paymaster", async () => {
-      const account = privateKeyToAccount(`0x${privateKey}`);
+    const client = createWalletClient({
+      account,
+      chain: avalanche,
+      transport: http(),
+    });
 
-      logConfig(bundlerUrl, paymasterUrl, account);
+    let smartAccount: BiconomySmartAccountV2;
 
-      const smartAccount = await buildSmartAccount(
-        polygon,
-        account,
+    const tx = {
+      to: account.address,
+      value: 1n,
+    };
+
+    beforeAll(async () => {
+      smartAccount = await createSmartAccountClient({
+        signer: client,
         bundlerUrl,
         paymasterUrl,
-        valueToSend,
-      );
+      });
+      await requireBalance(smartAccount, valueToSend);
+    });
+
+    it("should perform a native transfer without a paymaster", async () => {
+      // const receipt = await sendUserOperation(account, smartAccount, false);
+      const userOpResponse = await smartAccount.sendTransaction(tx);
+
+      const receipt = await userOpResponse.wait();
 
-      const receipt = await sendUserOperation(account, smartAccount);
       console.log(receipt);
 
       expect(receipt.success).toBe("true");
     });
-  });
 
-  describe.skip("bsc-mainnet", () => {
-    const chainId = 56;
+    if (paymasterUrl) {
+      it("should perform a native transfer using a paymaster", async () => {
+        if (!paymasterUrl) {
+          throw new Error("AVALANCHE_MAINNET_PAYMASTER_URL is not defined");
+        }
+
+        const unestimatedUserOperation: Partial<UserOperationStruct> =
+          await smartAccount.signUserOp({
+            sender: await smartAccount.getAccountAddress(),
+            nonce: await smartAccount.getNonce(),
+            initCode: "0x",
+            callData: await smartAccount.encodeExecute(tx.to, tx.value, "0x"),
+            callGasLimit: 1n,
+            verificationGasLimit: 1n,
+            preVerificationGas: 1n,
+            maxFeePerGas: 1n,
+            maxPriorityFeePerGas: 1n,
+            paymasterAndData: stubPaymasterAndData,
+          });
+
+        const gasEstimate = await smartAccount.bundler?.estimateUserOpGas(
+          unestimatedUserOperation,
+        );
+
+        const {
+          callGasLimit,
+          verificationGasLimit,
+          preVerificationGas,
+          maxFeePerGas,
+          maxPriorityFeePerGas,
+        } = gasEstimate!;
+
+        let estimatedUserOperation = await smartAccount.signUserOp({
+          ...unestimatedUserOperation,
+          callGasLimit: BigInt(callGasLimit),
+          verificationGasLimit: BigInt(verificationGasLimit),
+          preVerificationGas: BigInt(preVerificationGas),
+          maxFeePerGas: BigInt(maxFeePerGas),
+          maxPriorityFeePerGas: BigInt(maxPriorityFeePerGas),
+        });
 
-    const bundlerUrl = `${bundlerHostname}/api/v2/${chainId}/test`;
+        estimatedUserOperation.paymasterAndData = await sponsorUserOperation(
+          paymasterUrl,
+          estimatedUserOperation,
+        );
 
-    const paymasterUrl = process.env.BSC_MAINNET_PAYMASTER_URL;
-    if (!paymasterUrl) {
-      throw new Error("BSC_MAINNET_PAYMASTER_URL is not defined");
+        estimatedUserOperation = await smartAccount.signUserOp(
+          estimatedUserOperation,
+        );
+
+        const response = await smartAccount.bundler!.sendUserOp(
+          estimatedUserOperation,
+        );
+
+        const receipt = await response.wait();
+
+        console.log(receipt);
+
+        expect(receipt.success).toBe("true");
+      });
     }
+  });
+
+  describe("bsc-mainnet", () => {
+    const account = privateKeyToAccount(`0x${privateKey}`);
+
+    describe("EntryPoint v0.6.0", () => {
+      const bundlerUrl = `${bundlerHostname}/api/v2/${bsc.id}/test`;
 
-    it("should perform a native transfer using a paymaster", async () => {
-      const account = privateKeyToAccount(`0x${privateKey}`);
+      const paymasterUrl = process.env.BSC_MAINNET_PAYMASTER_URL;
 
-      logConfig(bundlerUrl, paymasterUrl, account);
+      logConfig(bsc.id, bundlerUrl, account, paymasterUrl);
 
-      const smartAccount = await buildSmartAccount(
-        bsc,
+      const client = createWalletClient({
         account,
-        bundlerUrl,
-        paymasterUrl,
-        valueToSend,
-      );
+        chain: bsc,
+        transport: http(),
+      });
 
-      const receipt = await sendUserOperation(account, smartAccount);
-      console.log(receipt);
+      let smartAccount: BiconomySmartAccountV2;
 
-      expect(receipt.success).toBe("true");
+      const tx = {
+        to: account.address,
+        value: 1n,
+      };
+
+      beforeAll(async () => {
+        smartAccount = await createSmartAccountClient({
+          signer: client,
+          bundlerUrl,
+          paymasterUrl,
+        });
+        await requireBalance(smartAccount, valueToSend);
+      });
+
+      it("should perform a native transfer without a paymaster", async () => {
+        // const receipt = await sendUserOperation(account, smartAccount, false);
+        const userOpResponse = await smartAccount.sendTransaction(tx);
+
+        const receipt = await userOpResponse.wait();
+
+        expect(receipt.success).toBe("true");
+      });
+
+      if (paymasterUrl) {
+        it("should perform a native transfer using a paymaster", async () => {
+          if (!paymasterUrl) {
+            throw new Error("AVALANCHE_MAINNET_PAYMASTER_URL is not defined");
+          }
+
+          const unestimatedUserOperation: Partial<UserOperationStruct> =
+            await smartAccount.signUserOp({
+              sender: await smartAccount.getAccountAddress(),
+              nonce: await smartAccount.getNonce(),
+              initCode: "0x",
+              callData: await smartAccount.encodeExecute(tx.to, tx.value, "0x"),
+              callGasLimit: 1n,
+              verificationGasLimit: 1n,
+              preVerificationGas: 1n,
+              maxFeePerGas: 1n,
+              maxPriorityFeePerGas: 1n,
+              paymasterAndData: stubPaymasterAndData,
+            });
+
+          const gasEstimate = await smartAccount.bundler?.estimateUserOpGas(
+            unestimatedUserOperation,
+          );
+
+          const {
+            callGasLimit,
+            verificationGasLimit,
+            preVerificationGas,
+            maxFeePerGas,
+            maxPriorityFeePerGas,
+          } = gasEstimate!;
+
+          let estimatedUserOperation = await smartAccount.signUserOp({
+            ...unestimatedUserOperation,
+            callGasLimit: BigInt(callGasLimit),
+            verificationGasLimit: BigInt(verificationGasLimit),
+            preVerificationGas: BigInt(preVerificationGas),
+            maxFeePerGas: BigInt(maxFeePerGas),
+            maxPriorityFeePerGas: BigInt(maxPriorityFeePerGas),
+          });
+
+          estimatedUserOperation.paymasterAndData = await sponsorUserOperation(
+            paymasterUrl,
+            estimatedUserOperation,
+          );
+
+          estimatedUserOperation = await smartAccount.signUserOp(
+            estimatedUserOperation,
+          );
+
+          const response = await smartAccount.bundler!.sendUserOp(
+            estimatedUserOperation,
+          );
+
+          const receipt = await response.wait();
+
+          expect(receipt.success).toBe("true");
+        });
+      }
     });
-  });
 
-  describe.skip("arbitrum-mainnet", () => {
-    const chainId = 42161;
+    describe("EntryPoint v0.7.0", () => {
+      const bundlerUrl = `${bundlerHostname}/api/v3/${bsc.id}/test`;
 
-    const bundlerUrl = `${bundlerHostname}/api/v2/${chainId}/test`;
+      logConfig(bsc.id, bundlerUrl, account, "");
 
-    const paymasterUrl = process.env.ARBITRUM_MAINNET_PAYMASTER_URL;
-    if (!paymasterUrl) {
-      throw new Error("ARBITRUM_MAINNET_PAYMASTER_URL is not defined");
-    }
+      it("should perform a native transfer without a paymaster", async () => {
+        const nexusClient = await createNexusClient({
+          signer: account,
+          chain: bsc,
+          transport: http(),
+          bundlerTransport: http(bundlerUrl),
+        });
+
+        const smartAccountAddress = nexusClient.account.address;
+        console.log(`Nexus address: ${smartAccountAddress}`);
+
+        const hash = await nexusClient.sendTransaction({
+          calls: [
+            {
+              to: smartAccountAddress,
+              value: 1n,
+            },
+          ],
+        });
+
+        const receipt = await nexusClient.waitForTransactionReceipt({ hash });
+        console.log(receipt);
+        expect(receipt.status).toBe("success");
+      });
+    });
+  });
+
+  describe("arbitrum-mainnet", () => {
+    const account = privateKeyToAccount(`0x${privateKey}`);
+
+    describe("EntryPoint v0.6.0", () => {
+      const bundlerUrl = `${bundlerHostname}/api/v2/${arbitrum.id}/test`;
 
-    it("should perform a native transfer using a paymaster", async () => {
-      const account = privateKeyToAccount(`0x${privateKey}`);
+      const paymasterUrl = process.env.ARBITRUM_MAINNET_PAYMASTER_URL;
 
-      logConfig(bundlerUrl, paymasterUrl, account);
+      logConfig(arbitrum.id, bundlerUrl, account, paymasterUrl);
 
-      const smartAccount = await buildSmartAccount(
-        arbitrum,
+      const client = createWalletClient({
         account,
-        bundlerUrl,
-        paymasterUrl,
-        valueToSend,
-      );
+        chain: arbitrum,
+        transport: http(),
+      });
 
-      const receipt = await sendUserOperation(account, smartAccount);
-      console.log(receipt);
+      let smartAccount: BiconomySmartAccountV2;
 
-      expect(receipt.success).toBe("true");
+      const tx = {
+        to: account.address,
+        value: 1n,
+      };
+
+      beforeAll(async () => {
+        smartAccount = await createSmartAccountClient({
+          signer: client,
+          bundlerUrl,
+          paymasterUrl,
+        });
+        await requireBalance(smartAccount, valueToSend);
+      });
+
+      it("should perform a native transfer without a paymaster", async () => {
+        // const receipt = await sendUserOperation(account, smartAccount, false);
+        const userOpResponse = await smartAccount.sendTransaction(tx);
+
+        const receipt = await userOpResponse.wait();
+
+        expect(receipt.success).toBe("true");
+      });
+
+      if (paymasterUrl) {
+        it("should perform a native transfer using a paymaster", async () => {
+          if (!paymasterUrl) {
+            throw new Error("ARBITRUM_MAINNET_PAYMASTER_URL is not defined");
+          }
+
+          const unestimatedUserOperation: Partial<UserOperationStruct> =
+            await smartAccount.signUserOp({
+              sender: await smartAccount.getAccountAddress(),
+              nonce: await smartAccount.getNonce(),
+              initCode: "0x",
+              callData: await smartAccount.encodeExecute(tx.to, tx.value, "0x"),
+              callGasLimit: 1n,
+              verificationGasLimit: 1n,
+              preVerificationGas: 1n,
+              maxFeePerGas: 1n,
+              maxPriorityFeePerGas: 1n,
+              paymasterAndData: stubPaymasterAndData,
+            });
+
+          const gasEstimate = await smartAccount.bundler?.estimateUserOpGas(
+            unestimatedUserOperation,
+          );
+
+          const {
+            callGasLimit,
+            verificationGasLimit,
+            preVerificationGas,
+            maxFeePerGas,
+            maxPriorityFeePerGas,
+          } = gasEstimate!;
+
+          let estimatedUserOperation = await smartAccount.signUserOp({
+            ...unestimatedUserOperation,
+            callGasLimit: BigInt(callGasLimit),
+            verificationGasLimit: BigInt(verificationGasLimit),
+            preVerificationGas: BigInt(preVerificationGas),
+            maxFeePerGas: BigInt(maxFeePerGas),
+            maxPriorityFeePerGas: BigInt(maxPriorityFeePerGas),
+          });
+
+          estimatedUserOperation.paymasterAndData = await sponsorUserOperation(
+            paymasterUrl,
+            estimatedUserOperation,
+          );
+
+          estimatedUserOperation = await smartAccount.signUserOp(
+            estimatedUserOperation,
+          );
+
+          const response = await smartAccount.bundler!.sendUserOp(
+            estimatedUserOperation,
+          );
+
+          const receipt = await response.wait();
+
+          expect(receipt.success).toBe("true");
+        });
+      }
     });
-  });
-});
 
-/**
- * A helper function to send a sponsored native transfer user operation
- * @param account viem account
- * @param smartAccount biconomy smart account
- * @returns receipt
- */
-async function sendUserOperation(
-  account: PrivateKeyAccount,
-  smartAccount: BiconomySmartAccountV2,
-) {
-  const tx = {
-    to: account.address,
-    value: 1n,
-  };
+    describe("EntryPoint v0.7.0", () => {
+      const bundlerUrl = `${bundlerHostname}/api/v3/${arbitrum.id}/test`;
 
-  const userOpResponse = await smartAccount.sendTransaction(tx, {
-    paymasterServiceData: { mode: PaymasterMode.SPONSORED },
-  });
+      logConfig(arbitrum.id, bundlerUrl, account, "");
 
-  return userOpResponse.wait();
-}
+      it("should perform a native transfer without a paymaster", async () => {
+        const nexusClient = await createNexusClient({
+          signer: account,
+          chain: arbitrum,
+          transport: http(),
+          bundlerTransport: http(bundlerUrl),
+        });
 
-/**
- * A helper function to build a biconomy smart account for a given chain
- * @param chain viem chain
- * @param account viem account
- * @param bundlerUrl biconomy bundler url
- * @param paymasterUrl biconomy paymaster url
- * @param valueToSend value in wei
- * @returns biconomy smart account
- */
-async function buildSmartAccount(
-  chain: Chain,
-  account: PrivateKeyAccount,
-  bundlerUrl: string,
-  paymasterUrl: string | undefined,
-  valueToSend: bigint,
-) {
-  const client = createWalletClient({
-    account,
-    chain,
-    transport: http(),
+        const smartAccountAddress = nexusClient.account.address;
+        console.log(`Nexus address: ${smartAccountAddress}`);
+
+        const hash = await nexusClient.sendTransaction({
+          calls: [
+            {
+              to: smartAccountAddress,
+              value: 1n,
+            },
+          ],
+        });
+
+        const receipt = await nexusClient.waitForTransactionReceipt({ hash });
+        console.log(receipt);
+        expect(receipt.status).toBe("success");
+      });
+    });
   });
 
-  const smartAccount = await createSmartAccountClient({
-    signer: client,
-    bundlerUrl,
-    paymasterUrl,
+  describe("polygon-mainnet", () => {
+    const account = privateKeyToAccount(`0x${privateKey}`);
+
+    describe("EntryPoint v0.6.0", () => {
+      const bundlerUrl = `${bundlerHostname}/api/v2/${polygon.id}/test`;
+
+      const paymasterUrl = process.env.POLYGON_MAINNET_PAYMASTER_URL;
+
+      logConfig(polygon.id, bundlerUrl, account, paymasterUrl);
+
+      const client = createWalletClient({
+        account,
+        chain: polygon,
+        transport: http(),
+      });
+
+      let smartAccount: BiconomySmartAccountV2;
+
+      const tx = {
+        to: account.address,
+        value: 1n,
+      };
+
+      beforeAll(async () => {
+        smartAccount = await createSmartAccountClient({
+          signer: client,
+          bundlerUrl,
+          paymasterUrl,
+        });
+        await requireBalance(smartAccount, valueToSend);
+      });
+
+      it("should perform a native transfer without a paymaster", async () => {
+        // const receipt = await sendUserOperation(account, smartAccount, false);
+        const userOpResponse = await smartAccount.sendTransaction(tx);
+
+        const receipt = await userOpResponse.wait();
+
+        expect(receipt.success).toBe("true");
+      });
+
+      if (paymasterUrl) {
+        it("should perform a native transfer using a paymaster", async () => {
+          if (!paymasterUrl) {
+            throw new Error("POLYGON_MAINNET_PAYMASTER_URL is not defined");
+          }
+
+          const unestimatedUserOperation: Partial<UserOperationStruct> =
+            await smartAccount.signUserOp({
+              sender: await smartAccount.getAccountAddress(),
+              nonce: await smartAccount.getNonce(),
+              initCode: "0x",
+              callData: await smartAccount.encodeExecute(tx.to, tx.value, "0x"),
+              callGasLimit: 1n,
+              verificationGasLimit: 1n,
+              preVerificationGas: 1n,
+              maxFeePerGas: 1n,
+              maxPriorityFeePerGas: 1n,
+              paymasterAndData: stubPaymasterAndData,
+            });
+
+          const gasEstimate = await smartAccount.bundler?.estimateUserOpGas(
+            unestimatedUserOperation,
+          );
+
+          const {
+            callGasLimit,
+            verificationGasLimit,
+            preVerificationGas,
+            maxFeePerGas,
+            maxPriorityFeePerGas,
+          } = gasEstimate!;
+
+          let estimatedUserOperation = await smartAccount.signUserOp({
+            ...unestimatedUserOperation,
+            callGasLimit: BigInt(callGasLimit),
+            verificationGasLimit: BigInt(verificationGasLimit),
+            preVerificationGas: BigInt(preVerificationGas),
+            maxFeePerGas: BigInt(maxFeePerGas),
+            maxPriorityFeePerGas: BigInt(maxPriorityFeePerGas),
+          });
+
+          estimatedUserOperation.paymasterAndData = await sponsorUserOperation(
+            paymasterUrl,
+            estimatedUserOperation,
+          );
+
+          estimatedUserOperation = await smartAccount.signUserOp(
+            estimatedUserOperation,
+          );
+
+          const response = await smartAccount.bundler!.sendUserOp(
+            estimatedUserOperation,
+          );
+
+          const receipt = await response.wait();
+
+          expect(receipt.success).toBe("true");
+        });
+      }
+    });
+
+    describe("EntryPoint v0.7.0", () => {
+      const bundlerUrl = `${bundlerHostname}/api/v3/${polygon.id}/test`;
+
+      logConfig(polygon.id, bundlerUrl, account, "");
+
+      it("should perform a native transfer without a paymaster", async () => {
+        const nexusClient = await createNexusClient({
+          signer: account,
+          chain: polygon,
+          transport: http(),
+          bundlerTransport: http(bundlerUrl),
+        });
+
+        const smartAccountAddress = nexusClient.account.address;
+        console.log(`Nexus address: ${smartAccountAddress}`);
+
+        const hash = await nexusClient.sendTransaction({
+          calls: [
+            {
+              to: smartAccountAddress,
+              value: 1n,
+            },
+          ],
+        });
+
+        const receipt = await nexusClient.waitForTransactionReceipt({ hash });
+        console.log(receipt);
+        expect(receipt.status).toBe("success");
+      });
+    });
   });
-  await requireBalance(smartAccount, valueToSend);
 
-  return smartAccount;
-}
+  describe.only("gnosis-mainnet", () => {
+    const account = privateKeyToAccount(`0x${privateKey}`);
+
+    describe("EntryPoint v0.6.0", () => {
+      const bundlerUrl = `${bundlerHostname}/api/v2/${gnosis.id}/test`;
+
+      const paymasterUrl = process.env.GNOSIS_MAINNET_PAYMASTER_URL;
+
+      logConfig(gnosis.id, bundlerUrl, account, paymasterUrl);
+
+      const client = createWalletClient({
+        account,
+        chain: gnosis,
+        transport: http(),
+      });
+
+      let smartAccount: BiconomySmartAccountV2;
+
+      const tx = {
+        to: account.address,
+        value: 1n,
+      };
+
+      beforeAll(async () => {
+        smartAccount = await createSmartAccountClient({
+          signer: client,
+          bundlerUrl,
+          paymasterUrl,
+        });
+        await requireBalance(smartAccount, valueToSend);
+      });
+
+      it("should perform a native transfer without a paymaster", async () => {
+        // const receipt = await sendUserOperation(account, smartAccount, false);
+        const userOpResponse = await smartAccount.sendTransaction(tx);
+
+        const receipt = await userOpResponse.wait();
+
+        expect(receipt.success).toBe("true");
+      });
+
+      if (paymasterUrl) {
+        it("should perform a native transfer using a paymaster", async () => {
+          if (!paymasterUrl) {
+            throw new Error("GNOSIS_MAINNET_PAYMASTER_URL is not defined");
+          }
+
+          const unestimatedUserOperation: Partial<UserOperationStruct> =
+            await smartAccount.signUserOp({
+              sender: await smartAccount.getAccountAddress(),
+              nonce: await smartAccount.getNonce(),
+              initCode: "0x",
+              callData: await smartAccount.encodeExecute(tx.to, tx.value, "0x"),
+              callGasLimit: 1n,
+              verificationGasLimit: 1n,
+              preVerificationGas: 1n,
+              maxFeePerGas: 1n,
+              maxPriorityFeePerGas: 1n,
+              paymasterAndData: stubPaymasterAndData,
+            });
+
+          const gasEstimate = await smartAccount.bundler?.estimateUserOpGas(
+            unestimatedUserOperation,
+          );
+
+          const {
+            callGasLimit,
+            verificationGasLimit,
+            preVerificationGas,
+            maxFeePerGas,
+            maxPriorityFeePerGas,
+          } = gasEstimate!;
+
+          let estimatedUserOperation = await smartAccount.signUserOp({
+            ...unestimatedUserOperation,
+            callGasLimit: BigInt(callGasLimit),
+            verificationGasLimit: BigInt(verificationGasLimit),
+            preVerificationGas: BigInt(preVerificationGas),
+            maxFeePerGas: BigInt(maxFeePerGas),
+            maxPriorityFeePerGas: BigInt(maxPriorityFeePerGas),
+          });
+
+          estimatedUserOperation.paymasterAndData = await sponsorUserOperation(
+            paymasterUrl,
+            estimatedUserOperation,
+          );
+
+          estimatedUserOperation = await smartAccount.signUserOp(
+            estimatedUserOperation,
+          );
+
+          const response = await smartAccount.bundler!.sendUserOp(
+            estimatedUserOperation,
+          );
+
+          const receipt = await response.wait();
+
+          expect(receipt.success).toBe("true");
+        });
+      }
+    });
+
+    describe.skip("EntryPoint v0.7.0", () => {
+      const bundlerUrl = `${bundlerHostname}/api/v3/${gnosis.id}/test`;
+
+      logConfig(gnosis.id, bundlerUrl, account, "");
+
+      it("should perform a native transfer without a paymaster", async () => {
+        const nexusClient = await createNexusClient({
+          signer: account,
+          chain: gnosis,
+          transport: http(),
+          bundlerTransport: http(bundlerUrl),
+        });
+
+        const smartAccountAddress = nexusClient.account.address;
+        console.log(`Nexus address: ${smartAccountAddress}`);
+
+        const hash = await nexusClient.sendTransaction({
+          calls: [
+            {
+              to: smartAccountAddress,
+              value: 1n,
+            },
+          ],
+        });
+
+        const receipt = await nexusClient.waitForTransactionReceipt({ hash });
+        console.log(receipt);
+        expect(receipt.status).toBe("success");
+      });
+    });
+  });
+});
 
 function logConfig(
+  chainId: number,
   bundlerUrl: string,
-  paymasterUrl: string,
   account: PrivateKeyAccount,
+  paymasterUrl?: string,
 ) {
-  console.log(`Bundler URL: ${bundlerUrl}`);
-  console.log(`Paymaster URL: ${paymasterUrl}`);
-  console.log(`EOA Address: ${account.address}`);
+  console.log(
+    JSON.stringify({
+      chainId,
+      bundlerUrl,
+      paymasterUrl,
+      eoaAddress: account.address,
+    }),
+  );
 }
 
 async function requireBalance(
@@ -304,3 +1018,38 @@ Balance: ${nativeBalance.amount} wei, required: ${valueToSend} wei`,
     );
   }
 }
+
+async function sponsorUserOperation(
+  paymasterUrl: string,
+  estimatedUserOperation: UserOperationStruct,
+) {
+  try {
+    const sponsorUserOperationResponse = await axios.post(paymasterUrl, {
+      id: 1,
+      jsonrpc: "2.0",
+      method: "pm_sponsorUserOperation",
+      params: [
+        estimatedUserOperation,
+        {
+          mode: "SPONSORED",
+          calculateGasLimits: false,
+          expiryDuration: 300,
+          sponsorshipInfo: {
+            webhookData: {},
+            smartAccountInfo: {
+              name: "BICONOMY",
+              version: "2.0.0",
+            },
+          },
+        },
+      ],
+    });
+
+    const { paymasterAndData } = sponsorUserOperationResponse.data.result;
+
+    return paymasterAndData;
+  } catch (err) {
+    const axiosError = err as AxiosError;
+    throw new Error(axiosError.message);
+  }
+}
diff --git a/yarn.lock b/yarn.lock
index 77f1bcdf..dbc38062 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -11,7 +11,7 @@
     debug "^4.3.4"
     safe-buffer "~5.1.2"
 
-"@adraffy/ens-normalize@^1.10.1":
+"@adraffy/ens-normalize@1.11.0", "@adraffy/ens-normalize@^1.10.1":
   version "1.11.0"
   resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.11.0.tgz#42cc67c5baa407ac25059fcd7d405cc5ecdb0c33"
   integrity sha512-/3DDPKHqqIqxUULp8yP4zODUY1i+2xvVWsv8A79xGWdCAG+8sb0hRh0Rk2QyOJUnnbyPUAZYcpBuRe3nS2OIUg==
@@ -787,6 +787,23 @@
   dependencies:
     merkletreejs "^0.4.0"
 
+"@biconomy/gas-estimations@0.2.51":
+  version "0.2.51"
+  resolved "https://registry.yarnpkg.com/@biconomy/gas-estimations/-/gas-estimations-0.2.51.tgz#8d238f615635be79f40251067be1f07c13b2bb24"
+  integrity sha512-ccy1ofAunjDLFjx+RWXUiav1r7MOj+Erh90eEvsFwWQufiXzoPqCYFXukuWUyb93bEBOEWjIwwVOzE31+su0gw==
+  dependencies:
+    dotenv "^16.4.5"
+    viem "^2.21.49"
+    zod "^3.22.4"
+    zod-validation-error "^2.1.0"
+
+"@biconomy/sdk@^0.0.19":
+  version "0.0.19"
+  resolved "https://registry.yarnpkg.com/@biconomy/sdk/-/sdk-0.0.19.tgz#91cad1280e9819588c3238130ca39ce1f1809e2a"
+  integrity sha512-rcxqfC+18Xy365mzOKb5oB64a8ZD4zC5GFOU1EClfal9gI0eFZRM2K3OKXOjUSjfipK5B5SiGDtsjh3DBlmNzQ==
+  dependencies:
+    "@silencelaboratories/walletprovider-sdk" "^0.3.0"
+
 "@commitlint/config-validator@^19.5.0":
   version "19.5.0"
   resolved "https://registry.yarnpkg.com/@commitlint/config-validator/-/config-validator-19.5.0.tgz#f0a4eda2109fc716ef01bb8831af9b02e3a1e568"
@@ -1779,7 +1796,7 @@
   dependencies:
     "@noble/hashes" "1.5.0"
 
-"@noble/curves@^1.4.0", "@noble/curves@^1.6.0", "@noble/curves@~1.7.0":
+"@noble/curves@1.7.0", "@noble/curves@^1.4.0", "@noble/curves@^1.6.0", "@noble/curves@~1.7.0":
   version "1.7.0"
   resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.7.0.tgz#0512360622439256df892f21d25b388f52505e45"
   integrity sha512-UTMhXK9SeDhFJVrHeUJ5uZlI6ajXg10O6Ddocf9S6GjbSBVZsJo88HzKwXznNfGpMTRDyJkqMjNDPYgf0qFWnw==
@@ -1801,7 +1818,7 @@
   resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.6.0.tgz#d4bfb516ad6e7b5111c216a5cc7075f4cf19e6c5"
   integrity sha512-YUULf0Uk4/mAA89w+k3+yUYh6NrEvxZa5T6SY3wlMvE2chHkxFUUIDI8/XW1QSC357iA5pSnqt7XEhvFOqmDyQ==
 
-"@noble/hashes@^1.4.0", "@noble/hashes@^1.5.0", "@noble/hashes@~1.6.0":
+"@noble/hashes@1.6.1", "@noble/hashes@^1.4.0", "@noble/hashes@^1.5.0", "@noble/hashes@~1.6.0":
   version "1.6.1"
   resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.6.1.tgz#df6e5943edcea504bac61395926d6fd67869a0d5"
   integrity sha512-pq5D8h10hHBjyqX+cfBm0i8JUXJ0UhczFc4r74zbuT9XgewFo2E3J1cOaGtdZynILNmQ685YWGzGE1Zv6io50w==
@@ -1941,6 +1958,14 @@
   resolved "https://registry.yarnpkg.com/@redis/time-series/-/time-series-1.1.0.tgz#cba454c05ec201bd5547aaf55286d44682ac8eb5"
   integrity sha512-c1Q99M5ljsIuc4YdaCwfUEXsofakb9c8+Zse2qxTadu8TalLXuAESzLvFAvNVbkmSlvlzIQOLpBCmWI9wTOt+g==
 
+"@rhinestone/module-sdk@^0.1.32":
+  version "0.1.32"
+  resolved "https://registry.yarnpkg.com/@rhinestone/module-sdk/-/module-sdk-0.1.32.tgz#32571e606b587de984bf56cba3569c91c0b7a2a6"
+  integrity sha512-wNzeIepHPhD0jiw3UOar+dAb6VKv4p8D4+947n0SLZHBdJ5S7moRCCL082NCo7Pz8+/C9kVriJASFeLZmJLo4g==
+  dependencies:
+    solady "^0.0.235"
+    tslib "^2.7.0"
+
 "@rtsao/scc@^1.1.0":
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/@rtsao/scc/-/scc-1.1.0.tgz#927dd2fae9bc3361403ac2c7a00c32ddce9ad7e8"
@@ -1974,7 +1999,7 @@
     "@noble/hashes" "~1.5.0"
     "@scure/base" "~1.1.7"
 
-"@scure/bip32@^1.5.0":
+"@scure/bip32@1.6.0", "@scure/bip32@^1.5.0":
   version "1.6.0"
   resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.6.0.tgz#6dbc6b4af7c9101b351f41231a879d8da47e0891"
   integrity sha512-82q1QfklrUUdXJzjuRU7iG7D7XiFx5PHYVS0+oeNKhyDLT7WPqs6pBcM2W5ZdwOwKCwoE1Vy1se+DHjcXwCYnA==
@@ -1999,7 +2024,7 @@
     "@noble/hashes" "~1.5.0"
     "@scure/base" "~1.1.8"
 
-"@scure/bip39@^1.4.0":
+"@scure/bip39@1.5.0", "@scure/bip39@^1.4.0":
   version "1.5.0"
   resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.5.0.tgz#c8f9533dbd787641b047984356531d84485f19be"
   integrity sha512-Dop+ASYhnrwm9+HA/HwXg7j2ZqM6yk2fyLWb5znexjctFY3+E+eU8cIWI0Pql0Qx4hPZCijlGq4OL71g+Uz30A==
@@ -2024,6 +2049,15 @@
   resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df"
   integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==
 
+"@silencelaboratories/walletprovider-sdk@^0.3.0":
+  version "0.3.0"
+  resolved "https://registry.yarnpkg.com/@silencelaboratories/walletprovider-sdk/-/walletprovider-sdk-0.3.0.tgz#c637fd3413e532fe6bd5f10eab9f194f56c1f6c6"
+  integrity sha512-5+yS95DwIufP0qOPuk81cXZ8gepcARXwuKRDAtjtf50JVX0MOMy6pR8f/1j5PATPdImzgI8905x3ZBgXfi+FKw==
+  dependencies:
+    "@noble/curves" "^1.6.0"
+    js-base64 "^3.7.7"
+    viem "2.21.32"
+
 "@sinclair/typebox@^0.27.8":
   version "0.27.8"
   resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e"
@@ -2918,6 +2952,11 @@ abitype@1.0.6, abitype@^1.0.6:
   resolved "https://registry.yarnpkg.com/abitype/-/abitype-1.0.6.tgz#76410903e1d88e34f1362746e2d407513c38565b"
   integrity sha512-MMSqYh4+C/aVqI2RQaWqbvI4Kxo5cQV40WQ4QFtDnNzCkqChm8MuENhElmynZlO0qUy/ObkEUaXtKqYnx1Kp3A==
 
+abitype@1.0.7:
+  version "1.0.7"
+  resolved "https://registry.yarnpkg.com/abitype/-/abitype-1.0.7.tgz#876a0005d211e1c9132825d45bcee7b46416b284"
+  integrity sha512-ZfYYSktDQUwc2eduYu8C4wOs+RDPmnRYMh7zNfzeMtGGgb0U+6tLGjixUic6mXf5xKKCcgT5Qp6cv39tOARVFw==
+
 abort-controller@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392"
@@ -4096,6 +4135,11 @@ dotenv@^16.0.3:
   resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.6.tgz#fc88e8a664087abf3e19d61e21f7feee1849bbb1"
   integrity sha512-JhcR/+KIjkkjiU8yEpaB/USlzVi3i5whwOjpIRNGi9svKEXZSe+Qp6IWAjFjv+2GViAoDRCUv/QLNziQxsLqDg==
 
+dotenv@^16.4.5:
+  version "16.4.7"
+  resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.7.tgz#0e20c5b82950140aa99be360a8a5f52335f53c26"
+  integrity sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==
+
 ee-first@1.1.1:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
@@ -4174,15 +4218,6 @@ enhanced-resolve@^5.17.1:
     graceful-fs "^4.2.4"
     tapable "^2.2.0"
 
-entry-point-gas-estimations@1.0.2:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/entry-point-gas-estimations/-/entry-point-gas-estimations-1.0.2.tgz#91e76fdcdca56f601a62a111579cc03c8112de05"
-  integrity sha512-ulYhxwPYPpam+EUOlM+LE7foRWeXYL6lZvzXMNOIvidqIBJxVkhX1fBTZRr6P8WNiwifSyo99iE+bFg5wdAHhA==
-  dependencies:
-    viem "^2.17.3"
-    zod "^3.22.4"
-    zod-validation-error "^2.1.0"
-
 env-paths@^2.2.1:
   version "2.2.1"
   resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2"
@@ -6246,6 +6281,11 @@ joycon@^3.1.1:
   resolved "https://registry.yarnpkg.com/joycon/-/joycon-3.1.1.tgz#bce8596d6ae808f8b68168f5fc69280996894f03"
   integrity sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==
 
+js-base64@^3.7.7:
+  version "3.7.7"
+  resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-3.7.7.tgz#e51b84bf78fbf5702b9541e2cb7bfcb893b43e79"
+  integrity sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw==
+
 js-sha3@0.8.0:
   version "0.8.0"
   resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840"
@@ -7880,6 +7920,11 @@ socks@^2.7.1:
     ip-address "^9.0.5"
     smart-buffer "^4.2.0"
 
+solady@^0.0.235:
+  version "0.0.235"
+  resolved "https://registry.yarnpkg.com/solady/-/solady-0.0.235.tgz#50ab6e403ed6935012df2c16803fcd58045f9a0e"
+  integrity sha512-JUEXLDG7ag3HmqUnrDG7ilhafH6R9bFPpwV63O2kH4UbnS2+gRGEOqqy4k01O7tHjo3MWkDD0cpG+UY9pjy/fQ==
+
 sonic-boom@^3.0.0, sonic-boom@^3.7.0:
   version "3.8.1"
   resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-3.8.1.tgz#d5ba8c4e26d6176c9a1d14d549d9ff579a163422"
@@ -8245,7 +8290,7 @@ tsconfig-paths@^3.15.0:
     minimist "^1.2.6"
     strip-bom "^3.0.0"
 
-tslib@^2.1.0, tslib@^2.4.0, tslib@^2.6.2:
+tslib@^2.1.0, tslib@^2.4.0, tslib@^2.6.2, tslib@^2.7.0:
   version "2.8.1"
   resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f"
   integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==
@@ -8469,17 +8514,32 @@ vary@^1, vary@~1.1.2:
   resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
   integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==
 
-viem@^2.17.3, viem@^2.21.28:
-  version "2.21.53"
-  resolved "https://registry.yarnpkg.com/viem/-/viem-2.21.53.tgz#a5ba6da48e5edded27dde286e431ae97034f4fc4"
-  integrity sha512-0pY8clBacAwzc59iV1vY4a6U4xvRlA5tAuhClJCKvqA6rXJzmNMMvxQ0EG79lkHr7WtBEruXz8nAmONXwnq4EQ==
+viem@2.21.32:
+  version "2.21.32"
+  resolved "https://registry.yarnpkg.com/viem/-/viem-2.21.32.tgz#b7f43b2004967036f83500260290cee45189f62a"
+  integrity sha512-2oXt5JNIb683oy7C8wuIJ/SeL3XtHVMEQpy1U2TA6WMnJQ4ScssRvyPwYLcaP6mKlrGXE/cR/V7ncWpvLUVPYQ==
   dependencies:
+    "@adraffy/ens-normalize" "1.11.0"
     "@noble/curves" "1.6.0"
     "@noble/hashes" "1.5.0"
     "@scure/bip32" "1.5.0"
     "@scure/bip39" "1.4.0"
     abitype "1.0.6"
     isows "1.0.6"
+    webauthn-p256 "0.0.10"
+    ws "8.18.0"
+
+viem@^2.21.49:
+  version "2.21.54"
+  resolved "https://registry.yarnpkg.com/viem/-/viem-2.21.54.tgz#76d6f86ab8809078f1ac140ac1a2beadbc86b9f6"
+  integrity sha512-G9mmtbua3UtnVY9BqAtWdNp+3AO+oWhD0B9KaEsZb6gcrOWgmA4rz02yqEMg+qW9m6KgKGie7q3zcHqJIw6AqA==
+  dependencies:
+    "@noble/curves" "1.7.0"
+    "@noble/hashes" "1.6.1"
+    "@scure/bip32" "1.6.0"
+    "@scure/bip39" "1.5.0"
+    abitype "1.0.7"
+    isows "1.0.6"
     ox "0.1.2"
     webauthn-p256 "0.0.10"
     ws "8.18.0"