PBS-lite Builder Guide
This doc explains how to participate in Umotu’s PBS-lite market using services/builder-relay. Every bid is backed by on-chain escrow; the relay enforces commitments, signs receipts for proposers, and slashes non-delivering builders automatically.
Builder Relays
Umotu operates 4 independent builder relays across different regions. Each relay maintains separate state, so builders must register with each relay they want to use. You can register with one relay (closest to you) or all four for maximum reach.
| Region | Relay URL | Location |
|---|---|---|
| Europe | https://builder-relay1.testnet.umotu.com | EU |
| North America | https://builder-relay2.testnet.umotu.com | US |
| South America | https://builder-relay3.testnet.umotu.com | South America |
| Asia | https://builder-relay4.testnet.umotu.com | Asia |
Each relay is associated with a specific validator. Builders compete for block space on each validator independently. Registering with multiple relays increases your chances of winning blocks.
Quick Start
- Choose which relay(s) to use based on your geographic location or register with all four.
- Fund a builder wallet (EOA) and register it with
BuilderEscrow. - Register with each relay via
POST /registerto obtain relay tokens. - Lock escrow for a target height, then submit bids to
/bidson your chosen relay(s). - Watch
/assignresponses; when you win, deliver the bundle + PaymentTx #1. - Monitor
/slashevents to make sure failed competitors are penalized.
RPC_URL=http://localhost:8080/rpc
ESCROW_ADDRESS=0xBuilderEscrow
BUILDER_ADDRESS=0xYourBuilder
BUILDER_PRIV_KEY=0xYourKey
# Choose one or use all four relays
BUILDER_RELAY_URL=https://builder-relay1.testnet.umotu.com
# BUILDER_RELAY_URL=https://builder-relay2.testnet.umotu.com
# BUILDER_RELAY_URL=https://builder-relay3.testnet.umotu.com
# BUILDER_RELAY_URL=https://builder-relay4.testnet.umotu.com
BUILDER_TOKEN=your-token-for-relay1
INTENT_SIGNATURE_KEY=0xOptionalKeyNote: If you want to submit bids to multiple relays, you'll need to manage separate tokens for each relay and send requests to each relay endpoint.
1. Register & Authenticate
Each builder needs a relay token for each relay they want to use. If self-registration is enabled (ENABLE_SELF_REGISTRATION=true), sign the message below and register with each relay separately.
BUILDER=0xYourBuilderAddress
NONCE=$(date +%s)
MESSAGE="UMOTU_RELAY_REGISTER:builder:${BUILDER}:${BUILDER}:${NONCE}"
SIG=$(cast wallet sign --private-key $BUILDER_PRIV_KEY "$MESSAGE")
# Register with relay 1 (EU)
curl -X POST https://builder-relay1.testnet.umotu.com/register \
-H "Content-Type: application/json" \
-d "{\"role\":\"builder\",\"address\":\"$BUILDER\",\"nonce\":\"$NONCE\",\"signature\":\"$SIG\"}"
# Register with relay 2 (US) - generate new nonce
NONCE=$(date +%s)
MESSAGE="UMOTU_RELAY_REGISTER:builder:${BUILDER}:${BUILDER}:${NONCE}"
SIG=$(cast wallet sign --private-key $BUILDER_PRIV_KEY "$MESSAGE")
curl -X POST https://builder-relay2.testnet.umotu.com/register \
-H "Content-Type: application/json" \
-d "{\"role\":\"builder\",\"address\":\"$BUILDER\",\"nonce\":\"$NONCE\",\"signature\":\"$SIG\"}"
# Repeat for relay 3 and 4 if desired...Each relay returns { token }. Store each token securely and include the appropriate token as Authorization: Bearer <token>when making requests to that specific relay. Tokens are relay-specific and cannot be used across different relays.
2. Lock Escrow
Before submitting a bid, lock collateral on BuilderEscrow. Each lock is keyed by keccak256(builder, height, bundleCommitment).
# Example: lock Bid for height 12345 with 2.5 UMT payment and 10% escrow
cast send $ESCROW_ADDRESS "lockBid(uint64,bytes32,uint256,uint64)" \
12345 \
0xBUNDLE_COMMITMENT \
2500000000000000000 \
$(($(date +%s)+30)) \
--value 250000000000000000
- payAmount: total builder payment (wei) that the proposer receives.
- expiresAt: UNIX seconds; keep it a bit ahead of the projected slot.
- Escrow: send at least
requiredEscrowAmount(builder, payAmount)(relay enforces this on submit).
3. Submit Bids
curl -X POST $BUILDER_RELAY_URL/bids \
-H "Authorization: Bearer $BUILDER_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"builderId": "'$BUILDER'",
"height": 12345,
"bundleCommitment": "0xBUNDLE_COMMITMENT",
"payAmount": "2500000000000000000",
"expiresAt": 1712345678
}'Relay checks on-chain escrow, keeps only the top MAX_BIDS_PER_HEIGHT (default 64), and returns { ok: true, bidId }.
- Use
GET /intentsto discover mandatory inclusion intents; incorporate them into your bundle. - Submit multiple bids (different bundles) per height if desired—just ensure each bid has a unique commitment.
4. Monitor & Assign
Proposers call GET /bids?height=N to see the top bids. When you win, they hit POST /assign and the relay returns a signed receipt.
# Proposer view (for reference)
curl -H "Authorization: Bearer $PROPOSER_TOKEN" "$BUILDER_RELAY_URL/bids?height=12345"
# Receipt lookup (builder or proposer token)
curl -H "Authorization: Bearer $BUILDER_TOKEN" "$BUILDER_RELAY_URL/receipts?bidId=<id>"If you need to verify what you won, fetch the receipt and confirm the signature; Delivery must match the commitment exactly.
5. Deliver Winning Block
- Send the full bundle (matching
bundleCommitment) to the proposer via your preferred channel. - Broadcast PaymentTx #1 from the builder wallet with
value = payAmountand metadata (height, builder, bundle) in calldata so the ABCI app can verify it. - Include any required intents + top-fee transactions; phones will audit compliance using the receipt’s
intentRoot.
If you fail to deliver before expiresAt, the relay (or proposer) will call /slash and you lose escrow proportional to the violation.
6. Slash & Disputes
curl -X POST $BUILDER_RELAY_URL/slash \
-H "Authorization: Bearer $PROPOSER_OR_BUILDER_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"height": 12345,
"builder": "0xBuilder",
"bundleCommitment": "0xBUNDLE_COMMITMENT",
"evidence": "0xdeadbeef"
}'The relay calls BuilderEscrow.slashOnBehalf. Provide any evidence (logs, receipts) as a hex blob. Successful slash pays the proposer + sentinel pool automatically.
REST API Reference
| Endpoint | Auth | Description |
|---|---|---|
POST /register | None (signed message) | Issue builder/proposer tokens. |
POST /bids | Builder token | Submit a sealed bid backed by escrow. |
GET /bids?height=N | Proposer token | List top bids for a height. |
POST /assign | Proposer token | Assign a bid, receive signed receipt. |
GET /receipts?bidId=… | Builder or proposer token | Fetch stored receipt. |
POST /intents | Signed payload | Publish inclusion intents (no auth token). |
GET /intents | Public | List active intents + Merkle root. |
POST /slash | Proposer token | Slash failed builders via escrow. |
GET /healthz | Public | Relay stats + liveness check. |