MEV Blocker Integration: Stop Frontrunning & Sandwich Attacks

We design and develop full-cycle blockchain solutions: from smart contract architecture to launching DeFi protocols, NFT marketplaces and crypto exchanges. Security audits, tokenomics, integration with existing infrastructure.
Showing 1 of 1All 1305 services
MEV Blocker Integration: Stop Frontrunning & Sandwich Attacks
Simple
~1 day
Frequently Asked Questions

Blockchain Development Services

Blockchain Development Stages

Latest works

  • image_website-b2b-advance_0.webp
    B2B ADVANCE company website development
    1349
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1247
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    949
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1183
  • image_logo-advance_0.webp
    B2B Advance company logo design
    642
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    921

MEV Blocker Integration: Stop Frontrunning & Sandwich Attacks

Your users are losing up to 15% on sandwich attacks with every large swap. Validators copy your limit orders and execute them ahead of you. We solve this — we integrate MEV Blocker into your dApp: a private RPC endpoint that prevents MEV bots from seeing the transaction until it is confirmed.

Why Regular RPCs Don't Protect

Public RPCs (Infura, Alchemy) — all transactions are visible in the mempool. MEV bots scan the mempool and pick profitable transactions. A sandwich attack: a bot sees your swap, buys before you, waits for your price move, then sells. Result: you buy higher, sell lower. MEV Blocker is tens of times better than public RPCs in terms of confidentiality: the transaction is hidden until block inclusion.

How MEV Blocker Works

MEV Blocker is a private RPC that sends transactions directly to a private mempool (Flashbots, Eden, BloxRoute). The transaction is not published to the public mempool until it is included in a block. Block builders can see the transaction, but they cannot attack it — they receive it only at block construction time.

// Example of switching to MEV Blocker RPC in MetaMask
const provider = new ethers.providers.JsonRpcProvider('https://rpc.mevblocker.io');

// Or via EIP-1193
await window.ethereum.request({
  method: 'wallet_switchEthereumChain',
  params: [{ chainId: '0x1', rpcUrls: ['https://rpc.mevblocker.io'] }],
});

What Our Work Includes

Component Description
RPC Setup Deploy private MEV Blocker RPC on the dApp side
Wallet Integration Automatic network switching on wallet connection
Transaction Monitoring Track inclusion success and speed
Team Training Provide documentation and best practices

Why Choose Us

10+ years in blockchain development, 150+ successful DeFi protocol integrations, certified Solidity and Rust engineers. We guarantee confidentiality — we sign an NDA. We assess your project in 1 day. Contact us for a consultation — we review your architecture, identify MEV leak points, and propose an optimal integration scheme.

Additional: Source code for flash loan protection (for reference)

Protection Against Flash Loan Attacks (Ancillary Service)

A flash loan is an uncollateralized loan that must be repaid in the same transaction. If not repaid, the entire transaction is reverted. From the perspective of the lending protocol (Aave, Uniswap V3), it is a risk-free operation: either the money is returned, or the transaction never happened.

The problem is not flash loans per se — they are legitimate tools for arbitrage, liquidations, and refinancing. The problem is that they give an attacker temporary access to huge capital (hundreds of millions of dollars) without collateral. If a protocol makes economic decisions based on easily manipulable data (DEX spot price, non-TWAP oracle), a single flash loan transaction can yield millions for an attacker.

Notable exploits: Beanstalk, Cream Finance, Mango Markets. Common thread: these protocols used data that could be shifted in a single transaction.

Anatomy of a Flash Loan Attack

A typical attack consists of four steps:

  1. Take out a flash loan from a lending protocol
  2. Manipulate state (pump/dump price in a DEX pool)
  3. Exploit the protocol (which reads the manipulated data)
  4. Repay the flash loan + fee, keep the profit

Concrete example — price oracle manipulation:

1. Flash loan: a large amount of DAI
2. Dump DAI into Uniswap V2 DAI/ETH pool (spot price of DAI drops)
3. Call the protocol that reads Uniswap V2 spot price to evaluate collateral
   → Collateral in DAI now "cheaper", can get discount on liquidation
   or evaluate debt in DAI as lower
4. Profit → repay flash loan

Another type — governance flash loan:

1. Flash loan governance tokens
2. Instant proposal creation + voting with enormous weight
3. Execute proposal (drain treasury)
4. Repay flash loan

(That's exactly how Beanstalk was attacked — the attacker used a single governance vote to pass a proposal transferring treasury to themselves.)

Protection 1: Price Oracle — TWAP Instead of Spot

TWAP (Time-Weighted Average Price) is the arithmetic mean price over a period. Uniswap V2/V3 stores cumulative price accumulators, from which TWAP for any period can be computed.

contract TWAPOracle {
    IUniswapV3Pool public pool;
    uint32 public constant TWAP_PERIOD = 30 minutes;
    
    function getTWAP() external view returns (uint256 price) {
        uint32[] memory secondsAgos = new uint32[](2);
        secondsAgos[0] = TWAP_PERIOD; // 30 minutes ago
        secondsAgos[1] = 0;           // now
        
        (int56[] memory tickCumulatives,) = pool.observe(secondsAgos);
        
        int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0];
        int24 arithmeticMeanTick = int24(tickCumulativesDelta / int56(uint56(TWAP_PERIOD)));
        
        // Convert tick to price
        price = TickMath.getSqrtRatioAtTick(arithmeticMeanTick);
        // ... convert sqrtPrice to human-readable
    }
}

Choosing the TWAP period is critical. Too short (1–5 minutes) — an attacker with enough capital can keep the manipulated price for several blocks. Too long (4–8 hours) — TWAP lags behind the market in volatile periods, causing incorrect liquidations.

Practice: 30 minutes is a reasonable default for most DeFi protocols. For highly volatile assets — 1–2 hours.

Chainlink as the Primary Oracle

Chainlink price feeds aggregate prices from many independent nodes with heartbeat updates. Manipulation would require compromising most oracle nodes — economically unfeasible.

contract PriceConsumer {
    AggregatorV3Interface public priceFeed;
    uint256 public constant HEARTBEAT = 3600; // 1 hour
    uint256 public constant MAX_STALENESS = HEARTBEAT * 2; // 2 hours maximum
    
    function getPrice() external view returns (uint256) {
        (
            uint80 roundId,
            int256 answer,
            ,
            uint256 updatedAt,
            uint80 answeredInRound
        ) = priceFeed.latestRoundData();
        
        // Staleness check: data not older than MAX_STALENESS
        require(block.timestamp - updatedAt <= MAX_STALENESS, "Stale price");
        
        // Round correctness check
        require(answeredInRound >= roundId, "Stale round");
        
        // Positive price check
        require(answer > 0, "Invalid price");
        
        return uint256(answer);
    }
}

General recommendation: use Chainlink as the primary oracle, Uniswap TWAP as a sanity check. If the two sources diverge by more than X%, pause operations.

Protection 2: Snapshot Voting Power

Governance flash loan attacks exploit the fact that voting power equals the current token balance. ERC-20Votes solves this via a checkpoint system.

// Voting power is fixed at the snapshot block (before voting starts)
uint256 votePower = token.getPastVotes(voter, proposalSnapshot);

// Flash loan AFTER snapshot yields no voting power
// Flash loan BEFORE snapshot requires holding tokens through voting delay

Voting delay — minimum period between proposal creation and voting start. With a voting delay of 2 days, an attacker must hold borrowed tokens for 2 days — economically unprofitable (fee + opportunity cost).

// OpenZeppelin Governor
constructor(...) GovernorSettings(
    2 days,  // votingDelay — protects against flash loan governance attacks
    5 days,  // votingPeriod
    threshold
) {}

Beanstalk was attacked precisely because it didn't use a voting delay: a proposal could be created and executed in one transaction.

Protection 3: Reentrancy Guard and Same-Block Checks

Some flash loan attacks exploit reentrancy or same-block state manipulation.

Same-Block Checks
contract Vault {
    mapping(address => uint256) private _depositBlock;
    
    function deposit(uint256 amount) external {
        _depositBlock[msg.sender] = block.number;
        // ...
    }
    
    function withdraw(uint256 amount) external {
        // Cannot deposit and withdraw in the same block
        require(
            _depositBlock[msg.sender] < block.number,
            "Flash loan protection: same block"
        );
        // ...
    }
}

This blocks the pattern: flash_loan → deposit → call function that reads vault balance → withdraw → repay_loan.

Drawback: legitimate users also cannot deposit and withdraw in the same block. For most protocols, this is acceptable.

Nonreentrant + View Functions

nonReentrant protects against reentrancy in state-changing functions. But view functions are not protected — they can be called from within another transaction.

If a view function is used by an external protocol to get price or TVL, state manipulation via reentrancy can change what that view function sees.

// VULNERABLE: state can be manipulated via reentrancy
function getSharePrice() external view returns (uint256) {
    return totalAssets() * 1e18 / totalSupply();
}

// totalAssets() reads the contract's balance — which can be temporarily inflated
function totalAssets() public view returns (uint256) {
    return IERC20(asset).balanceOf(address(this));
}

Solution: store a cached total assets value, updated only in protected functions.

Protection 4: Circuit Breakers and Rate Limiting

Maximum Volume Per Transaction
uint256 public constant MAX_SINGLE_DEPOSIT = 1_000_000e6; // $1M max

function deposit(uint256 amount) external {
    require(amount <= MAX_SINGLE_DEPOSIT, "Exceeds single tx limit");
    // ...
}

Flash loan attacks typically involve hundreds of millions. Limiting single-transaction volume reduces the maximum damage from any attack.

Pause Mechanism with Auto-Trigger
contract ProtectedProtocol is Pausable {
    uint256 public lastTVL;
    uint256 public constant TVL_DROP_THRESHOLD = 20; // 20% drop per transaction
    
    modifier checkTVLAnomaly() {
        uint256 tvlBefore = totalValueLocked();
        _;
        uint256 tvlAfter = totalValueLocked();
        
        if (tvlBefore > 0) {
            uint256 dropPercent = ((tvlBefore - tvlAfter) * 100) / tvlBefore;
            if (dropPercent > TVL_DROP_THRESHOLD) {
                _pause();
                emit EmergencyPause(tvlBefore, tvlAfter, dropPercent);
            }
        }
    }
}

Circuit breaker: if TVL drops more than N% in a single transaction, the protocol automatically pauses. This doesn't prevent the attack but limits its scale.

Time-Weighted Balances

Instead of current balance, use time-weighted average balance for critical calculations:

// ERC-20Votes checkpoint approach applied to liquidity
function getTimeWeightedLiquidity(address provider, uint256 lookback) 
    external view returns (uint256) 
{
    // Average liquidity over the lookback period
    // A single transaction's manipulation has minimal effect on the average
}

On-Chain Monitoring

A defense system is incomplete without monitoring. Forta Network is a decentralized detection network with bots monitoring on-chain activity.

// Forta bot: detecting potential flash loan attacks
async function handleTransaction(txEvent) {
    const findings = [];
    
    // Check for flash loan calldata in the transaction
    const flashLoanCalls = txEvent.filterFunction([
        'flashLoan(address,address,uint256,bytes)',
        'flash(address,address,uint256,uint256,bytes)'
    ]);
    
    if (flashLoanCalls.length > 0) {
        // Check for significant state changes in our protocol
        const protocolEvents = txEvent.filterLog(PROTOCOL_EVENTS, PROTOCOL_ADDRESS);
        
        if (protocolEvents.length > 0) {
            findings.push(Finding.fromObject({
                name: "Flash loan + protocol interaction",
                description: `Flash loan detected in same tx as protocol events`,
                alertId: "FLASH-LOAN-INTERACTION",
                severity: FindingSeverity.Medium,
                type: FindingType.Suspicious
            }));
        }
    }
    
    return findings;
}

Alerts from Forta can be sent to PagerDuty/Telegram via webhook, giving your team 1–2 minutes to respond before the attack spreads.

Comprehensive Defense Architecture

No single measure is sufficient. An effective defense system is layered:

Layer Mechanism Protects Against
Oracle Chainlink primary + TWAP sanity check Price manipulation
Governance Voting d

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

  1. 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.

  2. 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.

  3. 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.

  4. 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.