@mayflower-sys/evm-avm-interfaces
v202607.1306.150
Published
Solidity interfaces, shared types, errors, and event schemas for AVM EVM markets.
Downloads
64
Readme
AVM EVM Interfaces
Public Solidity interfaces, shared types, errors, and event schemas for AVM EVM markets.
This package is the ABI boundary. Use it to discover markets, read market state, quote actions, submit user transactions, and index canonical events.
Topology
An AVM EVM deployment is organized around one directory, many markets, and one canonical event stream:
Directory
|-- tenants
| `-- market groups
| `-- markets
|-- market id -> market proxy registry
|-- market kind -> pricing engine route
|-- event emitter pointer
`-- shared runtime pointers used by markets
Factory
`-- deploys market proxy + market tokens, then registers the market
Market proxy
|-- owns per-market state, token custody, positions, and operation flags
|-- exposes views and permissionless actions at the market address
|-- resolves its active engine through the directory by market kind
`-- emits canonical logs through the directory's event emitter
Event emitter
`-- canonical log address for indexersThe basic containment chain is:
Tenant -> MarketGroup -> MarketA tenant is a top-level namespace. A market group belongs to one tenant and carries group-level policy such as the fee schedule. A market belongs to one group, has one market kind, owns one reserve token / AVM token / option token set, and stores its own balances, positions, flags, and opaque engine state.
MarketKind is not an engine address. It is a stable semantic identifier. The
directory maps each kind to the currently active pricing-engine contract, and a
market resolves that route when it needs it.
Interface Map
| Interface or library | Main public use |
| ------------------------------ | ---------------------------------------------------------------------------------------------------------------- |
| IAvmDirectoryViews | Discover directories, tenants, groups, market records, engine routes, and the canonical event emitter. |
| IAvmFactory | Create markets where market creation is exposed, and predict market addresses from market ids. |
| IAvmEventEmitter | Index the canonical event stream for topology, policy, market actions, and positions. |
| IMarketViews | Read one market's identity, tokens, flags, balances, snapshot, and user positions. |
| IMarketQuoter | Get fee-aware, read-only buy, sell, floor-redemption, and option-exercise quotes before submitting spot actions. |
| IMarketLeverageQuoter | Get fee-aware, read-only borrow (cash-advance) quotes before submitting position actions. |
| IMarketActions | Submit permissionless spot actions: buy, sell, floor redemption, option exercise, and liquidity donation. |
| IMarketLeverageActions | Submit permissionless position actions: deposit/withdraw collateral, borrow, repay, and atomic expand/shrink. |
| ILeveragedPositionManagement | Submit the atomic expand and shrink flows composed into IMarketLeverageActions. |
| IMarketToken | Detect AVM and option ERC-20 tokens owned by a market. |
| IPricingCurve | Engine boundary for quotes and state transitions. Most frontends use IMarketQuoter instead. |
| DataTypes | Shared structs, branded identifiers, unit aliases, flags, balances, snapshots, and quote payloads. |
| Errors | Shared custom errors surfaced by implementations. |
Discovering Markets
Start from a known directory address.
To resolve a market from an off-chain id, call:
IAvmDirectoryViews.getMarket(marketId)to get the registered market record.IAvmDirectoryViews.isMarket(address)to check whether an address is a registered market.IAvmDirectoryViews.marketIdOf(address)to map a market address back to its id.
Once you have a market address, call IMarketViews on that address:
marketId(),groupId(),tenantId(), andmarketKind()identify where the market sits in the topology.tokens()returns the reserve token, AVM token, option token, and shared decimals.flags()tells you which user actions are currently enabled.balances()returns the market's aggregate reserve, debt, collateral, and revenue-escrow balances.snapshot()returns the richer aggregate state payload (DataTypes.MarketStateSnapshot).getPosition(holder)returns one holder's collateral and debt in that market.
Use the directory to walk upward:
market.groupId() -> directory.getMarketGroup(groupId) -> tenantId
tenantId -> directory.getTenant(tenantId)
marketKind -> directory.engineForKind(marketKind)For indexing-first applications, MarketCreated carries the same genesis facts
needed to seed a market without an immediate follow-up read.
Viewing State
IMarketViews.snapshot() returns DataTypes.MarketStateSnapshot. The snapshot
is intentionally broad: it captures the market's current policy, runtime
pointers, token supplies, internal reserve accounting, actual ERC-20 custody
balances, current price and floor values, total debt and collateral, and the
full opaque engine-state bytes.
For application display, the most commonly used fields are:
flags,groupFees, andplatformFeefor availability and fees.avmPriceInReserveTokenandfloorPriceInReserveTokenfor current price and floor display.avmTokenSupply,optionTokenSupply,reserveTokenBalance,totalDebtInReserveToken, andtotalCollateralInAvmTokenfor aggregate market stats.engine,engineStateHash, andengineStatefor forensic or engine-aware consumers.
Do not decode engineState unless you know the engine behind the market kind
and that engine's state encoding. For generic UIs, treat it as opaque bytes and
use engineStateHash for consistency checks.
Quoting And Actions
The usual transaction flow is:
- Read
IMarketViews.flags()and disable actions whose flag is false. - Format user input as
RawTokenQuantityin the relevant token's native decimals. - Call
IMarketQuoterfor fee-aware buy, sell, floor-redemption, and option-exercise previews (andIMarketLeverageQuoterfor borrow previews). - Ask for the required ERC-20 allowance where the action pulls tokens from the caller.
- Submit the matching
IMarketActionsorIMarketLeverageActionscall with a slippage bound where the method exposes one. - Confirm the transaction from the canonical event emitted through
IAvmEventEmitter.
Quote results are previews against current chain state. A quote can go stale if another transaction changes the market before the user's transaction is mined, so variable-price buy and sell actions include a minimum-output or maximum-input guard. Floor redemption is the exception: it is an exact AVM input redeemed at the guaranteed floor price, so its action method has no slippage parameter.
| User intent | Interface method |
| --------------------------------- | ------------------------------------------------------------------------------ |
| Buy with exact reserve input | buyWithExactReserveTokensIn(grossReserveTokensIn, minAvmTokensOut, receiver) |
| Buy exact AVM output | buyWithExactAvmTokensOut(avmTokensOut, maxReserveTokensIn, receiver) |
| Sell exact AVM input | sellWithExactAvmTokensIn(avmTokensIn, minReserveTokensOut, receiver) |
| Sell for exact reserve output | sellWithExactReserveTokensOut(netReserveTokensOut, maxAvmTokensIn, receiver) |
| Redeem exact AVM at the floor | redeemAtFloorWithExactAvmTokensIn(avmTokensIn, receiver) |
| Exercise option tokens | exerciseOptionTokens(optionTokenAmount, maxReserveTokensIn, receiver) |
| Deposit AVM collateral | depositCollateral(amount, onBehalfOf) |
| Withdraw AVM collateral | withdrawCollateral(amount) |
| Draw a reserve-token cash advance | borrow(grossDebtIncrease) |
| Repay reserve-token debt | repay(amount, onBehalfOf) |
| Expand a position atomically | expandWithExactReserveIn(...) or expandWithExactAvmOut(...) |
| Shrink a position atomically | shrinkWithExactAvmIn(...) or shrinkWithExactReserveOut(...) |
| Donate reserve liquidity | donateLiquidity(amount) |
Token movement depends on the action:
- Reserve-token inputs, such as buys, repayments, option exercise costs, leverage inputs, and donations, require the caller to let the market pull the reserve token.
depositCollateraltransfers AVM tokens from the caller into the market, so it requires the normal ERC-20 allowance path.- Sells, floor redemption, and option exercise burn the caller's AVM or option tokens directly through the market's mint/burn authority (no ERC-20 allowance needed on that side); frontends should still show the resulting balance change clearly.
Indexing Events
This package's IAvmEventEmitter defines the public market and topology event
schemas. Markets and control-plane contracts all emit through one configured
emitter, so an indexer watching that single address sees the whole canonical
stream; the directory exposes the current emitter address through
eventEmitter(). A few operational events in the table below (tenant lifecycle
and runtime-pointer changes) ride the same stream but are declared on the
non-public admin event surface rather than in this package.
Indexers should:
- Treat
MarketCreatedas the canonical "market exists" event. - Store both
marketaddress andmarketId; the address is the call target, and the id is the stable off-chain key.
Important event families:
| Event family | What it tells an indexer |
| --------------------------------------------------------------------------------------------- | ------------------------------------------------------- |
| TenantCreated, MarketGroupCreated, MarketCreated | Topology and genesis records. |
| TenantFeeChanged, MarketGroupFeesChanged, MarketFlagsChanged | Policy and availability timeline. |
| MarketKindEngineChanged, MarketBeaconUpgraded, MarketActionsImplChanged | Runtime pointer changes that may affect later behavior. |
| AvmTokensBought, AvmTokensSold, AvmTokensRedeemedAtFloor, OptionTokensExercised | Spot and option user actions. |
| PositionCreated, CollateralDeposited, CollateralWithdrawn, DebtBorrowed, DebtRepaid | Position lifecycle and cash-advance state. |
| LeveragedPositionExpanded, LeveragedPositionShrunk | Atomic leverage composition flows. |
| LiquidityDonated, RevenueCollected | Reserve top-ups and revenue escrow withdrawals. |
Market events include the market address and MarketId; fee-bearing spot and
position events also carry a FeeDistributionBreakdown. Events do not embed a
full market snapshot — read IMarketViews.snapshot() when you need to refresh
aggregate market state after an action.
Units And Identifiers
DataTypes.sol carries the shared unit vocabulary:
RawTokenQuantityis an unscaled integer count of a token's smallest unit. It uses the token's own decimals and does not imply 18 decimals.ExchangeRateis an unsigned 18-decimal ratio, used for prices and floor levels.Fixed18ValueandSignedFixed18Valueare 18-decimal fixed-point transports used at the engine boundary.MicroBpsis a raw integer count of micro basis points, where100_000_000is 100%.TenantId,GroupId,MarketId, andMarketKindare brandedbytes32identifiers.
External market entry points generally use RawTokenQuantity for token amounts
and ExchangeRate for price-like ratios. The engine boundary uses
Fixed18Value and SignedFixed18Value; markets handle the conversion between
raw token units and engine fixed-point values.
