Skip to main content
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.
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.

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

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 does.)
  3. Sign with the trader key or a registered delegate key (65-byte r||s||v, v).
  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:

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: 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.
  • executeMarketOrdersexecuteMarketOrder (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

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): 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 (digest verification, golden-vector tests, nonce pool) are worth mining.