Skip to content

Commit

Permalink
Merge pull request #51 from etherspot/simulateHandleOp
Browse files Browse the repository at this point in the history
Simulate handle op
  • Loading branch information
0xSulpiride authored Jul 18, 2023
2 parents e150c60 + e06559e commit 01dd1ab
Show file tree
Hide file tree
Showing 16 changed files with 166 additions and 88 deletions.
2 changes: 1 addition & 1 deletion lerna.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
],
"npmClient": "yarn",
"useWorkspaces": true,
"version": "0.0.15",
"version": "0.0.16",
"stream": "true",
"command": {
"version": {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "root",
"private": true,
"version": "0.0.15",
"version": "0.0.16",
"engines": {
"node": ">=18.0.0"
},
Expand Down
6 changes: 3 additions & 3 deletions packages/api/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "api",
"version": "0.0.15",
"version": "0.0.16",
"description": "The API module of Etherspot bundler client",
"author": "Etherspot",
"homepage": "https://https://github.com/etherspot/skandha#readme",
Expand Down Expand Up @@ -35,12 +35,12 @@
"class-transformer": "0.5.1",
"class-validator": "0.14.0",
"ethers": "5.7.2",
"executor": "^0.0.15",
"executor": "^0.0.16",
"fastify": "4.14.1",
"pino": "8.11.0",
"pino-pretty": "10.0.0",
"reflect-metadata": "0.1.13",
"types": "^0.0.15"
"types": "^0.0.16"
},
"devDependencies": {
"@types/connect": "3.4.35"
Expand Down
10 changes: 5 additions & 5 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cli",
"version": "0.0.15",
"version": "0.0.16",
"description": "> TODO: description",
"author": "zincoshine <[email protected]>",
"homepage": "https://https://github.com/etherspot/skandha#readme",
Expand Down Expand Up @@ -31,13 +31,13 @@
"url": "https://https://github.com/etherspot/skandha/issues"
},
"dependencies": {
"api": "^0.0.15",
"db": "^0.0.15",
"executor": "^0.0.15",
"api": "^0.0.16",
"db": "^0.0.16",
"executor": "^0.0.16",
"find-up": "5.0.0",
"got": "12.5.3",
"js-yaml": "4.1.0",
"types": "^0.0.15",
"types": "^0.0.16",
"yargs": "17.6.2"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/cmds/start/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
RocksDbController,
LocalDbController,
} from "db/lib";
import { ConfigOptions } from "executor/lib/config";
import { ConfigOptions } from "executor/lib/interfaces";
import { IDbController } from "types/lib";
import { mkdir, readFile } from "../../util";
import { IGlobalArgs } from "../../options";
Expand Down
4 changes: 2 additions & 2 deletions packages/db/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "db",
"version": "0.0.15",
"version": "0.0.16",
"description": "The DB module of Etherspot bundler client",
"author": "Etherspot",
"homepage": "https://github.com/etherspot/etherspot-bundler#readme",
Expand Down Expand Up @@ -37,6 +37,6 @@
"devDependencies": {
"@types/rocksdb": "3.0.1",
"prettier": "^2.8.4",
"types": "^0.0.15"
"types": "^0.0.16"
}
}
6 changes: 3 additions & 3 deletions packages/executor/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "executor",
"version": "0.0.15",
"version": "0.0.16",
"description": "The Relayer module of Etherspot bundler client",
"author": "Etherspot",
"homepage": "https://https://github.com/etherspot/skandha#readme",
Expand Down Expand Up @@ -33,7 +33,7 @@
"dependencies": {
"async-mutex": "0.4.0",
"ethers": "5.7.2",
"params": "^0.0.15",
"types": "^0.0.15"
"params": "^0.0.16",
"types": "^0.0.16"
}
}
37 changes: 9 additions & 28 deletions packages/executor/src/config.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,12 @@
// TODO: create a new package "config" instead of this file
import { NetworkName } from "types/lib";
import { BigNumberish, Wallet, providers, utils } from "ethers";

export interface NetworkConfig {
entryPoints: string[];
relayer: string;
beneficiary: string;
name?: NetworkName;
rpcEndpoint: string;
minInclusionDenominator: number;
throttlingSlack: number;
banSlack: number;
minSignerBalance: BigNumberish;
multicall: string;
}

export type BundlerConfig = Omit<
import { Wallet, providers, utils } from "ethers";
import {
BundlerConfig,
ConfigOptions,
NetworkConfig,
"entryPoints" | "rpcEndpoint" | "relayer" | "beneficiary"
>;

export type Networks = {
[network in NetworkName]?: NetworkConfig;
};

export interface ConfigOptions {
networks: Networks;
testingMode?: boolean;
unsafeMode: boolean;
}
Networks,
} from "./interfaces";

export class Config {
supportedNetworks: NetworkName[];
Expand Down Expand Up @@ -131,6 +109,9 @@ const bundlerDefaultConfigs: BundlerConfig = {
banSlack: 10,
minSignerBalance: utils.parseEther("0.1"),
multicall: "0xcA11bde05977b3631167028862bE2a173976CA11", // default multicall address
estimationBaseFeeDivisor: 25,
estimationStaticBuffer: 21000,
validationGasLimit: 10e6,
};

const RELAYER_ENV = (network: NetworkName): string | undefined =>
Expand Down
2 changes: 1 addition & 1 deletion packages/executor/src/executor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { BigNumber, providers } from "ethers";
import { NETWORK_NAME_TO_CHAIN_ID, NetworkName } from "types/lib";
import { IDbController } from "types/lib";
import { NetworkConfig } from "./config";
import { NetworkConfig } from "./interfaces";
import { Web3, Debug, Eth } from "./modules";
import {
MempoolService,
Expand Down
38 changes: 38 additions & 0 deletions packages/executor/src/interfaces.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { BigNumberish, BytesLike } from "ethers";
import { NetworkName } from "types/lib";

export interface Log {
blockNumber: number;
Expand Down Expand Up @@ -85,3 +86,40 @@ export interface Logger {
trace: LogFn;
silent: LogFn;
}

export interface NetworkConfig {
entryPoints: string[];
relayer: string;
beneficiary: string;
name?: NetworkName;
rpcEndpoint: string;
minInclusionDenominator: number;
throttlingSlack: number;
banSlack: number;
minSignerBalance: BigNumberish;
multicall: string;
// reduces baseFee by a given number in % before dividing paid gas
// use this as a buffer to callGasLimit
// 25% by default
estimationBaseFeeDivisor: number;
// adds certain amount of gas to callGasLimit
// 21000 by default
estimationStaticBuffer: number;
// gas limit during simulateHandleOps and simulateValidation calls
validationGasLimit: number;
}

export type BundlerConfig = Omit<
NetworkConfig,
"entryPoints" | "rpcEndpoint" | "relayer" | "beneficiary"
>;

export type Networks = {
[network in NetworkName]?: NetworkConfig;
};

export interface ConfigOptions {
networks: Networks;
testingMode?: boolean;
unsafeMode: boolean;
}
81 changes: 61 additions & 20 deletions packages/executor/src/modules/eth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ import { EntryPoint__factory } from "types/lib/executor/contracts/factories";
import { NetworkName } from "types/lib";
import { IPVGEstimator } from "params/lib/types/IPVGEstimator";
import { estimateOptimismPVG, estimateArbitrumPVG } from "params/lib";
import { NetworkConfig } from "../config";
import { deepHexlify, packUserOp } from "../utils";
import { NetworkConfig } from "../interfaces";
import { deepHexlify, getUserOpHash, packUserOp } from "../utils";
import { UserOpValidationService, MempoolService } from "../services";
import { Logger, Log } from "../interfaces";
import {
Expand Down Expand Up @@ -94,6 +94,21 @@ export class Eth {
if (!this.validateEntryPoint(entryPoint)) {
throw new RpcError("Invalid Entrypoint", RpcErrorCodes.INVALID_REQUEST);
}

//< checking for execution revert
await this.provider
.estimateGas({
from: entryPoint,
to: userOp.sender,
data: userOp.callData,
})
.catch((err) => {
const message =
err.message.match(/reason="(.*?)"/)?.at(1) ?? "execution reverted";
throw new RpcError(message, RpcErrorCodes.EXECUTION_REVERTED);
});
//>

const userOpComplemented: UserOperationStruct = {
paymasterAndData: userOp.paymasterAndData ?? "0x",
verificationGasLimit: 10e6,
Expand All @@ -102,14 +117,21 @@ export class Eth {
preVerificationGas: 0,
...userOp,
};

if (userOpComplemented.signature === "0x") {
userOpComplemented.signature = await this.getDummySignature({
userOp: userOpComplemented,
entryPoint: args.entryPoint,
});
}

let preVerificationGas: BigNumberish = this.calcPreVerificationGas(userOp);
userOpComplemented.preVerificationGas = preVerificationGas;

const { returnInfo } =
await this.userOpValidationService.validateForEstimation(
userOpComplemented,
entryPoint
);
const returnInfo = await this.userOpValidationService.validateForEstimation(
userOpComplemented,
entryPoint
);
if (this.pvgEstimator) {
preVerificationGas = await this.pvgEstimator(
entryPoint,
Expand All @@ -119,20 +141,29 @@ export class Eth {
}

// eslint-disable-next-line prefer-const
let { preOpGas, validAfter, validUntil } = returnInfo;
let { preOpGas, validAfter, validUntil, paid } = returnInfo;

const callGasLimit = await this.provider
.estimateGas({
from: entryPoint,
to: userOp.sender,
data: userOp.callData,
})
.then((b) => b.toNumber())
.catch((err) => {
const message =
err.message.match(/reason="(.*?)"/)?.at(1) ?? "execution reverted";
throw new RpcError(message, RpcErrorCodes.EXECUTION_REVERTED);
});
const block = await this.provider.getBlock("latest");

const { estimationBaseFeeDivisor, estimationStaticBuffer } = this.config;
const estimatedBaseFee = block.baseFeePerGas
?.mul(100)
.div(100 + (estimationBaseFeeDivisor || 0));

let callGasLimit: BigNumber;
if (!estimatedBaseFee) {
callGasLimit = BigNumber.from(paid).div(userOpComplemented.maxFeePerGas);
} else {
const lhs = BigNumber.from(userOpComplemented.maxFeePerGas);
const rhs = estimatedBaseFee.add(userOpComplemented.maxPriorityFeePerGas);
const divisor = lhs.lt(rhs) ? lhs : rhs; // min(maxFeePerGas, base + priorityFee)
callGasLimit = BigNumber.from(paid).div(divisor);
}
callGasLimit = callGasLimit.sub(preOpGas).add(estimationStaticBuffer || 0);

if (callGasLimit.lt(0)) {
callGasLimit = BigNumber.from(estimationStaticBuffer || 0);
}

const verificationGas = BigNumber.from(preOpGas).toNumber();
validAfter = BigNumber.from(validAfter);
Expand All @@ -143,6 +174,7 @@ export class Eth {
if (validAfter === BigNumber.from(0)) {
validAfter = undefined;
}

return {
preVerificationGas,
verificationGas,
Expand Down Expand Up @@ -279,6 +311,15 @@ export class Eth {
});
}

async getDummySignature(args: SendUserOperationGasArgs): Promise<string> {
const randomWallet = ethers.Wallet.createRandom();
const chainId = await this.getChainId();
const dummySignature = randomWallet.signMessage(
getUserOpHash(args.userOp, args.entryPoint, chainId)
);
return dummySignature;
}

/**
* eth_chainId
* @returns EIP-155 Chain ID.
Expand Down
Loading

0 comments on commit 01dd1ab

Please sign in to comment.