Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
Multiplexer
Originally developed as an internal MEV launchpad, Multiplexer is now open-sourced. It provides a flexible smart contract system for executing complex transaction sequences, featuring a Solidity executor contract and a Rust library for building execution flows.
⚠️ WARNING: This contract has not been audited. Using this contract with real assets could result in permanent loss of funds. Use at your own risk.
🚀 Quick Start
# Clone the repository
# Install dependencies and compile contracts
# (This uses build.rs to compile contracts/executor.sol and contracts/proxy.sol)
# Run tests (requires a mainnet fork RPC URL)
ETH_RPC_URL=https://eth-mainnet.alchemyapi.io/v2/YOUR_API_KEY
Architecture
The system consists of:
executor.sol: The core contract that executes sequences of operations based on provided bytecode. It manages memory (txData) and handles callbacks.proxy.sol: A simple immutable proxy contract used to deploy the executor logic, allowing for potential future upgrades (though the current proxy is basic).- Rust Library (
src/): Provides aFlowBuilderutility to easily construct the bytecode sequences for the executor, abstracting away the low-level opcode details.
Example Usage
Morpho Flash Loan Example (Rust FlowBuilder)
This example demonstrates how to construct the bytecode for a Morpho flash loan using the Rust FlowBuilder. The goal is to borrow 100 WETH, and the callback data (inner_flow_bytes) will contain the instructions to approve the repayment to Morpho.
use ;
use FlowBuilder;
// Define necessary constants
const ONEHUNDRED_ETH: U256 = uint!; // 100e18
const WETH9: Address = address!;
const MORPHO: Address = address!;
// Simplified Sol definitions for the example
sol!
/// Generates the bytecode for a Morpho flash loan flow.
/// The flow borrows 100 WETH and sets up the callback to approve repayment.
// --- How to use the generated bytecode ---
Low-Level Bytecode Example
Here's an example sequence that performs a basic contract call using the raw opcodes:
# Assume target_addr = 0x... target contract address
# Assume eth_value = 1 ether (in wei)
# Assume function selector = 0xaabbccdd
# Bytecode Sequence:
0x01 0x0040 # CLEARDATA: Allocate 64 bytes for calldata
0x03 <target_addr> # SETADDR: Set target contract address
0x04 <eth_value> # SETVALUE: Set ETH value to send (1 ether)
0x02 0x0000 0x0004 # SETDATA: Set function selector at offset 0, length 4
aabbccdd # ↳ Function selector bytes
0x0A # SETFAIL: Enable revert on failure
0x06 # CALL: Execute the call
0x00 # EOF: End sequence
Core Features
- Sequential execution of multiple operations in a single transaction
- Support for flash loans from multiple protocols (Morpho, Aave)
- Low-level operation support (calls, creates, delegate calls)
- Memory management for transaction data
- Fail-safe mechanisms with configurable error handling
Operations
The contract supports the following operations, encoded as single-byte opcodes:
| Opcode | Operation | Description | Encoding Format |
|---|---|---|---|
| 0x00 | EOF | End of flow marker | 0x00 |
| 0x01 | CLEARDATA | Clear transaction data buffer | 0x01 + [size: uint16] |
| 0x02 | SETDATA | Set data at specific offset | 0x02 + [offset: uint16] + [size: uint16] + [ bytes] |
| 0x03 | SETADDR | Set target address | 0x03 + [address: bytes20] |
| 0x04 | SETVALUE | Set ETH value for calls | 0x04 + [value: uint256] |
| 0x05 | EXTCODECOPY | Copy external contract code | 0x05 + [addr: bytes20] + [dataOffset: uint16] + [codeOffset: uint16] + [size: uint16] |
| 0x06 | CALL | Perform external call | 0x06 |
| 0x07 | CREATE | Deploy new contract | 0x07 |
| 0x08 | DELEGATECALL | Perform delegate call | 0x08 |
| 0x09 | SETCALLBACK | Set callback address for flash loans | 0x09 + [address: bytes20] |
| 0x0A | SETFAIL | Enable revert on call failure | 0x0A |
| 0x0B | CLEARFAIL | Disable revert on call failure | 0x0B |
Memory Management
The contract maintains a dynamic bytes array (txData) as a working buffer for all operations:
- Memory Layout:
- 0x00-0x20: Length of array (32 bytes)
- 0x20-onwards: Actual data bytes
Operations that interact with this buffer:
- CLEARDATA: Clears and resizes the buffer
- SETDATA: Writes data at specific offsets
- EXTCODECOPY: Copies external contract code into the buffer
- CALL/DELEGATECALL/CREATE: Read from the buffer for execution
Flash Loan Support
The contract implements callbacks for multiple flash loan protocols:
Morpho Flash Loan Callback
function onMorphoFlashLoan(uint256 amount, bytes calldata data)
When Morpho calls this function on the executor, the executor will execute the bytecode passed in data.
Aave Flash Loan Callback
function executeOperation(
address asset,
uint256 amount,
uint256 premium,
address initiator,
bytes calldata params
)
Security Considerations
- Owner-only access control
- Callback address validation for flash loans (
SETCALLBACK) - Automatic callback address clearing after use (prevents re-entrancy with old callback data)
- Optional failure handling with
SETFAIL/CLEARFAIL - Memory bounds checking for all operations
Development
The contract is developed in Solidity and includes a comprehensive test suite written in Rust. The tests use Anvil for local blockchain simulation.