Skip to content

Latest commit

 

History

History
155 lines (121 loc) · 5.5 KB

ORDERFLOW.md

File metadata and controls

155 lines (121 loc) · 5.5 KB

Submitting order flow

How to get transactions and bundles into rbuilder, and exactly what the mev_sendBundle adapter does and does not translate.

TEST-ONLY CREDENTIALS. Every private key, mnemonic, BLS secret and JWT in this repository is public and well known. Never use any of them on a network that holds value.

🔙 back to the README


Submitting transactions

Helper

scripts/send-test-tx.sh
scripts/send-test-tx.sh --value 1000000000000000000 --priority-gwei 50
scripts/send-test-tx.sh --endpoint rbuilder     # skip reth's mempool

Response shape:

{
  "tx_hash": "0x9c2f…",
  "sender": "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC",
  "nonce": 17,
  "target_block": 154,
  "endpoints": ["rbuilder", "reth-mempool"],
  "responses": { "rbuilder": {"jsonrpc":"2.0","id":1,"result":"0x9c2f…"} }
}

Raw curl

Straight to rbuilder's order-input RPC (bypasses the mempool entirely):

curl -s -X POST http://127.0.0.1:8645 \
  -H 'content-type: application/json' \
  --data '{"jsonrpc":"2.0","id":1,"method":"eth_sendRawTransaction","params":["0x02f8…"]}'
{"jsonrpc":"2.0","id":1,"result":"0x9c2f…"}

Through reth's mempool, which reaches rbuilder over IPC:

curl -s -X POST http://127.0.0.1:8545 \
  -H 'content-type: application/json' \
  --data '{"jsonrpc":"2.0","id":1,"method":"eth_sendRawTransaction","params":["0x02f8…"]}'

Checking inclusion

curl -s -X POST http://127.0.0.1:8545 -H 'content-type: application/json' \
  --data '{"jsonrpc":"2.0","id":1,"method":"eth_getTransactionReceipt","params":["0x9c2f…"]}' | jq .
{
  "jsonrpc": "2.0", "id": 1,
  "result": {
    "blockNumber": "0x9a",
    "status": "0x1",
    "gasUsed": "0x5208",
    "effectiveGasPrice": "0x2540be400"
  }
}

Submitting bundles

eth_sendBundle

scripts/send-test-bundle.sh                     # 2 txs, last one tips coinbase
scripts/send-test-bundle.sh --txs 3 --reverting # middle tx always reverts
scripts/send-test-bundle.sh --replaceable --nonce 1
scripts/send-test-bundle.sh --replaceable --uuid <UUID> --nonce 2   # replace it
scripts/cancel-test-bundle.sh --uuid <UUID> --nonce 3               # cancel it

Raw:

curl -s -X POST http://127.0.0.1:8645 \
  -H 'content-type: application/json' \
  --data '{
    "jsonrpc":"2.0","id":1,"method":"eth_sendBundle",
    "params":[{
      "txs":["0x02f8…","0x02f8…"],
      "blockNumber":"0x9b",
      "revertingTxHashes":["0xdead…"],
      "replacementUuid":"7a3f0a1e-1f1a-4b2e-9c1a-1f0e2d3c4b5a",
      "replacementNonce":1,
      "signingAddress":"0x976EA74026E726554dB657fA54763abd0C3a0aa9"
    }]
  }'
{"jsonrpc":"2.0","id":1,"result":{"bundleHash":"0x1f4c…"}}

Notes that matter:

  • Replaceable bundles need all three of replacementUuid (or uuid), replacementNonce and signingAddress. rbuilder's RawBundleMetadata::decode_replacement_data rejects a partial set as IncorrectReplacementData.
  • ignore_cancellable_orders must be false. rbuilder's default is true, which silently drops every order carrying a replacement uuid. This project sets it to false in configs/rbuilder/rbuilder.toml.tmpl.
  • Cancellation is eth_sendBundle with an empty txs array plus the uuid and a higher replacementNonce (eth_cancelBundle also works).
  • X-Flashbots-Signature is sent by the helpers for realism. The open-source rbuilder RPC server does not verify it.

mev_sendBundle -- read this

The open-source rbuilder does not implement mev_sendBundle. At the pinned commit, crates/rbuilder/src/live_builder/order_input/rpc_server.rs registers exactly three methods (eth_sendBundle, eth_cancelBundle, eth_sendRawTransaction) and rbuilder_primitives::Order has only Bundle and Tx variants -- there is no ShareBundle type in the public tree.

Rather than pretend otherwise, this project ships the smallest reasonable adapter: orderflow-shim (workload/mev_shim.py) on port 8646. It accepts MEV-Share mev_sendBundle v0.1, rewrites it into the equivalent eth_sendBundle, and forwards everything else to rbuilder untouched.

MEV=1 scripts/send-test-bundle.sh
curl -s -X POST http://127.0.0.1:8646 \
  -H 'content-type: application/json' \
  --data '{
    "jsonrpc":"2.0","id":1,"method":"mev_sendBundle",
    "params":[{
      "version":"v0.1",
      "inclusion":{"block":"0x9b","maxBlock":"0x9d"},
      "body":[{"tx":"0x02f8…","canRevert":false},{"tx":"0x02f8…","canRevert":true}],
      "metadata":{"signingAddress":"0x976EA74026E726554dB657fA54763abd0C3a0aa9"}
    }]
  }'
mev_sendBundle field Handling
inclusion.block → blockNumber
body[].tx → txs[]
body[].canRevert: true → revertingTxHashes[] (keccak256 of the raw tx)
replacementUuid / replacementNonce / signingAddress (top level or under metadata) passed through
validity.refund (exactly one entry) + validity.refundConfig[0].address → version:"v2", refundPercent, refundRecipient, refundTxHashes
inclusion.maxBlock ignored -- eth_sendBundle targets one block
privacy.* ignored -- meaningless on a single-builder devnet
body[].hash (backrun a hinted tx) rejected with a JSON-RPC error
body[].bundle (nested bundle) rejected with a JSON-RPC error
validity.refund with >1 entry rejected with a JSON-RPC error

Every translation and rejection is logged to /experiments/orderflow-shim.jsonl.