Skip to content

A basic Constant Product Automated Market Maker, a Uniswap V2 Price Oracle and some math related to CPAMM

Notifications You must be signed in to change notification settings

Aboudoc/Constant-Product-AMM

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

38 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Contributors Forks Stargazers Issues MIT License LinkedIn


Logo

Constant Product Automated Market Maker

A basic Constant Product AMM
Explore the docs »

View Demo · Report Bug · Request Feature

Table of Contents
  1. About The Project
  2. Getting Started
  3. Usage
  4. Constant Product AMM
  5. Time Weighted Average Price
  6. Uniswap V2 Price Oracle
  7. Constant Product AMM Spot Price Examples
  8. Uniswap V3 Price Oracle
  9. Geometric Mean
  10. Uniswap V3 TWAP and Geometric Mean
  11. Uniswap V3 TWAP Inverse Price
  12. Roadmap
  13. Contributing
  14. License
  15. Contact
  16. Acknowledgments

About The Project

This project shows a basic Constant Product Automated Market Maker.

You will also find all the Maths used in Uniswap V2 and Uniswap V3

(back to top)

Built With

  • Hardhat
  • Ethers

(back to top)

Getting Started

To get a local copy up and running follow these simple example steps.

Prerequisites

  • npm

    npm install npm@latest -g
  • hardhat

    npm install --save-dev hardhat
    npm install @nomiclabs/hardhat-ethers @nomiclabs/hardhat-waffle

    run:

    npx hardhat

    verify:

    npx hardhat verify --network goerli "contract address" "pair address"

Installation

  1. Clone the repo

    git clone https://github.com/Aboudoc/Constant-Product-AMM.git
  2. Install NPM packages

    npm install
  3. Dependencies

    npm i @uniswap/v2-core @uniswap/v2-periphery

(back to top)

Usage

If you need testnet funds, use the Alchemy testnet faucet.

This project shows a basic example of Constant Product AMM

Constant Product AMM

Constant product AMM (automated market maker) is a decentralized exchange where 2 tokens are traded.

(back to top)

Why is it called constant product?

Maths

Swap - How many dy for dx?

Maths

Uniswap trading fee = 0.3%

Maths

Add liquidity - How many dx, dy to add?

Maths

Add liquidity - How many shares to mint?

Maths

Motivation:

Maths

What is L0 and L1

Maths

Simplify the equation:

Maths

Conclusion

Maths

Remove liquidity - How many tokens to withdraw?

Maths

Time Weighted Average Price

Maths

How do we compute the Time Weighted Average Price from Tk to Tn?

Maths

(back to top)

Uniswap V2 Price Oracle

We saw the math to calculate TWAP, you can also calculate it in Uniswap V2 using Solidity.

This is the purpose of UniswapV2Twap contract

In Uniswap V2, the numbers are represented in decimals, but Solidity does not have any decimal datatypes, so we'ell be using FixedPoint.sol library

The datatype FixedPoint.uq112x112 represents a decimal number as follows:

range: [0, 2e112 - 1] resolution: 1 / 2e112

The IUniswapV2Pair contract is the pair contract that holds the two tokens and does the swaps

Constructor

Since we're using Solidity 0.6, constructor must be declared as public

  1. We set the pair first
  2. We set token0 and token1 from pair
  3. We record price0CumulativeLast and price1CumulativeLast and the last time that these variables were updated: blockTimestampLast using getReserves(), it returns 3 outputs but we only need the third

Function update

  1. To get the current price0Cumulative, current price1Cumulative and blockTimestamp, we call currentCumulativePrices() on UniswapV2OracleLibrary by passing in the address of the pair

  2. Calculate how much time has elapsed since the last time we called update(). This time elapsed must be greather than the period defined as state variable

  3. Calculate the price averages (price0Average and price1Average) by taking the current price cumulative, substracting it from the last price cumulative, and dividing it over the time elapsed. Cast it into a FixedPoint => Note that up112x112 is a struct and the input for this struct must be a uint224 => cast the calcul expression

    The expression below, used to calculate the price averages, is the exact same equation that we derived from How do we compute the Time Weighted Average Price from Tk to Tn?

    price0Average = FixedPoint.uq112x112(
      uint224((price0Cumulative - price0CumulativeLast) / timeElapsed)
    );
    price1Average = FixedPoint.uq112x112(
      uint224((price1Cumulative - price1CumulativeLast) / timeElapsed)
    );

    Keep in mind that we don't care if the numbers overflows This is why we are not using SafeMath

  4. Finally, update the state variables: price0CumulativeLast, price1CumulativeLast and blockTimestampLast

Function consult

Giving the token and the amount of token put in, this function will calculate the amount out using the price0Average and price1Average

  1. The token must be token0 or token1
  2. Compute amountOutusing price0Average and amountIn argument (.mul). We have to put it back to uint using a function called decode144()

Additional Reading

You can find more in the following article Using the new Uniswap v2 as oracle

(back to top)

Constant Product AMM Spot Price

Maths

P = Y / X from geometry

Maths

P = Y / X from calculus

Maths

Constant Product AMM Spot Price Examples

Uniswap V2

Maths

Uniswap V3

Maths

Uniswap V3 Twap

Maths

However, virtual reserves are not tracked in Uni V3

The Tick that is used to compute the current price is tracked in Uni V3

Maths

Example

Maths

Pricing difference between Uni V2 and Uni V3

Maths

(back to top)

Uniswap V3 Price Oracle

Constructor

  1. Set token0 and token1
  2. get the pool by calling getPool() on, IUniswapV3Factory and set the state variable
  3. To call getPool() we need to pass in 3 parameters: address of the tokens, and the fee => set factory address and fee (uint24)
  4. Check that the pool is a valid pool (not address(0)) and finally set it (state variable)

Function estimateAmountOut

  1. Define tokenIn and tokenOut
  2. Get the average tick: Call consult() on OracleLibrary like so:
    (int24 tick, ) = OracleLibrary.consult(pool, secondsAgo);

We'll copy paste the code to compute tick directly from the library to save some gas

  1. Call GetQuoteAtTick() on OracleLibrary to set the amountOut

Forking mainnet

hardhat.config.js

  networks: {
        hardhat: {
          forking: {
            url: `https://eth-mainnet.alchemyapi.io/v2/${process.env.ALCHEMY_API_KEY}`,
       },
     },
  }

.env

ALCHEMY_API_KEY=...

terminal1

ALCHEMY_API_KEY=...
npx hardhat node --fork https://eth-mainnet.g.alchemy.com/v2/$ALCHEMY_API_KEY

terminal2

npx hardhat test --network localhost

(back to top)

Geometric Mean

Maths

Example

Maths

Comapraison With Arithmetic Mean

Maths

(back to top)

Uniswap V3 TWAP and Geometric Mean

Maths
Maths
Maths

(back to top)

Uniswap V3 TWAP Inverse Price

Maths

Not in Uniswap V2

Maths

(back to top)

Note

This contract assumes that token0 and token1 both have same decimals

Consider fees = 0.3%

Further reading

(...soon)

Sources

(back to top)

Roadmap

  • Uniswap V3 TWAP
  • Further reading
  • Deploy script
  • Unit test

See the open issues for a full list of proposed features (and known issues).

(back to top)

Contributing

Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.

If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again!

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Commit your Changes (git commit -m 'Add some AmazingFeature')
  4. Push to the Branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

(back to top)

License

Distributed under the MIT License. See LICENSE.txt for more information.

(back to top)

Contact

Reda Aboutika - @twitter - [email protected]

Project Link: https://github.com/Aboudoc/Constant-Product-AMM.git

(back to top)

Acknowledgments

(back to top)


About

A basic Constant Product Automated Market Maker, a Uniswap V2 Price Oracle and some math related to CPAMM

Topics

Resources

Stars

Watchers

Forks

Packages

No packages published