VimenDocs
Reference

VimenZap API

The external interface of the VimenZap2 router.

The live router is VimenZap2 (0x99c8…12c1). Stateless: no owner, no admin, no pause, no upgradeability; it holds nothing between transactions. Design rationale: VimenZap internals.

Types

/// One pool traversal. zeroForOne = true consumes key.currency0, produces key.currency1.
struct Hop {
    PoolKey key;
    bool zeroForOne;
}

/// One Rialto-filled leg. `data` is the Rialto quote API's tx.data verbatim;
/// the call target is always resolved from Rialto's on-chain router registry,
/// never taken from the quote.
struct RialtoCall {
    uint256 legIndex;   // which constituent this call fills (mint) / sells (redeem)
    uint256 sellAmount; // exact input from the quote
    address spender;    // allowance spender from the quote
    bytes   data;       // tx.data from the quote, unmodified
}

legs is always Hop[][]: one swap path per constituent, in constituents() order. The contract validates path endpoints and connectivity per leg (PathDiscontinuous, PathInputMismatch, PathOutputMismatch).

Mint

zapMint

function zapMint(
    address basket,
    uint256 basketAmount,
    address paymentCurrency,   // address(0) = native ETH (sent as msg.value)
    uint256 maxSpend,
    Hop[][] calldata legs,
    address to,
    uint256 deadline
) external payable nonReentrant returns (uint256 spent)

Buys every constituent for exactly basketAmount with exact-output Uniswap v4 swaps, mints, and sends the basket to to. Spends at most maxSpend; unspent native ETH is refunded. Requires a prior ERC-20 approval of paymentCurrency to the router (or use the Permit2 variant).

zapMintPermit2

function zapMintPermit2(
    address basket, uint256 basketAmount, address paymentCurrency,
    uint256 maxSpend, Hop[][] calldata legs, address to, uint256 deadline,
    Permit2Data calldata permit
) external nonReentrant returns (uint256 spent)

zapMint without the approve transaction: the payer signs a Permit2 SignatureTransfer for (paymentCurrency, maxSpend, spender = router) and funds flow straight into the PoolManager. One signature, one transaction, no allowance left behind. Requires the once-ever approval of the payment token to canonical Permit2 (0x0000…78BA3). Nonce replay is rejected.

zapMint2

function zapMint2(
    address basket, uint256 basketAmount, address paymentCurrency,
    uint256 maxSpend, Hop[][] calldata legs, RialtoCall[] calldata rialtoCalls,
    address to, uint256 deadline, Permit2Data calldata permit
) external nonReentrant returns (uint256 spent)

Mixed-venue mint: each constituent is filled either by a Uniswap v4 path or a Rialto call; coverage is verified exactly once per leg (LegNotCovered / LegDoublyCovered). Rialto approvals are exact and reset to zero around each call, the call target is resolved from Rialto's on-chain router registry (never from user data), and if a constituent balance doesn't grow by the required amount the whole zap reverts. permit with an empty signature falls back to a standard allowance pull. Native ETH is not supported on this path (NativeNotSupported).

Redeem

zapRedeem

function zapRedeem(
    address basket, uint256 basketAmount, address outputCurrency,
    uint256 minOut, Hop[][] calldata legs, address to, uint256 deadline
) external nonReentrant returns (uint256 received)

Pulls the basket, redeems in-kind, sells every constituent on Uniswap v4, and pays outputCurrency to to. Reverts MinOutNotMet below your floor.

zapRedeem2

The mixed-venue mirror of zapMint2: Rialto legs sell the exact redeemed amounts (RialtoSellMismatch otherwise), minOut is enforced on the combined total, and any leftover constituent dust is swept to the recipient rather than stranded.

Quotes (eth_call only)

function quoteZapMint(address basket, uint256 basketAmount, address paymentCurrency, Hop[][] calldata legs)
    external returns (uint256 totalIn, uint256[] memory legIn);

function quoteZapRedeem(address basket, uint256 basketAmount, address outputCurrency, Hop[][] calldata legs)
    external returns (uint256 totalOut, uint256[] memory legOut);

/// Basket-free exact-output quote for arbitrary legs (prices the Uniswap side
/// of a mixed-venue mint; Rialto legs are quoted by Rialto's API).
function quoteLegs(address[] calldata tokens, uint256[] calldata amounts, address paymentCurrency, Hop[][] calldata legs)
    external returns (uint256 totalIn, uint256[] memory legIn);

These run the real swaps inside a v4 unlock and revert with the amounts (QuoteResult), so an eth_call returns exact execution numbers: same math, same pools, same block. They are not view (they would mutate if broadcast); call them, never send them.

Events

event ZapMinted(address indexed sender, address indexed basket, address inputCurrency, uint256 basketAmount, uint256 spent);
event ZapRedeemed(address indexed sender, address indexed basket, address outputCurrency, uint256 basketAmount, uint256 received);

Errors worth handling

ErrorMeaning
Expireddeadline passed
LegUnderfilled(leg)Range liquidity ran out mid-swap (v4 exact-output fills partially instead of reverting; the router rejects it)
MaxSpendExceeded(required, maxSpend)Execution would cost more than your cap
MinOutNotMet(out, minOut)Redeem output below your floor
PathDiscontinuous / PathInputMismatch / PathOutputMismatchMalformed swap path for a leg
LegNotCovered / LegDoublyCoveredMixed-venue coverage must be exactly one venue per leg
RialtoSellMismatch(leg)Rialto call's sell amount ≠ the leg's exact requirement
RialtoRouterPausedRialto's registry reports its router paused
WrongMsgValuemsg.value inconsistent with paymentCurrency/maxSpend
NativeNotSupportedETH input/output on the *2 mixed-venue paths

On this page