# avantis

basefun doesn't reinvent perps. It uses [Avantis](https://avantisfi.com/) — the established Base-native perpetuals exchange with 99 markets across crypto, FX, commodities, equities, and indices.

## What basefun touches

| Avantis contract    | Address (Base mainnet)                       | Used for                                               |
| ------------------- | -------------------------------------------- | ------------------------------------------------------ |
| **Trading**         | `0x44914408af82bC9983bbb330e3578E1105e11d4e` | `openTrade`, `closeTradeMarket`, `delegatedAction`     |
| **TradingStorage**  | `0x8a311D7048c35985aa31C131B9A13e03a5f7422d` | Read open trades for a trader+pair+index               |
| **PairStorage**     | `0x5db3772136e5557EFE028Db05EE95C84D76faEC4` | Market metadata (display name, group, fee config)      |
| **PairInfos**       | `0x81F22d0Cc22977c91bEfE648C9fddf1f2bd977e5` | **`getTradePnL(trader, pair, index)`** — drives LT NAV |
| **PriceAggregator** | `0x64e2625621970F8cfA17B294670d61CB883dA511` | Pyth price update relay (handled by Avantis, not us)   |
| **USDC**            | `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913` | Collateral asset                                       |

## Delegated action pattern

Avantis supports a trader EOA setting one or more **delegates** that can call `openTrade` / `closeTradeMarket` on its behalf via `delegatedAction(traderAddr, calldata)`.

basefun uses this so the **off-chain keeper EOA** is the on-chain Avantis trader, but the actual `openTrade` call is constructed by the **LeveragedToken contract** (`encodeOpenTrade(usdc)`) using its known `pairIndex`, `leverage`, `buyLong` immutables. This:

* Keeps the trade parameters tamper-proof (the LT contract can't lie about which market).
* Lets the keeper own the USDC briefly without being able to misuse it (Avantis pulls from `msg.sender`, which inside `delegatedAction` is the keeper).

The keeper does **not** sign on behalf of the LT. The LT is a smart contract with no key. The LT just exposes the calldata blob the keeper should submit.

## Sequence on a buy

```
Trader →   buy(usdc) on BondingCurveV2
           usdc.transferFrom(buyer, curve)
           split 1% fees (treasury, creator)
           LT.mint(netUSDC, 0):
               usdc.transferFrom(curve, keeper, netUSDC)   ← USDC now on keeper EOA
               _mint(curve, ltOut)
           token.transfer(buyer, tokensOut)
           emit Bought

Keeper (off-chain, ~next block):
           Avantis.delegatedAction(
               keeper,
               LT.encodeOpenTrade(usdcAmount)
           )
           → Avantis.openTrade(trade, type=0, slippage=3e10)
               pulls usdcAmount from keeper
               opens the perp
           LT.notePositionOpened()
               nextTradeIndex += 1
```

After this, the LT's `nav()` will include the new trade's PnL in subsequent reads.

## Sequence on a sell

```
Trader →   sell(tokens) on BondingCurveV2
           token.transferFrom(seller, curve)
           ltBurn = ltBalance × usdcGross / reserveUSDC
           LT.redeem(ltBurn, 0):
               usdcOut = ltBurn × nav / supply
               _burn(curve, ltBurn)
               usdc.transferFrom(keeper, LT, usdcOut)       ← USDC pulled back from keeper
               usdc.transfer(curve, usdcOut)
           split 1% fees, send 99% to seller

Keeper (off-chain, runs continuously):
           Watches LT's collateralDeposited and pending sell pressure.
           Periodically closes proportional Avantis position size to keep
           keeper USDC balance ≥ pending redeems.
           LT.noteCollateralWithdrawn(usdcReleased)
```

The "keep USDC balance sufficient" logic lives in the keeper's rebalance loop and isn't on-chain.

## Constraints from Avantis

| Constraint                            | Effect on basefun                                                                                                                                                    |
| ------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Notional minimum ≈ $101 per trade     | First LT mint per `(pair, lev, dir)` needs ≥ \~$20 USDC × leverage. The `INITIAL_BUY_FLOOR_USDC = $20` constant ensures this for the most common leverage (5×).      |
| Liquidation at ≤ 20% remaining health | If the underlying moves against the position hard enough, Avantis liquidates and the LT's NAV drops to whatever USDC is left. Curve `reserveUSDC` falls accordingly. |
| `openTrade` takes a slippage param    | LT hardcodes `3e10` (3%) — generous enough that fast markets don't fail to open.                                                                                     |
| Avantis fees (open, close, funding)   | Embedded in trade PnL; surfaced to LT holders via NAV. No separate accounting.                                                                                       |
| Per-pair max position size            | Aggregating across all basefun tokens with the same `(pair, lev, dir)` keeps individual launches well below cap.                                                     |

## What happens at graduation

The bonding curve calls `LT.redeem(ltBalance, 0)` at the very end of the graduation-triggering buy. This:

1. Burns all the LT shares the curve owns.
2. Pulls a proportional slice of USDC from the keeper.
3. **Implicitly closes the matching slice of the Avantis perp** when the keeper's next rebalance tick fires.

After graduation, the basefun token no longer has perp exposure. Post-grad price is purely Uni V2 AMM dynamics. The leverage thesis lives during the curve phase only.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://basefun.gitbook.io/basefun-docs/avantis.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
