QAXE markets
QAXE trades in two places. QaxeBurnVault.sweep always buys from the first; the second exists so
wallets, aggregators, and screeners that only understand a standard AMM pair can see and trade QAXE
too.
1. The BondingCurve's internal pool (graduated)
QAXE's BondingCurve (0x004Bc407903A51506bcF0b1aB423958c5991c237)
has graduated: graduated() == true. Past graduation, buys and sells execute against real
reserves only — poolQuaiReserve() / poolTokenReserve() — with no virtual liquidity carried
over from the bonding phase. This is the pool QaxeBurnVault.sweep and the V1 probe vault both
buy from.
quoteBuy(uint256 quaiIn)/quoteSell(uint256 tokensIn)— constant-product quotes against the live pool reserves.buy(uint256 minTokensOut) payabletakes the curve's own fee (feeBps(), owner-adjustable, currently 1%, split 50/50 between the token's creator and the Hartii treasury) off the top before quoting — always quote on the net amount (msg.value - msg.value*feeBps/10000), never the gross, or your floor will be systematically too high.- Liquidity here is locked by construction: there is no LP token, no withdraw path, and no
owner action that drains
poolQuaiReserve/poolTokenReserveoutside of buys and sells themselves.
2. The Quainance V2 QAXE/WQUAI pair (standard)
A second, standard Uniswap-V2-style pair, for the ecosystem tooling that only recognizes a normal AMM pair:
| Address | |
|---|---|
| Quainance V2 router | 0x000284FD8Df039CFF2949b62D854dc43c2Eae6E1 |
| Quainance V2 factory | 0x000993E799424EEB1f1d6AdAa0e68006f4C696Fe |
| WQUAI | 0x006C3e2AaAE5DB1bCd11A1a097cE572312EADdBB |
| QAXE/WQUAI pair | 0x005592Ec74fB9690b7361B834bf38dC03537356F |
How it was seeded
On 2026-09-23 the treasury seeded the pair with 200,000 QAXE + 608.43 QUAI, matching the internal pool's price at that moment to the wei (rounded up by 1 wei so the new pair never opens cheaper than the internal pool — nothing is handed to an immediate arbitrage at creation).
- The seed amount is computed as
quaiAmt = ceil(qaxeAmt * poolQuaiReserve / poolTokenReserve)against the curve's live reserves at seed time. - LP tokens went to the treasury (
addLiquidityETH(..., to: treasury, ...)) — reversible, not burned. MINIMUM_LIQUIDITYis the standard Uniswap-V2 constant,1000, permanently locked in the pair as with any V2 pool — verified live:pair.MINIMUM_LIQUIDITY() == 1000.- The seeding script refuses outright if a QAXE/WQUAI pair already exists with nonzero
totalSupply()(use the add-liquidity path instead of re-seeding), and refuses if sending the seed would breach a 250 QUAI treasury reserve floor.
Verified live (2026-09-23): reserves 608.434495 QUAI / 200,000 QAXE, LP total supply
11,031.124278.
How to trade it
import { quais } from 'quais';
const ROUTER = quais.getAddress('0x000284fd8df039cff2949b62d854dc43c2eae6e1');
const WQUAI = quais.getAddress('0x006c3e2aaae5db1bcd11a1a097ce572312eaddbb');
const QAXE = quais.getAddress('0x0035187a7660f595d93cd53a4d16c635d6cffc8f');
const routerAbi = [
'function getAmountsOut(uint256 amountIn, address[] path) view returns (uint256[] amounts)',
'function swapExactETHForTokens(uint256 amountOutMin, address[] path, address to, uint256 deadline) payable returns (uint256[] amounts)',
'function swapExactTokensForETH(uint256 amountIn, uint256 amountOutMin, address[] path, address to, uint256 deadline) returns (uint256[] amounts)',
];
const router = new quais.Contract(ROUTER, routerAbi, provider);
// Quote buying QAXE with 1 QUAI:
const [, tokensOut] = await router.getAmountsOut(quais.parseQuai('1'), [WQUAI, QAXE]);
// Buy — path [WQUAI, QAXE], value in native QUAI:
const routerWrite = router.connect(wallet);
const deadline = BigInt(Math.floor(Date.now() / 1000) + 1200);
const minOut = (tokensOut * 99n) / 100n;
await (await routerWrite.swapExactETHForTokens(minOut, [WQUAI, QAXE], await wallet.getAddress(), deadline,
{ value: quais.parseQuai('1') })).wait();
// Sell — QAXE must be approved to the ROUTER first, not the pair:
const qaxe = new quais.Contract(QAXE, ['function approve(address, uint256) returns (bool)'], wallet);
await (await qaxe.approve(ROUTER, tokensToSell)).wait();
const [, quaiOut] = await router.getAmountsOut(tokensToSell, [QAXE, WQUAI]);
await (await routerWrite.swapExactTokensForETH(tokensToSell, (quaiOut * 99n) / 100n, [QAXE, WQUAI],
await wallet.getAddress(), deadline)).wait();Fee formula, verified to the wei
The pair charges the standard Uniswap-V2 0.3% swap fee. Verified live by recomputing the constant-product formula independently and comparing against a simulated swap:
amountInWithFee = amountIn * 997
amountOut = amountInWithFee * reserveOut / (reserveIn * 1000 + amountInWithFee)For a 1 QUAI buy against the live reserves above, both the recomputed formula and a
swapExactETHForTokens.staticCall returned exactly 327.190179 QAXE — confirmed equal to the
wei.
Price parity and arbitrage
The two venues are checked to agree within 1% by recomputing each venue's own price independently
(reserveQuai/reserveQaxe for the pair, poolQuaiReserve/poolTokenReserve for the curve).
Measured live (2026-09-23): pair 3.042172e-3 vs. curve 3.042143e-3 QUAI/QAXE — a 0.0010%
difference, well inside tolerance. Nothing enforces this on-chain; it holds because arbitrage
between the two venues is unrestricted (anyone can buy cheap on one and sell on the other) and the
pair was seeded at the curve's exact price, so there was nothing to arbitrage away at creation.
A full round trip was also verified on-chain: buying QAXE with treasury QUAI on the V2 pair and
immediately selling everything received back, confirming transfers, the approve step, and both
swap paths (swapExactETHForTokens then swapExactTokensForETH) all execute correctly end to end.
Adding liquidity
Anyone can add to the pair through the standard router call, no special permission required:
const routerAbi2 = [
'function addLiquidityETH(address token, uint256 amountTokenDesired, uint256 amountTokenMin, uint256 amountETHMin, address to, uint256 deadline) payable returns (uint256 amountToken, uint256 amountETH, uint256 liquidity)',
];Quote your token amount against the pair's live reserves first (getReserves()) so you don't
donate value to the pool by adding at the wrong ratio — the router's own minimums
(amountTokenMin/amountETHMin) protect you from a reserve move between your quote and your send,
not from a bad ratio you chose yourself.