[M3] - Dynamic Stableswap 🏅

This is an improvement on the traditional stableswap that protects liquidity providers against arbitrageurs during times of great volatility, such as when a stablecoin depegs. This is done by making swap fees a dynamic function of volatility.

Challenges

#BUIDLathon 2023 DeFi Track

Pool 15,000 MATIC

This is an innovative defi project!

Polygon DeFi UX Challenge

Pool 1,000 ETH

What I did: One of the main problems with retail using LP pools is the lack of monitoring systems they have, meaning in times of great volatility, their money will be the last to exit, meaning that they will take on heavy losses. Challenges I ran into: None Feedback: Easy to integrate with!

Best Multi-Network Deployment using Infura

Pool 5,000 ETH

What I did: Used multiple network infura endpoints in my hardhat deployment config. Here is the demo video: https://www.youtube.com/watch?v=6ZkX_UEwrJ8&ab_channel=AlbertSu Challenges I ran into: I had to make an infura account instead of just using a public endpoint Feedback: Deployments were pretty smooth

Best Use of Polygon

Ranked 10,000 ETH

What I did: One of the main problems with retail using LP pools is the lack of monitoring systems they have, meaning in times of great volatility, their money will be the last to exit, meaning that they will take on heavy losses. Polygon is cheap and has plenty of liquidity, meaning it is a great first test for Dynamic Stableswap! Challenges I ran into: None Feedback: Easy to integrate with!

Open Aurora Bounty

Ranked 6,000 ETH

What I did: Ported over contracts to Aurora and integrated it into the frontend. The problem with this dynamic stableswap model is that it requires much more computation than a normal stableswap’s swap, meaning that it is best suited for high throughput and cheap chains. Challenges I ran into: Aurora was lowkey one of the best developer experiences I had, the faucet was super easy to use, all endpoints and block explorers are online and easy to find, and someone at the venue conviniently had cards with a code to get gas with. Feedback: Good stuff, I’d be interested in build on Aurora even after the conference due to the easy of building.

Bring Functionality to Metis

Ranked 2,500 ETH

What I did: Ported over contracts to Metis and integrated it into the frontend. The problem with this dynamic stableswap model is that it requires much more computation than a normal stableswap’s swap, meaning that it is best suited for high throughput and cheap chains. Challenges I ran into: None, deployments were very smooth. Feedback: Good stuff, Pe4enable#5069 was very helpful on discord!

Deploy your smart contract on Scroll

Pool 10,000 USDC

What I did: Ported over contracts to Scroll L2 and integrated it into the frontend. The problem with this dynamic stableswap model is that it requires much more computation than a normal stableswap’s swap, meaning that it is best suited for high throughput and cheap chains. Challenges I ran into: The faucet was kind of confusing, as there were multiple versions of the same chain, L1 and L2. There was also the fact that you had to bridge testnet eth around, which was kind of annoying. Feedback: Richard and Srikar were both super helpful in the Blockchain at Berkeley <> Scroll group chat!

Best Defi/NFT Project on Mantle

Ranked 6,000 ETH

What I did: Ported over contracts to Mantle and integrated it into the frontend. The problem with this dynamic stableswap model is that it requires much more computation than a normal stableswap’s swap, meaning that it is best suited for high throughput and cheap chains. Challenges I ran into: Getting funds from the faucet was annoying Feedback: The mantle devs telegram group was very helpful: https://t.me/mantledevs, also, Cooper was very helpful!

Port over Ethereum dApps to Neon-EVM

Ranked 5,000 ETH

What I did: Ported over contracts to Neon and integrated it into the frontend. The problem with this dynamic stableswap model is that it requires much more computation than a normal stableswap’s swap, meaning that it is best suited for high throughput and cheap chains. Challenges I ran into: The neon faucet wasn’t working for me the first day, but got a chance to talk to https://t.me/a_falaleev at the venue which helped with that. Feedback: RPC was very smooth, didn’t need to modify any of the existing deploy scripts I had to deploy.

zkBob Bounty

Pool 10,000 USDC

What I did: I deployed a pool to optimism that contains the zkBOB <> USDC pair. Challenges I ran into: Finding the zkBOB stablecoin was kind of annoying. Feedback: This project seems super cool - I had never seen anything like it and I’ve seen pretty much everything related to defi in these last three years. Also, the people tabling at the venue on saturday were super helpful!

Project details

For a well formatted version:

https://hackmd.io/@albertsu/dynamic-stableswap

Dynamic Stable Swap

Links

App: https://dynamicstableswap.netlify.app/#/
Contracts Github: https://github.com/AlbertSu123/dynamicstableswap-contracts
Frontend Github: https://github.com/AlbertSu123/hgh

Description

This is a slight improvement on the traditional curve stableswap that protects liquidity providers against arbitrageurs during times of great volatility, such as when a stablecoin depegs.

Traditionally, stableswap are used to swap between different pegged assets, such as USDC <> DAI or STETH <> ETH. Liquidity providers provide liquidity for each of the pegged assets in equal amounts in exchange for swap fees and liquidity mining incentives. However, during periods of high volatility, arbitrageurs will provide toxic flow to the pool, effectively stealing money from the liquidity providers. The absolute worst case scenario is when a stablecoin depegs, and arbitrageurs instantly rush in to sell the depegged stablecoins for the other stablecoins in the pool. Current stableswap and general AMM design doesn’t account for this edge case, as the trading fees are statically set and do not change after the pool is deployed.

Dynamic Stableswap’s solution is to make the fees a function of the past volume, which is used as a proxy for volatility. We assume that if the volume is high, then volatility is high as well, which means fees for that specific pool should be increased. Fees are uncapped, meaning that they can exceed 100%, effectively blocking arbitrageurs from making swaps when a stablecoin depegs.

How it works

Goals

  • During abnormal trading conditions, increase the percentage the protocol takes in trading fees.

  • When trading volume increases, increase the percentage the protocol takes in trading fees.

  • [Meta] Protect liquidity providers from impermanent loss, stablecoin depeg events, bridge exploits, and massive arbitraging.

  • [Meta] Maximize profits for liquidity providers.

Implementation

  1. Make fees a function of the volume traded in the last hour.

  2. Store recent volumes denominated in the number of LP tokens traded.

  3. Every 10 minutes, update the swap fee with the following function.

Depeg Protection

Depeg Protection is an extension of the Dynamic Fees feature. If a stablecoin in an liquidity pool based AMM, typically arbitrageuers will come in instantly and drain the liquidity pool of the non-depegged stablecoins, leaving only the worthless stablecoins in the pool.

The goal of Depeg protection is to prevent this from happening by raising fees such that it would no longer be profitable for arbitrageuers to come in and drain the non-depegged stablecoins from the pool. This happens by monitoring the volume traded in the pool and raising fees linearly such that if volume is too high, the swap fee would disincentivize arbitrageurs.

Sponsor Challenges

Neon EVM - Port over Ethereum dApps to Neon-EVM

What I did: Ported over contracts to Neon and integrated it into the frontend. The problem with this dynamic stableswap model is that it requires much more computation than a normal stableswap’s swap, meaning that it is best suited for high throughput and cheap chains.
Challenges I ran into: The neon faucet wasn’t working for me the first day, but got a chance to talk to https://t.me/a_falaleev at the venue which helped with that.
Feedback: RPC was very smooth, didn’t need to modify any of the existing deploy scripts I had to deploy.

Near - Open Aurora Bounty

What I did: Ported over contracts to Aurora and integrated it into the frontend. The problem with this dynamic stableswap model is that it requires much more computation than a normal stableswap’s swap, meaning that it is best suited for high throughput and cheap chains.
Challenges I ran into: Aurora was lowkey one of the best developer experiences I had, the faucet was super easy to use, all endpoints and block explorers are online and easy to find, and someone at the venue conviniently had cards with a code to get gas with.
Feedback: Good stuff, I’d be interested in build on Aurora even after the conference due to the easy of building.

Scroll - Deploy your smart contract on Scroll

What I did: Ported over contracts to Scroll L2 and integrated it into the frontend. The problem with this dynamic stableswap model is that it requires much more computation than a normal stableswap’s swap, meaning that it is best suited for high throughput and cheap chains.
Challenges I ran into: The faucet was kind of confusing, as there were multiple versions of the same chain, L1 and L2. There was also the fact that you had to bridge testnet eth around, which was kind of annoying.
Feedback: Richard and Srikar were both super helpful in the Blockchain at Berkeley <> Scroll group chat!

zkBob Bounty

What I did: I deployed a pool to optimism that contains the zkBOB <> USDC pair.
Challenges I ran into: Finding the zkBOB stablecoin was kind of annoying.
Feedback: This project seems super cool - I had never seen anything like it and I’ve seen pretty much everything related to defi in these last three years. Also, the people tabling at the venue on saturday were super helpful!

Metis - Bring Functionality to Metis

What I did: Ported over contracts to Metis and integrated it into the frontend. The problem with this dynamic stableswap model is that it requires much more computation than a normal stableswap’s swap, meaning that it is best suited for high throughput and cheap chains.
Challenges I ran into: None, deployments were very smooth.
Feedback: Good stuff, Pe4enable#5069 was very helpful on discord!

Infura - Best Multi-Network Deployment using Infura

What I did: Used multiple network infura endpoints in my hardhat deployment config.

Here is the demo video: https://www.youtube.com/watch?v=6ZkX_UEwrJ8&ab_channel=AlbertSu
Challenges I ran into: I had to make an infura account instead of just using a public endpoint
Feedback: Deployments were pretty smooth

Mantle - Best Defi/NFT project on Mantle

What I did: Ported over contracts to Mantle and integrated it into the frontend. The problem with this dynamic stableswap model is that it requires much more computation than a normal stableswap’s swap, meaning that it is best suited for high throughput and cheap chains.
Challenges I ran into: Getting funds from the faucet was annoying
Feedback: The mantle devs telegram group was very helpful: https://t.me/mantledevs, also, Cooper was very helpful!

Polygon - DeFi UX Challenge

What I did: One of the main problems with retail using LP pools is the lack of monitoring systems they have, meaning in times of great volatility, their money will be the last to exit, meaning that they will take on heavy losses.
Challenges I ran into: None
Feedback: Easy to integrate with!

Source Code

https://github.com/AlbertSu123/dynamicstableswap-contracts/blob/9a629224f64ab5af03f5510229741e8bf3b72099/contracts/Swap.sol#L514

The main part of the logic:

function updateSwapFee(uint256 tradeVolume) internal {
        // if we are still in the last element of recentVolume's timestamp(recentVolume.timestamp + 10 min >= block.timestamp)
        if (
            recentVolume[recentVolume.length.sub(1)].timestamp.add(
                10 minutes
            ) >= block.timestamp
        ) {
            // add volume to the last element of recentVolume
            recentVolume[recentVolume.length.sub(1)].volume = recentVolume[
                recentVolume.length.sub(1)
            ].volume.add(tradeVolume);
        } else {
            // Average volume += (average volume - volume removed) * (10 mins / time pool has been active)
            averageVolume = averageVolume
                .add(
                    averageVolume.sub(recentVolume[recentVolumePointer].volume)
                )
                .mul(
                    (10 minutes / (block.timestamp.sub(creationTimestamp)))
                );
            // remove the first element in recentVolume
            recentVolumePointer = recentVolumePointer.add(1);
            // append a new element to recentVolume, set timestamp to block.timestamp, volume to volume
            recentVolume.push(
                TradeVolume({volume: tradeVolume, timestamp: block.timestamp})
            );
        }

        // Calculate hourlyVolume by summing volume inside recentVolume
        uint256 hourlyVolume = 0;
        uint256 rvLength = recentVolume.length;
        uint256 rvPointer = recentVolumePointer;
        for (uint256 i = rvPointer; i < rvLength; ++i) {
            hourlyVolume += recentVolume[i].volume;
        }

        // call swapStorage.setSwapFee(newSwapFee) with fees =  A * volume / average volume + B
        uint256 newSwapFee = (feeFactor.mul(hourlyVolume))
            .div(averageVolume)
            .add(baseFee);
        swapStorage.setSwapFee(newSwapFee);
    }