╔══════════════════════════════════════════════╗ ║ HOW Z A M M WORKS ║ ╚══════════════════════════════════════════════╝
ERC-20 → one-token-per-address • transfer ≈ 50k gas ERC-1155 → batch/gaming focus • high calldata overhead ERC-6909 → multi-token, minimal ABI, operator approvals
ERC-6909 provides a multi-asset interface with operator approvals and efficient transfers. ZAMM uses it for user coins, LP shares, and transient credits in a single contract without auxiliary deployments.
struct PoolKey { uint256 id0; // 0 for ETH, non-zero for ERC-6909 IDs uint256 id1; address token0; // 0x0 for ETH, contract address otherwise address token1; uint256 feeOrHook; // 0-10,000 bp OR packed hook flags + address } poolId = keccak256(abi.encode(PoolKey))
Token ordering rules ensure canonical pool IDs: addresses in ascending order, or for same ERC-6909 contract, IDs in ascending order with both non-zero.
k = reserve0 × reserve1
amountInWithFee = amountIn × (10,000 − feeBp) amountOut = (amountInWithFee × reserveOut) ──────────────────────────────── (reserveIn × 10,000 + amountInWithFee)
Hooks can modify fee rates at runtime via beforeAction
return value. The base curve is constant-product unless hooks modify reserves directly.
0-10,000 → static fee in basis points > 10,000 → bit 255: BEFORE flag | bit 254: AFTER flag | bits 159-0: hook address
Hook interface provides two callbacks:
beforeAction(bytes4 sig, uint256 poolId, address sender, bytes data)
→ returns new fee (optional)
afterAction(bytes4 sig, uint256 poolId, address sender, int256 d0, int256 d1, int256 dLiq, bytes data)
If neither flag is set, defaults to after-only hook.
First LP | Sets initial price, burns 1,000 minimum liquidity tokens, mints remainder to provider. |
Subsequent LPs |
Proportional deposit calculated via mulDiv , LP tokens minted proportionally.
|
Protocol fee | 1⁄6 of √k growth minted to feeTo address when enabled. |
Remove | Burn LP tokens, transfer proportional share of reserves, update kLast . |
coin(creator, supply, uri)
returns a fresh ERC-6909 ID and mints initial supply to creator.
Much more gas-efficient than deploying separate ERC-20 contracts.
maker → makeOrder() • escrows ETH if selling ETH, supports partial fills taker → fillOrder() • fills order slice or remainder, transfers assets maker → cancelOrder() • cancels order, refunds any escrowed ETH
Orders support any asset type recognized by ZAMM (ETH, ERC-20, ERC-6909). Partial fills allow gradual order execution.
lockup()
stores hash-keyed unlock time; unlock()
verifies timestamp and transfers assets.
tstore
, enabling flash-like patterns and multi-hop swaps.
Re-entrancy guard | Assembly-based mutex using transient storage. |
Swap (ETH→coin) | Single _safeTransfer call for output. |
Swap (ERC-20→ERC-20) | One transferFrom + one transfer . |
Native ZAMM coins | Most efficient—only _mint /_burn calls, no external transfers. |
Add liquidity | Higher cost for first LP (price setting), lower for subsequent. |
1. Deploy ZAMM contract 2. Create coins via coin() if needed 3. Add liquidity via addLiquidity() 4. Deploy hook contracts if using dynamic behavior 5. Trade via swap functions or orderbook
ZAMM combines AMM functionality, coin creation, OTC trading, and asset locking into a single auditable contract. The ERC-6909 foundation enables efficient multi-asset operations without auxiliary contracts.