- actors - actors implementation
- actors-macros - macros for actors
- debug-provider - debug api provider for node + anvil, HttpCachedTransport
- defi-abi - sol! wrapper for contracts interface
- defi-actors - defi actors crate
- defi-blockchain - loom configuration module
- defi-entities - defi entities crate
- defi-events - defi events crate
- defi-pools - defi exchange pools implementation
- flashbots - flashbots client
- loom-revm-db - optimized InMemoryDB
- multicaller - multicaller interaction crate
- topology - topology crate
- types - defi types crate
- utils - various helpers
- loom - backrun bot
- loom_exex - backrun bot as ExEx module
- loom_anvil - anvil testing framework
- replayer - blocks replayer
- keys - keys encryption tool
- gasbench - gas consumption benchmark utility
- nodebench - nodes benchmark utility
Telegram chat : https://t.me/dexloom_com
config.toml example
[node]
mode = "ws"
# Nodes.
[clients]
local = { url = "PATH_TO_RETH_IPC_ENDPOINT", transport = "ipc", db_path = "PATH_TO_RETH_DATA_FOLDER/db", node = "reth" }
#another way to connect to WS
#local = { url = "PATH_TO_RETH_IPC_ENDPOINT", transport = "ipc", db_path = "PATH_TO_RETH_DATA_FOLDER/db", node = "reth" }
#remote node
#remote = { url = "PATH_TO_RETH_IPC_ENDPOINT", transport = "ws", node = "geth" }
[blockchains]
# Ethereum mainnet. chain id = 1
mainnet = { }
# Setup signer with encrypted private key
[signers]
env_signer = { type = "env", bc = "mainnet" }
# Swapstep encoder with address of multicaller deployed
[encoders]
mainnet = { type = "swapstep", address = "0x0000000000000000000000000000000000000000" }
# Preloaders for signers and encoders
[preloaders]
mainnet = { client = "local", bc = "mainnet", encoder = "mainnet", signers = "env_signer" }
[actors]
# Blocks managing actor
[actors.node]
mainnet_node = { client = "local", bc = "mainnet" }
# Uncomment this and comment node actors for ExEx
#[actors.node_exex]
#mainnet_node = { url = "http://[::1]:10000", bc = "mainnet" }
# Subscribe to mempool transactions
[actors.mempool]
mainnet = { client = "local", bc = "mainnet" }
mainnet_remote = { client = "remote", bc = "mainnet" }
# Nonce and balance monitor
[actors.noncebalance]
mainnet = { client = "local", bc = "mainnet" }
# Pool loader : history, new and protocol loaders
[actors.pools]
mainnet = { client = "local", bc = "mainnet", history = true, new = true, protocol = true }
# Price actor
[actors.price]
mainnet = { client = "local", bc = "mainnet" }
# Broadcaster actor
[actors.broadcaster]
mainnet = { type = "flashbots", client = "local", bc = "mainnet" }
# Transaction estimators
[actors.estimator]
# EVM estimator
mainnet = { type = "evm", bc = "mainnet", encoder = "mainnet" }
# Node estimator. Geth estimator is ok for nodes supporting eth_callBundle method only
#mainnet = { client = "local", bc = "mainnet", type = "geth", encoder = "mainnet" }
Private key encryption password is individual secret key that is generated automatically but can be replaced
It is located in ./crates/defi-entities/private.rs and looks like
pub const KEY_ENCRYPTION_PWD: [u8; 16] = [35, 48, 129, 101, 133, 220, 104, 197, 183, 159, 203, 89, 168, 201, 91, 130];
To change key encryption password run and replace content of KEY_ENCRYPTION_PWD
cargo run --bin keys generate-password
To get encrypted key run:
cargo run --bin keys encrypt --key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
DATA=<ENCRYPTED_PRIVATE_KEY> cargo run --bin loom
Makefile is shipped with following important commands:
- build - builds all binaries
- fmt - formats loom with rustfmt
- pre-release - check code with rustfmt and clippy
- clippy - check code with clippy
Testing Loom requires two environment variables pointing at archive node:
- MAINNET_WS - websocket url of archive node
- MAINNET_HTTP - http url of archive node
To run tests:
make test
- Paradigm - Paradigm. All those inspiring products : RETH / REVM / Alloy / Ethers
- darkforestry - AMM Crate
- 0xKitsune - Uniswap Math crate
- Onbjerg - Flashbots crate
THE SOFTWARE IS PROVIDED "AS IS", USE AT YOUR OWN RISK