MEV Resistance
RP1 implements multiple layers of MEV (Maximal Extractable Value) protection to ensure fair transaction ordering.
The MEV Problem
On most blockchains, validators/miners can:
- Front-run: See your trade, execute theirs first
- Sandwich: Buy before your trade, sell after
- Back-run: Execute profitable transactions after yours
Without Protection:
User submits: Buy 1000 TOKEN at market price
Attacker sees mempool:
1. Attacker buys TOKEN (price goes up)
2. User's buy executes (at higher price)
3. Attacker sells TOKEN (profit!)
User loses ~2-5% to MEV extraction
RP1's Solution
1. Encrypted Mempool
Transactions are encrypted until block proposal:
┌─────────────────────────────────────────────────────────────┐
│ User Transaction │
│ │ │
│ ┌─────▼─────┐ │
│ │ Encrypt │ (Threshold public key) │
│ └─────┬─────┘ │
│ │ │
│ ┌─────▼─────┐ │
│ │ Mempool │ (Encrypted, opaque) │
│ └─────┬─────┘ │
│ │ │
│ ┌─────▼─────┐ │
│ │ Block │ (Proposer decrypts) │
│ │ Proposal │ │
│ └─────┬─────┘ │
│ │ │
│ ┌───────────┴───────────┐ │
│ ▼ ▼ ▼ │
│ Decrypt Decrypt Decrypt │
│ │
│ Fair ordering (no front-running possible) │
└─────────────────────────────────────────────────────────────┘
2. Threshold Encryption
Uses Shamir's Secret Sharing for decryption:
// Configuration
type ThresholdConfig struct {
Threshold int // Minimum shares needed (e.g., 7)
TotalParts int // Total key holders (e.g., 10)
Committee []string // Validator addresses holding shares
}
// Encryption
encrypted := ThresholdEncrypt(tx, publicKey) // Anyone can encrypt
// Decryption requires threshold cooperation
shares := CollectShares(validators, encrypted) // 7 of 10 needed
decrypted := ThresholdDecrypt(shares, encrypted)
- 7-of-10 threshold by default
- No single party can decrypt alone
- Decryption only at block proposal time
3. Commit-Reveal Scheme
Alternative for sensitive transactions:
Phase 1 (Commit):
User submits: Hash(tx_data + secret)
Phase 2 (Reveal):
User submits: tx_data + secret
Validators verify: Hash(tx_data + secret) == commitment
Timeline:
Block N: Submit commitment
Block N+1: Submit reveal
Block N+2: Transaction executes
4. Fair Ordering
Transactions ordered by commit timestamp, not gas price:
Traditional: Higher gas = earlier execution (auction for position)
RP1: First-committed = first-executed (fair FIFO)
┌──────────────────────────────────────────┐
│ Mempool Ordering │
│ │
│ T=0: Tx-A committed │
│ T=1: Tx-B committed (higher gas) │
│ T=2: Tx-C committed │
│ │
│ Execution order: A → B → C │
│ (Not B → A → C based on gas) │
└──────────────────────────────────────────┘
Protection Levels
| Method | Protection | Latency | Use Case |
|---|---|---|---|
| Encrypted Mempool | Full | +0ms | Default for all |
| Commit-Reveal | Full | +2 blocks | High-value trades |
| Standard | None | +0ms | Non-sensitive |
Using MEV Protection
TypeScript SDK
import { RP1Client, MEVProtection } from '@rp1/sdk';
const client = new RP1Client('https://rpc.rp.one');
// Encrypted transaction (default)
const tx = await client.swap({
tokenIn: 'urp1',
tokenOut: 'uusdc',
amountIn: '1000000',
protection: MEVProtection.ENCRYPTED, // default
});
// Commit-reveal for large trades
const largeTx = await client.swap({
tokenIn: 'urp1',
tokenOut: 'uusdc',
amountIn: '100000000000', // Large amount
protection: MEVProtection.COMMIT_REVEAL,
});
CLI
# Standard encrypted (automatic)
rp1d tx dex swap urp1 uusdc 1000000 --from wallet
# Explicit commit-reveal
rp1d tx dex swap urp1 uusdc 1000000 \
--from wallet \
--mev-protection commit-reveal
Validator Responsibilities
Validators in the threshold committee must:
- Hold key share securely (HSM recommended)
- Participate in decryption at block proposal
- Never collude to decrypt early
Slashing conditions:
- Early decryption attempt: 100% stake slash
- Non-participation in decryption: Jail + 1% slash
Security Analysis
| Attack | Protected | Mechanism |
|---|---|---|
| Front-running | ✅ | Encryption hides tx content |
| Sandwich | ✅ | Can't see victim's trade |
| Back-running | ⚠️ | Post-execution visible |
| Time-bandit | ✅ | Instant finality |
| Censorship | ⚠️ | Requires committee collusion |
Performance Impact
| Metric | Without MEV Protection | With MEV Protection |
|---|---|---|
| Latency | ~200ms | ~200ms |
| Throughput | 100K TPS | 95K TPS |
| Proof size | N/A | +64 bytes/tx |
Configuration
app.toml
[mev-protection]
enabled = true
default_method = "encrypted" # or "commit-reveal"
threshold = 7
total_parts = 10
committee_rotation = "100 blocks"
[commit-reveal]
reveal_window = 2 # blocks
max_pending = 10000