Swap Signatures

MEVSwap uses signatures to let retail users swap tokens securely on Uniswap V4 pools. Signatures are required to protect against toxic orderflow (bots & market makers).

Get Started

  1. Grab an API Key from Merkle Blockchain Services.

  2. Request a Signature:

    {
      "chain_id": 1,
      "pool_id": "0x0000000000000000000000000000000000000000", // uniswap v4 pool id
      "sender": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", // the signer of the swap transaction
      "zero_for_one": true,
      "amount_specified": "-1000000000000000000", // Negative for input, positive for output
      "deadline": "1600000000"
    }
    {
        "signature": "0xabcdef1234567890..."
    }
  3. Build HookData:

    /// @notice Struct containing authorization data for hook
    struct HookData {
        // -------- FOR MEV AUCTIONS --------
        /// @notice nonce committed by MEV bot
        uint256 nonce; // use 0 for signature swaps
        // --------- FOR SWAPS --------
        /// @notice Signature authorizing the swap
        bytes signature;
        /// @notice deadline after which the signature is invalid
        uint256 deadline;
        /// @notice the swapper address
        address swapper;
    }

    Encode it:

    const hookData = ethers.utils.defaultAbiCoder.encode(
      ["uint256", "bytes", "uint256", "address"],
      [0, "0xabcdef1234567890...", 1600000000, "0xabcdef1234567890abcdef1234567890abcdef12"]
    );
  4. Example: Swap with Universal Router:

    • Exact Input (e.g., 1 ETH → USDC):

      const commands = "0x10"; // Commands.V4_SWAP
      const inputs = [[
        ["SWAP_EXACT_IN_SINGLE", poolKey, true, "-1000000000000000000", "0", hookData],
        ["SETTLE_ALL", "ETH", "1000000000000000000"],
        ["TAKE_ALL", "USDC", "0"]
      ]];
      await universalRouter.execute(commands, inputs, deadline, { value: "1000000000000000000" });
    • Exact Output (e.g., USDC → 1 ETH):

      const commands = "0x10"; // Commands.V4_SWAP
      const inputs = [[
        ["SWAP_EXACT_OUT_SINGLE", poolKey, false, "1000000000000000000", "340282366920938463463374607431768211455", hookData],
        ["SETTLE_ALL", "USDC", "340282366920938463463374607431768211455"],
        ["TAKE_ALL", "ETH", "1000000000000000000"]
      ]];
      await universalRouter.execute(commands, inputs, deadline);

Last updated

Was this helpful?