Pick your path
Five integration paths into Motoswap. Pick by what you are building, not by what you already know.
Motoswap looks like Uniswap V2 from a distance and behaves like it in the math. It does not behave like it at the entry points, and every integration that assumes a vanilla V2 fork breaks in the same three places. Pick your path below; each page front-loads the differences that matter for that job.
| You are building | Path | What you'll use | Page |
|---|---|---|---|
| An aggregator or routing engine | Quote and execute through FeeRouter | Chain reads: the core router's getAmountsOut plus the fee legs | Aggregators |
| A trading or Telegram bot | One swap loop: discover, quote, submit, confirm | REST + chain writes | Trading bots |
| A scanner, indexer, or analytics pipeline | Event streams and enumeration | RPC logs + the event catalog | Scanners and indexers |
| An AI agent or data consumer | REST only, no keys, ETag-cached | The public API | AI agents |
| A listing site, chart site, or launch tracker | Discover coins, price a curve, catch graduation | Curve reads + REST | Listing moto.fun coins |
The three facts every integrator needs
These are repeated on every path page because getting any one wrong ships a bug.
1. You cannot call the pair or the core router
MotoSwapPair.swap requires factory.swapAllowed(msg.sender), and so does
every swap function on MotoSwapRouter02, the core router. Only the core
router and the FeeRouter are admitted. FeeRouter is the only public way
to swap, it is exact-input only, and it charges the full fee. There are no
flash swaps. Liquidity functions and the read functions on the core router
stay permissionless.
2. There is no hardcoded init code hash
Pairs are ERC-1967 beacon proxies. The CREATE2 init code hash depends on the
deployment, so derive pair addresses with the hash from
factory.pairCodeHash(), or skip derivation and read factory.getPair.
A pasted Uniswap-style hex"96e8ac..." constant will compute addresses that
do not exist.
3. The protocol fee lands on the quote leg, and the side moves
FeeRouter skims protocolFeeBps, plus creatorFeeBps for a token with an
active creator, from whichever end of the path is the more senior quote asset
(WETH > USDT > USDC > MOTO at launch settings), or from the first interior
quote leg when neither endpoint is quote. Quote your trade on the wrong side
and your amountOutMin is unfillable. The contract tells you the side:
feeRouter.feeOnOutput(path) is a public view. There is no quote view; the
recipe is on the aggregators page.
One deployment, three phases
The deployment has moved through three launch phases, and the contract set
changed with them: prelaunch and vamp (the MOTO token and the launch farm, no DEX) came before
dex, which is the live phase. GET /config is the single source of truth:
launchPhaseis"prelaunch","vamp", or"dex". It reads"dex": the Motoswap DEX contracts and the moto.fun curve are deployed. In"vamp"the MOTO token and the launch farm were deployed and the DEX contracts were not. Per-contract status is on addresses.- A zero address means that contract is unset for the current phase. Never hardcode addresses; they also change on redeploy.
- The DEX surface documented across these pages (factory,
FeeRouter, pools, Rakeback) is thedexphase. Branch on the phase before you route: duringvamp(launch farming), trading ran on canonical Uniswap V2 (uniswapV2Router/uniswapV2Factoryin the same response) and the launch farm accepted Uniswap LP.
const cfg = await fetch("https://api.motoswap.org/config")
.then((r) => r.json());
if (cfg.launchPhase !== "dex") {
// The Motoswap AMM is not the trading venue yet. cfg.addresses.feeRouter
// is the zero address in this state. Do not take an address from anywhere else.
}