Skip to content

Commit

Permalink
feat: flashbots (#130)
Browse files Browse the repository at this point in the history
  • Loading branch information
0xSulpiride authored Dec 8, 2023
1 parent 93597de commit 6bb7c8c
Show file tree
Hide file tree
Showing 37 changed files with 1,174 additions and 620 deletions.
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ Or follow the steps below:
"throttlingSlack": 10, # optional, see EIP-4337
"banSlack": 50 # optional, see EIP-4337
"minStake": 10000000000, # optional, min stake of an entity (in wei)
"minUnstakeDelay": 1, # optional, min unstake delay of an entity
"minUnstakeDelay": 0, # optional, min unstake delay of an entity
"minSignerBalance": 1, # optional, default is 0.1 ETH. If the relayer's balance drops lower than this, it will be selected as a fee collector
"multicall": "0xcA11bde05977b3631167028862bE2a173976CA11", # optional, multicall3 contract (see https://github.com/mds1/multicall#multicall3-contract-addresses)
"estimationStaticBuffer": 21000, # adds certain amount of gas to callGasLimit on estimation
Expand All @@ -100,7 +100,10 @@ Or follow the steps below:
"paymaster": [],
"account": []
},
"bundleGasLimitMarkup": 25000 # adds some amount of additional gas to a bundle tx
"bundleGasLimitMarkup": 25000, # adds some amount of additional gas to a bundle tx
"relayingMode": "classic"; # optional, allows to switch to Flashbots Builder api if set to "flashbots", see packages/executor/src/interfaces.ts for more
"bundleInterval": 10000, # bundle creation interval
"bundleSize": 4 # max size of a bundle, 4 userops by default
}
}
}
Expand Down
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": "1.0.26-alpha",
"version": "1.0.27-alpha",
"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": "1.0.26-alpha",
"version": "1.0.27-alpha",
"engines": {
"node": ">=18.0.0"
},
Expand Down
8 changes: 4 additions & 4 deletions packages/api/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "api",
"version": "1.0.26-alpha",
"version": "1.0.27-alpha",
"description": "The API module of Etherspot bundler client",
"author": "Etherspot",
"homepage": "https://https://github.com/etherspot/skandha#readme",
Expand Down Expand Up @@ -35,13 +35,13 @@
"class-transformer": "0.5.1",
"class-validator": "0.14.0",
"ethers": "5.7.2",
"executor": "^1.0.26-alpha",
"executor": "^1.0.27-alpha",
"fastify": "4.14.1",
"monitoring": "^1.0.26-alpha",
"monitoring": "^1.0.27-alpha",
"pino": "8.11.0",
"pino-pretty": "10.0.0",
"reflect-metadata": "0.1.13",
"types": "^1.0.26-alpha"
"types": "^1.0.27-alpha"
},
"devDependencies": {
"@types/connect": "3.4.35"
Expand Down
14 changes: 7 additions & 7 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cli",
"version": "1.0.26-alpha",
"version": "1.0.27-alpha",
"description": "> TODO: description",
"author": "zincoshine <[email protected]>",
"homepage": "https://https://github.com/etherspot/skandha#readme",
Expand Down Expand Up @@ -38,15 +38,15 @@
"@libp2p/peer-id-factory": "2.0.1",
"@libp2p/prometheus-metrics": "1.1.3",
"@multiformats/multiaddr": "12.1.3",
"api": "^1.0.26-alpha",
"db": "^1.0.26-alpha",
"executor": "^1.0.26-alpha",
"api": "^1.0.27-alpha",
"db": "^1.0.27-alpha",
"executor": "^1.0.27-alpha",
"find-up": "5.0.0",
"got": "12.5.3",
"js-yaml": "4.1.0",
"monitoring": "^1.0.26-alpha",
"node": "^1.0.26-alpha",
"types": "^1.0.26-alpha",
"monitoring": "^1.0.27-alpha",
"node": "^1.0.27-alpha",
"types": "^1.0.27-alpha",
"yargs": "17.6.2"
},
"devDependencies": {
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": "1.0.26-alpha",
"version": "1.0.27-alpha",
"description": "The DB module of Etherspot bundler client",
"author": "Etherspot",
"homepage": "https://github.com/etherspot/etherspot-bundler#readme",
Expand Down Expand Up @@ -33,7 +33,7 @@
"dependencies": {
"@chainsafe/ssz": "0.10.1",
"@farcaster/rocksdb": "5.5.0",
"types": "^1.0.26-alpha"
"types": "^1.0.27-alpha"
},
"devDependencies": {
"@types/rocksdb": "3.0.1",
Expand Down
9 changes: 5 additions & 4 deletions packages/executor/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "executor",
"version": "1.0.26-alpha",
"version": "1.0.27-alpha",
"description": "The Relayer module of Etherspot bundler client",
"author": "Etherspot",
"homepage": "https://https://github.com/etherspot/skandha#readme",
Expand Down Expand Up @@ -31,10 +31,11 @@
"check-readme": "typescript-docs-verifier"
},
"dependencies": {
"@flashbots/ethers-provider-bundle": "0.6.2",
"async-mutex": "0.4.0",
"ethers": "5.7.2",
"monitoring": "^1.0.26-alpha",
"params": "^1.0.26-alpha",
"types": "^1.0.26-alpha"
"monitoring": "^1.0.27-alpha",
"params": "^1.0.27-alpha",
"types": "^1.0.27-alpha"
}
}
28 changes: 26 additions & 2 deletions packages/executor/src/config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// TODO: create a new package "config" instead of this file and refactor
import { BigNumber, Wallet, providers, utils } from "ethers";
import { NetworkName } from "types/lib";
import { IEntity } from "types/lib/executor";
import { IEntity, RelayingMode } from "types/lib/executor";
import { getAddress } from "ethers/lib/utils";
import {
BundlerConfig,
Expand Down Expand Up @@ -260,6 +260,27 @@ export class Config {
conf.bundleGasLimitMarkup || bundlerDefaultConfigs.bundleGasLimitMarkup
)
);
conf.relayingMode = fromEnvVar(
network,
"RELAYING_MODE",
conf.relayingMode || bundlerDefaultConfigs.relayingMode
) as RelayingMode;

conf.bundleInterval = Number(
fromEnvVar(
network,
"BUNDLE_INTERVAL",
conf.bundleInterval || bundlerDefaultConfigs.bundleInterval
)
);

conf.bundleSize = Number(
fromEnvVar(
network,
"BUNDLE_SIZE",
conf.bundleSize || bundlerDefaultConfigs.bundleSize
)
);

// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
if (!conf.whitelistedEntities) {
Expand Down Expand Up @@ -297,7 +318,7 @@ const bundlerDefaultConfigs: BundlerConfig = {
throttlingSlack: 10,
banSlack: 50,
minStake: utils.parseEther("0.01"),
minUnstakeDelay: 1,
minUnstakeDelay: 0,
minSignerBalance: utils.parseEther("0.1"),
multicall: "0xcA11bde05977b3631167028862bE2a173976CA11", // default multicall address
estimationStaticBuffer: 35000,
Expand All @@ -313,6 +334,9 @@ const bundlerDefaultConfigs: BundlerConfig = {
useropsTTL: 300, // 5 minutes
whitelistedEntities: { paymaster: [], account: [], factory: [] },
bundleGasLimitMarkup: 25000,
bundleInterval: 10000, // 10 seconds
bundleSize: 4, // max size of bundle (in terms of user ops)
relayingMode: "classic",
};

const NETWORKS_ENV = (): string[] | undefined => {
Expand Down
27 changes: 27 additions & 0 deletions packages/executor/src/entities/MempoolEntry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { getAddress, hexValue } from "ethers/lib/utils";
import * as RpcErrorCodes from "types/lib/api/errors/rpc-error-codes";
import RpcError from "types/lib/api/errors/rpc-error";
import { UserOperationStruct } from "types/lib/executor/contracts/EntryPoint";
import { MempoolEntryStatus } from "types/lib/executor";
import { now } from "../utils";
import { IMempoolEntry, MempoolEntrySerialized } from "./interfaces";

Expand All @@ -16,7 +17,10 @@ export class MempoolEntry implements IMempoolEntry {
paymaster?: string;
lastUpdatedTime: number;
userOpHash: string;
status: MempoolEntryStatus;
hash?: string; // keccak256 of all referenced contracts
transaction?: string; // hash of a submitted bundle
submitAttempts: number;

constructor({
chainId,
Expand All @@ -29,6 +33,9 @@ export class MempoolEntry implements IMempoolEntry {
userOpHash,
hash,
lastUpdatedTime,
status,
transaction,
submitAttempts,
}: {
chainId: number;
userOp: UserOperationStruct;
Expand All @@ -40,6 +47,9 @@ export class MempoolEntry implements IMempoolEntry {
userOpHash: string;
hash?: string | undefined;
lastUpdatedTime?: number | undefined;
status?: MempoolEntryStatus | undefined;
transaction?: string | undefined;
submitAttempts?: number | undefined;
}) {
this.chainId = chainId;
this.userOp = userOp;
Expand All @@ -51,9 +61,23 @@ export class MempoolEntry implements IMempoolEntry {
this.paymaster = paymaster;
this.hash = hash;
this.lastUpdatedTime = lastUpdatedTime ?? now();
this.status = status ?? MempoolEntryStatus.New;
this.transaction = transaction;
this.submitAttempts = submitAttempts ?? 0;
this.validateAndTransformUserOp();
}

/**
* Set status of an entry
* If status is Pending, transaction hash is required
*/
setStatus(status: MempoolEntryStatus, transaction?: string): void {
this.status = status;
if (transaction) {
this.transaction = transaction;
}
}

/**
* To replace an entry, a new entry must have at least 10% higher maxPriorityFeePerGas
* and 10% higher maxPriorityFeePerGas than the existingEntry
Expand Down Expand Up @@ -159,6 +183,9 @@ export class MempoolEntry implements IMempoolEntry {
hash: this.hash,
userOpHash: this.userOpHash,
lastUpdatedTime: this.lastUpdatedTime,
transaction: this.transaction,
submitAttempts: this.submitAttempts,
status: this.status,
};
}
}
8 changes: 7 additions & 1 deletion packages/executor/src/entities/interfaces.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { BigNumberish, BytesLike } from "ethers";
import { ReputationStatus } from "types/lib/executor";
import { MempoolEntryStatus, ReputationStatus } from "types/lib/executor";
import { UserOperationStruct } from "types/lib/executor/contracts/EntryPoint";

export interface IMempoolEntry {
Expand All @@ -13,6 +13,9 @@ export interface IMempoolEntry {
userOpHash: string;
lastUpdatedTime: number;
hash?: string;
status: MempoolEntryStatus;
transaction?: string;
submitAttempts: number;
}

export interface MempoolEntrySerialized {
Expand All @@ -37,6 +40,9 @@ export interface MempoolEntrySerialized {
userOpHash: string;
hash: string | undefined;
lastUpdatedTime: number;
transaction: string | undefined;
submitAttempts: number;
status: MempoolEntryStatus;
}

export interface IReputationEntry {
Expand Down
13 changes: 11 additions & 2 deletions packages/executor/src/executor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@ export class Executor {
this.reputationService,
this.config,
this.logger,
this.metrics
this.metrics,
this.networkConfig.relayingMode
);
this.eventsService = new EventsService(
this.chainId,
Expand Down Expand Up @@ -150,7 +151,15 @@ export class Executor {

if (this.config.testingMode || options.bundlingMode == "manual") {
this.bundlingService.setBundlingMode("manual");
this.logger.info(`${this.networkName}: set to manual bundling mode`);
this.logger.info(`${this.networkName}: [X] MANUAL BUNDLING`);
}

if (this.networkConfig.relayingMode === "flashbots") {
if (!this.networkConfig.rpcEndpointSubmit)
throw Error(
"If you want to use Flashbots Builder API, please set API url in 'rpcEndpointSubmit' in config file"
);
this.logger.info(`${this.networkName}: [X] FLASHBOTS BUIDLER API`);
}

if (this.networkConfig.conditionalTransactions) {
Expand Down
12 changes: 11 additions & 1 deletion packages/executor/src/interfaces.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { BigNumber, BigNumberish, BytesLike } from "ethers";
import { NetworkName } from "types/lib";
import { IWhitelistedEntities } from "types/lib/executor";
import { IWhitelistedEntities, RelayingMode } from "types/lib/executor";
import { Executor } from "./executor";
import { MempoolEntry } from "./entities/MempoolEntry";

Expand Down Expand Up @@ -131,6 +131,16 @@ export interface NetworkConfig {
whitelistedEntities: IWhitelistedEntities;
// adds some amount of gas to a estimated bundle
bundleGasLimitMarkup: number;
// relaying mode: via Flashbots Builder API or classic relaying
// default is "classic"
// if flashbots is used, "rpcEndpointSubmit" must be set
relayingMode: RelayingMode;
// Interval of bundling
// default is 10 seconds
bundleInterval: number;
// max bundle size in terms of user ops
// default is 4
bundleSize: number;
}

export type BundlerConfig = Omit<
Expand Down
5 changes: 4 additions & 1 deletion packages/executor/src/modules/debug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
IEntryPoint__factory,
StakeManager__factory,
} from "types/lib/executor/contracts";
import { MempoolEntryStatus } from "types/lib/executor";
import {
BundlingService,
MempoolService,
Expand Down Expand Up @@ -65,7 +66,9 @@ export class Debug {
*/
async dumpMempool(): Promise<UserOperationStruct[]> {
const entries = await this.mempoolService.dump();
return entries.map((entry) => entry.userOp);
return entries
.filter((entry) => entry.status === MempoolEntryStatus.New)
.map((entry) => entry.userOp);
}

/**
Expand Down
6 changes: 5 additions & 1 deletion packages/executor/src/modules/skandha.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ export class Skandha {
return {
chainId: this.chainId,
flags: {
unsafeMode: this.config.unsafeMode,
testingMode: this.config.testingMode,
redirectRpc: this.config.redirectRpc,
},
Expand Down Expand Up @@ -115,6 +114,11 @@ export class Skandha {
eip2930: this.networkConfig.eip2930,
useropsTTL: this.networkConfig.useropsTTL,
whitelistedEntities: this.networkConfig.whitelistedEntities,
bundleGasLimitMarkup: this.networkConfig.bundleGasLimitMarkup,
relayingMode: this.networkConfig.relayingMode,
bundleInterval: this.networkConfig.bundleInterval,
bundleSize: this.networkConfig.bundleSize,
minUnstakeDelay: this.networkConfig.minUnstakeDelay,
};
}

Expand Down
Loading

0 comments on commit 6bb7c8c

Please sign in to comment.