Presiona ESC para cerrar

Creando un Bot JIT: Stack de Rust y Smart Contracts Atómicos

Este es el tercer artículo de nuestra serie “Depredadores en los Pools: El Arte y la Matemática de la Liquidez JIT”. Ahora pasamos a la parte de ingeniería: cómo convertir fórmulas matemáticas en código que se ejecuta más rápido de lo que puedes parpadear.

En 2026, la liquidez JIT ya no es una competencia de ideas, sino de infraestructura. Si tu bot está escrito en Python y se comunica con un nodo público vía HTTP, no solo perderás —ni siquiera notarás cuándo te quitan tus ganancias.

1. Stack tecnológico: Por qué Rust domina

En el mundo del MEV, la lucha se mide en microsegundos de latencia.

  • Lenguaje: Rust. El uso de la biblioteca Alloy (sucesora de ethers-rs) se ha convertido en estándar de la industria. Alloy permite trabajar con tipos de datos de Ethereum sin asignaciones de memoria innecesarias y ofrece serialización/deserialización de JSON-RPC ultra rápida.
  • Conexión: IPC/WebSockets. Los bots no usan HTTP. Se conectan a un nodo local vía IPC (Inter-Process Communication) para minimizar la pila de red.
  • Nodo propio (Geth/Reth): Los jugadores principales usan Reth (Rust Ethereum), ya que permite personalizar el motor para simular transacciones en paralelo.

2. Smart Contract: Atomicidad o muerte

Para que un ataque JIT sea seguro, las operaciones “Entrar al pool” y “Salir del pool” deben estar conectadas por una lógica infalible. Si agregas liquidez pero no puedes retirarla en el mismo bloque, te arriesgas a una gran pérdida impermanente (Impermanent Loss).

El bot utiliza un Executor Contract. Su tarea es recibir comandos de un script off-chain y ejecutar una serie de llamadas al NonfungiblePositionManager (NFPM) de Uniswap v3.

Ejemplo de arquitectura del contrato (Solidity 0.8.x):

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface INonfungiblePositionManager {
    struct MintParams {
        address token0;
        address token1;
        uint24 fee;
        int24 tickLower;
        int24 tickUpper;
        uint256 amount0Desired;
        uint256 amount1Desired;
        uint256 amount0Min;
        uint256 amount1Min;
        address recipient;
        uint256 deadline;
    }
    function mint(MintParams calldata params) external returns (uint256 tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);
    function decreaseLiquidity(uint256 tokenId, uint128 liquidity, uint256 amount0Min, uint256 amount1Min, uint256 deadline) external;
    function collect(uint256 tokenId, address recipient, uint128 amount0Max, uint128 amount1Max) external;
}
contract JITExecutor {
    address private immutable owner;
    INonfungiblePositionManager public immutable nftManager;
    constructor(address _nftManager) {
        owner = msg.sender;
        nftManager = INonfungiblePositionManager(_nftManager);
    }
    function performJit(
        INonfungiblePositionManager.MintParams calldata mintParams
    ) external {
        require(msg.sender == owner, "Unauthorized");
        (uint256 tokenId, uint128 liquidity, , ) = nftManager.mint(mintParams);
    }
    function withdrawJit(uint256 tokenId, uint128 liquidity) external {
        nftManager.decreaseLiquidity(tokenId, liquidity, 0, 0, block.timestamp);
        nftManager.collect(tokenId, msg.sender, type(uint128).max, type(uint128).max);
    }
}

3. Flashbots Bundles: Pegando la realidad

Las transacciones del bot JIT deben rodear la transacción de la víctima. Para ello se utiliza el mecanismo de Bundles.

El bot envía un arreglo de transacciones a Flashbots (o a otro relé MEV como BeaverBuild o Titan):

  • [Tx_Mint] — Tu transacción de adición de liquidez.
  • [Tx_Target] — La transacción del usuario en el mempool que interceptaste.
  • [Tx_Burn] — Tu transacción de retiro.

Detalle poco conocido: Para ahorrar gas, los bots avanzados a veces no hacen el Burn en el mismo bloque si están seguros de que el precio no saldrá del tick en el siguiente bloque. Pero esto ya es un riesgo de “LP pasivo”. Un verdadero depredador JIT siempre cierra la posición en el bloque $N$.

4. Lógica del bot off-chain (Off-chain Engine)

Un bot Rust funciona en un ciclo infinito:

  • Streaming del mempool: escucha newPendingTransactions.
  • Simulación: Para cada gran transacción, el bot hace una “ejecución virtual” usando eth_call o revm (Rust EVM) para ver cuántas comisiones recibirá.
  • Generación de bundle: Si la ganancia > 0, se forma el paquete.
  • Bidding: El bot agrega coinbase.transfer() — soborno al validador.

Insider: En 2026, la propina (tip) al validador puede llegar al 99% de la ganancia del bot. Los bots compiten por el 1% restante de ganancia neta, porque en volúmenes de millones de dólares, incluso el 1% es mucho dinero.

5. Consejo práctico: uso de multicall

Para máxima eficiencia, utiliza la lógica multicall dentro de tu contrato. Esto permite ejecutar approve, mint, decreaseLiquidity y collect en una sola transacción si usas tus propios fondos y no Flash Loans. Ahorra alrededor de 40–60k de gas en llamadas repetidas.

Resumen del artículo

La arquitectura de un bot JIT es la cúspide de la ingeniería de smart contracts. Creas liquidez “desechable” que existe solo por fracciones de segundo.

En el próximo artículo: pasaremos a la “artillería pesada”. ¿Cómo hacer ataques JIT sin tener millones propios? Analizaremos Flash-JIT y el uso de Flash Loans para capturar el 99,9% de la liquidez en pools gigantes.


Dominio de la Liquidez JIT: La Guía Completa sobre MEV en Uniswap: Parte 3 de 5

Astra EXMON

Astra is the official voice of EXMON and the editorial collective dedicated to bringing you the most timely and accurate information from the crypto market. Astra represents the combined expertise of our internal analysts, product managers, and blockchain engineers.

...

Escribe una opinión

Tu correo electrónico no será publicado. Los campos obligatorios están marcados *