Vortex

Combines the eficiency of traditional market making with the decentralization of AMMs.

Vortex

Created At

ETHGlobal Lisbon 2026

Project Description

Vortex brings prop-style market making onchain without giving a central operator unrestricted pricing power. Makers keep assets in Aqua, while SwapVM enforces fees, inventory limits and trade safety. Vortex Swap compares Aqua liquidity with Uniswap and executes the best net route. Vortex Grow runs atomic WBTC→USDC→WBTC cycles only when the maker ends with more WBTC. Offchain systems find opportunities; onchain contracts guarantee the outcome.

How it's Made

STACK

Vortex is built as a pnpm monorepo with four workspaces.

The contracts use Solidity and Foundry. The backend runs on Fastify, viem and Zod. The frontend uses Next.js App Router, wagmi, viem and RainbowKit.

A shared package contains the Zod schemas, contract addresses and EIP-712 typed data used by both the frontend and backend. This prevents either side from inventing a slightly different request or signature format.

HOW IT FITS TOGETHER

The core design rule is:

Offchain proposes. Onchain disposes.

The backend finds opportunities, compares venues and prepares transactions. The contracts independently decide whether those transactions are safe enough to settle.

For Vortex Swap, the backend requests two quotes in parallel:

An official 1inch Aqua + SwapVM quote.

A live Uniswap Trading API quote.

Both routes are ranked by net output rather than headline output. Gas is converted into the output token, so the comparison reflects what the user actually receives.

Once a route is selected, the backend opens a single-use quote session that expires after 45 seconds. The browser only receives the session identifier and the final executable transaction. It never reconstructs the order or modifies the target, calldata or value.

1INCH AQUA

Aqua lets makers provide liquidity without transferring custody to a pool. Their assets remain in their wallets while Aqua tracks a virtual balance assigned to each strategy.

This creates an important safety distinction.

Virtual balance is not the same as executable liquidity.

A maker may allocate 1 WBTC virtually and later transfer most of that WBTC out of their wallet. Aqua would still display the original virtual allocation, but the strategy could no longer settle the full amount.

Vortex therefore defines executable liquidity as:

The minimum of the Aqua virtual balance, the maker’s wallet balance and the allowance granted to Aqua.

We have a lens test that demonstrates this directly: strategy coverage falls from 10,000 basis points to 2,500 basis points after the maker removes part of the underlying balance.

SWAPVM

SwapVM is where the Aqua market-making strategy actually lives.

Our pricing contract is a real SwapVM Extruction target. It calculates the quote, inventory adjustment, safety fee, maximum size and post-trade exposure.

The strategy bytecode is generated using 1inch’s own ProgramBuilder logic through function-pointer lookup. This prevents our local encoding from silently drifting away from the official SwapVM format.

UNISWAP

The Uniswap Trading API is load-bearing, not decorative.

It benchmarks every Aqua quote. When Uniswap provides the better net result, it builds the transaction that the user signs and broadcasts.

One of the most useful API fields is gasFeeQuote. Because it expresses gas cost in the output token, Vortex can compare venues using:

Minimum output minus gas cost.

This removes the need for a separate ETH price feed from the quote-selection hot path.

Uniswap v4 also provides the programmable pool infrastructure behind Vortex PermAMM. Its dynamic-fee hook places part of the maker’s pricing policy directly onchain.

THE INTERESTING ENGINEERING PROBLEMS

Compiler isolation

Uniswap v4 PoolManager uses an exact Solidity 0.8.26 pragma, while Aqua and SwapVM require Solidity 0.8.30.

Solidity chooses one compiler for each compilation unit, which means a 0.8.30 contract cannot directly import PoolManager.

We solved this by adding a dedicated file whose only purpose is to compile v4-core as an independent 0.8.26 unit. Tests then deploy the genuine PoolManager bytecode using deployCode and interact with it through IPoolManager.

The result is deterministic CI using the real contract bytecode, without depending on a fork or external RPC.

Hook-address mining

Uniswap v4 encodes hook permissions into the hook contract’s address.

A hook cannot simply be deployed to any address. We mine a CREATE2 salt until the resulting address contains the exact permission bits required by Vortex.

SwapVM taker-traits encoding

SwapVM taker traits are not a normal ABI struct.

They use a packed byte layout containing a 20-byte slice table, two bytes of flags and a variable tail. Passing an empty 0x value as “no options” reverts because the parser still expects the first 22 bytes.

We ported 1inch’s TakerTraitsLib.build logic to TypeScript and validated the generated bytes against the deployed router.

This also allowed us to bind the quoted minimum output directly into the calldata threshold. If execution falls below the amount shown to the user, the router reverts instead of silently filling at a worse price.

Fork funding

Funding WBTC on an Arbitrum fork was less straightforward than expected because the token is behind a proxy and its balance-storage slot could not be reliably discovered.

Instead of modifying storage, we impersonate the Aave v3 aWBTC reserve and use it as a real token holder.

Token ordering

Uniswap v4 sorts pool currencies by address. This means token0 and token1 ordering depends on deployment addresses rather than token names.

Our first test deployment accidentally produced the favorable order, so the tests passed. A later deployment produced the reverse order and reverted with a 99.99% oracle-price deviation because the reference price was not inverted when WBTC became token1.

We fixed the price-orientation logic and made token deployment overridable. The entire hook suite now runs in both token orders: 21 tests in the normal orientation and the same 21 tests in the reversed orientation.

A guard also verifies that the second suite genuinely flipped the token order.

This is one of the strongest engineering stories in the project: the tests were green, the deployment failed, and the failure exposed an assumption that the original tests had accidentally hidden.

ARCHITECTURAL ENFORCEMENT

Vortex Swap’s Aqua execution path must remain independent from Vortex PermAMM.

A CI script fails if the Aqua settlement module references the Uniswap v4 module. We also have an integration test proving that an Aqua + SwapVM trade settles successfully when no v4 contracts have been deployed.

Additional CI checks enforce the commit-message convention and reject frontend code that presents mocked data as live market data.

WHY THE TESTS MATTER

The project includes 639 automated tests covering:

Aqua virtual and real balance accounting.

Direct ERC-20 settlement.

SwapVM quote and execution consistency.

Inventory-aware pricing.

Minimum safety fees.

Maker coverage.

Uniswap API venue comparison.

Dynamic v4 fees.

Both token orientations.

Grow profitability and atomic reverts.

The goal is not simply to show that the happy path works. It is to prove that invalid quotes, stale data, insufficient balances, wrong token orientation and unprofitable Grow routes cannot settle.

The best story to tell when asked what went wrong is the token-ordering failure.

Everything was green locally. Deployment reverted with a 99.99% price deviation. The problem was not Uniswap or the oracle—it was an unstated assumption hidden by deterministic mock deployment addresses.

We fixed the implementation, forced both orientations in testing and added a guard proving that the test setup actually exercises the reversed case.

That is how we know the tests are testing the protocol rather than merely confirming our assumptions.

background image mobile

Join the mailing list

Get the latest news and updates