CORE DEFI PRIMITIVES AND MECHANICS

Creating DeFi Protocols With AMMs and Protocol Owned Liquidity Innovations

8 min read
#DeFi #Liquidity #Smart Contract #Yield Farming #AMM
Creating DeFi Protocols With AMMs and Protocol Owned Liquidity Innovations

Introduction

Decentralized finance (DeFi) has moved beyond the simple exchange of tokens to a rich ecosystem where liquidity is created algorithmically and protocols own portions of that liquidity themselves. At the heart of this ecosystem lie Automated Market Makers (AMMs) and the newer Protocol Owned Liquidity (POL) models. Understanding how to construct a robust AMM—see our blueprint of AMM liquidity pools and POL strategies—and then how to layer POL on top of it is essential for any developer or architect looking to build the next wave of DeFi protocols.

This article walks through the fundamentals of AMMs, explains how to design and implement them, then dives into POL innovations, showing how protocols can own liquidity, create incentive structures, and integrate governance. By the end, you will have a clear blueprint for building a DeFi protocol that leverages both AMM mechanics and POL efficiency.


Core DeFi Primitives

Before building an AMM, it is useful to revisit the core primitives that underpin DeFi:

  • Token Standards (ERC‑20, ERC‑721, etc.) provide composable assets.
  • Smart Contracts host logic on-chain, enforce rules, and provide auditability.
  • Oracles supply off‑chain data (price feeds, time stamps) to on‑chain contracts.
  • Governance Tokens, as discussed in our post on core DeFi foundations, allow stakeholders to steer protocol upgrades and parameter changes.

An AMM sits on top of these primitives, orchestrating swaps, liquidity provision, and price discovery. POL adds another layer of governance‑driven liquidity ownership.


Designing an Automated Market Maker

1. The Constant‑Product Formula

The most famous AMM, Uniswap, uses the constant‑product invariant:

x · y = k

where x and y are the reserves of two tokens, and k is a constant. Swaps adjust reserves to keep k unchanged, delivering an implicit price. Learn more about this invariant in our deep dive into AMM mechanics and their impact on DeFi.

2. Alternative Pricing Curves

Other AMMs employ different invariants to achieve distinct properties:

Curve Formula Typical Use‑case
Constant‑Product x · y = k General liquidity
Constant‑Sum x + y = k Stablecoins
Weighted Product x^a · y^b = k Impermanent‑loss mitigation
Curve’s StableSwap Polynomial invariant Stablecoin pegs

Choosing a curve depends on target assets, expected volatility, and desired user experience.

3. Liquidity Provision

Liquidity providers (LPs) deposit token pairs into the pool. In return, they receive pool tokens (LP tokens) representing their share of the pool. LP tokens can be redeemed for the underlying assets plus a portion of the collected fees.

Key parameters:

  • Initial Reserves: The first liquidity added sets the pool’s initial price.
  • Fee Structure: Typically a 0.3 % fee split among LPs; higher fees can attract more LPs but may discourage trades.
  • Token Weighting: In weighted pools, each token’s reserve is raised to a power; this influences how much of each token is needed for a trade.

4. Swap Execution Flow

  1. User submits a swap request (token A for token B).
  2. Contract calculates the new reserves using the chosen invariant.
  3. Fees are deducted and added to the pool.
  4. The difference between the pre‑swap and post‑swap reserves determines the output amount.
  5. The user receives token B, and the pool updates its state.

Below is a simplified pseudocode for a constant‑product swap:

function swap(uint256 amountIn, address tokenIn, address tokenOut) external {
    uint256 amountOut = getAmountOut(amountIn, tokenIn, tokenOut);
    _transfer(tokenIn, address(this), amountIn);
    _transfer(address(this), msg.sender, amountOut);
    emit Swap(msg.sender, tokenIn, tokenOut, amountIn, amountOut);
}

5. Impermanent Loss and Mitigation

Impermanent loss occurs when the relative price of the deposited tokens diverges from the price at which they were deposited. The loss is “impermanent” because if the price reverts, the loss disappears. However, LPs incur fees that can offset this loss. Mitigation strategies include:

  • Higher Fees: Capture more value per trade.
  • Stablecoin Pairs: Lower volatility reduces loss.
  • Weighted Pools: Adjust the exponent to reduce exposure to price swings.
  • Liquidity Incentives: Token rewards (e.g., governance tokens) can compensate for loss. For more on impermanent loss, see our post on why AMMs matter.

6. Front‑Running & Sandwich Attacks

Front‑running occurs when a malicious actor observes a pending transaction and inserts a transaction before it to exploit price slippage. Sandwich attacks involve placing a transaction before and after the victim’s to profit from the temporary price shift.

Countermeasures:

  • Time‑Weighted Average Price (TWAP) oracles to smooth price data.
  • Commit‑Reveal Schemes: Users commit to swap amounts, revealing only after a delay.
  • Minimum Trade Size: Discourage small, easily front‑run trades.

7. Oracle Integration

Oracles provide external price data to guard against manipulation. Common approaches:

  • Median Price Feeds: Combine multiple sources to find a consensus price.
  • Chainlink Aggregator: Decentralized price feeds with reputation systems.
  • Reputation‑Based Oracle Networks: Stakeholders provide price data and are penalized for misreporting.

Implementing an oracle contract is straightforward:

interface IOracle {
    function latestAnswer() external view returns (int256);
}

The AMM can query IOracle to fetch the latest external price before computing slippage.


Building the AMM Smart Contract

1. Define the Interface

interface IUniswapV2Pair {
    function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
    function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
    function mint(address to) external returns (uint liquidity);
    function burn(address to) external returns (uint amount0, uint amount1);
}

2. Constructor and State Variables

contract MyAMM {
    IERC20 public immutable token0;
    IERC20 public immutable token1;
    uint256 public fee; // e.g., 300 for 0.3%
    uint112 private reserve0;
    uint112 private reserve1;

    mapping(address => uint256) public lpBalances;
    uint256 public totalSupply; // LP token supply

    constructor(address _token0, address _token1, uint256 _fee) {
        token0 = IERC20(_token0);
        token1 = IERC20(_token1);
        fee = _fee;
    }
}

3. Reserves Synchronization

function _updateReserves(uint256 balance0, uint256 balance1) internal {
    reserve0 = uint112(balance0);
    reserve1 = uint112(balance1);
}

4. Adding Liquidity

function addLiquidity(uint256 amount0, uint256 amount1) external returns (uint256 liquidity) {
    token0.transferFrom(msg.sender, address(this), amount0);
    token1.transferFrom(msg.sender, address(this), amount1);

    uint256 balance0 = token0.balanceOf(address(this));
    uint256 balance1 = token1.balanceOf(address(this));

    _updateReserves(balance0, balance1);

    if (totalSupply == 0) {
        liquidity = sqrt(amount0 * amount1) - MINIMUM_LIQUIDITY;
        lpBalances[address(0)] = MINIMUM_LIQUIDITY; // lock minimum liquidity
    } else {
        liquidity = min((amount0 * totalSupply) / reserve0, (amount1 * totalSupply) / reserve1);
    }
    require(liquidity > 0, "INSUFFICIENT_LIQUIDITY");

    totalSupply += liquidity;
    lpBalances[msg.sender] += liquidity;
    emit Mint(msg.sender, amount0, amount1);
}

5. Removing Liquidity

function removeLiquidity(uint256 liquidity) external returns (uint256 amount0, uint256 amount1) {
    require(lpBalances[msg.sender] >= liquidity, "INSUFFICIENT_LP");

    amount0 = (liquidity * reserve0) / totalSupply;
    amount1 = (liquidity * reserve1) / totalSupply;

    lpBalances[msg.sender] -= liquidity;
    totalSupply -= liquidity;

    token0.transfer(msg.sender, amount0);
    token1.transfer(msg.sender, amount1);

    uint256 balance0 = token0.balanceOf(address(this));
    uint256 balance1 = token1.balanceOf(address(this));
    _updateReserves(balance0, balance1);

    emit Burn(msg.sender, amount0, amount1);
}

6. Swapping Tokens

function swap(uint256 amountIn, address tokenIn, address to) external returns (uint256 amountOut) {
    require(tokenIn == address(token0) || tokenIn == address(token1), "INVALID_TOKEN");
    bool zeroForOne = tokenIn == address(token0);

    IERC20 inputToken = zeroForOne ? token0 : token1;
    IERC20 outputToken = zeroForOne ? token1 : token0;

    inputToken.transferFrom(msg.sender, address(this), amountIn);
    uint256 balanceIn = inputToken.balanceOf(address(this));
    uint256 balanceOut = outputToken.balanceOf(address(this));

    uint256 amountInWithFee = (amountIn * (1e4 - fee)) / 1e4;
    amountOut = (amountInWithFee * balanceOut) / (balanceIn + amountInWithFee);

    outputToken.transfer(to, amountOut);
    _updateReserves(
        zeroForOne ? balanceIn : balanceOut,
        zeroForOne ? balanceOut : balanceIn
    );

    emit Swap(msg.sender, tokenIn, address(outputToken), amountIn, amountOut);
}

7. Security Checks

  • Reentrancy Guard: Use nonReentrant modifier from OpenZeppelin.
  • Input Validation: Ensure amountIn > 0, output > 0.
  • Slippage: Allow users to specify max slippage tolerance; revert if exceeded.
  • Event Emission: Mint, Burn, Swap events for off‑chain monitoring.

Protocol Owned Liquidity

POL Concept

POL flips the traditional AMM model: instead of individual LPs supplying liquidity, the protocol itself supplies a portion of the pool. POL flips the traditional AMM model, as we explore in our post on beyond liquidity pools, understanding POL models. By shifting liquidity ownership to the treasury, protocols can stabilize pools and reduce reliance on external capital.

POL Models

POL models can be categorized into:

  • Static Allocation: Fixed percentage of reserves added from the treasury.
  • Dynamic Allocation: Adjusted by on‑chain risk metrics or governance decisions.
  • Hybrid Models: Combine user‑provided LPs with treasury reserves to balance incentives.

POL Percentages

The [POL percent](/post/beyond-liquidity-pools-understanding-pol-models-in-defi) determines how much of the pool is owned by the protocol at any given time.


Building a POL‑Enabled AMM

Treasury Contract

contract Treasury {
    function add(uint256 amount) external { /* ... */ }
    function transferFrom(address from, address to, uint256 amount) external { /* ... */ }
}

Call _adjustReserves() in swap, mint, and burn functions to keep pool balanced.

Treasury Contribution

function _adjustReserves() internal {
    // Example: 5% of reserves for each token
    uint256 token0Contribution = (reserve0 * POL_PERCENT) / 10000;
    uint256 token1Contribution = (reserve1 * POL_PERCENT) / 10000;

    treasury.transferFrom(address(this), token0, token0Contribution);
    treasury.transferFrom(address(this), token1, token1Contribution);

    _updateReserves(reserve0 + token0Contribution, reserve1 + token1Contribution);
}

Fee Allocation

function _collectFee(uint256 amount) internal returns (uint256 protocolFee) {
    protocolFee = (amount * PROTOCOL_FEE) / 1e4;
    treasury.add(protocolFee);
    return amount - protocolFee;
}

Governance Functions

function setPolicy(address _policy) external onlyOwner {
    policy = _policy;
}

function updatePOLPercent(uint256 newPercent) external onlyGovernance {
    require(newPercent <= MAX_POL_PERCENT, "EXCEEDS_LIMIT");
    POL_PERCENT = newPercent;
}

Building a complete POL‑enabled AMM is covered in detail in our post on building DeFi protocols with AMMs and protocol‑owned liquidity.


Best Practices for AMM & POL Development

  1. Unit and Integration Tests: Cover edge cases such as zero liquidity, large swaps, and reentrancy.
  2. Formal Verification: Especially for treasury logic where funds are at risk.
  3. Gas Optimization: Use packed storage and unchecked blocks where safe.
  4. Event Logging: Emit comprehensive events for off‑chain monitoring and analytics.
  5. User Experience: Provide clear slippage calculators and risk disclosures.
  6. Audit Trail: Keep on‑chain history of governance proposals and parameter changes.
  7. Security Audits: Hire third‑party auditors for the treasury and liquidity logic.

Future Outlook

  • Composable Liquidity: AMMs and POL will increasingly interoperate with derivatives, options, and cross‑chain bridges.
  • Dynamic Risk Management: On‑chain risk scores and automated liquidity adjustments could become standard.
  • Hybrid Incentive Models: Combining liquidity mining, staking, and governance yields complex reward structures that will drive user engagement.
  • Governance Evolution: Quadratic voting and reputation‑based systems may reduce the influence of large holders on liquidity decisions.

Conclusion

Building a DeFi protocol that marries AMM mechanics with Protocol Owned Liquidity requires a deep understanding of liquidity provisioning, price discovery, risk management, and governance. By carefully selecting the pricing curve, structuring liquidity incentives, integrating robust oracles, and designing a treasury that can adapt to market conditions, developers can create protocols that are both efficient and secure.

The evolving landscape of DeFi will continue to push for more sophisticated liquidity models. Protocols that can dynamically balance user‑provided liquidity with treasury‑owned reserves, while aligning incentives through transparent governance, will likely lead the next wave of DeFi innovation.

Emma Varela
Written by

Emma Varela

Emma is a financial engineer and blockchain researcher specializing in decentralized market models. With years of experience in DeFi protocol design, she writes about token economics, governance systems, and the evolving dynamics of on-chain liquidity.

Discussion (6)

LU
Lucia 8 months ago
Marco I gotta ask, how do these models scale with real world usage? The example curves look good, but I'm concerned about gas costs on mainnet. Also, what's your take on cross‑chain liquidity? The article touched but didn't go deep.
MA
Max 8 months ago
If I'm honest, the model described is basically a remix of Uniswap v3 + automated liquidity pools. The real innovation? Custom oracles for pricing. They don't fully discuss market depth. Also, the author keeps using the term "reserves" in a blurry way. I'd have added a clearer taxonomy of reserve types.
MA
Marco 8 months ago
Max, yeah but their fee model is missing slippage curves in a volatile environment.
IV
Ivan 8 months ago
Read through, and honestly I think the paper overstates the benefits. Pool ownership can lead to governance centralization. Also, they ignore the risk of impermanent loss in high volatility. I'm skeptical that this won't just end up like another failed launch.
EL
Elena 8 months ago
Agree with Ivan, but remember that protocol‑owned liquidity can be rebalanced automatically. It reduces human intervention which is huge advantage. Impermanent loss is still an issue but the math changes with dynamic fee tiers.
MA
Marco 8 months ago
Great breakdown on POL mechanisms. The way the article describes slippage adjustments in multi‑reserve AMMs makes a lot of sense. I'm thinking of trying this in my own protocol.
GA
Gaius 8 months ago
As a humble scholar of ancient markets, I find your reference to AMMs akin to the Roman forum's constant exchange dynamics. The concept of a protocol owning liquidity reminds me of state‑run grain reserves. But the application here is a bit … foreign. I'm curious about its failure points.
AU
Aurelia 7 months ago
Well Gaius, the point isn't to replicate a grain reserve. It's to ensure the protocol has a buffer against liquidity shocks. Think of it as a state‑sponsored bank deposit. The ancient analogue is far from perfect but interesting.
SO
Sophia 8 months ago
Yo, kinda hard to follow those math parts. If you want to use it, just set the constant product thing, y = fxy and let the smart contract handle it. No need to be a math nerd. Also the idea of Protocol Owned Liquidity sounds like someone trying to own the game.
MI
Milo 8 months ago
Sophia, for a real dev you gotta understand that POL isn't just about owning, it's about optimizing for slippage and pool health. If you deploy a damn good pool, you still need to know how fees and AMM math interact.

Join the Discussion

Contents

Sophia Yo, kinda hard to follow those math parts. If you want to use it, just set the constant product thing, y = fxy and let t... on Creating DeFi Protocols With AMMs and Pr... Feb 21, 2025 |
Gaius As a humble scholar of ancient markets, I find your reference to AMMs akin to the Roman forum's constant exchange dynami... on Creating DeFi Protocols With AMMs and Pr... Feb 20, 2025 |
Marco Great breakdown on POL mechanisms. The way the article describes slippage adjustments in multi‑reserve AMMs makes a lot... on Creating DeFi Protocols With AMMs and Pr... Feb 18, 2025 |
Ivan Read through, and honestly I think the paper overstates the benefits. Pool ownership can lead to governance centralizati... on Creating DeFi Protocols With AMMs and Pr... Feb 13, 2025 |
Max If I'm honest, the model described is basically a remix of Uniswap v3 + automated liquidity pools. The real innovation?... on Creating DeFi Protocols With AMMs and Pr... Feb 05, 2025 |
Lucia Marco I gotta ask, how do these models scale with real world usage? The example curves look good, but I'm concerned abou... on Creating DeFi Protocols With AMMs and Pr... Jan 31, 2025 |
Sophia Yo, kinda hard to follow those math parts. If you want to use it, just set the constant product thing, y = fxy and let t... on Creating DeFi Protocols With AMMs and Pr... Feb 21, 2025 |
Gaius As a humble scholar of ancient markets, I find your reference to AMMs akin to the Roman forum's constant exchange dynami... on Creating DeFi Protocols With AMMs and Pr... Feb 20, 2025 |
Marco Great breakdown on POL mechanisms. The way the article describes slippage adjustments in multi‑reserve AMMs makes a lot... on Creating DeFi Protocols With AMMs and Pr... Feb 18, 2025 |
Ivan Read through, and honestly I think the paper overstates the benefits. Pool ownership can lead to governance centralizati... on Creating DeFi Protocols With AMMs and Pr... Feb 13, 2025 |
Max If I'm honest, the model described is basically a remix of Uniswap v3 + automated liquidity pools. The real innovation?... on Creating DeFi Protocols With AMMs and Pr... Feb 05, 2025 |
Lucia Marco I gotta ask, how do these models scale with real world usage? The example curves look good, but I'm concerned abou... on Creating DeFi Protocols With AMMs and Pr... Jan 31, 2025 |