diff --git a/CODEOWNERS b/CODEOWNERS deleted file mode 100644 index ed399c4..0000000 --- a/CODEOWNERS +++ /dev/null @@ -1,2 +0,0 @@ -* @uniswap/developer-experience - diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a0774db..53fa9a0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -17,7 +17,7 @@ Thanks for giving a little extra love to our docs site! Below are some basic gui Set up your fork with the following terminal commands, or an alteration of them to suit your environment: ``` -cd uniswap-docs +cd ring-docs git remote add upstream https://github.com/RingProtocol/docs.git git fetch upstream git pull --rebase upstream main diff --git a/blog/gas-optimization.md b/blog/gas-optimization.md deleted file mode 100644 index 16bba18..0000000 --- a/blog/gas-optimization.md +++ /dev/null @@ -1,145 +0,0 @@ ---- -title: An Introduction to Gas Optimization -authors: - - name: Moody Salem - url: https://github.com/moodysalem - - name: Noah Zinsmeister - url: https://github.com/NoahZinsmeister - - name: Connor Martin - url: https://github.com/Yorkemartin -hide_table_of_contents: true -image: /use.png -slug: intro-to-gas-optimization ---- - -
-
-
-
-## Gas Optimization
-
-:::tip Get Started
-
-To help devs get their contracts into tip-top shape before deployment, we reconfigured our most used gas snapshot tool as a simple npm package: [The Uniswap Gas Snapshot Test](https://www.npmjs.com/package/@uniswap/snapshot-gas-cost)
-
-:::
-
-At Uniswap Labs, many of the smart contracts we’ve written have gone on to become the most frequently called smart contracts on the Ethereum blockchain.
-
-Tens of thousands of ETH are spent every month by users interacting with the Uniswap Protocol contracts. Multiples of that still are spent on the many protocol forks deployed across Ethereum and other environments.
-
-Due to the protocol’s significant use, and reuse in the form of forks, a change in the gas optimization of a piece of protocol code that saves 1% in gas translates to millions of dollars saved by the DeFi community over the lifetime of the contracts.
-
-As a result, it is difficult to overstate the significance of these optimizations. Considerable effort goes into this work, [which](https://github.com/RingProtocol/v3-core/commit/705be1eefc56a3620afe96a725c3a68951e8d4a9) [frequently](https://github.com/RingProtocol/v3-core/commit/7689aa8e2adecbcf94198f79cb4f230d0419d009) [continues](https://github.com/RingProtocol/v3-core/commit/225399176cf1fa562aa74345b7885e1244d95417) [right](https://github.com/RingProtocol/v3-core/commit/ebcdb5225a3cf4188f4752f59fe52e6b0071909d) [up](https://github.com/RingProtocol/v3-core/commit/49ce1c3a600e4c0e22e272b2144a3082663cb1ea) [to](https://github.com/RingProtocol/v3-core/commit/5b485192df944273882397d804d13c2e4ebb25da) [deployment](https://github.com/RingProtocol/v3-core/commit/723f90cbea93fc09ff06303bd4db03ce3b0847a1).
-
-While much of the discourse around gas optimization takes the form of specific implementation techniques, which can be quite fun to read and experiment with, we think a more helpful thing to write about is the development of a process in pursuit of gas optimization, rather than a collection of specific optimizations which may become dated as Ethereum progresses.
-
-## Measurement
-
-If there’s one lesson to learn from this post, it’s that all optimization starts with measurement. The single biggest tool in our arsenal of gas optimization is the [snapshot test](https://jestjs.io/docs/snapshot-testing) borrowed from Jest snapshot testing. For V3, we used a snippet in combination with the [mocha-chai-jest-snapshot](https://www.npmjs.com/package/mocha-chai-jest-snapshot) plugin to record gas costs in [hundreds of situations.](https://github.com/RingProtocol/v3-core/blob/ed88be38ab2032d82bf10ac6f8d03aa631889d48/test/__snapshots__/UniswapV3Pool.gas.spec.ts.snap)
-
-The code below, which we use in our development process, has been implemented in an NPM package for easy use in your project: [The Uniswap Gas Snapshot Test.](https://www.npmjs.com/package/@uniswap/snapshot-gas-cost)
-
-
-
-
-
----
-
-### Buy Limit Orders
-
-> The Current price of a DAI / ETH pool is 1,500 DAI / ETH. You expect that ETH will rebound after it drops to 1,000 at the next market downturn, so you would like to place a range order swapping DAI to ETH at the price of 1,000 DAI / ETH. This is possible, as the price space below the spot price is denominated in the lower-priced asset, DAI. You can provide DAI at the price of 1,000 DAI / ETH, which will be swapped for ETH when the spot price of ETH drops past 1,000 DAI / ETH.
-
-As the above examples show, in a concentrated-liquidity AMM, the two paired assets in a given pool are separated above and below the spot price, with the higher price asset available above the spot price and the lower-priced asset below.
-
-The following examples show limit order styles that are unable to be replicated due to the separation of assets in price space.
-
----
-
-### Buy Stop Orders
-
-> The current price of a DAI / ETH pool is 1,500 DAI / ETH. You expect the price of ETH to rocket up to 3,000 once it hits 2,000 DAI/ ETH, So you would like to place a range order from DAI to ETH at a price of 2,000 DAI/ETH. This is not possible as the price space above 1,500 DAI / ETH is denominated in ETH - and thus, you cannot provide the DAI necessary at your desired price to be swapped into ETH.
-
----
-
-### Stop-Loss Orders
-
-> The current price of a DAI / ETH pool is 1,500 DAI / ETH. You expect once the price of ETH drops to below 1,000, it will tank to 200. So you would like to place a range order from ETH to DAI at a price of 1,000. This is not possible as the price space below the spot price is denominated in DAI, and so you cannot allocate the ETH necessary at 1,000 to be swapped into DAI.
-
----
-
-## Fees
-
-The fees due to your liquidity position will be denominated in both tokens of the given pair. In any of the above examples, after swapping ETH for DAI, or DAI for ETH, a small amount of both ETH and DAI will be due to your account as liquidity provisioning rewards.
-
-Approaches to concentration when setting range orders are up to the user. Selecting a wider range may generate more fees if there is price churn within your range, at the cost of increasing the risk of having your order unfilled if the spot price reverses before completing your full range.
diff --git a/docs/concepts/uniswap-protocol.md b/docs/concepts/ring-protocol.md
similarity index 78%
rename from docs/concepts/uniswap-protocol.md
rename to docs/concepts/ring-protocol.md
index 92f63cd..fa0f773 100644
--- a/docs/concepts/uniswap-protocol.md
+++ b/docs/concepts/ring-protocol.md
@@ -1,5 +1,5 @@
---
-id: uniswap-protocol
+id: ring-protocol
title: The Ring Protocol
sidebar_position: 2
---
@@ -12,10 +12,10 @@ At a high level, Ring wraps original ERC-20 assets into `FewToken`, then uses th
Today, the most important parts of Ring are:
-- `Few Protocol`: the core wrapping layer
-- `Ring Swap (v2)`: Ring's native AMM built around `FewToken`
+- `Ring Swap (v2)`: Ring's native AMM product line built around `FewToken`
+- `Few Protocol`: the core wrapping layer that turns original ERC-20 assets into `FewToken`
- `Uniswap v4 integration`: `FewToken` can also be used in Uniswap v4 liquidity environments
-- products such as launch infrastructure, wallet, and future lending integrations that build on the same FEW model
+- Ring Wallet and selected integrations that build on the same FEW model
## How does Ring compare to a typical market?
@@ -37,13 +37,14 @@ The core idea is simple:
### What Ring is not
-Ring should not be understood as a full version-by-version clone of Uniswap.
+Ring should not be understood as a version-by-version AMM family.
In particular:
-- Ring currently operates `Ring Swap (v2)` as its native swap protocol
-- Ring does **not** currently operate a separate native `Ring v4` AMM
-- when Ring documentation refers to v4 in the current product stack, it should be understood as `FewToken` integration with `Uniswap v4`
+- `Ring Swap (v2)` is a top-level Ring product line.
+- Ring docs should not imply additional native AMM product lines.
+- When Ring documentation refers to v4 in the current product stack, it should be understood as `FewToken`
+ integration with `Uniswap v4`.
### Mission
diff --git a/docs/contracts/fewv2/_category_.json b/docs/contracts/fewv2/_category_.json
deleted file mode 100644
index 554b012..0000000
--- a/docs/contracts/fewv2/_category_.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "label": "Few Protocol",
- "position": 2.2,
- "collapsed": true
-}
diff --git a/docs/contracts/fewv2/overview.md b/docs/contracts/fewv2/overview.md
deleted file mode 100644
index d483a7a..0000000
--- a/docs/contracts/fewv2/overview.md
+++ /dev/null
@@ -1,46 +0,0 @@
----
-id: overview
-title: Few Protocol Overview
-sidebar_position: 1
----
-
-# Few Protocol
-
-`Few Protocol` is the core asset layer of Ring.
-
-It wraps original ERC-20 assets into `FewToken`, which are then used across Ring products and external integrations.
-
-## Why Few exists
-
-The purpose of `Few Protocol` is to expand usable liquidity and improve capital efficiency.
-
-In practice, Ring uses Few so that:
-
-- liquidity can be organized around wrapped assets
-- trading systems can work with `FewToken` instead of only original ERC-20 assets
-- Ring can compete more effectively in routing, quoting, and execution
-
-## Where Few is used today
-
-Today, `FewToken` is used in two main places:
-
-1. `Ring Swap (v2)`, which is Ring's native AMM and routing system
-2. `Uniswap v4` liquidity environments, where `FewToken` can also be deployed through integration flows
-
-## Important distinction
-
-Few is the core Ring mechanism.
-
-But Few should not be confused with a separate "Ring v4" protocol.
-
-- Ring's native swap protocol is `Ring Swap (v2)`
-- v4-related documentation in the current stack refers to `FewToken` integration with `Uniswap v4`
-
-## In this section
-
-This section covers:
-
-- how to integrate with Few-based token wrapping
-- how to resolve `FewToken` addresses
-- how to map `FewToken` back to underlying ERC-20 assets
-- deployment information for Few-related contracts
diff --git a/docs/contracts/liquidity-launchpad/01-introduction.md b/docs/contracts/liquidity-launchpad/01-introduction.md
deleted file mode 100644
index 0376272..0000000
--- a/docs/contracts/liquidity-launchpad/01-introduction.md
+++ /dev/null
@@ -1,107 +0,0 @@
----
-id: Overview
-title: Overview
-sidebar_position: 1
-unlisted: true
----
-
-# Introduction & Overview
-
-:::warning
-This section is not part of the current public Ring core launch surface.
-
-The Ring public product line currently centers on `FewToken` and `Ring Swap (v2)`. The liquidity launchpad materials are retained as advanced reference for a future or optional rollout and should not be read as a currently public, broadly supported product commitment.
-:::
-
-## What is the Ring Liquidity Launchpad?
-
-The Ring Liquidity Launchpad is a framework for bootstrapping initial liquidity through fair, transparent price discovery (see whitepaper). In the current Ring stack, the launchpad is designed to seed liquidity into `Uniswap v4` pools rather than into a separate native `Ring v4` AMM.
-
-It combines three critical functions into a single, composable system:
-
-1. **Price Discovery** - Run fair auctions using a novel Continuous Clearing Auction (CCA) mechanism to establish market price
-2. **Liquidity Bootstrapping** - Automatically seed Uniswap v4 pools with auction proceeds at the discovered price
-3. **Token Creation** (Optional) - Deploy new ERC-20 tokens with rich metadata and optional cross-chain capabilities
-
-Unlike traditional approaches that rely on centralized market makers or expose participants to timing games and manipulation, the Ring Liquidity Launchpad provides an open mechanism for boostrapping deep liquidity on decentralized exchanges.
-
-The system is composable - it is not limited to the intial set of implementation contracts. Other auction and LBPStrategy implementations are welcome!
-
-### Key Benefits
-
-- **Fair Price Discovery** - Continuous clearing auctions eliminate timing games and establish credible market prices
-- **Immediate Deep Liquidity** - Seamless transition from price discovery to active Uniswap v4 trading with substantial initial depth
-- **Permissionless** - Anyone can bootstrap liquidity or participate in price discovery without gatekeepers
-- **Transparent** - All parameters are immutable after they are set
-- **Composable** - Modular architecture supports multiple auction formats and distribution strategies
-- **Gas Efficient** - Optimized implementations using Permit2, multicall, and efficient data structures
-
-## Core Components
-
-The Ring Liquidity Launchpad framework is built on three coordinated components that work together to bootstrap liquidity:
-
-1. **[Liquidity Launcher →](https://github.com/Uniswap/liquidity-launcher)** Central orchestration contract that coordinates distribution and liquidity deployment
-2. **[Token Factory →](https://github.com/Uniswap/uerc20-factory)** (Optional) Creates new ERC-20 tokens with metadata, or integrates existing tokens
-3. **Liquidity Strategies** - Modular contracts for different price discovery and liquidity mechanisms (prebuilt [LBP Strategy](https://github.com/Uniswap/liquidity-launcher) or [custom strategies](./quickstart/example-configuration.md))
-
-Each component is designed to be composable and extensible, allowing you to customize your liquidity bootstrapping while maintaining security and fairness guarantees.
-
-## High-Level Architecture
-
-
-
-### Example Flow
-
-The following is a high level overview of how the [LBP Strategy Basic](https://github.com/Uniswap/liquidity-launcher) contracts interface and work with the [Continuous Clearing Auction](https://github.com/Uniswap/continuous-clearing-auction/).
-
-The following actions must be performed atomically within one transaction.
-
-1. **Prepare Token** (Optional)
-
- Launch a new token using `LiquidityLauncher.createToken()` via the [UERC20Factory](https://github.com/Uniswap/liquidity-launcher/blob/96860d8239785e717cff1e4189643b9acee925ff/src/token-factories/uerc20-factory), which deploys a UERC20 or UERC20Superchain token and mints the initial supply to the launcher. Alternatively, use an existing token and approve the launcher to distribute it.
-
-2. **Deploy Strategies**
-
- Call `LiquidityLauncher.distributeToken()` to deploy a new LBPStrategy instance via factory. The strategy will validate that the auction parameters and eventual pool configuraiton are valid, and if so, it will deploy a CCA auction with the desired amount of tokens to sell. The `LiquidityLauncher` contract will transfer tokens to the LBPStrategy and then they will be transferred into the auction.
-
- We use an optimistic transfer then call pattern throughout the contracts to trigger an action after performing an ERC20 transfer.
-
-3. **Auction Completion**
-
- When the auction ends, all of the raised funds will be swept to a specified `fundsRecipient`. The LBPStrategy will ensure that it is the recipient of both the raised funds and any leftover unsold tokens.
-
- The LBPStrategy will also read the following data from the `IAuction` interface:
- ```solidity
- interface IContinuousClearingAuction {
- function currencyRaised() external view returns (uint256);
- function clearingPrice() external view returns (uint256);
- }
- ```
-
-4. **Seeding Liquidity**
-
- Anyone can call the `migrate()` function on the `LBPStrategy` after the configured `migrationBlock`. This does the following:
- - Initialize a new Uniswap v4 pool at the price from the auction
- - Deploy a full-range LP position using the auction proceeds + reserve tokens
- - (Optionally) deploy a one-sided position with remaining tokens
- - Mint the LP NFT to the a specified `positionRecipient`
- - Sweep any leftover tokens or raised funds to a configured `operator`
-
-5. **After Migration**
-
- The pool will be live on Uniswap v4 with deep liquidity around the discovered price. Participants in the auction can claim their purchased tokens on the auction after `claimBlock`, and these instances of the LBPStrategy + Auction contracts should hold no funds after all bids are withdrawn and all actions performed.
-
-## Next Steps
-
-- Learn about the [Continous Clearing Auction](./05-auction-mechanism.md) mechanism
-- Read the whitepaper to learn more about the mechanism
-
-## Smart Contracts
-
-| Contract | Description | Source | Ethereum Mainnet | Additional network status |
-|----------|-------------|--------|------------------|---------------------------|
-| **LiquidityLauncher** | Central orchestration contract | [liquidity-launcher](https://github.com/Uniswap/liquidity-launcher) | [0x00000008412db3394C91A5CbD01635c6d140637C](https://etherscan.io/address/0x00000008412db3394C91A5CbD01635c6d140637C) | Not yet published in these docs |
-| **UERC20Factory** | Standard ERC-20 token factory | [uerc20-factory](https://github.com/Uniswap/uerc20-factory) | [0x0cde87c11b959e5eb0924c1abf5250ee3f9bd1b5](https://etherscan.io/address/0x0cde87c11b959e5eb0924c1abf5250ee3f9bd1b5) | Not yet published in these docs |
-| **LBPStrategyBasicFactory** | LBP strategy factory | [liquidity-launcher](https://github.com/Uniswap/liquidity-launcher) | [0x00000010F37b6524617b17e66796058412bbC487](https://etherscan.io/address/0x00000010F37b6524617b17e66796058412bbC487) | Not yet published in these docs |
-| **ContinuousClearingAuction** | Continuous clearing auction factory | [continuous-clearing-auction](https://github.com/Uniswap/continuous-clearing-auction) | Not yet published | Not yet published in these docs |
-| **Permit2** | Token approval manager | [Uniswap](https://github.com/Uniswap/permit2) | [0x000000000022D473030F116dDEE9F6B43aC78BA3](https://etherscan.io/address/0x000000000022D473030F116dDEE9F6B43aC78BA3) | Shared upstream deployment |
diff --git a/docs/contracts/liquidity-launchpad/05-auction-mechanism.md b/docs/contracts/liquidity-launchpad/05-auction-mechanism.md
deleted file mode 100644
index 51bd265..0000000
--- a/docs/contracts/liquidity-launchpad/05-auction-mechanism.md
+++ /dev/null
@@ -1,346 +0,0 @@
----
-id: CCA
-title: Continuous Clearing Auction
-sidebar_position: 2
-unlisted: true
----
-
-# Continuous Clearing Auction (CCA)
-
-**Repository:** [github.com/Uniswap/continuous-clearing-auction](https://github.com/Uniswap/continuous-clearing-auction)
-
-The Continuous Clearing Auction (CCA) is a novel auction mechanism that generalizes the uniform-price auction into continuous time. It provides fair price discovery for bootstrapping initial liquidity while eliminating timing games and encouraging early participation (see [whitepaper](/whitepaper_cca.pdf)).
-
-## Overview
-
-Bootstrapping initial liquidity for new tokens is challenging. Traditional approaches suffer from various weaknesses:
-- **Fixed-price sales** lead to mispricing and priority races, creating thin or unstable liquidity
-- **Dutch auctions** create timing games and favor professionals over genuine participants
-- **One-shot auctions** enable demand reduction and last-minute sniping
-- **Bonding curves** are path-dependent and vulnerable to manipulation
-- **Centralized market makers** require trust and extract significant value
-
-CCA addresses these issues through a unique approach: **automatic bid spreading over time** combined with **continuous price discovery**.
-
-## Deployment Addresses
-
-Ring deployment addresses for CCA contracts have not been published yet.
-
-### Mechanism overview
-
-For a detailed overview, please read the [whitepaper](/whitepaper_cca.pdf).
-
-The most important element to understand about a Continuous Clearing Auction (CCA) is that tokens are sold over time to the current set of active participants. Participants are comprised of two things, a budget and a max price.
-
-The clearing price of the auction in a block is the price which all bidders in that block pay. This is the same concept as in uniform price auctions. But in CCA this price is gradually discovered over time. Every block, some number of tokens (as defined by the configured release schedule) are allocated to bids with higher max prices, then those with lower max prices.
-
-Because we require users to specify a maximum price, there exists a clearing price for which there are not enough "active" participants in the auction to purchase all of the tokens that are being sold, since a bid is removed from the auction once it falls below the clearingPrice. The current price of the auction will always be just below this price, ensuring that all of the supply can be sold to the current set of bids.
-
-At a high level it has these benefits:
-- No participant can concentrate demand at a single moment
-- Timing of bid submission matters less than valuation
-- Early bidders naturally gain more exposure to lower prices
-- Sniping and last-minute gaming become ineffective
-
-## Technical overview
-
-### Auction Configuration
-
-The auction and its supply curve are configured through the AuctionFactory which deploys individual Auction contracts with configurable parameters.
-
-```solidity
-interface IAuctionFactory {
- function initializeDistribution(
- address token,
- uint256 amount,
- bytes calldata configData
- ) external returns (address);
-}
-
-/// @notice Parameters for the auction
-/// @dev token and totalSupply are passed as constructor arguments
-struct AuctionParameters {
- address currency; // token to raise funds in. Use address(0) for ETH
- address tokensRecipient; // address to receive leftover tokens
- address fundsRecipient; // address to receive all raised funds
- uint64 startBlock; // Block which the first step starts
- uint64 endBlock; // When the auction finishes
- uint64 claimBlock; // Block when the auction can claimed
- uint256 tickSpacing; // Fixed granularity for prices
- address validationHook; // Optional hook called before a bid
- uint256 floorPrice; // Starting floor price for the auction
- uint128 requiredCurrencyRaised; // Amount of currency required to be raised for the auction to graduate
- bytes auctionStepsData; // Packed bytes describing token issuance schedule
-}
-
-constructor(
- address _token,
- uint128 _totalSupply,
- AuctionParameters memory _parameters
-) {}
-```
-
-The factory decodes `configData` into `AuctionParameters` and deploys the Auction contract via CREATE2.
-
-## Types
-
-### Q96 Fixed-Point Math
-
-The auction uses Q96 fixed-point arithmetic for price and demand representation:
-
-```solidity
-library FixedPoint96 {
- uint8 internal constant RESOLUTION = 96;
- uint256 internal constant Q96 = 0x1000000000000000000000000; // 2^96
-}
-```
-
-- **Price**: Stored as as a Q96 fixed point number to allow for fractional prices
-- **Demand**: Currency amounts are scaled by Q96 to prevent significant precision loss in calculations
-
-#### MPS terms (Milli-Basis Points)
-
-**MPS = 1e7** (10 million), each representing one thousandth of a basis point:
-
-```solidity
-library ConstantsLib {
- uint24 public constant MPS = 1e7; // 10,000,000
-}
-```
-
-#### ValueX7
-
-A custom uint256 type that represents values which have either been implicitly or explicitly multiplied by 1e7 (ConstantsLib.MPS). These values will be suffixed in the code with `_X7` for clarity.
-
-```solidity
-/// @notice A ValueX7 is a uint256 value that has been multiplied by MPS
-/// @dev X7 values are used for supply values to avoid intermediate division by MPS
-type ValueX7 is uint256;
-```
-
-### Auction steps (supply issuance schedule)
-
-The auction steps define the supply issuance schedule. The auction steps are packed into a bytes array and passed to the constructor along with the other parameters. Each step is a packed `uint64` with the first 24 bits being the per-block issuance rate in MPS (milli-bips), and the last 40 bits being the number of blocks to sell over.
-
-```solidity
-/// AuctionStepLib.sol
-
-function parse(bytes8 data) internal pure returns (uint24 mps, uint40 blockDelta) {
- mps = uint24(bytes3(data));
- blockDelta = uint40(uint64(data));
-}
-```
-
-For example, to sell 1 basis point of supply per block for 100 blocks, then 2 basis points for the next 100 blocks, the packed `uint64` would be:
-
-```solidity
-uint24 mps = 1000; // 1000 mps = 1 basis point
-uint40 blockDelta = 100; // 100 blocks
-bytes8 packed1 = uint64(mps) | (uint64(blockDelta) << 24);
-
-mps = 2000; // 2000 mps = 2 basis points
-blockDelta = 100; // 100 blocks
-bytes8 packed2 = uint64(mps) | (uint64(blockDelta) << 24);
-
-bytes packed = abi.encodePacked(packed1, packed2);
-```
-
-The data is deployed to an external SSTORE2 contract for cheaper reads over the lifetime of the auction.
-
-### Validation Hooks
-
-Optional validation hooks allow custom logic to be executed before bids are accepted, enabling features like allowlists, rate limiting, or complex validation rules.
-
-```solidity
-interface IValidationHook {
- function validate(
- uint256 maxPrice,
- uint128 amount,
- address owner,
- address sender,
- bytes calldata hookData
- ) external;
-}
-```
-
-Any validation hook set in the auction parameters is called during `_submitBid()`. It MUST revert to prevent a bit from being submitted in the auction.
-
-## Contract Entrypoints
-
-### submitBid()
-
-Users can submit bids specifying the currency amount they want to spend. The bid id is returned to the user and can be used to claim tokens or exit the bid. The `prevTickPrice` parameter is used to determine the location of the tick to insert the bid into. The hint must be the price of the tick immediately preceding it in the linked list of prices.
-
-- For convenience, if the `prevTickPrice` is not provided, the contract will iterate through every tick starting from the floor price until it reaches the correct position.
-- This will be gas intensive and should not be used unless the caller is sure that `maxPrice` is already initialized, as it will not perform the search.
-
-A bid's `maxPrice` is the maximum price the bidder is willing to pay.
-The `amount` is the amount of currency the user is bidding, and `owner` is the address of the user who will receive any purchased tokens or refunded currency.
-
-The Auction enforces the following rules on bid prices:
-
-- Bids must be strictly above the current clearing price
-- The maximum bid price must be below the computed MAX_BID_PRICE based on the total supply of the auction.
-
-```solidity
-interface IContinuousClearingAuction {
- function submitBid(
- uint256 maxPrice,
- uint128 amount,
- address owner,
- uint256 prevTickPrice,
- bytes calldata hookData
- ) external payable returns (uint256 bidId);
-
- /// @notice Optional function if the maxPrice is already initialized or if the caller doesn't care about gas efficiency.
- function submitBid(
- uint256 maxPrice,
- uint128 amount,
- address owner,
- bytes calldata hookData
- ) external payable returns (uint256 bidId);
-}
-
-event BidSubmitted(uint256 indexed id, address indexed owner, uint256 price, uint256 amount);
-event TickInitialized(uint256 price);
-```
-
-### checkpoint()
-
-The auction is checkpointed once every block with a new bid. The checkpoint is a snapshot of the auction state up to (NOT including) that block. Checkpoints ultimately determine the token allocations for each bid.
-
-```solidity
-interface IContinuousClearingAuction {
- function checkpoint() external returns (Checkpoint memory _checkpoint);
-}
-
-event CheckpointUpdated(uint256 indexed blockNumber, uint256 clearingPrice, uint24 cumulativeMps);
-```
-
-### exitBid()
-
-Users can use `exitBid` to exit their bid after the auction has ended, or to receive a refund of their currency if the auction has not graduated. This function requires that the bid has a max price above the final clearing price of the auction. This means that the bid was never outbid or partially filled.
-
-```solidity
-interface IContinuousClearingAuction {
- /// @notice Exit a bid where max price is above final clearing price
- function exitBid(uint256 bidId) external;
-}
-
-event BidExited(uint256 indexed bidId, address indexed owner, uint256 tokensFilled, uint256 currencyRefunded);
-```
-
-### exitPartiallyFilledBid()
-
-Exiting partially filled bids is more complex than fully filled ones. The `exitPartiallyFilledBid` function requires the user to provide two checkpoint hints (`lastFullyFilledCheckpointBlock`, `outbidBlock`). These are used to determine the checkpoints immediately before and after the period of time in which the bid was partially filled (auction.clearingPrice == bid.maxPrice).
-
-- `lastFullyFilledCheckpointBlock`: Last checkpoint where clearing price is strictly < bid.maxPrice
-- `outbidBlock`: First checkpoint where clearing price is strictly > bid.maxPrice, or 0 if the final clearing price is equal to the bid's max price at the end of the auction, since it was never outbid.
-
-Checkpoints also store a cumulative value (`currencyRaisedAtClearingPriceQ96_X7`) which tracks the amount of currency raised from bids at the clearing price. This is reset every time the clearing price changes, but this is used to determine the user's pro-rata share of the tokens sold at the clearing price.
-
-**Decision tree for determining when to use `exitBid` vs `exitPartiallyFilledBid`:**
-
-
-
-### claimTokens()
-
-Users can claim purchased tokens after the auction's claim block. The bid must be exited before claiming tokens, and the auction must have graduated.
-
-```solidity
-interface IContinuousClearingAuction {
- function claimTokens(uint256 bidId) external;
-}
-
-event TokensClaimed(uint256 indexed bidId, address indexed owner, uint256 tokensFilled);
-```
-
-Anyone can call this function for any valid bid id.
-
-### isGraduated()
-
-Auctions are graduated if the currency raised meets or exceeds the required threshold set by the auction launcher on deployment.
-
-A core invariant of the auction is that no bids can be exited before the auction has graduated.
-
-```solidity
-interface IContinuousClearingAuction {
- /// @notice Whether the auction has graduated (currency raised >= required)
- function isGraduated() external view returns (bool);
-}
-```
-
-### sweepCurrency() and sweepUnsoldTokens()
-
-After an auction ends, raised currency and unsold tokens can be withdrawn to the designated recipients in the auction deployment parameters.
-
-```solidity
-interface IContinuousClearingAuction {
- /// @notice Withdraw all raised currency (only for graduated auctions)
- function sweepCurrency() external;
-
- /// @notice Withdraw any unsold tokens
- function sweepUnsoldTokens() external;
-}
-
-event CurrencySwept(address indexed fundsRecipient, uint256 currencyAmount);
-event TokensSwept(address indexed tokensRecipient, uint256 tokensAmount);
-```
-
-Note:
-
-- `sweepCurrency()` is only callable by anyone after the auction ends, and only for graduated auctions
-- `sweepUnsoldTokens()` is callable by anyone after the auction ends and will sweep different amounts depending on graduation.
-- For graduated auctions: sweeps all tokens that were not sold per the supply issuance schedule
-- For non-graduated auctions: sweeps total supply of tokens
-
-## Integration guidelines
-
-### Incorrect configuration of the auction parameters
-
-CCA auctions are highly configurable. As such, it is important to ensure that the configurations of each auction instance are not only correct but protect against known risks.
-
-Ensure that the following parameters are correctly set:
-
-- `token` and `currency`
-- `totalSupply` is not too large (see [note on total supply and maximum bid price](#note-on-total-supply-and-maximum-bid-price) below)
-- `startBlock`, `endBlock`, and `claimBlock`
-- `tickSpacing` is not too small (see [note on ticks](#note-on-ticks) below)
-- `floorPrice` is correctly set
-- `requiredCurrencyRaised` is not set too high where the auction will never graduate
-- `auctionStepsData` avoids common pitfalls (see [note on auction steps](#note-on-auction-steps) below)
-
-### Extra funds sent to the auction are not recoverable
-Do NOT send more tokens than intended in `totalSupply` to the auction. They will not be recoverable.
-
-Likewise, any `currency` sent directly to the auction and not through `submitBid` will not be lost.
-
-### Note on total supply and maximum bid price
-
-The following limitations regarding total supply and maximum bid prices should be considered:
-
-- The maximum total supply that can be sold in the auction is 1e30 wei of `token`. For a token with 18 decimals, this is 1 trillion tokens.
-- The auction also ensures that the total currency raised does not exceed the maximum allowable liquidity for a Uniswap v4 liquidity position used by the current Ring launch flow. The lowest bound for this is 2^107 wei (given the smallest possible tick spacing of 1).
-
-Given a total supply of:
-
-- 1 trillion 18 decimal tokens (1e30), the maximum bid price is 2^110. The max ratio of currency to token is 2^(110-96) = 2^14 = 16384.
-- 1 billion 6 decimal tokens (1e15), the maximum bid price is 2^160. The max ratio of currency to token is 2^(160-96) = 2^64 = 18446744073709551616.
-
-We strongly recommend that the `currency` is chosen to be more valuable than `token`, and that the total supply is not excessively large.
-
-### Note on ticks
-
-Ticks in the auction govern where bids can be placed. They have no impact on the potential clearingPrices of the auction and merely serve to prevent users from being outbid by others by infinitesimally small amounts and for gas efficiency in finding new clearing prices.
-
-Generally integrators should choose a tick spacing of AT LEAST 1 basis point of the floor price. 1% or 10% is also reasonable.
-
-Setting too small of a tick spacing will make the auction extremely gas inefficient, and in specific cases, can result in a DoS attack where the auction cannot finish.
-
-### Note on auction steps
-
-Steps in the auction create the supply issuance schedule. Generally each step should be monotonically increasing in the amount of tokens sold, and the last block of the auction MUST sell a significant amount of tokens.
-
-This is because the final clearing price of the auction is used to initialize a Uniswap v4 liquidity pool in the current Ring launch flow, and if only a small number of tokens are sold at the end, the final price will be easy to manipulate.
-
-See the [whitepaper](/whitepaper_cca.pdf) for more details.
\ No newline at end of file
diff --git a/docs/contracts/liquidity-launchpad/_category_.json b/docs/contracts/liquidity-launchpad/_category_.json
deleted file mode 100644
index 46507a7..0000000
--- a/docs/contracts/liquidity-launchpad/_category_.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "label": "Liquidity Launchpad",
- "position": 7,
- "collapsed": true
-}
diff --git a/docs/contracts/liquidity-launchpad/images/TokenLauncherOverview.png b/docs/contracts/liquidity-launchpad/images/TokenLauncherOverview.png
deleted file mode 100644
index c55e492..0000000
Binary files a/docs/contracts/liquidity-launchpad/images/TokenLauncherOverview.png and /dev/null differ
diff --git a/docs/contracts/liquidity-launchpad/images/exitBidDiagram.png b/docs/contracts/liquidity-launchpad/images/exitBidDiagram.png
deleted file mode 100644
index 4882e5a..0000000
Binary files a/docs/contracts/liquidity-launchpad/images/exitBidDiagram.png and /dev/null differ
diff --git a/docs/contracts/liquidity-launchpad/quickstart/_category_.json b/docs/contracts/liquidity-launchpad/quickstart/_category_.json
deleted file mode 100644
index d739680..0000000
--- a/docs/contracts/liquidity-launchpad/quickstart/_category_.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "label": "Quickstart",
- "position": 3,
- "collapsed": true
-}
diff --git a/docs/contracts/liquidity-launchpad/quickstart/example-configuration.md b/docs/contracts/liquidity-launchpad/quickstart/example-configuration.md
deleted file mode 100644
index ebc482f..0000000
--- a/docs/contracts/liquidity-launchpad/quickstart/example-configuration.md
+++ /dev/null
@@ -1,276 +0,0 @@
----
-id: example-configuration
-title: Example configuration
-sidebar_position: 3
----
-
-# Configuring a CCA auction
-This section will walk you through each parameter of a CCA auction and an example configuration. For more details please refer to the [technical reference](/docs/contracts/liquidity-launchpad/05-auction-mechanism.md).
-
-### Prerequisites
-Basic understanding of the CCA auction mechanism and Solidity is assumed. This guide continues from the [previous section](/docs/contracts/liquidity-launchpad/quickstart/local-deployment.md).
-
-## Auction Parameters
-The `AuctionParameters` struct parameterizes a new CCA auction. It is encoded and passed to the `ContinuousClearingAuctionFactory` contract when deploying a new auction. The struct definition is as follows:
-
-```solidity
-/// from: https://github.com/Uniswap/continuous-clearing-auction/blob/main/src/interfaces/IContinuousClearingAuction.sol
-struct AuctionParameters {
- address currency; // token to raise funds in. Use address(0) for ETH
- address tokensRecipient; // address to receive leftover tokens
- address fundsRecipient; // address to receive all raised funds
- uint64 startBlock; // Block which the first step starts
- uint64 endBlock; // When the auction finishes
- uint64 claimBlock; // Block when the auction can claimed
- uint256 tickSpacing; // Fixed granularity for prices
- address validationHook; // Optional hook called before a bid
- uint256 floorPrice; // Starting floor price for the auction
- uint128 requiredCurrencyRaised; // Amount of currency required to be raised for the auction to graduate
- bytes auctionStepsData; // Packed bytes describing token issuance schedule
-}
-```
-
-We'll cover each parameter in detail below.
-
-### currency
-The `currency` parameter is the address of the token that will be used to raise funds for the auction. This can be any ERC20 token or the native token of the chain (address(0)).
-
-### tokensRecipient
-The `tokensRecipient` parameter is the address that will receive the leftover tokens after the auction is complete. Depending on the implementation, this may be a trusted EOA address or a strategy contract address if the auction is being used to bootstrap a liquidity pool.
-
-### fundsRecipient
-The `fundsRecipient` parameter is the address that will receive the funds raised during the auction. Again, depending on the implementation, this may be a trusted EOA address or a strategy contract address if the auction is being used to bootstrap a liquidity pool.
-
-### startBlock
-The `startBlock` parameter is the block number at which the auction will start. Once the auction starts, the supply schedule will begin and bids will be accepted. Note that `startBlock` is inclusive so the auction will start exactly on the block specified.
-
-### endBlock
-The `endBlock` parameter is the block number at which the auction will end. Note that `endBlock` is exclusive so the auction will end on the block specified. No more bids are accepted at and after the end block.
-
-### claimBlock
-The `claimBlock` parameter is the block number at which purchased tokens can be claimed. It must be at or after the `endBlock`.
-
-### tickSpacing
-The `tickSpacing` parameter denotes the **minimum** price increment for bids. It is used to prevent users from being outbid by others by infinitesimally small amounts and for gas efficiency in finding new clearing prices. Generally integrators should choose a tick spacing of AT LEAST 1 basis point of the floor price. 1% or 10% is also reasonable.
-
-Bids can only be placed at increments of tickSpacing, but the auction may clear at any price.
-
-### validationHook
-The `validationHook` parameter is an optional contract that can be used to validate bids before they are accepted. It is called before a bid is accepted and can be used to reject bids that do not meet certain criteria. It must implement the `IValidationHook` interface. Use `address(0)` to opt-out of validation.
-
-### floorPrice
-The `floorPrice` parameter is the starting floor price for the auction. It is the minimum price at which bids will be accepted.
-
-All prices in the auction are represented as the ratio of `currency` to `token`. For example, a floor price with an integer component of 1000 means that 1000 `currency` is required to purchase 1 `token`. Additionally, the price is represented as a Q96 fixed-point number to allow for fractional prices. For more details about the Q-number format please refer to this wikipedia [article](https://en.wikipedia.org/wiki/Q_(number_format)).
-
-Using the above example, a floor price of 1000 would be represented as `1000 << 96` or `1000 * 2^96`.
-
-### requiredCurrencyRaised
-The `requiredCurrencyRaised` parameter is the amount of `currency` required to be raised for the auction to graduate. If the auction does not raise this amount, the auction will not graduate and all bidders will be able to withdraw their initial bid amounts. No tokens will be sold and the `totalSupply` will be swept back to the `tokensRecipient`.
-
-### auctionStepsData
-The `auctionStepsData` parameter is a packed bytes array that describes the token issuance schedule. It is used to determine the amount of tokens that will be sold in each block. It is a series of `uint64` values that represent the per-block issuance rate in MPS (milli-bips), and the number of blocks to sell over.
-
-For more details about the auction steps please refer to the [technical reference](/docs/contracts/liquidity-launchpad/05-auction-mechanism.md#auction-steps-supply-issuance-schedule).
-
-## Example configuration
-Let's create an example configuration for a CCA auction. We'll use the script we started in the [previous section](/docs/contracts/liquidity-launchpad/quickstart/local-deployment.md).
-
-Here's the script copy and pasted for convenience:
-
-```solidity
-// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.0;
-
-import {Script} from "forge-std/Script.sol";
-import {ContinuousClearingAuctionFactory} from "../src/ContinuousClearingAuctionFactory.sol";
-import {IDistributionContract} from "../src/interfaces/external/IDistributionContract.sol";
-import {console2} from "forge-std/console2.sol";
-
-contract ExampleCCADeploymentScript is Script {
- function setUp() public {}
-
- function run() public {
- vm.startBroadcast();
- ContinuousClearingAuctionFactory factory = new ContinuousClearingAuctionFactory();
- console2.log("Factory deployed to:", address(factory));
-
- // TODO: configure the auction and deploy it via `initializeDistribution()`
-
- vm.stopBroadcast();
- }
-}
-```
-
-First, make sure to import the `AuctionParameters` struct from the `IContinuousClearingAuction` interface:
-
-```solidity
-import {AuctionParameters} from "../src/interfaces/IContinuousClearingAuction.sol";
-```
-
-Then, we can configure the auction parameters:
-
-```solidity
-address deployer = vm.envAddress("DEPLOYER");
-
-AuctionParameters memory parameters = AuctionParameters({
- currency: address(0), // We'll use the native token for this example
- tokensRecipient: deployer,
- fundsRecipient: deployer,
- startBlock: uint64(block.number), // Start the auction on the current block
- endBlock: uint64(block.number + 100), // End the auction after 100 blocks
- claimBlock: uint64(block.number + 100), // Allow claims at the end of the auction
- tickSpacing: 79228162514264334008320, // Use a tick spacing equal to the floor price
- validationHook: address(0), // Use no validation hook
- floorPrice: 79228162514264334008320, // Use a floor price representing a ratio of 1:1,000,000 (1 ETH for 1 million tokens)
- requiredCurrencyRaised: 0, // No graduation threshold
- auctionStepsData: bytes("") // Leave this blank for now
-});
-```
-
-Let's build the auction steps data. For simplicity, we'll sell tokens following a monotonically increasing schedule. We'll sell 10% over 50 blocks, 49% over 49 blocks, and the final 41% in the last block. See the [note about auction steps](/docs/contracts/liquidity-launchpad/05-auction-mechanism.md#note-on-auction-steps) for more details about the rationale behind this example schedule.
-
-To derive the steps:
-- First tranche: 10% over 50 blocks
-Express 10% in MPS as 1e6 (1,000,000). Over 50 blocks this is 1e6 / 50 = 20,000 MPS per block.
-Pack this into a bytes8 value:
-
-```solidity
-bytes8 firstTranche = uint64(20_000) | (uint64(50) << 24);
-```
-
-Repeat this for the rest of the tranches to get the final auction steps data:
-```solidity
-bytes8 secondTranche = uint64(100_000) | (uint64(49) << 24); // 49e6 / 49 = 100_000 MPS per block
-bytes8 thirdTranche = uint64(4_100_000) | (uint64(1) << 24); // 41e6 / 1 = 4_100_000 MPS per block
-```
-
-Finally, pack the auction steps data into a bytes array:
-```solidity
-bytes memory auctionStepsData = abi.encodePacked(firstTranche, secondTranche, thirdTranche);
-
-// Set the auction steps data
-parameters.auctionStepsData = auctionStepsData;
-```
-
-You can leverage the [AuctionStepsBuilder](https://github.com/Uniswap/continuous-clearing-auction/blob/main/test/utils/AuctionStepsBuilder.sol) helper library to build the auction steps data.
-
-Before we can finish the script we need to deploy a MockERC20 token to use in the auction. You can use the `ERC20Mock` contract in `@openzeppelin/contracts/mocks/token/ERC20Mock.sol`, or any other MockERC20 token you prefer.
-
-```solidity
-import {ERC20Mock} from '@openzeppelin/contracts/mocks/token/ERC20Mock.sol';
-```
-
-Now let's finish the script:
-
-```solidity
- using AuctionStepsBuilder for bytes;
-
- function run() public {
- address deployer = vm.envAddress("DEPLOYER");
-
- vm.startBroadcast();
- ContinuousClearingAuctionFactory factory = new ContinuousClearingAuctionFactory();
- console2.log("Factory deployed to:", address(factory));
-
- ERC20Mock token = new ERC20Mock();
- uint256 totalSupply = 1_000_000_000e18; // 1 billion tokens
-
- bytes memory auctionStepsData = AuctionStepsBuilder.init().addStep(20_000, 50).addStep(100_000, 49).addStep(4_100_000, 1);
-
- AuctionParameters memory parameters = AuctionParameters({
- currency: address(0),
- tokensRecipient: deployer,
- fundsRecipient: deployer,
- startBlock: uint64(block.number),
- endBlock: uint64(block.number + 100),
- claimBlock: uint64(block.number + 100),
- tickSpacing: 79228162514264334008320,
- validationHook: address(0),
- floorPrice: 79228162514264334008320,
- requiredCurrencyRaised: 0,
- auctionStepsData: auctionStepsData
- });
-
- IDistributionContract auction = IDistributionContract(factory.initializeDistribution(address(token), totalSupply, abi.encode(parameters), bytes32(0)));
- token.mint(address(auction), totalSupply);
- console2.log("Auction deployed to:", address(auction));
-
- vm.stopBroadcast();
- }
-```
-
-This will deploy the mock token, deploy the auction contract, and mint the total supply (1 billion tokens) to the auction contract.
-
-The final step in the script is to ensure that we call `onTokensReceived()` on the auction contract to register the receipt of the tokens.
-
-```solidity
- token.mint(address(auction), totalSupply);
- auction.onTokensReceived();
-```
-
-The complete script should look like this:
-
-```solidity
-// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.0;
-
-import {Script} from "forge-std/Script.sol";
-import {ContinuousClearingAuctionFactory} from "../src/ContinuousClearingAuctionFactory.sol";
-import {AuctionParameters} from "../src/interfaces/IContinuousClearingAuction.sol";
-import {IDistributionContract} from "../src/interfaces/external/IDistributionContract.sol";
-import {AuctionStepsBuilder} from "../test/utils/AuctionStepsBuilder.sol";
-import {ERC20Mock} from '@openzeppelin/contracts/mocks/token/ERC20Mock.sol';
-import {console2} from "forge-std/console2.sol";
-
-contract ExampleCCADeploymentScript is Script {
- using AuctionStepsBuilder for bytes;
- function setUp() public {}
-
- function run() public {
- address deployer = vm.envAddress("DEPLOYER");
-
- vm.startBroadcast();
- ContinuousClearingAuctionFactory factory = new ContinuousClearingAuctionFactory();
- console2.log("Factory deployed to:", address(factory));
-
- ERC20Mock token = new ERC20Mock();
- uint256 totalSupply = 1_000_000_000e18; // 1 billion tokens
-
- bytes memory auctionStepsData = AuctionStepsBuilder.init().addStep(20_000, 50).addStep(100_000, 49).addStep(4_100_000, 1);
-
- AuctionParameters memory parameters = AuctionParameters({
- currency: address(0),
- tokensRecipient: deployer,
- fundsRecipient: deployer,
- startBlock: uint64(block.number),
- endBlock: uint64(block.number + 100),
- claimBlock: uint64(block.number + 100),
- tickSpacing: 79228162514264334008320,
- validationHook: address(0),
- floorPrice: 79228162514264334008320,
- requiredCurrencyRaised: 0,
- auctionStepsData: auctionStepsData
- });
-
- IDistributionContract auction = IDistributionContract(factory.initializeDistribution(address(token), totalSupply, abi.encode(parameters), bytes32(0)));
-
- token.mint(address(auction), totalSupply);
- auction.onTokensReceived();
-
- console2.log("Auction deployed to:", address(auction));
- vm.stopBroadcast();
- }
-}
-```
-
-Let's run the script:
-```bash
-forge script scripts/ExampleCCADeploymentScript.s.sol:ExampleCCADeploymentScript \
---rpc-url http://localhost:8545 --private-key - -Consider the case where a liquidity provider adds 10,000 DAI and 100 WETH to a pool (for a total value of $20,000), the liquidity pool is now 100,000 DAI and 1,000 ETH in total. Because the amount supplied is equal to 10% of the total liquidity, the contract mints and sends the market maker “liquidity tokens” which entitle them to 10% of the liquidity available in the pool. These are not speculative tokens to be traded. They are merely an accounting or bookkeeping tool to keep track of how much the liquidity providers are owed. If others subsequently add/withdraw coins, new liquidity tokens are minted/burned such that everyone’s relative percentage share of the liquidity pool remains the same. - -**Now let’s assume the price trades on Coinbase from $100 to $150. The Ring contract should reflect this change as well after some arbitrage. Traders will add DAI and remove ETH until the new ratio is now 150:1.** - -What happens to the liquidity provider? The contract reflects something closer to 122,400 DAI and 817 ETH (to check these numbers are accurate, 122,400 \* 817 = 100,000,000 (our constant product) and 122,400 / 817 = 150, our new price). Withdrawing the 10% that we are entitled to would now yield 12,240 DAI and 81.7 ETH. The total market value here is $24,500. Roughly $500 worth of profit was missed out on as a result of the market making. - -**Obviously no one wants to provide liquidity out of charitable means, and the revenue isn’t dependent on the ability to flip out of good trades (there is no flipping). Instead, 0.3% of all trade volume is distributed proportionally to all liquidity providers. By default, these fees are put back into the liquidity pool, but can be collected any time. It’s difficult to know what the trade-off is between revenues from fees and losses from directional movements without knowing the amount of in-between trades. The more chop and back and forth, the better.** - -## Why is my liquidity worth less than I put in? - -To understand why the value of a liquidity provider’s stake can go down despite income from fees, we need to look a bit more closely at the formula used by Ring to govern trading. The formula really is very simple. If we neglect trading fees, we have the following: - -- `eth_liquidity_pool * token_liquidity_pool = constant_product` - -In other words, the number of tokens a trader receives for their ETH and vice versa is calculated such that after the trade, the product of the two liquidity pools is the same as it was before the trade. The consequence of this formula is that for trades which are very small in value compared to the size of the liquidity pool we have: - -- `eth_price = token_liquidity_pool / eth_liquidity_pool` - -Combining these two equations, we can work out the size of each liquidity pool at any given price, assuming constant total liquidity: - -- `eth_liquidity_pool = sqrt(constant_product / eth_price)` -- `token_liquidity_pool = sqrt(constant_product * eth_price)` - -So let’s look at the impact of a price change on a liquidity provider. To keep things simple, let’s imagine our liquidity provider supplies 1 ETH and 100 DAI to the Ring DAI exchange, giving them 1% of a liquidity pool which contains 100 ETH and 10,000 DAI. This implies a price of 1 ETH = 100 DAI. Still neglecting fees, let’s imagine that after some trading, the price has changed; 1 ETH is now worth 120 DAI. What is the new value of the liquidity provider’s stake? Plugging the numbers into the formulae above, we have: - -- `eth_liquidity_pool = 91.2871` -- `dai_liquidity_pool = 10954.4511` - -"Since our liquidity provider has 1% of the liquidity tokens, this means they can now claim 0.9129 ETH and 109.54 DAI from the liquidity pool. But since DAI is approximately equivalent to USD, we might prefer to convert the entire amount into DAI to understand the overall impact of the price change. At the current price then, our liquidity is worth a total of 219.09 DAI. What if the liquidity provider had just held onto their original 1 ETH and 100 DAI? Well, now we can easily see that, at the new price, the total value would be 220 DAI. So our liquidity provider lost out by 0.91 DAI by providing liquidity to Ring instead of just holding onto their initial ETH and DAI." - -"Of course, if the price were to return to the same value as when the liquidity provider added their liquidity, this loss would disappear. **For this reason, we can call it an **impermanent loss**.** Using the equations above, we can derive a formula for the size of the impermanent loss in terms of the price ratio between when liquidity was supplied and now. We get the following:" - -- "`impermanent_loss = 2 * sqrt(price_ratio) / (1+price_ratio) — 1`" - -- "Which we can plot out to get a general sense of the scale of the impermanent loss at different price ratios:" -  - -- "Or to put it another way:" - - - "a 1.25x price change results in a 0.6% loss relative to HODL" - - "a 1.50x price change results in a 2.0% loss relative to HODL" - - "a 1.75x price change results in a 3.8% loss relative to HODL" - - "a 2x price change results in a 5.7% loss relative to HODL" - - "a 3x price change results in a 13.4% loss relative to HODL" - - "a 4x price change results in a 20.0% loss relative to HODL" - - "a 5x price change results in a 25.5% loss relative to HODL" - -- "N.B. The loss is the same whichever direction the price change occurs in (i.e. a doubling in price results in the same loss as a halving)." --> - -diff --git a/docs/contracts/v2/concepts/03-advanced-topics/04-security.md b/docs/contracts/v2/concepts/03-advanced-topics/04-security.md deleted file mode 100644 index 92a4c8c..0000000 --- a/docs/contracts/v2/concepts/03-advanced-topics/04-security.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -id: security -title: Security ---- - -## Audit & Formal Verification - -Between January 8 and April 30, a team of six engineers reviewed and formally verified crucial components of the smart contracts for Ring V2. - -Their past work includes smart contract development on and formal verification of multi-collateral DAI. - -The scope of work includes: - -- Formal verification of the core smart contracts -- Code review of core smart contracts -- Numerical error analysis -- Code review of periphery smart contracts (during ongoing development) - -The report also has a "Design Comments" section that provided a deep technical understanding of some of the choices made in Ring V2. - -> Note: The audit report is no longer available at its original URL. The audit was completed by a team of six engineers between January and April 2020. - -## Bug Bounty - -Ring has an open and ongoing bug [bounty program](https://cantina.xyz/bounties/f9df94db-c7b1-434b-bb06-d1360abdd1be) on Cantina. - -## Considerations when building on Ring V2 - -When integrating Ring V2 into another on-chain system, particular care must be taken to avoid security vulnerabilities, avenues for manipulations, and the potential loss of funds. - -As a preliminary note: smart contract integrations can happen at two levels: directly with [Pair](../../reference/smart-contracts/pair) contracts, or through the [Router](../../reference/smart-contracts/router-02). Direct interactions offer maximal flexibility but require the most work to get right. Mediated interactions offer more limited capabilities but stronger safety guarantees. - -There are two primary categories of risk associated with Ring V2. The first involves so-called "static" errors. These can include sending too many tokens to a pair during a swap (or requesting too few tokens back) or allowing transactions to linger in the mempool long enough for the sender's expectations about prices to no longer be accurate. - -One may address these errors with fairly straightforward logic checks. Executing these logic checks is the primary purpose of routers. Those who interact directly with pairs must perform these checks themselves (with the help of the [Library](../../reference/smart-contracts/library)). - -"Dynamic" risk, the second category, involves runtime pricing. Because Ethereum transactions occur in an adversarial environment, naively written smart contracts can, and will, be exploited for profit. For example, suppose a smart contract checks the asset ratio in a Ring pool at runtime and trades against it, assuming that the ratio represents the "fair" or "market" price of these assets. In that case, it is highly vulnerable to manipulation. A malicious actor could, e.g., trivially insert transactions before and after the naive transaction (a so-called "sandwich" attack), causing the smart contract to trade at a radically worse price, profit from this at the trader's expense, and then return the contracts to their original state, all at a low cost. (One important caveat is that these types of attacks are mitigated by trading in highly liquid pools, or at low values.) - -The best way to protect against these attacks is to introduce a price oracle. An oracle is any device that returns desired information, in this case, a pair's spot price. The best "oracle" is simply a traders' off-chain observation of the prevailing price, which can be passed into the trade as a safety check. This strategy is best suited to retail trading venues where users initiate transactions on their own behalf. However, it is often the case that a trusted price observation is not available (e.g., in multi-step, programmatic interactions involving Ring V2). Without a price oracle, these interactions will be forced to trade at whatever the (potentially manipulated) rate on Ring is. For details on the Ring V2 approach to oracles, see [Oracles](../core-concepts/oracles). diff --git a/docs/contracts/v2/concepts/03-advanced-topics/05-math.md b/docs/contracts/v2/concepts/03-advanced-topics/05-math.md deleted file mode 100644 index e164a6f..0000000 --- a/docs/contracts/v2/concepts/03-advanced-topics/05-math.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -id: math -title: Math ---- - -This section will be expanded in the future. In the mean time, the [Ring V2 whitepaper](https://uniswap.org/whitepaper.pdf) has most relevant math for Ring V2. diff --git a/docs/contracts/v2/concepts/03-advanced-topics/06-research.md b/docs/contracts/v2/concepts/03-advanced-topics/06-research.md deleted file mode 100644 index 30b25e4..0000000 --- a/docs/contracts/v2/concepts/03-advanced-topics/06-research.md +++ /dev/null @@ -1,53 +0,0 @@ ---- -id: research -title: Research ---- - -The automated market maker is a new concept, and as such, new research comes out frequently. We've selected some of the most thoughtful here. - -## Uniswap's Financial Alchemy - -Authors: Dave White, Martin Tassy, Charlie Noyes, and Dan Robinson - -> An automated market maker is a type of decentralized exchange that lets customers trade between on-chain assets like USDC and ETH. Ring is the most popular AMM on Ethereum. Like most AMMs, Ring facilitates trading between a particular pair of assets by holding reserves of both assets. It sets the trading price between them based on the size of its reserves in such a way that prices will stay in line with the broader market. Anybody who would like to can join the “pool” for a particular pair and become a liquidity provider, or LP, so-called because they provide liquid assets for others to trade against. LPs contribute assets to both reserves simultaneously, taking on some of the risk of trading in exchange for a share of the returns. - -- [Uniswap's Financial Alchemy](https://research.paradigm.xyz/uniswaps-alchemy) - -## An analysis of Ring markets - -Authors: Guillermo Angeris, Hsien-Tang Kao, Rei Chiang, Charlie Noyes, Tarun Chitra - -> Uniswap---and other constant product markets---appear to work well in practice despite their simplicity. In this paper, we give a simple formal analysis of constant product markets and their generalizations, showing that, under some common conditions, these markets must closely track the reference market price. We also show that Ring satisfies many other desirable properties and numerically demonstrate, via a large-scale agent-based simulation, that Ring is stable under a wide range of market conditions. - -- [An analysis of Ring markets](https://arxiv.org/abs/1911.03380) - -## Improved Price Oracles: Constant Function Market Makers - -Authors: Guillermo Angeris, Tarun Chitra - -> Automated market makers, first popularized by Hanson's logarithmic market scoring rule (or LMSR) for prediction markets, have become important building blocks, called 'primitives,' for decentralized finance. A particularly useful primitive is the ability to measure the price of an asset, a problem often known as the pricing oracle problem. In this paper, we focus on the analysis of a very large class of automated market makers, called constant function market makers (or CFMMs) which includes existing popular market makers such as Uniswap, Balancer, and Curve, whose yearly transaction volume totals to billions of dollars. We give sufficient conditions such that, under fairly general assumptions, agents who interact with these constant function market makers are incentivized to correctly report the price of an asset and that they can do so in a computationally efficient way. We also derive several other useful properties that were previously not known. These include lower bounds on the total value of assets held by CFMMs and lower bounds guaranteeing that no agent can, by any set of trades, drain the reserves of assets held by a given CFMM. - -- [Improved Price Oracles: Constant Function Market Makers](https://arxiv.org/abs/2003.10001) - -## Pintail research - -Published [medium](https://medium.com/@pintail) articles by Pintail. - -- [Understanding Ring Returns](https://medium.com/@pintail/understanding-uniswap-returns-cc593f3499ef) -- [Uniswap: A Good Deal for Liquidity Providers?](https://medium.com/@pintail/uniswap-a-good-deal-for-liquidity-providers-104c0b6816f2) - -## Liquidity Provider Returns in Geometric Mean Markets - -Authors: Alex Evans - -> Geometric mean market makers (G3Ms), such as Ring and Balancer, comprise a popular class of automated market makers (AMMs) defined by the following rule: the reserves of the AMM before and after each trade must have the same (weighted) geometric mean. This paper extends several results known for constant-weight G3Ms to the general case of G3Ms with time-varying and potentially stochastic weights. These results include the returns and no-arbitrage prices of liquidity pool (LP) shares that investors receive for supplying liquidity to G3Ms. Using these expressions, we show how to create G3Ms whose LP shares replicate the payoffs of financial derivatives. The resulting hedges are model-independent and exact for derivative contracts whose payoff functions satisfy an elasticity constraint. These strategies allow LP shares to replicate various trading strategies and financial contracts, including standard options. G3Ms are thus shown to be capable of recreating a variety of active trading strategies through passive positions in LP shares. - -- [Liquidity Provider Returns in Geometric Mean Markets](https://arxiv.org/abs/2006.08806) - -## The Replicating Portfolio of a Constant Product Market - -Authors: Joseph Clark - -> We derive the replicating portfolio of a constant product market. This is structurally short volatility (selling options) which explains why positive transaction costs are needed to induce liquidity providers to participate. Where futures and options markets do not exist, this payoff can be used to create them. - -- [https://papers.ssrn.com/sol3/papers.cfm?abstract_id=3550601](https://papers.ssrn.com/sol3/papers.cfm?abstract_id=3550601) diff --git a/docs/contracts/v2/concepts/03-advanced-topics/_category_.json b/docs/contracts/v2/concepts/03-advanced-topics/_category_.json deleted file mode 100644 index 321360c..0000000 --- a/docs/contracts/v2/concepts/03-advanced-topics/_category_.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "label": "Advanced Topics", - "position": 3 -} diff --git a/docs/contracts/v2/concepts/_category_.json b/docs/contracts/v2/concepts/_category_.json index 74b831d..994b9e4 100644 --- a/docs/contracts/v2/concepts/_category_.json +++ b/docs/contracts/v2/concepts/_category_.json @@ -1,5 +1,5 @@ { "label": "Concepts", - "position": 2, + "position": 4, "collapsed": false } diff --git a/docs/contracts/fewv2/deployments.md b/docs/contracts/v2/deployments.md similarity index 88% rename from docs/contracts/fewv2/deployments.md rename to docs/contracts/v2/deployments.md index cd57a9e..c337940 100644 --- a/docs/contracts/fewv2/deployments.md +++ b/docs/contracts/v2/deployments.md @@ -1,9 +1,9 @@ --- -title: Ring Protocol Contracts +title: Ring Swap Deployments sidebar_position: 2 --- -The latest version of Ring Swap and Few Protocol are deployed at the addresses listed below. +The latest Ring Swap (v2), FewFactory, router, wrapper, and hook contracts are deployed at the addresses listed below. ## Mainnet Deployments @@ -34,22 +34,6 @@ The latest version of Ring Swap and Few Protocol are deployed at the addresses l ### MegaETH Mainnet -| Value | MegaETH Mainnet | -| --- | --- | -| Network Name | `MegaETH Mainnet` | -| Chain ID | `4326` | -| Native Token | `ETH` | -| Official RPC | `https://mainnet.megaeth.com/rpc` | -| Official WebSocket | `wss://mainnet.megaeth.com/ws` | -| dRPC | `https://megaeth.drpc.org` | -| Etherscan | [mega.etherscan.io](https://mega.etherscan.io/) | -| Blockscout | [megaeth.blockscout.com](https://megaeth.blockscout.com/) | -| MegaETH Docs | [docs.megaeth.com](https://docs.megaeth.com/) | -| Network Status | [uptime.megaeth.com](https://uptime.megaeth.com/) | - -The official RPC may reject some unauthenticated script requests. For CLI usage, `https://megaeth.drpc.org` -can be used as a fallback RPC. - | Contract | MegaETH Mainnet Address | | --- | --- | | WETH | `0x4200000000000000000000000000000000000006` | @@ -58,7 +42,7 @@ can be used as a fallback RPC. | fwWETH | `0x65c46c31E340D6C546309733CF50Ef4d150094C4` | | FewETHWrapper | `0xb0Bd0CD58551b71079F36B198276832242D02C0F` | | Ring Swap Factory | `0x47C436602d2598d0ef4b50888F29a528B6Bccc95` | -| UniswapV2Router02 | `0xE73442C4b87283D75768F3668B411fc2348B429b` | +| V2-Compatible Router | `0xE73442C4b87283D75768F3668B411fc2348B429b` | | Ring Swap Router | `0x88a9A29FA981721C04fdC367ab7e3C83A4C65db9` | | UniversalRouter | `0x9256667638ED96ba4eCb30bD23efD2A182e1bC98` | | Timelock | `0xb0BEa0daA0E57c43d92711f9dF2d0D54CebEEA72` | diff --git a/docs/contracts/v2/fewtoken/_category_.json b/docs/contracts/v2/fewtoken/_category_.json new file mode 100644 index 0000000..8cfb30f --- /dev/null +++ b/docs/contracts/v2/fewtoken/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "FewToken Wrapping", + "position": 3, + "collapsed": false +} diff --git a/docs/contracts/fewv2/get-erc20-token-address-via-fewfactory.md b/docs/contracts/v2/fewtoken/get-erc20-token-address-via-fewfactory.md similarity index 97% rename from docs/contracts/fewv2/get-erc20-token-address-via-fewfactory.md rename to docs/contracts/v2/fewtoken/get-erc20-token-address-via-fewfactory.md index 95802dc..49b7f2b 100644 --- a/docs/contracts/fewv2/get-erc20-token-address-via-fewfactory.md +++ b/docs/contracts/v2/fewtoken/get-erc20-token-address-via-fewfactory.md @@ -1,6 +1,6 @@ --- title: Get ERC20 Token Address from FewToken -sidebar_position: 4 +sidebar_position: 3 --- FewTokens wrap original ERC20 tokens. In UI and analytics workflows, you may need to map back to the underlying token. diff --git a/docs/contracts/fewv2/get-fewtoken-address-via-fewfactory.md b/docs/contracts/v2/fewtoken/get-fewtoken-address-via-fewfactory.md similarity index 98% rename from docs/contracts/fewv2/get-fewtoken-address-via-fewfactory.md rename to docs/contracts/v2/fewtoken/get-fewtoken-address-via-fewfactory.md index d285f48..0875c00 100644 --- a/docs/contracts/fewv2/get-fewtoken-address-via-fewfactory.md +++ b/docs/contracts/v2/fewtoken/get-fewtoken-address-via-fewfactory.md @@ -1,6 +1,6 @@ --- title: Get FewToken Address via FewFactory -sidebar_position: 3 +sidebar_position: 2 --- Ring Swap uses wrapped tokens (FewTokens) in pools and swap paths. diff --git a/docs/contracts/fewv2/integrating.md b/docs/contracts/v2/fewtoken/integrating.md similarity index 62% rename from docs/contracts/fewv2/integrating.md rename to docs/contracts/v2/fewtoken/integrating.md index 84bc296..ac37726 100644 --- a/docs/contracts/fewv2/integrating.md +++ b/docs/contracts/v2/fewtoken/integrating.md @@ -1,13 +1,14 @@ --- -title: Integrating with Ring Protocol +title: FewToken Integration sidebar_position: 1 --- -Ring keeps compatibility with Uniswap v2-style integration patterns while introducing `Few Protocol` as a wrapping layer. +Ring Swap (v2) keeps compatibility with v2-style AMM integration patterns while introducing `Few Protocol` +as a wrapping layer. ## Integration Overview -To integrate `Ring Swap (v2)` for swap and liquidity flows, replace your existing Uniswap-style integration points with Ring deployments: +To integrate `Ring Swap (v2)` for swap and liquidity flows, replace your existing v2-style integration points with Ring deployments: - Ring Swap Factory - Ring Swap Pair Init Code @@ -28,9 +29,11 @@ When integrating: ## Important note -Ring currently operates `Ring Swap (v2)` as its native AMM. +Ring Swap (v2) is a native Ring product line. The `v2` label describes the compatible AMM design; it is not +part of a public Ring product-version ladder. -If you are integrating with v4-related workflows elsewhere in these docs, that should generally be understood as `FewToken` integration with `Uniswap v4`, not as a separate native Ring v4 protocol. +If you are integrating with v4-related workflows elsewhere in these docs, that should generally be understood as +`FewToken` integration with `Uniswap v4`, not as a separate native v4 protocol. ## Swap Path Example diff --git a/docs/contracts/v2/guides/_category_.json b/docs/contracts/v2/guides/_category_.json index 6809046..f4409ea 100644 --- a/docs/contracts/v2/guides/_category_.json +++ b/docs/contracts/v2/guides/_category_.json @@ -1,5 +1,5 @@ { "label": "Guides", - "position": 3, + "position": 5, "collapsed": false } diff --git a/docs/contracts/v2/guides/interface-integration/01-using-the-api.md b/docs/contracts/v2/guides/interface-integration/01-using-the-api.md index 5e9ed0b..b426cd9 100644 --- a/docs/contracts/v2/guides/interface-integration/01-using-the-api.md +++ b/docs/contracts/v2/guides/interface-integration/01-using-the-api.md @@ -1,6 +1,7 @@ --- id: using-the-api title: 'Using the API' +draft: true --- In this guide we will create a web interface that consumes and displays data from the Ring Subgraph. The goal is to provide a quick overview of a setup that you can extend to create your own UIs and analytics around Ring data. diff --git a/docs/contracts/v2/guides/interface-integration/03-iframe-integration.mdx b/docs/contracts/v2/guides/interface-integration/03-iframe-integration.mdx deleted file mode 100644 index 81e7b62..0000000 --- a/docs/contracts/v2/guides/interface-integration/03-iframe-integration.mdx +++ /dev/null @@ -1,69 +0,0 @@ ---- -id: iframe-integration -title: Iframe Integration ---- - -:::note Swap Widget -These docs are deprecated. Please refer to the current Ring interface and SDK documentation for supported embedding and integration paths. -::: - -Ring can be used within other sites as an iframe. An iframe shows an exact version of the Ring frontend site and can have custom prefilled settings. - -## Why You May Want This - -Integrating the Ring site directly into your web application can be useful for a variety of reasons. - -The interface allows users to buy, sell, send, or provide liquidity for ERC20 tokens. An iframe integration may be useful if your application provides services around these ERC20 tokens. \(For example, users can buy DAI through a Ring iframe on your site, then allow users to lend that DAI on your site\). - -It can also be useful if your application requires users to acquire some token in order to use some service \(For example, allow users to buy "REP" token so they can engage in prediction markets on the Augur Dapp\). - -## iframe vs. custom UI - -One benefit of an iframe integration is that the your site will automatically keep up with any improvements/additions to the site. After the initial integration is setup no further work is needed to pull in updates as the exchange site is updated over time. - -## Example - -```text - -``` - -An example of an Iframe integration can be found on the FOAM site [https://map.foam.space/](https://map.foam.space/#/at/?lng=-74.0045300&lat=40.6771800&zoom=5.00) - -To see the iframe, click the dropdown in the top right and click `Get FOAM`. - -## Add To Your Site - -To include a Ring iframe within your site just add an iframe element within your website code and link to the Ring frontend. - -Linking to a ETH <-> DAI swap page would look something like this. To link to a token of your choice replace the address after `outputCurrency` with the token address of the token you want to link to. - -```text - -``` - -You can customize the selected page, selected custom tokens and more using URL query parameters. See [Custom Linking](custom-interface-linking). diff --git a/docs/contracts/v2/guides/smart-contract-integration/01-quick-start.md b/docs/contracts/v2/guides/smart-contract-integration/01-quick-start.md index 9a98bcb..a0e2830 100644 --- a/docs/contracts/v2/guides/smart-contract-integration/01-quick-start.md +++ b/docs/contracts/v2/guides/smart-contract-integration/01-quick-start.md @@ -1,205 +1,84 @@ --- id: quick-start -title: Smart Contract Quick start +title: Smart Contract Quick Start --- -Developing smart contracts for Ethereum involves a variety of off-chain tools used for producing and testing bytecode -that runs on the [Ethereum Virtual Machine (EVM)](