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
delegatecallpreservesaddress(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
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:- Bootstrap from meta.
GET {tx-builder}/v2/metareturns all contract addresses, EIP-712 domains, enums, and units. Never hard-code. - 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.) - Sign with the trader key or a registered delegate key (65-byte
r||s||v,v∈ ). - 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.
- 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 theintentExecutedsignature registry are both gone. QuerynonceBitmap(signer, wordPos)or track issued nonces locally. - Deadlines are milliseconds (
deadline / 1000 >= block.timestampon-chain). Delegate expiry is seconds. Don’t mix them up. - Close intents bind the position’s open timestamp.
CloseTradeReqcarries_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 revertsPositionMismatch()). - 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.
/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)
TheOrderType 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.positionSizeUSDCinside emittedTradestructs is repurposed to holdblock.timestampafter registration (v1 behavior, still true).LimitExecutedoverloads fields by path: on limit opens,percentProfitcarries the trigger price andusdcSentToTraderis hard-coded0; on closes they carry real profit and payout. Branch onorderType.isCoinExposureFixeddistinguishes 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.fulfillnow takesoffChainSpreadParams { spreadP, bookDepth, impactParam, byPass, maxSpreadP, … }instead ofint 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-pairwalletOI(trader, pair)caps. - Custom errors. Reverts are 4-byte custom-error selectors
(
Errors.InvalidNonce(),Errors.PositionMismatch(),Errors.InvalidDeadline(),Errors.OnlyBatchedFlowAllowed(), …) with a few residualError(string)cases. Decode both. - View mutability changed. Some conceptual reads are non-
viewin v2 because they delegatecall into extensions (pairCloseFeeP,correctTp,withinExposureLimits, …). That is fine overeth_callbut breaks strictstaticcallassumptions. ConverselyMulticall.getPositionsis nowviewand returns compact arrays (active entries only; key ontrade.pairIndex/trade.index, not array offset). - Removed views:
pairLongOI/pairShortOI(useopenInterestUSDC(pair, side)),getTradePriceImpact(superseded byapplySpread). - Delegation model. v1’s single delegate per trader becomes multiple
delegates with expiries:
setDelegate(delegate, expiry)or gaslesssetDelegateWithSig(...); revoke withremoveDelegate(delegate).delegatedActionauthorizes againstisEnabled && 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 bymaxSpreadP), replacing v1’s exp-based price/skew impact functions. The on-chainSpreadChargedevent 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
- Bootstrap from
/v2/metaon testnet and replace hard-coded addresses, enums, and units. - Move reads to the API surface (or update multicall decoders for the compact-array and per-pair-wallet-OI changes).
- Rebuild event decoding from v2 ABIs; run v1 and v2 indexers side by side across the upgrade rather than merging schemas.
- Move writes to signed intents (or update your calldata + broadcast path for the changed signatures), including the nonce-bitmap and ms-deadline conventions.
- Update risk math: funding in liquidation/PnL, spread on close, maker/taker close fees.
- Dry-run the full loop on testnet, then cut over — mainnet has run v2 since the August 12, 2026 upgrade.