> ## Documentation Index
> Fetch the complete documentation index at: https://sdk.avantisfi.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Direct Integrators

> v1 to v2 for teams that call the contracts or decode their events directly: MMs, indexers, keepers, risk engines.

This guide is for integrations that bypass the SDK: custom market-making
stacks, event indexers, execution bots, risk engines, and data warehouses.
It inventories what breaks at the contract and API level, and what the
recommended v2 integration looks like.

<Note>
  This page is a distillation. A field-accurate delta reference (every event
  signature, struct, formula, and ABI change between v1 and v2) is available
  from the Avantis team on request.
</Note>

## What stays the same

* **All proxy addresses.** The upgrade swaps implementations behind the
  existing proxies (TradingStorage, PairStorage, PairInfos, Trading,
  Execute, TradingCallbacks, PriceAggregator, VaultManager, Referral, the
  tranche). Anything keyed on contract address keeps working.
* **Log emitter addresses.** v2 splits the monoliths into
  facade-plus-delegatecall modules, but `delegatecall` preserves
  `address(this)`, so logs still surface on the proxy addresses you
  already subscribe to.
* **Chain.** Base (8453), USDC collateral, same core position model
  (pair index + per-pair trade index).

## What breaks, at a glance

| Area               | Break                                                                                                                                        |
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------- |
| Event ABIs         | Most trading events gained fields → **different topic0**. Filters and decoders must be rebuilt (see below).                                  |
| Write entry points | TP/SL updates and TWAP are **signed-intent only**; several function signatures changed; `updateTpAndSl` / `updateSl` public entries removed. |
| Keeper interfaces  | `PriceAggregator.fulfill` takes an `offChainSpreadParams` struct instead of `int spreadP`; `executeMarketOrders` → `executeMarketOrder`.     |
| Reverts            | String reverts replaced by **custom errors** (4-byte selectors) protocol-wide, with a few residual strings.                                  |
| Reads              | Several views removed or reshaped (`pairLongOI`/`pairShortOI` gone, `walletOI` is per-pair, some views became non-`view`).                   |
| Formulas           | Funding fees exist now (in liquidation price and trade value); **spread applies on close**; close fee is maker/taker, not flat.              |
| Vault              | Dual tranche (Junior + Senior + VeTranche) collapses to a single ERC-4626 `AvantisTranche`.                                                  |

## The recommended v2 write path: signed intents

v1 integrators built calldata and broadcast transactions themselves. In v2
the primary write path is **EIP-712 signed intents** submitted to Avantis
services, which handle price attachment, spread parameters, and execution:

1. **Bootstrap from meta.** `GET {tx-builder}/v2/meta` returns all contract
   addresses, EIP-712 domains, enums, and units. Never hard-code.
2. **Fetch or build the intent.** `POST {tx-builder}/v2/intents/*` returns
   the exact typed-data payload plus its digest; verify your
   locally-computed digest matches before signing. (High-frequency systems
   can mirror the schemas locally and skip the round-trip; this is what
   the SDK's [local intent builder](/advanced/mm-fast-path) does.)
3. **Sign** with the trader key or a registered delegate key (65-byte
   `r||s||v`, `v` ∈ {27, 28}).
4. **Submit**: market opens/closes/increases go to the batched-market
   endpoint (`POST /market/execute-batched`, order lifecycle streamed back
   as SSE); TP/SL updates relay through the operator entry point; TWAP
   intents go to the TWAP API; partial TP/SL triggers are stored off-chain
   via the core API.

Key intent conventions (these bite people):

* **Nonces are an unordered Permit2-style bitmap**, not a counter. Each
  intent carries a signer-chosen 256-bit `nonce`; any unused value works,
  ordering is not required. The v1-era monotonic nonce and the
  `intentExecuted` signature registry are both gone. Query
  `nonceBitmap(signer, wordPos)` or track issued nonces locally.
* **Deadlines are milliseconds** (`deadline / 1000 >= block.timestamp`
  on-chain). Delegate **expiry is seconds**. Don't mix them up.
* **Close intents bind the position's open timestamp.** `CloseTradeReq`
  carries `_openTimestamp`, which must equal the on-chain trade's
  timestamp. Re-read the position right before signing, because margin
  updates and partial closes refresh it (mismatch reverts
  `PositionMismatch()`).
* **Two EIP-712 domains**, both `("AvantisTrading", "1", chainId)`: trading
  intents verify against the TradingRouter proxy, referral intents against
  the Referral contract (separate nonce bitmap).
* **Delegate authorization is checked at submission time.** Revoking a
  delegate kills its in-flight intents.

Direct self-broadcast calldata (via your own node) remains available for
most actions through the tx-builder `/v2/trade/*`, `/v2/limit/*`,
`/v2/margin/*`, `/v2/position/*` routes. But TP/SL update has **no**
calldata path in v2 (intent-only), and user-initiated TWAP contract
entry points revert `OnlyBatchedFlowAllowed()`.

### Order-type enum (v2)

The `OrderType` enum grew from 9 values to 22. New values in v2:

```text theme={null}
0-8   MARKET_OPEN … LIMIT_CLOSE_PNL          (as in v1)
9     INCREASE_SIZE
10    DECREASE_SIZE                          (reserved, not wired)
11    LIMIT_PARTIAL_CLOSE                    (partial TP/SL)
12-16 …_WITH_COIN_EXPOSURE family            (coin-sized open/close/increase)
17-18 TWAP_OPEN / TWAP_CLOSE
19-20 (reserved, not wired)
21    TWAP_CANCEL
```

## Indexers: event migration

**Most changed events have a new topic0.** Solidity derives it from the
full parameter type list, and nearly every trading event gained fields.
Rebuild your filter sets and decoders from the v2 ABIs; don't try to reuse
v1 signatures. Headline changes:

| Event                                           | Change                                                                                             |
| ----------------------------------------------- | -------------------------------------------------------------------------------------------------- |
| `MarketOrderInitiated`                          | 9 → 13 fields (`minLeverage`, `maxLeverage`, `coinExposure`, `isCoinExposureFixed`, `wantedPrice`) |
| `MarketExecuted`                                | 8 → 10 fields (`coinExposure`, `isCoinExposureFixed`)                                              |
| `LimitExecuted`                                 | 9 → 10 fields (`coinExposure`)                                                                     |
| `OIUpdated`                                     | 5 → 9 fields (coin OI and USD OI, both sides)                                                      |
| `MarginUpdated`                                 | 8 → 9 fields (`coinExposure`)                                                                      |
| `OpenLimitPlaced`                               | 10 → 12 fields (`coinExposure`, `timestamp`)                                                       |
| `TpUpdated` / `SlUpdated` / `SlUpdateInitiated` | gained `tradeOpenTimestamp`                                                                        |
| `FeesCharged` (PairInfos)                       | gained signed `fundingFee`                                                                         |
| `PriceReceived`                                 | gained `PriceSourcing`                                                                             |
| `TradingContractAdded`                          | renamed `TradingContractUpdated(address, bool)`                                                    |

Entirely new event families to decode: funding
(`AccFundingFeesStored`, `TradeInitialAccFundingFeesStored`,
`FundingParamsUpdated`), spread attribution (`SpreadCharged`), position
increases (`IncreasePositionRequested`, `PositionSizeIncreased`,
`PositionIncreaseRegistered`), partial TP/SL (`PartialTpSlInitiated`,
`TpSlExecuted`), TWAP lifecycles (`Open/CloseTwapInitiated`,
`…SliceRequested`, `…SliceFilled`, `TwapCanceled`),
whitelists (`WhitelistModified`), and builder codes
(`RegisteredBuilderCode` etc., plus `BuilderFeesCharged`; note the latter
emits from the **trader's own EOA address** via the EIP-7702 smart-account
template, not from a protocol proxy).

Semantic traps that survive an ABI update:

* `Trade.positionSizeUSDC` inside emitted `Trade` structs is repurposed to
  hold `block.timestamp` after registration (v1 behavior, still true).
* `LimitExecuted` overloads fields by path: on limit **opens**,
  `percentProfit` carries the trigger price and `usdcSentToTrader` is
  hard-coded `0`; on closes they carry real profit and payout. Branch on
  `orderType`.
* `isCoinExposureFixed` distinguishes coin-sized orders (`true`) from
  USDC-sized orders (`false`). Don't assume it's always set.
* Metric definitions shift: v1 "borrow fee" = rollover only; v2 = rollover
  * funding. v1 wallet OI is one number per trader; v2 is per-pair. Close
    fees are direction/skew-dependent. Schema-version any series spanning
    the upgrade rather than merging raw data.

## Bots, keepers, and on-chain callers

* **`PriceAggregator.fulfill`** now takes
  `offChainSpreadParams { spreadP, bookDepth, impactParam, byPass, maxSpreadP, … }`
  instead of `int spreadP`. This is a hard ABI break.
* **`executeMarketOrders` → `executeMarketOrder`** (singular) on the router.
* **New preflight checks** to avoid surprise reverts: `isCloseOnly(pair)`
  (blocks opens, limit placements, margin deposits, increases),
  `isPairOIHardCapped(pair)`, and per-pair `walletOI(trader, pair)` caps.
* **Custom errors.** Reverts are 4-byte custom-error selectors
  (`Errors.InvalidNonce()`, `Errors.PositionMismatch()`,
  `Errors.InvalidDeadline()`, `Errors.OnlyBatchedFlowAllowed()`, …) with a
  few residual `Error(string)` cases. Decode both.
* **View mutability changed.** Some conceptual reads are non-`view` in v2
  because they delegatecall into extensions (`pairCloseFeeP`, `correctTp`,
  `withinExposureLimits`, …). That is fine over `eth_call` but breaks
  strict `staticcall` assumptions. Conversely `Multicall.getPositions` is
  now `view` and returns **compact arrays** (active entries only; key on
  `trade.pairIndex`/`trade.index`, not array offset).
* **Removed views**: `pairLongOI` / `pairShortOI` (use
  `openInterestUSDC(pair, side)`), `getTradePriceImpact` (superseded by
  `applySpread`).
* **Delegation model.** v1's single delegate per trader becomes multiple
  delegates with **expiries**: `setDelegate(delegate, expiry)` or gasless
  `setDelegateWithSig(...)`; revoke with `removeDelegate(delegate)`.
  `delegatedAction` authorizes against `isEnabled && expiry > now`.

## Formula changes for risk engines

* **Liquidation price** subtracts funding:
  `dist = openPrice × (collateral × 0.85 − rolloverFee − fundingFee) / (collateral × leverage)`.
  v1 had no funding term.
* **Spread applies on close.** v1 closed at the raw oracle price; v2
  applies the flow-based spread on both opens and closes (unfavorable to
  the trader). Realized-PnL and execution-quality models must include it.
* **Spread model** is sqrt-based on decayed flow volume
  (`impactParam × sqrt(|finalVol| / bookDepth)` + constant spread, capped
  by `maxSpreadP`), replacing v1's exp-based price/skew impact functions.
  The on-chain `SpreadCharged` event attributes each component.
* **Close fee is maker/taker**: `pairCloseFeeP(pair, coinOI, buy)` blends
  by direction and skew, replacing v1's flat per-pair rate.
* **Funding** is price-aware and coin-OI socialized: accumulators advance
  at validated oracle prices (per trade-flow touch and on a keeper
  cadence), accrued per unit of coin OI on each side.
* **OI caps**: basis is the single tranche's assets; hard-capped pairs
  bypass the dynamic TVL-based cap; wallet OI caps are per-pair.

## Removed v1 features

| v1 feature                                               | v2                                                                       |
| -------------------------------------------------------- | ------------------------------------------------------------------------ |
| Junior/Senior tranches + VeTranche locking               | single ERC-4626 `AvantisTranche`; no lock, utilization-gated withdrawals |
| Exp-based spread functions                               | `applySpread` (flow-based)                                               |
| `EARLY_CLOSE` time-delay on market close and TP triggers | removed; closes and TP triggers proceed immediately                      |
| Public `updateTpAndSl` / `updateSl` entry points         | signed-intent only (`UpdateTpSlReq` via operator batch)                  |
| Single-delegate `delegations` mapping                    | multiple delegates with expiry (see above)                               |
| MM-only `openTradeMarketMaker`                           | generalized to `openTradeWithCoinExposure`, no whitelist required        |

## Reads: prefer the APIs

v1 integrations leaned on multicall fan-outs. The v2 read surface is
served over HTTP (the Multicall contract still exists as a fallback):

| Need                                                                     | v2 source                                                                                        |
| ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------ |
| Addresses, domains, enums, units                                         | tx-builder `GET /v2/meta`                                                                        |
| Positions + liquidation price, rollover, funding, limit orders           | core API `GET /user-data?trader=` (raw scales) or tx-builder `GET /v2/positions`                 |
| Pair catalog: fees, funding, OI + caps, leverage envelopes, market hours | data API `GET /v2/trading` (human units; [Socket.IO](/data/socket-io) `RES:DATA` for live diffs) |
| Dynamic spread quote                                                     | risk API `GET /v2/dynamic-spread/{pair}`                                                         |
| Prices (REST, SSE stream, OHLCV)                                         | feed API                                                                                         |
| Trade/order history with full fee breakdowns, portfolio analytics        | history API `/v2/history/*`                                                                      |

Units on the raw/on-chain surfaces: USDC amounts 1e6; prices, leverage,
slippage percentages, and coin exposure 1e10.

## Suggested migration order

1. Bootstrap from `/v2/meta` on testnet and replace hard-coded addresses,
   enums, and units.
2. Move reads to the API surface (or update multicall decoders for the
   compact-array and per-pair-wallet-OI changes).
3. Rebuild event decoding from v2 ABIs; run v1 and v2 indexers side by side
   across the upgrade rather than merging schemas.
4. Move writes to signed intents (or update your calldata + broadcast path
   for the changed signatures), including the nonce-bitmap and ms-deadline
   conventions.
5. Update risk math: funding in liquidation/PnL, spread on close,
   maker/taker close fees.
6. Dry-run the full loop on testnet, then cut over — mainnet has run v2
   since the August 12, 2026 upgrade.

The Python SDK implements all of the above and is itself a reference
implementation. Even if you don't adopt it wholesale, its
[signing internals](https://github.com/Avantis-Labs/avantis_trader_sdk)
(digest verification, golden-vector tests, nonce pool) are worth mining.
