Skip to main content

Validator Onboarding

This guide explains how validators integrate with shMONAD to receive priority fees and MEV rewards.

Overview

By default, priority fees are sent to the beneficiary address a validator sets in their node.toml config file. When onboarded to shMONAD, a coinbase contract is deployed for the validator, which becomes the new destination for both priority fees and MEV rewards.

The Coinbase Contract

When a validator is onboarded to shMONAD:

  1. A coinbase contract is deployed specifically for that validator
  2. The validator updates their beneficiary address in node.toml to point to this coinbase contract
  3. A restart of monad-bft is required for the change to take effect

Once configured:

  • Priority fees are sent to the coinbase contract
  • MEV rewards are also sent to the coinbase contract
tip

MEV rewards will be higher if you run the MEV Sidecar (see below), but rewards can still be received without it if a successful searcher call to the auction handler ends up in one of your blocks.

Configuration Options

The coinbase contract has several configurable parameters. Only the validator's auth address can call the configuration functions.

Default Values

ParameterDefault Value
Priority Fee Commission RateSame as staking commission rate
MEV Commission RateSame as staking commission rate
Donation Rate0
Commission RecipientAuth address

Update Functions

All rate parameters use a scale of 1e18 (so 10% would be 1e17).

FunctionDescription
updatePriorityCommissionRate(uint256)Update the commission rate for priority fees
updateMEVCommissionRate(uint256)Update the commission rate for MEV rewards
updateShMonadDonationRate(uint256)Update the donation rate for priority fees
updateCommissionRecipient(address)Change where commissions are sent
updateCommissionRateFromStakingConfig()Reset both priority fee and MEV commission rates to match the staking commission rate
updateAuthAddress()Update auth address when it changes in the staking precompile

View Functions

FunctionDescription
getPriorityCommissionRate()Returns the current priority fee commission rate
getMEVCommissionRate()Returns the current MEV commission rate
getCommissionRecipient()Returns the current commission recipient address
AUTH_ADDRESS()Returns the validator's auth address

Donation Rate

The donation rate is a portion of priority fees only that goes to shMONAD and is counted as revenue. This boosts your validator's stake allocation.

Key points:

  • Donation rate + commission rate cannot exceed 1e18 (100%)
  • Donation rate does not apply to MEV rewards (these were already counted as revenue when first received by shMONAD)
note

Increasing your donation rate can boost your stake allocation, as the donated portion counts toward shMONAD revenue attributed to your validator.

Order of Operations

For new validators joining shMONAD, follow this sequence:

  1. Get onboarded to shMONAD - A coinbase contract will be deployed for you
  2. Update beneficiary address - Change your node.toml beneficiary to the coinbase contract address and restart monad-bft
  3. Run the sidecar - Set up the MEV Sidecar to earn MEV rewards
caution

Following the correct order of operations is important to ensure no funds are lost during the transition.

Coinbase Contract Interface

interface ICoinbase {
// Update functions (only callable by auth address)
function updatePriorityCommissionRate(uint256 newCommissionRate) external;
function updateMEVCommissionRate(uint256 newCommissionRate) external;
function updateShMonadDonationRate(uint256 newDonationRate) external;
function updateCommissionRecipient(address newRecipient) external;
function updateCommissionRateFromStakingConfig() external;

// Auth address update (callable by previous or new auth address)
function updateAuthAddress() external;

// View functions
function getPriorityCommissionRate() external view returns (uint256);
function getMEVCommissionRate() external view returns (uint256);
function getCommissionRecipient() external view returns (address);
function AUTH_ADDRESS() external view returns (address);

// Immutable values
function VAL_ID() external view returns (uint64);
function SHMONAD() external view returns (address);
}

MEV Sidecar

To participate in the FastLane MEV program, validators are required to run the MEV Sidecar on the same machine that is running the validator Monad node. Starting from v0.12.6, monad-bft allows external applications to access the content of its local transaction mempool and to communicate transaction ordering preferences. The MEV Sidecar inspects transactions and scores them according to the MEV they hold.

The MEV Sidecar is provided as a Debian package. This guide assumes a Monad node ≥ v0.12.6 is running and synchronized on the validator's machine, and has been installed following the Monad official instructions.

Installation

Install the latest MEV Sidecar version, v0.0.11.

Add FastLane repository
sudo wget -qO - https://fastlane.xyz/apt/fastlane-apt-key.gpg.bin -O /usr/share/keyrings/fastlane-apt-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/fastlane-apt-keyring.gpg] https://fastlane-apt-repo.s3.amazonaws.com stable main" | sudo tee /etc/apt/sources.list.d/fastlane.list
Create FastLane directory
FASTLANE_HOME=/home/monad/fastlane/
mkdir -p $FASTLANE_HOME
Configure for testnet
echo -e "NETWORK='testnet'" > $FASTLANE_HOME/.env
Configure for mainnet
echo -e "NETWORK='mainnet'" > $FASTLANE_HOME/.env
Install sidecar
sudo apt update && sudo apt install fastlane-sidecar=0.0.11
Verify installation
dpkg -l fastlane-sidecar | grep fastlane-sidecar

Run

Enable and start the service
sudo systemctl enable fastlane-sidecar
sudo systemctl start fastlane-sidecar
Check status
sudo systemctl status fastlane-sidecar
View logs
sudo journalctl -fu fastlane-sidecar

Checking the Installation

Health check
curl http://localhost:8765/health | jq
  • last_received_at - Must be a recent timestamp, indicating the sidecar is functioning properly
  • tx_received - Number of transactions the sidecar received from monad-bft. Must be non-zero to be considered healthy
note

monad-bft gets transactions from the network when the validator is about to become the next leader (as per Monad design), therefore tx_received can show 0 for a few minutes before it starts increasing.

Optional Overrides

The MEV Sidecar works out of the box. This section outlines possible configuration overrides.

Custom Home Directory

Default value is /home/monad/fastlane/. For a custom location, ensure a .env file exists there with the appropriate content (see Installation section) and is accessible by the monad user.

Edit the service configuration
sudo systemctl edit fastlane-sidecar

Add the following in the editor that opens:

Custom home directory override
[Service]
ExecStart=
ExecStart=/usr/bin/fastlane-sidecar \
--log-level info \
--home </your/custom/path> \
--network "${NETWORK}"

EnvironmentFile=
EnvironmentFile=</your/custom/path/>.env

ReadWritePaths=
ReadWritePaths=</your/custom/path/>

Save and exit, then reload:

Reload systemd
sudo systemctl daemon-reload

Custom Health Check Port

The sidecar exposes a health check endpoint on default port 8765. For a custom port:

Edit the service configuration
sudo systemctl edit fastlane-sidecar

Add the following in the editor that opens:

Custom port override
[Service]
ExecStart=
ExecStart=/usr/bin/fastlane-sidecar \
--log-level info \
--network "${NETWORK}" \
--monitoring-port <CUSTOM_PORT>

Save and exit, then reload:

Reload systemd
sudo systemctl daemon-reload

CPU Pinning

Each Monad application is assigned a set of CPUs to optimize performance. By default, the MEV Sidecar reuses the CPUs assigned to the monad-rpc application, as it should be doing very little on a validator node.

For validators with more than 16 CPUs available who prefer to isolate the sidecar:

Edit the service configuration
sudo systemctl edit fastlane-sidecar

Add the following in the editor that opens (replace CPU values as needed):

CPU pinning override
[Service]
AllowedCPUs=16-19
CPUAffinity=16,17,18,19

Save and exit, then reload:

Reload systemd
sudo systemctl daemon-reload