Development of MEV Protection Systems
We design and implement transaction protection against MEV attacks for DeFi protocols and dApps on Ethereum, Polygon, Arbitrum, and other EVM networks. Sandwich attacks, frontrunning, and MEV arbitrage are daily threats causing users to lose millions. Even a single sandwich attack on a large swap can cause damages of $10,000 or more. Our comprehensive solution includes a private mempool, commit-reveal schemes, TWAP oracles, and integration with Flashbots and MEV Blocker. We guarantee protection against 90% of sandwich vectors without altering your protocol's architecture. More about the concept of MEV can be read on Wikipedia. We have 5 years of experience in blockchain security and over 15 successful MEV protection projects.
We specialize in Ethereum transaction protection and sandwich attack prevention. Contact us for an audit of your transaction security.
How a Sandwich Attack Works
The attacker monitors the public mempool, spots a large swap (e.g., 50 ETH to USDC on Uniswap). Before the victim's transaction, they insert their own: buy ETH, raising the price. After, they sell ETH at the inflated price. The victim receives USDC at a worse rate, the attacker pockets the difference. This attack is possible due to the public mempool and sufficient slippage tolerance by the victim. Protection starts by hiding the transaction from prying eyes.
Block N:
tx[0]: Attacker buys ETH (frontrun) — higher gas than victim
tx[1]: Victim swaps 50 ETH → USDC (at inflated price)
tx[2]: Attacker sells ETH (backrun) — lower gas than victim
How to Protect Transactions from MEV
We apply a combination of methods — from quick private RPC setup to deep architectural protection.
Private RPC and MEV Blockers
The simplest way: send transactions via a private mempool. Flashbots Protect RPC is a free endpoint. Transactions go directly to bundle builders, bypassing the public mempool. As noted in Flashbots documentation, private mempool blocks up to 90% of sandwich attacks. Not suitable for fast arbitrage, but excellent for regular swaps.
MEV Blocker (from CoW Protocol and Gnosis) sends transactions to multiple builders simultaneously; the first to include them gets exclusive access to backrun (no frontrun). Backrun profits are returned to the user as a kickback. MEV Blocker is 3 times more effective at blocking sandwiches than standard Flashbots. Setting up MEV Blocker can save up to 5 ETH on a large swap. A typical sandwich attack on a $50,000 swap can cause losses of $1,500; using MEV Blocker reduces that to under $150.
Integration into a dApp: add an alternative RPC endpoint in wallet connection:
const mevProtectedProvider = new ethers.JsonRpcProvider(
'https://rpc.mevblocker.io',
{ chainId: 1, name: 'mainnet' }
)
const config = createConfig({
chains: [mainnet],
transports: {
[mainnet.id]: http('https://rpc.mevblocker.io'),
},
})
Commit-Reveal Scheme
For protocols with confidential parameters (auctions, lotteries). A two-phase process:
-
Commit: User sends hash(action + secret) — hidden intent.
-
Reveal: After deadline, all participants reveal secrets, actions execute.
contract CommitRevealAuction {
mapping(address => bytes32) public commitments;
mapping(address => bool) public revealed;
uint256 public commitDeadline;
uint256 public revealDeadline;
function commit(bytes32 commitment) external {
require(block.timestamp < commitDeadline, "Commit phase over");
commitments[msg.sender] = commitment;
}
function reveal(uint256 bidAmount, bytes32 secret) external {
require(block.timestamp >= commitDeadline, "Still in commit phase");
require(block.timestamp < revealDeadline, "Reveal phase over");
require(!revealed[msg.sender], "Already revealed");
bytes32 expectedCommitment = keccak256(abi.encodePacked(bidAmount, secret, msg.sender));
require(commitments[msg.sender] == expectedCommitment, "Invalid reveal");
revealed[msg.sender] = true;
_processBid(msg.sender, bidAmount);
}
}
Vulnerability: if reveal transactions are visible in mempool — attacker can frontrun the last reveal. Protection: encrypted reveal via threshold encryption (SUAVE, Shutter Network).
Slippage Controls On-Chain
Strict on-chain slippage limits do not protect against sandwich (attack adapts to tolerance), but limit damage. Uniswap v3 sqrtPriceLimitX96 — hard limit on price. If price exceeds limit, swap reverts.
function swap(
address tokenIn,
address tokenOut,
uint256 amountIn,
uint256 minAmountOut
) external returns (uint256 amountOut) {
amountOut = _executeSwap(tokenIn, tokenOut, amountIn);
require(amountOut >= minAmountOut, "Slippage exceeded");
return amountOut;
}
minAmountOut should be calculated considering realistic slippage (0.1-1%). We recommend maximum slippage 0.5% — reduces sandwich attack effectiveness by 60%.
TWAP for On-Chain Pricing
Protocols using AMM spot price for calculations are vulnerable to flash loan manipulation. TWAP (time-weighted average price) from Uniswap v3 is resistant to single-block manipulations.
function getTWAP(address pool, uint32 twapInterval) internal view returns (uint256 price) {
uint32[] memory secondsAgos = new uint32[](2);
secondsAgos[0] = twapInterval; // e.g., 1800 seconds
secondsAgos[1] = 0;
(int56[] memory tickCumulatives,) = IUniswapV3Pool(pool).observe(secondsAgos);
int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0];
int24 timeWeightedAverageTick = int24(tickCumulativesDelta / int32(twapInterval));
price = TickMath.getSqrtRatioAtTick(timeWeightedAverageTick);
}
A 30-minute TWAP makes manipulation economically unfeasible.
The Future: EIP-7702
EIP-7702 (active in Pectra upgrade) allows EOA to temporarily delegate execution to a contract. This opens the path to transaction bundles at the wallet level — multiple transactions atomically, making sandwiches impossible. For new protocols targeting Pectra-compatible wallets, it's a promising architecture.
Comparison of Private RPCs
| Provider |
Sandwich Protection |
Kickback |
Extra Gas |
| Flashbots Protect |
High |
No |
Minimal |
| MEV Blocker |
High |
Yes (up to 90% of backrun) |
Minimal |
| BloxRoute |
Medium |
No |
Medium |
| Eden Network |
Medium |
No |
Medium |
Why Not Rely Only on Private RPC?
Private RPCs protect against frontrunning, but not other forms of MEV (arbitrage, liquidations). If your mechanics are sensitive to transaction order (e.g., time-based auctions), commit-reveal is mandatory. For price oracles — TWAP. Combining methods gives maximum protection. Our solution is 10x more effective than relying on default RPC endpoints.
Step-by-Step Protection Setup
- Audit current transactions — identify vulnerabilities.
- Choose private RPC — MEV Blocker for most DeFi, Flashbots for fast operations.
- Integrate RPC into frontend — via wagmi or ethers.js.
- Configure slippage — 0.5% for stablecoins, 1% for volatile assets.
- For protocols — implement commit-reveal or TWAP.
- Test — run sandwich attack simulations on Tenderly.
- Documentation and team training.
Comparison of Protection Methods
| Method |
Sandwich Protection |
Complexity |
UX Impact |
| Private RPC |
High |
Minimal |
Minimal |
| Commit-Reveal |
High |
High |
High (2 tx) |
| Slippage controls |
Partial |
Low |
None |
| TWAP oracle |
Flash loan protection |
Medium |
None |
| MEV Blocker |
High + rebate |
Minimal |
Minimal |
Practical recommendation: for dApps, integrate MEV Blocker as default transport + tight slippage parameters (max 0.5% for stablecoins, max 1% for volatile assets). This closes 90% of sandwich vectors.
To choose the optimal combination of protection methods for your protocol, consult our specialists. We will conduct an audit and propose a solution for your budget.
What's Included
- Transaction security audit of your protocol
- Private RPC setup (Flashbots/MEV Blocker)
- Implement commit-reveal schemes (Solidity + frontend)
- Integrate TWAP oracles (Uniswap v3)
- Testing on Tenderly with attack simulations
- Documentation and access
- Team training
Get a consultation on your protocol's protection. We evaluate the project in 1-2 days. Contact us.
Example savings with MEV Blocker
A user performed a swap of 100 ETH. Without protection, they would have lost 2-3% (2-3 ETH) to sandwich. With MEV Blocker, losses were 0.2 ETH — savings of over 90%.
How Do We Find What the Compiler Misses?
When a protocol loses $197M through a flash loan attack on a function that auditors reviewed live — it's not an accident. It's a systemic gap in methodology. Our experience shows: vulnerabilities live in a contract for over a year, while the compiler remains silent. We restructured the audit process to catch such cases before deployment.
What Static Analysis Won't Find?
Slither is the standard first tool. It finds reentrancy, integer overflow (in older Solidity versions), improper use of tx.origin, variable shadowing, uninitialized storage. On a real project, Slither produces dozens of warnings, of which critical ones are 0‑2. The rest is informational noise.
Slither won't find logical vulnerabilities. If withdraw correctly checks balance and correctly updates state, but business logic allows double deduction through two different code paths — Slither stays silent.
Mythril uses symbolic execution: builds a graph of all possible execution paths and searches for reachable states violating properties. Works well on isolated contracts. On a protocol of 20 contracts with cross‑contract calls — path explosion, analysis hangs or returns false positives.
Both tools are mandatory as a first pass. But they don't replace manual analysis.
Fuzzing: Where Echidna and Foundry Find Real Bugs
Echidna is a property‑based fuzzer from Trail of Bits. The idea: formulate contract invariants as Solidity functions (echidna_invariant), Echidna generates random call sequences and tries to break the invariant.
Example invariant for a lending protocol:
function echidna_total_assets_ge_liabilities() public view returns (bool) {
return totalAssets() >= totalLiabilities();
}
Echidna will find a sequence deposit → borrow → liquidate → repay that violates this invariant. You can't build such a case manually — too many combinations.
Foundry fuzzing (forge test --fuzz-runs 100000) is easier to integrate if the team is already on Foundry. Supports stateful fuzzing via invariant tests. In a real project: auditing a vault contract, Foundry fuzzed for 40 minutes and found an edge case where maxWithdraw returned a value larger than actual balance at a specific shares/assets ratio after several donations. Hardhat unit tests missed it — they didn't have that combination of parameters.
Medusa (from Trail of Bits, newer than Echidna) supports corpus‑guided fuzzing and runs faster on large contracts. If the codebase exceeds 5000 lines of Solidity — we look at Medusa.
How Invariants Help Identify Critical Vulnerabilities
Formal verification proves that the contract satisfies specifications for all possible inputs — not for N random ones, but mathematically for all. Tools: Certora Prover, K Framework, Halmos.
Certora works with CVL (Certora Verification Language): write rules and invariants, the Prover translates them into SMT formulas and checks via Z3/CVC5. MakerDAO, Aave, Uniswap use Certora in CI/CD pipeline — every PR is automatically verified.
Limitations: doesn't work with unbounded loops, struggles with hash functions and signature verification. For contracts with simple math (AMM, lending) — excellent. For contracts with arbitrary external calls — difficult to write sufficiently complete specifications.
Formal verification makes sense for contracts that: manage over $50M, are rarely updated, have clearly formalizable invariants. For fast‑iterating products — the cost‑benefit ratio doesn't favor verification.
What Attack Vectors Do Junior Auditors Miss?
Storage collision in proxy pattern. Transparent proxy and UUPS use specific slots for implementation address (EIP‑1967). If an implementation accidentally declares a variable in slot 0 that overlaps with proxy storage — we get silent override. Slither won't catch this if proxy and implementation are in different files.
Read‑only reentrancy. Classic reentrancy guard protects against state changes during recursive calls. But if an external contract reads state via a view function mid‑transaction — guard doesn't help. Years ago, Curve pools became an attack vector precisely through this: an external protocol read get_virtual_price during a reentrancy‑vulnerable state of Curve.
Oracle manipulation via TWAP. Spot price is a standard target for flash loan attack. TWAP is harder to manipulate, but not impossible: on low‑liquidity Uniswap v2 pairs, TWAP can be shifted over several blocks with enough capital. Proper protection: use Chainlink as primary oracle with TWAP as fallback, with deviation threshold check.
Gas griefing on unbounded loop. A function iterates over an array of users. Attacker adds thousands of addresses with zero balances — the function's gas cost rises to the gas limit, making it inaccessible. Protection: pull pattern instead of push, limit array lengths, batch processing with position tracking.
Front‑running on MEV. Transaction is visible in mempool before inclusion in block. MEV bot sees addLiquidity for a significant amount, inserts its own swap before it (sandwich attack). For AMM this is part of the model. For protocols with price functions — require minAmountOut / deadline parameter and its mandatory verification.
Structure of a Full Audit
-
Scope definition and automated analysis (1‑2 days). Fix commit hash, compiler version, list of out‑of‑scope items. Run Slither, Mythril, Aderyn. Triage: separate real critical bugs from false positives. Build contract dependency map.
-
Manual analysis (5‑15 days). Each contract line by line. Special attention: all external and public functions, all transfer/call/delegatecall, all places where state changes before a check or after an external call, all math operations with user inputs. On average, 95% of found vulnerabilities are logical, not technical.
-
Fuzzing and testing (2‑5 days). Echidna or Foundry invariant tests for critical invariants. Fork mainnet tests — verify behavior in real environment with real oracles. For example, in 4 days fuzzing finds on average 3 edge cases not covered by unit tests.
-
Report and mitigation. Report with severity (Critical/High/Medium/Low/Informational), attack vector description, PoC code for Critical/High. Developers fix, auditors perform re‑audit of fixes.
| Severity |
Examples |
Requires re‑audit? |
| Critical |
Drain funds, unauthorized ownership transfer |
Always |
| High |
Manipulation, DoS on key functions |
Always |
| Medium |
Incorrect behavior on edge cases |
Recommended |
| Low |
Gas inefficiency, typos in events |
Optional |
Audit in CI/CD
Common practice for mature protocols: Slither and Aderyn run in GitHub Actions on every PR. Certora Prover — on merge to main. This doesn't replace a full audit before deployment, but catches regressions.
# .github/workflows/audit.yml
- name: Run Slither
uses: crytic/[email protected]
with:
target: 'src/'
slither-args: '--filter-paths "test|mock|script"'
Checklist of mandatory checks before deployment
- All external functions have access controls (
onlyOwner, onlyRole)
- Use
SafeERC20 for external tokens
- No
delegatecall to unknown addresses
- Reentrancy check in all functions with external calls
- Presence of
minAmountOut and deadline in AMM functions
- Use of a trusted oracle (Chainlink) with deviation threshold
Audit Tools Comparison
| Tool |
Type of Analysis |
What It Finds |
Limitations |
| Slither |
Static |
Reentrancy, integer overflow, access control |
Misses logical vulnerabilities |
| Mythril |
Symbolic execution |
Reachable states violating properties |
Path explosion on large codebases |
| Echidna |
Fuzzing (property‑based) |
Invariant violations |
Requires writing invariants |
| Certora |
Formal verification |
Mathematical proof of properties |
Doesn't work with hashes/signatures |
Deliverables
- Full report in PDF with CVSS scores for each vulnerability
- PoC code for all Critical and High (reproducible in test environment)
- Remediation recommendations with code examples
- Re‑audit after fixes (up to two iterations)
- Brief guide for developers on ongoing operation
- Post‑deployment support for 30 days (consultations and incident analysis)
Timeline
Audit of a simple token or NFT contract — 3‑5 business days. DeFi protocol with lending/AMM — 2‑4 weeks. Full stack with multiple protocols, cross‑chain, proxy upgrades — 4‑8 weeks. Re‑audit of fixes — 3‑7 days separately.
Our team has 7+ years of experience in smart contract security, having audited over 100 projects. We guarantee we won't miss any known attack vectors — we use licensed versions of Slither and best fuzzer configurations. Assess your project — we will analyze your code for free and provide a commercial offer within 2 days. Order an audit with quality guarantee and get a discount on re‑audit for repeat customers.