Logo

dev-resources.site

for different kinds of informations.

Constant Product Market Maker (CAMM): The standard in Decentralized Finance

Published at
1/11/2023
Categories
web3
blockchain
beginners
vyper
Author
rabuawad
Categories
4 categories in total
web3
open
blockchain
open
beginners
open
vyper
open
Author
8 person written this
rabuawad
open
Constant Product Market Maker (CAMM): The standard in Decentralized Finance

Decentralized finance (DeFi) has been gaining a lot of momentum in recent years, and Automated Market Maker (AMM) has been a key technology driving this trend. AMMs are decentralized exchanges (DEXs) that allow users to trade cryptocurrencies without the need for an intermediary. However, a breed of AMM called Constant Product Market Maker (CPMM) is the dominant implementation DeFi space.

How CPMMs are useful

CPMMs are useful for several reasons:

  • Efficient liquidity provision: CPMMs are designed to provide liquidity more efficiently than traditional AMMs. They do this by using a constant product formula which ensures that the liquidity pool is always in a balanced state, no matter how much the prices fluctuate. This results in lower slippage for users and more predictable pricing for traders.
  • Lower impermanent loss: Traditional AMMs can have a problem called impermanent loss (IL) where liquidity providers can experience a loss if the price of the asset changes. CPMMs, on the other hand, have a lower IL, as the constant product formula helps to minimize the impact of price fluctuations on liquidity providers.
  • Better token price stability: CPMMs are better suited for stablecoin markets as they are less sensitive to price fluctuations, ensuring a more stable token price.

A Code Sample

Here is an example of a simple CPMM smart contract, written in the Vyper programming language:

# @version >=0.3.3
from vyper.interfaces import ERC20

token0: public(address)
token1: public(address)

reserve0: public(uint256)
reserve1: public(uint256)

totalSupply: public(uint256)
balanceOf: HashMap[address, uint256]


@external
def __init__(_token0: address, _token1: address):
    self.token0 = _token0
    self.token1 = _token1


@internal
def _mint(_to: address, _amount: uint256):
    self.balanceOf[_to] += _amount
    self.totalSupply += _amount


@internal
def _burn(_from: address, _amount: uint256):
    self.balanceOf[_from] -= _amount
    self.totalSupply -= _amount


@internal
def _update(_reserve0: uint256, _reserve1: uint256):
    self.reserve0 = _reserve0
    self.reserve1 = _reserve1


@external
def swap(_tokenIn: address, _amountIn: uint256) -> uint256:
    assert _tokenIn == self.token0 or _tokenIn == self.token1, "invalid token" 
    assert _amountIn > 0, "amount in is zero"

    tokenIn: ERC20 = empty(ERC20)
    tokenOut: ERC20 = empty(ERC20)
    reserveIn: uint256 = 0
    reserveOut: uint256 = 0

    if _tokenIn == self.token0:
        tokenIn = ERC20(self.token0)
        tokenOut = ERC20(self.token1)
        reserveIn = self.reserve0
        reserveOut = self.reserve1
    else:
        tokenIn = ERC20(self.token1)
        tokenOut = ERC20(self.token0)
        reserveIn = self.reserve1
        reserveOut = self.reserve0

    tokenIn.transferFrom(msg.sender, self, _amountIn)

    amountInWithFee: uint256 = (_amountIn * 997) / 1000
    amountOut: uint256 = (reserveOut * amountInWithFee) / (reserveIn + amountInWithFee)

    tokenOut.transfer(msg.sender, amountOut)
    self._update(ERC20(self.token0).balanceOf(self), ERC20(self.token1).balanceOf(self))

    return amountOut


@external
def addLiquidity(_amount0: uint256, _amount1: uint256) -> uint256:
    ERC20(self.token0).transferFrom(msg.sender, self, _amount0)
    ERC20(self.token1).transferFrom(msg.sender, self, _amount1)

    if self.reserve0 > 0 or self.reserve1 > 0:
        assert self.reserve0 * _amount1 == self.reserve1 * _amount0, "x / y != dx / dy"

    shares: uint256 = 0
    if self.totalSupply == 0:
        shares = isqrt(_amount0 * _amount1)
    else:
        shares = min(
            (_amount0 * self.totalSupply) / self.reserve0,
            (_amount0 * self.totalSupply) / self.reserve0,
        )

    assert shares > 0, "shares are zero"
    self._mint(msg.sender, shares)

    return shares


@external
def removeLiquidity(_shares: uint256) -> (uint256, uint256):
    bal0: uint256 = ERC20(self.token0).balanceOf(self)
    bal1: uint256 = ERC20(self.token1).balanceOf(self)

    amount0: uint256 = (_shares * bal0) / self.totalSupply
    amount1: uint256 = (_shares * bal1) / self.totalSupply
    assert amount0 > 0 and amount1 > 0, "amount0 or amount is zero"

    self._burn(msg.sender, _shares)
    self._update(bal0 - amount0, bal1 - amount1)

    ERC20(self.token0).transfer(msg.sender, amount0)
    ERC20(self.token1).transfer(msg.sender, amount1)

    return (amount0, amount1)

Enter fullscreen mode Exit fullscreen mode

This example is quite basic, most real-world AMM smart contracts use more complex mechanisms to calculate prices and determine the amounts of assets that are exchanged in a trade.

In the code above the contract provide the functionality to deposit, withdraw and trade assets on a pool, the trading functionality uses the current state of the pool to determine the amounts of assets that are exchanged, you could use a different mechanism to price the assets like a constant product or a bonding curve.

Please keep in mind that, this is just a sample code, it should not be used in production as is, it lacks many important aspects such

vyper Article's
24 articles in total
Favicon
Vyper - Write your First Python Smart Contract (Series)
Favicon
vyper挺好玩的
Favicon
How to use 'initializes' and 'exports' in vyper: Modular Vyper code arrangement.
Favicon
A Simple Vyper smart contract to fetch the price of BTC using Chainlink and Apeworx.
Favicon
Vyper beginner's tutorial: Variables.
Favicon
Mastering Vyper Functions(part1 )
Favicon
How to compile, deploy and interact with smart contracts using Apeworx(ape) and VS Code.
Favicon
Vyper: For loops and Arrays.
Favicon
Mastering functions in Vyper(part2)
Favicon
Vyper Beginner's tutorial: Syntax and Structure.
Favicon
How to interact with Smart Contracts using Python and Django.
Favicon
How to Interact with Smart Contracts locally using web3.py
Favicon
Writing Smart Contracts using Vyper, Remix IDE and deploying them on BNB Smart Chain.
Favicon
Create your own Uniswap DeFi Application🦄! From scratch using Vyper & Python🐍
Favicon
Challenge #2: 🪙 Multi Token Vendor | Speedrun Ethereum With Vyper
Favicon
Introduction to EVM Smart Contract development
Favicon
Challenge #1: 🥩 Decentralized Staking App | Speedrun Ethereum With Vyper 🐍
Favicon
Challenge #0: 🖼️ Simple NFT Example | Speedrun Ethereum With Vyper 🐍
Favicon
Understanding Chainlink VRF: A Tool for Random Number Generation on the Blockchain
Favicon
Constant Product Market Maker (CAMM): The standard in Decentralized Finance
Favicon
Compiling and testing Vyper contract using Foundry
Favicon
Usando constant e immutable para reduzir o custo de gás
Favicon
ERC20 Token with Vyper and Brownie
Favicon
Try Vyper in Truffle v5.

Featured ones: