Every pool maintains the invariant x·y = k, where x and y are the two reserves. A swap moves along that curve: putting one asset in pushes its reserve up, which pulls the other down, and the price you receive is the ratio between what entered and what left.
Output for a given input, after the swap fee, is computed as:
amountInWithFee = amountIn × (10000 − feeBps) numerator = amountInWithFee × reserveOut denominator = (reserveIn × 10000) + amountInWithFee amountOut = numerator / denominator
Worked example. With a reserve of 1,000,000 DNR against 50,000 USDC.e at a 0.30% fee, swapping 10,000 DNR yields:
amountInWithFee = 10,000 × 9,970 = 99,700,000 numerator = 99,700,000 × 50,000 = 4,985,000,000,000 denominator = 10,000,000,000 + 99,700,000 = 10,099,700,000 amountOut ≈ 493.58 USDC.e
Division always rounds down. The direction is deliberate: any fraction of a unit that cannot be paid out stays in the pool and accrues to liquidity providers. Rounding the other way would let a trader extract a sub-unit of value on every swap — negligible once, unbounded when repeated.