├── README.md ├── architecture.md ├── specs ├── bundles │ ├── refund-recipient.md │ └── v0.1.md └── events │ └── v0.1.md └── tests └── v0.1 ├── README.md └── tests.json /README.md: -------------------------------------------------------------------------------- 1 | # mev-share 2 | 3 | This repository stores the technical specifications for the MEV-share protocol, which is described in this [design doc](https://collective.flashbots.net/t/mev-share-programmably-private-orderflow-to-share-mev-with-users/1264). It is intended to host discussion, development, and release notes for the protocol. Find the current specifications in `/specs` and see issues for active discussions around design tradeoffs and features. 4 | 5 | Coordinating on one interface for orderflow auctions will reduce switching costs, increase competition, and create a more fair and efficient market. 6 | 7 | ## Motivations 8 | 9 | Today, orderflow originators like wallets and dapps do not actively participate in MEV. Their users generate MEV when transacting, but this value is captured by builders, searchers, and validators – not users, wallets, or dapps. 10 | 11 | [MEV-Share](https://collective.flashbots.net/t/mev-share-programmably-private-orderflow-to-share-mev-with-users/1264) enables MEV redistribution whereby MEV generated by transactions can be redistributed to the initiating user, orderflow provider, and any other destination. 12 | 13 | Importantly, **MEV-Share is an open-source protocol, not a product or company**. MEV-share uses commitments and privacy to facilitate permissionless collaboration between orderflow originators and searchers, similarly to what MEV-Boost did for builders and validators. It is credibly neutral, permissionless for searchers, and does not enshrine a single block builder. Aggregating order flow to MEV-Share will greatly reduce proprietary order flow as a centralizing force on Ethereum while enabling orderflow originators to participate in the MEV supply chain. 14 | 15 | > Note: The MEV-Share Matchmaker was renamed to the MEV-Share Node. This change is reflected in the specifications after June 2023. 16 | 17 | ## Minimum standardizable interfaces 18 | 19 | There are many parties that may interact as part of the MEV-share protocol: 20 | 1. Orderflow providers / sources (users, wallets, dapps) 21 | 2. Searchers 22 | 3. MEV-Share Nodes 23 | 4. Blockspace providers / proxies (builders, sequencers, validators, bundlers) 24 | 25 | A minimum set of interfaces includes: 26 | 1. How orderflow providers send orderflow and preferences (eg. privacy, redistribution) to MEV-Share Nodes 27 | 2. How MEV-Share Nodes share information about orderflow with searchers 28 | 3. How searchers send bids, orderflow, and preferences (eg. validity conditions) to MEV-Share Nodes 29 | 4. How MEV-Share Nodes send orderflow and preferences to blockspace providers 30 | 5. How value is redistributed to orderflow providers, blockspace providers, and MEV-Share Nodes 31 | 32 | ## Current architecture and APIs 33 | 34 | The MEV-share design is actively being developed. You can find the latest architecture diagram in `./architecture.md` and individual API specifications can be found in the `/specs` folder. See `/bundles` for bundle APIs and `/events` for event streaming APIs (each version has its own file). 35 | 36 | Concretely, MEV-share extends the bundle API to support privacy settings, validity conditions, and complex bundle bodies. This API is used for interfaces (1), (3), and (4) above. (2) is handled by a new streaming endpoint and (5) is at the discretion of the block builder, but must fulfill the validity conditions. 37 | 38 | ## Open Questions and Contributions 39 | 40 | There are several questions around design tradeoffs and feature support. You can find existing conversations in the issues of this repo, or add your own issue to suggest a change or request a feature. 41 | -------------------------------------------------------------------------------- /architecture.md: -------------------------------------------------------------------------------- 1 | ![mev-share architecture diagram](https://github.com/flashbots/mev-share/assets/2029632/35e0a2b9-6334-4cfd-94a4-679a788874dd) 2 | 3 | https://excalidraw.com/#json=1l2qz7Dp_bbEnOtwb8Wk5,bFNry1-SY4W34J59xkiFzA 4 | -------------------------------------------------------------------------------- /specs/bundles/refund-recipient.md: -------------------------------------------------------------------------------- 1 | # `eth_sendBundle` 2 | 3 | MEV-Share Nodes can use the `eth_sendBundle` method to send a bundle of transactions to a block builder. Specifically, the `refund-recipient` version of `eth_sendBundle` extends the [standard `eth_sendBundle` API](https://docs.flashbots.net/flashbots-auction/searchers/advanced/rpc-endpoint#eth_sendbundle) to support two additional fields (`refundPercent` and `refundRecipient`) which can optionally be set to specify how refunds from MEV-Share should be distributed. 4 | 5 | 6 | * [`eth_sendBundle`](#eth_sendbundle) 7 | * [JSON-RPC Scheme](#json-rpc-scheme) 8 | * [`txs`](#txs) 9 | * [`blockNumber`](#blocknumber) 10 | * [`minTimestamp`](#mintimestamp) 11 | * [`maxTimestam`](#maxtimestam) 12 | * [`revertingTxHashes`](#revertingtxhashes) 13 | * [`replacementUuid`](#replacementuuid) 14 | * [`refundPercent`](#refundpercent) 15 | * [`refundRecipient`](#refundrecipient) 16 | * [Example](#example) 17 | 18 | 19 | ## JSON-RPC Scheme 20 | 21 | ```typescript 22 | { 23 | jsonrpc: "2.0", 24 | id: 1, 25 | method: "eth_sendBundle", 26 | params: [{ 27 | txs: Array, 28 | blockNumber: string, 29 | minTimestamp?: number, 30 | maxTimestamp?: number, 31 | revertingTxHashes?: Array, 32 | replacementUuid?: string, 33 | refundPercent?: number, 34 | refundRecipient?: string, 35 | }] 36 | } 37 | ``` 38 | 39 | _NOTE: Optional fields are marked with a `?`._ 40 | 41 | ### `txs` 42 | 43 | A list of signed transactions to execute in an atomic bundle. 44 | 45 | ### `blockNumber` 46 | 47 | A hex encoded block number for which this bundle is valid on. 48 | 49 | ### `minTimestamp` 50 | 51 | The minimum timestamp for which this bundle is valid, in seconds since the unix epoch. 52 | 53 | ### `maxTimestam` 54 | 55 | The maximum timestamp for which this bundle is valid, in seconds since the unix epoch. 56 | 57 | ### `revertingTxHashes` 58 | 59 | A list of tx hashes that are allowed to revert or be discarded from the beginning of the bundle. 60 | 61 | ### `replacementUuid` 62 | 63 | UUID that can be used to cancel/replace this bundle. 64 | 65 | ### `refundPercent` 66 | 67 | The percent(from 0 to 99) of full bundle ETH reward that should be passed back to the user(`refundRecipient`) at the end of the bundle. 68 | 69 | ### `refundRecipient` 70 | 71 | Address of the wallet that will receive the ETH reward refund from this bundle, default value = EOA of the first transaction inside the bundle. 72 | 73 | If the `refundPercent` field is set, the builder will pass `refundPercent` of the total ETH reward generated by last transaction inside the bundle to the user (minus burned base fee). The builder will keep the remaining amount. 74 | 75 | ## Example 76 | 77 | Request: 78 | 79 | ```typescript 80 | { 81 | jsonrpc: "2.0", 82 | id: 1, 83 | method: "eth_sendBundle", 84 | params: [ 85 | { 86 | "txs": ["0x123abc...", "0x456def..."], 87 | "blockNumber": "0xb63dcd", 88 | "minTimestamp": 0, 89 | "maxTimestamp": 1615920932 90 | } 91 | ] 92 | } 93 | ``` 94 | 95 | Response: 96 | 97 | ```typescript 98 | { 99 | jsonrpc: "2.0", 100 | id: "123", 101 | result: { 102 | "bundleHash": "0x2228f5d8954ce31dc1601a8ba264dbd401bf1428388ce88238932815c5d6f23f" 103 | } 104 | } 105 | ``` 106 | -------------------------------------------------------------------------------- /specs/bundles/v0.1.md: -------------------------------------------------------------------------------- 1 | # `mev_sendBundle` 2 | 3 | Users and searchers can use `mev_sendBundle` to send a bundle of transactions [and transaction hashes] to a MEV-Share Node. Nodes can use `mev_sendBundle` to send a bundle of transactions to a block builder. 4 | 5 | 6 | * [`mev_sendBundle`](#mev_sendbundle) 7 | * [JSON-RPC Request](#json-rpc-request-scheme) 8 | * [`version`](#version) 9 | * [`inclusion`](#inclusion) 10 | * [`body`](#body) 11 | * [Example](#example) 12 | * [Bundle Composition](#bundle-composition) 13 | * [`validity`](#validity) 14 | * [`privacy`](#privacy) 15 | * [JSON-RPC Response](#json-rpc-response-scheme) 16 | * [`bundleHash`](#bundlehash) 17 | 18 | 19 | ## JSON-RPC Request Scheme 20 | 21 | ```typescript 22 | type requestBody = { 23 | jsonrpc: "2.0", 24 | id: string | number, 25 | method: "mev_sendBundle", 26 | params: [{ /* MevSendBundleParams */ 27 | version: "v0.1", // Not optional 28 | inclusion: { 29 | block: string, // hex-encoded number 30 | maxBlock?: string, // hex-encoded number 31 | }, 32 | body: Array< 33 | { hash: string } | 34 | { tx: string, canRevert: boolean } | 35 | { bundle: MevSendBundleParams } 36 | >, 37 | validity? : { 38 | refund?: Array<{ 39 | bodyIdx: number, 40 | percent: number, 41 | }>, 42 | refundConfig?: Array<{ 43 | address: string, 44 | percent: number, 45 | }>, 46 | }, 47 | privacy?: { 48 | hints?: Array< 49 | "calldata" | 50 | "contract_address" | 51 | "logs" | 52 | "function_selector" | 53 | "hash" | 54 | "tx_hash" 55 | >, 56 | builders?: Array, 57 | }, 58 | }] 59 | } 60 | ``` 61 | 62 | NOTE: Optional fields are marked with a `?`. 63 | 64 | ### `version` 65 | 66 | Version of MEV-Share API specification to use. 67 | 68 | ### `inclusion` 69 | 70 | Data used by block builders to check if bundle should be considered for inclusion in their block-building attempt. Data from `inclusion` is used as input for a predicate function that is fast to compute. 71 | 72 | | Param | Type Info | Description | 73 | |-|-|-| 74 | | `block` | Hex-encoded string | The [first] block in which this bundle must be included. | 75 | | `maxBlock` | Hex-encoded string; optional | The maximum block height in which this bundle _may_ be included. | 76 | 77 | If only `block` is specified, the bundle may only be included in that block. If `maxBlock` is specified, the bundle may be included in any block between `block` and `maxBlock`, inclusively. 78 | 79 | ### `body` 80 | 81 | An array of transactions to be sent; the body of the bundle. Each item in the array may include per-transaction validity conditions. 82 | 83 | A transaction is wrapped in an object to specify which type of transaction it is. 84 | 85 | Transactions picked up from listening to the mev-share endpoint will only give listeners a transaction hash (and not a signature). These transactions are placed in the array with the `{hash}` wrapper. 86 | 87 | New signed transactions are placed in the array with the `{tx, canRevert}` wrapper. 88 | 89 | If `canRevert` is true, the item is allowed to either revert or be discarded from the bundle. 90 | 91 | #### Example 92 | 93 | An example (backrun) might look something like this: 94 | 95 | ```json 96 | ... 97 | "body": [ 98 | { 99 | "hash": "0x3232323232323232323232323232323232323232323232323232323232323232" 100 | }, 101 | { 102 | "tx": "0x020424242424212312312312301230123012301230123012301230123012032424242123123124242421231231242424212312312424242123123124242421231231", 103 | "canRevert": false 104 | } 105 | ] 106 | ``` 107 | 108 | ### Bundle Composition 109 | 110 | Bundles are designed to support composition with other bundles. 111 | 112 | By specifying a bundle _hash_ in the `body` parameter, searchers can nest bundles within their bundles, achieving the same atomicity as if the transactions in the nested bundle were in the parent bundle. 113 | 114 | Bundles appear the same as transactions in the event stream; this is why the `hash` is named as such. It can be either a bundle hash or a transaction hash. 115 | 116 | ```json 117 | "body": [ 118 | { "hash": "0x4567..." }, // bundle hash 119 | { "hash": "0x3232..." }, // transaction hash 120 | { "tx": "0x0204...", "canRevert": false } // signed tx 121 | ] 122 | ``` 123 | 124 | Entire bundles can also be included using the `{bundle}` wrapper. This example backruns a bundle with a transaction: 125 | 126 | ```json 127 | { 128 | ..., 129 | "body": [ 130 | { 131 | "bundle": { 132 | "version": "v0.2", 133 | "inclusion": { 134 | "block": "0x463e", 135 | "maxBlock": "0x4648" 136 | }, 137 | "body": [ 138 | { 139 | "tx": "0x02..." 140 | } 141 | ], 142 | "privacy": { 143 | "hints": [ 144 | "calldata" 145 | ] 146 | }, 147 | "validity": { 148 | "refundConfig": [ 149 | { 150 | "address": "0x8EC1237b1E80A6adf191F40D4b7D095E21cdb18f", 151 | "percent": 100 152 | } 153 | ] 154 | } 155 | } 156 | }, 157 | { 158 | "tx": "0x02..." 159 | } 160 | ], 161 | ... 162 | } 163 | ``` 164 | 165 | ### `validity` 166 | 167 | Requirements for the bundle to be included in a block, checked by the builder _after_ the bundle is considered for placement in a block. 168 | 169 | For example, refund (MEV kickback) parameters are considered as a post-inclusion predicate, so they are specified here. 170 | 171 | | Param | Type Info | Description | 172 | |-|-|-| 173 | | `refund` | Array of objects | Specifies the minimum percent of a given bundle's earnings to redistribute for it to be included in a builder's block. | 174 | | `refund.bodyIdx` | Number | Index of the entry in `body` to which the refund percentage applies. | 175 | | `refund.percent` | Number | Minimum refund percentage required for this bundle to be eligible for use by another searcher, paid by said searcher from the profit generated by including this bundle in theirs. | 176 | | `refundConfig` | Array of objects | Specifies what addresses should receive what percent of the overall refund for this bundle, if it is enveloped by another bundle (eg. a searcher backrun). The sum of percents in this array should equal 100. | 177 | | `refundConfig.address` | String | Address which receives the portion of the refund. | 178 | | `refundConfig.percent` | Number | Percentage of refund to pay to the address. | 179 | 180 | The `refundConfig` is specified by the original party (eg. user) who sends an input to MEV-Share. Given some refund X, the `refundConfig` specifies what % of X should be paid to what address(es). The `refundConfig` is not aware of the precise refund amount X, because this is not known until after the input has been sent to MEV-Share. 181 | 182 | The `refund` is set by the MEV-Share Node. It identifies what items in the bundle should be refunded -- ie. when a searcher submits a new bundle back to the MEV-Share Node, what indices contained hashes. The builder must simulate the bundle without these input transactions to determine what portion of the overall bundle payment came from searcher bids and should be redistributed. If bundles contain multiple input items then the MEV-Share Node is responsible for allocating the searcher bids across the other items in the bundle. The party who submits the input to the MEV-Share Node could also use this field to specify their preference for what percentage of the searcher bid they receive. The MEV-Share Node would use this information when producing the final `refund` field that is sent to a block builder. 183 | 184 | ### `privacy` 185 | 186 | Preferences on what data should be shared about the bundle and its transactions. Optional. 187 | 188 | | Param | Type Info | Description | 189 | |-|-|-| 190 | | `hints` | Array of strings; optional | Each item additively specifies which data about all transactions in the bundle to share. If no hints are specified, no data is shared. Transactions from other users that do not specify the same hints will not share additional information. | 191 | | `builders` | Array of strings; optional | Builders that have permission to receive this bundle and include it in a block. | 192 | 193 | ## JSON-RPC Response Scheme 194 | 195 | ```typescript 196 | type responseBody = { 197 | "bundleHash": string // hex-string 198 | } 199 | ``` 200 | 201 | ### `bundleHash` 202 | 203 | Hash of the list of bundle bodies defined by [bundle composition](#bundle-composition). If there is only one bundle in the list, the `bundleHash` returns the hash of that bundle body. 204 | -------------------------------------------------------------------------------- /specs/events/v0.1.md: -------------------------------------------------------------------------------- 1 | # event-stream 2 | 3 | Events on MEV-Share are distributed via an SSE endpoint. Searchers listen to this endpoint to receive a stream of new events, which contain data they can use in their bundles. 4 | 5 | 6 | * [event-stream](#event-stream) 7 | * [Event Scheme](#event-scheme) 8 | * [`hash`](#hash) 9 | * [`logs`](#logs) 10 | * [`txs`](#txs) 11 | * [Stream Logic](#stream-logic) 12 | 13 | 14 | ## Event Scheme 15 | 16 | ```typescript 17 | { 18 | hash: string, 19 | logs?: LogParams[], 20 | txs: Array<{ 21 | to?: string, 22 | functionSelector?: string, 23 | callData?: string, 24 | }>, 25 | } 26 | ``` 27 | 28 | _NOTE: Optional fields are marked with a `?`._ 29 | 30 | ### `hash` 31 | 32 | Hex-string of the transaction or bundle hash. 33 | 34 | ### `logs` 35 | 36 | Array of JSON-encoded event logs emitted by executing the transaction. 37 | 38 | ### `txs` 39 | 40 | Transactions from the event. If the event itself is a transaction, txs will only have one entry. Bundle events may have more. 41 | 42 | | Field | Type | Description | 43 | | ----- | ---- | ----------- | 44 | | `to` | Hex-string | Transaction recipient address. | 45 | | `functionSelector` | Hex-string | 4-byte function selector. | 46 | | `callData` | Hex-string | Calldata of the transaction. | 47 | 48 | ### Stream Logic 49 | 50 | Users subscribe to the stream by making an HTTP GET request on the stream endpoint. 51 | 52 | The endpoint should send an event with the message `:ping` every 15 seconds if no other messages were sent in the last 15 seconds. 53 | -------------------------------------------------------------------------------- /tests/v0.1/README.md: -------------------------------------------------------------------------------- 1 | # About 2 | 3 | This document provides a set of example bundles and their expected execution results. 4 | 5 | Tests can be found in the file [test.json](./test.json), where the test suite's JSON object is described. 6 | 7 | ## Preparing State 8 | 9 | The transactions in the bundles expect the blockchain state to be set to state in the `genesisAlloc` field. 10 | 11 | ## Preparing the Block State 12 | 13 | Each test case must be applied on top of a fresh block with the state described above and the header set to the value of the `header` field. 14 | 15 | Relevant values from the header include: 16 | 17 | * `number` - block number 18 | * `gasLimit` - block gas limit 19 | * `miner` - builder's address 20 | * `baseFeePerGas` - base fee per gas 21 | 22 | 23 | ## Applying Test Bundles 24 | 25 | Individual tests are objects within the `tests` array and include the following fields: 26 | 27 | * `name` - a short test description 28 | * `bundle` - the bundle to be executed 29 | * `shouldFail` - set to true if the bundle is expected to fail 30 | * `extractedRefunds` - an array of extracted values from the backruns in the bundle 31 | 32 | ### How to Interpret extractedRefunds 33 | 34 | The exact method of paying kickbacks may vary from builder to builder. 35 | Some may use one transaction per kickback, while others may use a contract to batch multiple payments. 36 | 37 | Different payment methods will yield slightly different kickback values. 38 | Instead of providing an exact kickback amount, we offer a value extracted by a backrun, 39 | the percentage of the value to be used for refunds, and a refund split to be potentially divided among multiple recipients. 40 | 41 | The `extractedRefunds` array contains the following information for each backrun: 42 | 43 | * `value` - values paid to the builder by the kickback 44 | * `percent` - percentage of the value to be used for refunds 45 | * `refundSplit` - an object that maps an address to the percentage of the refund to be paid to that address 46 | 47 | Example: 48 | ```json 49 | { 50 | "extractedRefunds": [ 51 | { 52 | "value": "0x1636110e9abbc00", 53 | "percent": 90, 54 | "refundSplit": { 55 | "0xc87037874aed04e51c29f582394217a0a2b89d80": 100 56 | } 57 | } 58 | ] 59 | } 60 | ``` 61 | In this example, 100030342000000000 wei is paid to the builder by the backrun, 62 | and 90% of that value should be used for refunds. 63 | 100% of the refund value should be paid to the address 0xc87037874aed04e51c29f582394217a0a2b89d80. 64 | 65 | To calculate the exact refund value, we must factor in the kickback transaction cost, 66 | which depends on the specific details of the kickback implementation. 67 | 68 | Let's assume that we take 30_000 * BASE_FEE * NUM_RECIPIENTS from the refund value upfront, 69 | and then take 90% of the remaining value and split it between the refund recipients. 70 | 71 | For a base fee of 200 gwei and 1 recipient, we get: 72 | ``` 73 | refund = 100030342000000000 - 30000 * 200000000000 * 1 = 94030342000000000 74 | kickback-tx-value = 94030342000000000 * 90% * 100% = 84627307800000000 75 | ``` 76 | 77 | The builder's refund transaction will have `tx.value = kickback-tx-value` 78 | -------------------------------------------------------------------------------- /tests/v0.1/tests.json: -------------------------------------------------------------------------------- 1 | { 2 | "genesisAlloc": { 3 | "0x3845794654dfec95145512fd33866dbc481893ea": { 4 | "balance": "0x0" 5 | }, 6 | "0x3e7dfb3e26a16e3dbf6dfeeff8a5ae7a04f73aad": { 7 | "balance": "0xde0b6b3a7640000" 8 | }, 9 | "0xc100000000000000000000000000000000000000": { 10 | "code": "0x6000351561000957fe5b600060006000600034416000f1", 11 | "balance": "0x0" 12 | }, 13 | "0xc87037874aed04e51c29f582394217a0a2b89d80": { 14 | "balance": "0xde0b6b3a7640000" 15 | } 16 | }, 17 | "header": { 18 | "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", 19 | "sha3Uncles": "0x0000000000000000000000000000000000000000000000000000000000000000", 20 | "miner": "0x3845794654dfec95145512fd33866dbc481893ea", 21 | "stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", 22 | "transactionsRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", 23 | "receiptsRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", 24 | "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 25 | "difficulty": null, 26 | "number": "0x1", 27 | "gasLimit": "0x1c9c380", 28 | "gasUsed": "0x0", 29 | "timestamp": "0x0", 30 | "extraData": "0x", 31 | "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", 32 | "nonce": "0x0000000000000000", 33 | "baseFeePerGas": "0x2e90edd000", 34 | "withdrawalsRoot": null, 35 | "hash": "0xf87a518fd4eec209b489cd38d510015b117d265ab1befde00588eac94c1e6696" 36 | }, 37 | "tests": [ 38 | { 39 | "name": "simple bundle", 40 | "bundle": { 41 | "version": "v0.1", 42 | "inclusion": { 43 | "block": "0x1" 44 | }, 45 | "body": [ 46 | { 47 | "tx": "0x02f86b0180843b9aca00852ecc889a0082520894c87037874aed04e51c29f582394217a0a2b89d808080c080a0a463985c616dd8ee17d7ef9112af4e6e06a27b071525b42182fe7b0b5c8b4925a00af5ca177ffef2ff28449292505d41be578bebb77110dfc09361d2fb56998260" 48 | } 49 | ], 50 | "validity": {} 51 | }, 52 | "shouldFail": false 53 | }, 54 | { 55 | "name": "bundle with reverting tx", 56 | "bundle": { 57 | "version": "v0.1", 58 | "inclusion": { 59 | "block": "0x1" 60 | }, 61 | "body": [ 62 | { 63 | "tx": "0x02f86b0180843b9aca00852ecc889a0082520894c87037874aed04e51c29f582394217a0a2b89d808080c080a0a463985c616dd8ee17d7ef9112af4e6e06a27b071525b42182fe7b0b5c8b4925a00af5ca177ffef2ff28449292505d41be578bebb77110dfc09361d2fb56998260" 64 | }, 65 | { 66 | "tx": "0x02f86b0101843b9aca00852ecc889a008261a894c1000000000000000000000000000000000000008001c001a0bf350b29d1340b2f2074b8bb31f6869423b3577f9b858045f2fab49c144b7410a02e8c836f575f877d0a64a0b0252755caa1d1942daa1d58ed60c4ed7b40849be1" 67 | } 68 | ], 69 | "validity": {} 70 | }, 71 | "shouldFail": true 72 | }, 73 | { 74 | "name": "bundle with invalid tx (nonce mismatch)", 75 | "bundle": { 76 | "version": "v0.1", 77 | "inclusion": { 78 | "block": "0x1" 79 | }, 80 | "body": [ 81 | { 82 | "tx": "0x02f86b0180843b9aca00852ecc889a0082520894c87037874aed04e51c29f582394217a0a2b89d808080c080a0a463985c616dd8ee17d7ef9112af4e6e06a27b071525b42182fe7b0b5c8b4925a00af5ca177ffef2ff28449292505d41be578bebb77110dfc09361d2fb56998260" 83 | }, 84 | { 85 | "tx": "0x02f86b0180843b9aca00852ecc889a0082520894c87037874aed04e51c29f582394217a0a2b89d808080c080a0a463985c616dd8ee17d7ef9112af4e6e06a27b071525b42182fe7b0b5c8b4925a00af5ca177ffef2ff28449292505d41be578bebb77110dfc09361d2fb56998260" 86 | } 87 | ], 88 | "validity": {} 89 | }, 90 | "shouldFail": true 91 | }, 92 | { 93 | "name": "bundle with reverting tx that is allowed to revert", 94 | "bundle": { 95 | "version": "v0.1", 96 | "inclusion": { 97 | "block": "0x1" 98 | }, 99 | "body": [ 100 | { 101 | "tx": "0x02f86b0180843b9aca00852ecc889a0082520894c87037874aed04e51c29f582394217a0a2b89d808080c080a0a463985c616dd8ee17d7ef9112af4e6e06a27b071525b42182fe7b0b5c8b4925a00af5ca177ffef2ff28449292505d41be578bebb77110dfc09361d2fb56998260" 102 | }, 103 | { 104 | "tx": "0x02f86b0101843b9aca00852ecc889a008261a894c1000000000000000000000000000000000000008001c001a0bf350b29d1340b2f2074b8bb31f6869423b3577f9b858045f2fab49c144b7410a02e8c836f575f877d0a64a0b0252755caa1d1942daa1d58ed60c4ed7b40849be1", 105 | "canRevert": true 106 | } 107 | ], 108 | "validity": {} 109 | }, 110 | "shouldFail": false 111 | }, 112 | { 113 | "name": "bundle with invalid tx (nonce mismatch) that is allowed to revert", 114 | "bundle": { 115 | "version": "v0.1", 116 | "inclusion": { 117 | "block": "0x1" 118 | }, 119 | "body": [ 120 | { 121 | "tx": "0x02f86b0180843b9aca00852ecc889a0082520894c87037874aed04e51c29f582394217a0a2b89d808080c080a0a463985c616dd8ee17d7ef9112af4e6e06a27b071525b42182fe7b0b5c8b4925a00af5ca177ffef2ff28449292505d41be578bebb77110dfc09361d2fb56998260" 122 | }, 123 | { 124 | "tx": "0x02f86b0180843b9aca00852ecc889a0082520894c87037874aed04e51c29f582394217a0a2b89d808080c080a0a463985c616dd8ee17d7ef9112af4e6e06a27b071525b42182fe7b0b5c8b4925a00af5ca177ffef2ff28449292505d41be578bebb77110dfc09361d2fb56998260", 125 | "canRevert": true 126 | } 127 | ], 128 | "validity": {} 129 | }, 130 | "shouldFail": true 131 | }, 132 | { 133 | "name": "bundle with backrun of tx", 134 | "bundle": { 135 | "version": "v0.1", 136 | "inclusion": { 137 | "block": "0x1" 138 | }, 139 | "body": [ 140 | { 141 | "tx": "0x02f86b0180843b9aca00852ecc889a0082520894c87037874aed04e51c29f582394217a0a2b89d808080c080a0a463985c616dd8ee17d7ef9112af4e6e06a27b071525b42182fe7b0b5c8b4925a00af5ca177ffef2ff28449292505d41be578bebb77110dfc09361d2fb56998260" 142 | }, 143 | { 144 | "tx": "0x02f8730180843b9aca00852ecc889a008288b894c10000000000000000000000000000000000000088016345785d8a000080c001a07c8890151fed9a826f241d5a37c84062ebc55ca7f5caef4683dcda6ac99dbffba069108de72e4051a764f69c51a6b718afeff4299107963a5d84d5207b2d6932a4" 145 | } 146 | ], 147 | "validity": { 148 | "refund": [ 149 | { 150 | "bodyIdx": 0, 151 | "percent": 90 152 | } 153 | ] 154 | } 155 | }, 156 | "shouldFail": false, 157 | "extractedRefunds": [ 158 | { 159 | "value": "0x1636110e9abbc00", 160 | "percent": 90, 161 | "refundSplit": { 162 | "0xc87037874aed04e51c29f582394217a0a2b89d80": 100 163 | } 164 | } 165 | ] 166 | }, 167 | { 168 | "name": "bundle with backrun of bundle", 169 | "bundle": { 170 | "version": "v0.1", 171 | "inclusion": { 172 | "block": "0x1" 173 | }, 174 | "body": [ 175 | { 176 | "bundle": { 177 | "version": "v0.1", 178 | "inclusion": { 179 | "block": "0x1" 180 | }, 181 | "body": [ 182 | { 183 | "tx": "0x02f86b0180843b9aca00852ecc889a0082520894c87037874aed04e51c29f582394217a0a2b89d808080c080a0a463985c616dd8ee17d7ef9112af4e6e06a27b071525b42182fe7b0b5c8b4925a00af5ca177ffef2ff28449292505d41be578bebb77110dfc09361d2fb56998260" 184 | }, 185 | { 186 | "tx": "0x02f86b0101843b9aca00852ecc889a0082520894c87037874aed04e51c29f582394217a0a2b89d808080c080a0ae5cf1bda12d0b4a51abb35fe716254ab4bbfaeb48cc1851662cef0f20bb43eea03e1fce95aed8e8607d8e26eea91f1fa22ede8f92c8d0335944a4850aaadc37bb" 187 | } 188 | ], 189 | "validity": {} 190 | } 191 | }, 192 | { 193 | "tx": "0x02f8730180843b9aca00852ecc889a008288b894c10000000000000000000000000000000000000088016345785d8a000080c001a07c8890151fed9a826f241d5a37c84062ebc55ca7f5caef4683dcda6ac99dbffba069108de72e4051a764f69c51a6b718afeff4299107963a5d84d5207b2d6932a4" 194 | } 195 | ], 196 | "validity": { 197 | "refund": [ 198 | { 199 | "bodyIdx": 0, 200 | "percent": 90 201 | } 202 | ] 203 | } 204 | }, 205 | "shouldFail": false, 206 | "extractedRefunds": [ 207 | { 208 | "value": "0x1636110e9abbc00", 209 | "percent": 90, 210 | "refundSplit": { 211 | "0xc87037874aed04e51c29f582394217a0a2b89d80": 100 212 | } 213 | } 214 | ] 215 | }, 216 | { 217 | "name": "bundle with backrun of bundle with refund config", 218 | "bundle": { 219 | "version": "v0.1", 220 | "inclusion": { 221 | "block": "0x1" 222 | }, 223 | "body": [ 224 | { 225 | "bundle": { 226 | "version": "v0.1", 227 | "inclusion": { 228 | "block": "0x1" 229 | }, 230 | "body": [ 231 | { 232 | "tx": "0x02f86b0180843b9aca00852ecc889a0082520894c87037874aed04e51c29f582394217a0a2b89d808080c080a0a463985c616dd8ee17d7ef9112af4e6e06a27b071525b42182fe7b0b5c8b4925a00af5ca177ffef2ff28449292505d41be578bebb77110dfc09361d2fb56998260" 233 | }, 234 | { 235 | "tx": "0x02f86b0101843b9aca00852ecc889a0082520894c87037874aed04e51c29f582394217a0a2b89d808080c080a0ae5cf1bda12d0b4a51abb35fe716254ab4bbfaeb48cc1851662cef0f20bb43eea03e1fce95aed8e8607d8e26eea91f1fa22ede8f92c8d0335944a4850aaadc37bb" 236 | } 237 | ], 238 | "validity": { 239 | "refundConfig": [ 240 | { 241 | "address": "0xc87037874aed04e51c29f582394217a0a2b89d80", 242 | "percent": 50 243 | }, 244 | { 245 | "address": "0x3e7dfb3e26a16e3dbf6dfeeff8a5ae7a04f73aad", 246 | "percent": 50 247 | } 248 | ] 249 | } 250 | } 251 | }, 252 | { 253 | "tx": "0x02f8730180843b9aca00852ecc889a008288b894c10000000000000000000000000000000000000088016345785d8a000080c001a07c8890151fed9a826f241d5a37c84062ebc55ca7f5caef4683dcda6ac99dbffba069108de72e4051a764f69c51a6b718afeff4299107963a5d84d5207b2d6932a4" 254 | } 255 | ], 256 | "validity": { 257 | "refund": [ 258 | { 259 | "bodyIdx": 0, 260 | "percent": 90 261 | } 262 | ] 263 | } 264 | }, 265 | "shouldFail": false, 266 | "extractedRefunds": [ 267 | { 268 | "value": "0x1636110e9abbc00", 269 | "percent": 90, 270 | "refundSplit": { 271 | "0x3e7dfb3e26a16e3dbf6dfeeff8a5ae7a04f73aad": 50, 272 | "0xc87037874aed04e51c29f582394217a0a2b89d80": 50 273 | } 274 | } 275 | ] 276 | }, 277 | { 278 | "name": "bundle with backrun of backrun of user tx", 279 | "bundle": { 280 | "version": "v0.1", 281 | "inclusion": { 282 | "block": "0x1" 283 | }, 284 | "body": [ 285 | { 286 | "bundle": { 287 | "version": "v0.1", 288 | "inclusion": { 289 | "block": "0x1" 290 | }, 291 | "body": [ 292 | { 293 | "tx": "0x02f86b0180843b9aca00852ecc889a0082520894c87037874aed04e51c29f582394217a0a2b89d808080c080a0a463985c616dd8ee17d7ef9112af4e6e06a27b071525b42182fe7b0b5c8b4925a00af5ca177ffef2ff28449292505d41be578bebb77110dfc09361d2fb56998260" 294 | }, 295 | { 296 | "tx": "0x02f8730180843b9aca00852ecc889a008288b894c10000000000000000000000000000000000000088016345785d8a000080c001a07c8890151fed9a826f241d5a37c84062ebc55ca7f5caef4683dcda6ac99dbffba069108de72e4051a764f69c51a6b718afeff4299107963a5d84d5207b2d6932a4" 297 | } 298 | ], 299 | "validity": { 300 | "refund": [ 301 | { 302 | "bodyIdx": 0, 303 | "percent": 90 304 | } 305 | ], 306 | "refundConfig": [ 307 | { 308 | "address": "0x3e7dfb3e26a16e3dbf6dfeeff8a5ae7a04f73aad", 309 | "percent": 100 310 | } 311 | ] 312 | } 313 | } 314 | }, 315 | { 316 | "tx": "0x02f8730101843b9aca00852ecc889a008288b894c10000000000000000000000000000000000000088016345785d8a000080c001a0650c394d77981e46be3d8cf766ecc435ec3706375baed06eb9bef21f9da2828da064965fdf88b91575cd74f20301649c9d011b234cefb6c1761cc5dd579e4750b1" 317 | } 318 | ], 319 | "validity": { 320 | "refund": [ 321 | { 322 | "bodyIdx": 0, 323 | "percent": 80 324 | } 325 | ] 326 | } 327 | }, 328 | "shouldFail": false, 329 | "extractedRefunds": [ 330 | { 331 | "value": "0x1636110e9abbc00", 332 | "percent": 90, 333 | "refundSplit": { 334 | "0xc87037874aed04e51c29f582394217a0a2b89d80": 100 335 | } 336 | }, 337 | { 338 | "value": "0x1636110e9abbc00", 339 | "percent": 80, 340 | "refundSplit": { 341 | "0x3e7dfb3e26a16e3dbf6dfeeff8a5ae7a04f73aad": 100 342 | } 343 | } 344 | ] 345 | } 346 | ] 347 | } --------------------------------------------------------------------------------