# 1inch Aqua (https://docs.helico.site/docs/1inch-aqua)

Two Aqua apps, an allowance ledger that moves no tokens, and one SwapVM instruction of ours.

Aqua is an **allowance ledger, not a vault**. Shipping a strategy writes an entry and moves
nothing; a fill pulls from the maker's own wallet at the moment it fills. The wallet never stops
holding its own money.

That one property is why Helico is built on it, and it has a consequence that is easy to state
and easier to disbelieve: &#x2A;*one wallet's balance can back several positions at once.**

```
ship $2,800–3,200   3 Aqua events, 0 token transfers
ship $2,900–3,100   3 Aqua events, 0 token transfers
ship $1,000–9,000   3 Aqua events, 0 token transfers

committed  30 WETH against 10 held  —  300%
moved      0 WETH   0 USDC
```

Three concentrated ranges on the same ten ETH, on a fork of Arbitrum One. 300% is not leverage:
whichever strategy fills first gets the tokens and the rest revert inside `pull`. It is a number
an agent has to watch, which is one of the jobs [the subgraph](https://docs.helico.site/docs/thegraph) does here.

## Two apps, because one cannot quote a one-sided maker
**`HelicoMandateSwap`** is an Aqua app in which the strategy *is* the mandate: an expiry, a named
agent contract, and a per-token ceiling on what may leave the wallet. Aqua files a strategy under
the hash of bytes it never reads, so every field is enforced in our contract or nowhere.

It prices as a constant product — and that is a real limit rather than a stylistic one. **The
price *is* the ratio of the two sides**, so a maker holding only USDC has no price at all. Which
is exactly the maker this product is built for: their USDC is earning in a lending market, and a
fill is settled out of it mid-swap.

**`HelicoOracleBoard`** quotes that maker from a Chainlink feed, and brakes itself on Aqua's own
ledger:

```
bid = mid × (BPS − spread − skew) / BPS
ask = mid × (BPS + spread − skew) / BPS
```

Both sides shift **down** as base inventory accumulates, so selling into the board gets steadily
worse and buying the inventory back gets steadily better. Inventory is pushed home by the price
rather than by anyone watching — the behaviour a constant product gets for free, rebuilt on top of
a feed that knows nothing about who holds what.

Against the live ETH/USD feed on Arbitrum One:

```
chainlink ETH/USD  2483.504394
bid                2476.053880    empty inventory, the feed less 0.30%
ask                2490.954907
bid, half full     2451.218836    bent by half the skew
```

## What they refuse, and why each refusal is named
* **A maker with debt**, at the venue the swap actually draws on. A lending market blocks a
  borrower from withdrawing collateral, so one ordinary borrow would otherwise disable a mandate
  and the failure would arrive as the market's error after the mandate looked fine.
* **A venue that does not match the pool.** A receipt token is an address the maker writes into
  their own mandate, so anything it says about itself could have been made up. The pool is asked
  which receipt it issues, not the other way round.
* **A stale feed.** The board refuses the fill rather than quoting yesterday's number.
* **A quote that answers for a swap that would revert** — the quote applies the same rules the
  swap does, or an agent builds a transaction that cannot land.

A venue that simply cannot pay is **skipped, not fatal**: liquidity is one of three conditions,
and ending the search at the first strands a funded market further down the list.

## Never an approval
**Aqua's ledger is the only way this code moves anyone's tokens.** It never takes an ERC-20
approval for a user's assets — not for a token, and especially not for a lending receipt. An
approval outlives the mandate, ignores the ceiling, and survives `dock`. The ledger does none of
those: it is a number the owner shipped, it falls as it is spent, and docking destroys it.

## SwapVM
**Powered by SwapVM — © Degensoft Ltd 2025.** `contracts/src/swapvm/` is a redeployment of
Degensoft's `AquaSwapVMRouter` with one instruction added. Their VM, transfer phase, Aqua
accounting and every published instruction are unchanged; the addition is **opcode 34**, marked as
ours under their licence.

Why it exists: every SwapVM curve prices against `balanceOut`, and Aqua answers that from what the
maker *shipped* — a number written with no transfer and no balance check. So a maker may commit
43,000 USDC while holding 5,000. The curve is right; what breaks is the transfer at the end,
because tokens earning yield elsewhere are not there to pull. No published instruction can close
that — none of them has a concept of a lending market. Ours unwinds exactly the shortfall, once,
inside the transaction that needs it.

## Deployed
|                          | Arbitrum One                                                                                     |
| ------------------------ | ------------------------------------------------------------------------------------------------ |
| `HelicoMandateSwap`      | [`0xA16D3138…87Ed`](https://arbiscan.io/address/0xA16D313816247628DeB7d89DC7a3Cf4aDb5287Ed#code) |
| `HelicoAquaSwapVMRouter` | [`0xb8c9f14d…c3be`](https://arbiscan.io/address/0xb8c9f14d46bf387a6d70d796df30f11a0eb8c3be)      |
| Canonical Aqua, 1inch's  | `0x1111113CCf1426A8E30e2bfF5E005d929bF6a90a`                                                     |

The [README](https://github.com/0xHelico/helico#1inch-aqua) points at the exact lines behind each
claim here, pinned to the commit they were read from.
