Giter Site home page Giter Site logo

rift-protocol's Introduction

rift-protocol

See the Rift Documentation for more information.

** THERE IS CURRENTLY NO RIFT TOKEN **

Getting Started

  1. Install foundry
  2. Bootstrap with ALCHEMY_API_KEY=<your api key> make bootstrap (alternately you can add ALCHEMY_API_KEY to a .env file and run make bootstrap)
  3. Compile contracts with make build
  4. Run tests with make test

Contributing

If you want to contribute, but aren't sure where to start, you can create a new discussion or reach out on discord.

Contract Structure

Core

The Core.sol contract is only deployed once per chain. It maintains important parameters across all vault deployments (and any future Rift contracts). In particular, it maintains:

  • protocolFee: protocol wide fee out of 10_000.
  • feeTo: the beneficiary of the protocol fee, i.e. the treasury.
  • registeredVaults: a list of Rift Vaults that have been registered.
  • paused: state of the Rift Protocol, paused in dire circumstances.

Additionally, it manages permissions.

  • Governor: can register vaults, set the protocolFee & feeTo, and add and revoke roles, can enable or disable the whitelist.
  • Strategist: can move vaults to the next epoch, set floor variables for a vault.
  • Pauser: can pause the Rift Protocol, or a specific vault.
  • Guardian: can rescue funds from a vault, only if the vault (or protocol) is paused.
  • Whitelisted: can interact with Rift Vaults as a user. Whitelist can be disabled.

Refs

  • Any contract that wishes to interact with the Core contract and use its state / parameters / permissions can do so by inheriting the CoreReference.sol contract, which provides a useful interface to the Core.

Vaults

This stores the important logic for accepting deposits and withdraws, does the accounting for returns, and interacts with DEXs.

Vault is the base class inherited by each DEX type's contract. Parameters defined on initializaiton:

  • coreAddress: the address of the core contract
  • epochDuration: length of each epoch in seconds
  • token0: token that receives the interest rate floor (in practice, the ETH side)
  • token1: token that receives the interest rate ceiling (in practice, the DAO side)
  • token0FloorNum: interest rate floor for the token0 side, out of 10000. This will be set to ~10000, to guarantee lossless returns for the token0 side.
  • token1FloorNum: interest rate floor for the token1 side, out of 10000. This will be set to a low amount, just to keep internal accounting consistent.
  • isNativeVault: this indicates if a vault accepts the native token for this chain on the token0 side. If yes, token0 is the wrapped native token, otherwise, token0 can be an arbitrary ERC20 token.

Note: Vaults do not currently support fee on transfer / deflationary tokens.

Deposits

Users can deposit into a Vault by calling depositToken0 or depositToken1. Users must have approved the token before this transaction, unless it is an ETH Vault, in which case they can include the amount being deposited in msg.value. The contract updates the accounting balances for this user accordingly, and queues up their deposit to be included in the next epoch.

The deposit accounting checks if the user had previously deposited. If they had already requested a deposit for the current epoch, it simply adds their new deposit to the queued amount. If the user deposited in an epoch that has completed, we now know the exchange rate for that epoch. So we can convert their fulfilled token deposit amount to "day 0" tokens, and add it to their total day0Token balance.

Withdraws

Users can withdraw from a Vault by calling withdrawToken0 or withdrawToken1. Users specify the amount being withdrawn in units of Day 0 Balance. They cannot specify the withdraw amount in absolute tokens, because we won't know the exchange rate for their Day 0 Tokens until this epoch closes. But they do have a Day 0 Balance, so they can choose to withdraw some or all of it for the end of the epoch. This withdraw pattern allows the protocol to prevent frontrunning in DEXs.

Similar to the way we do deposit accounting, we first need to check previous deposit and withdraw requests, and mark them as having been fulfilled if they were from a previous epoch. We then add on the new withdraw request to any other withdraw requests submitted for the current epoch.

Claims

After users submit a withdraw request, and the current epoch finishes, they can claim their tokens by calling claimToken0 or claimToken1. These functions check the users claimable balance, zeros out their claim, and sends them their tokens.

Moving to the next epoch

This function allows the Vault's strategist role to move the Vault to its next epoch, collecting new deposit and withdraw requests, and pairing up the newly available amounts of token0 and token1 into the DEX pool. The strategist specifies the expected pool balances in the DEX pool, and the Vault checks that the current balances are within that expected range, preventing any potential frontrunning. This allows us to set minAmounts to 0 when interacting with DEX routers to add liquidity, remove liquidity, and makes swaps, because we already guaranteed certain pool balances, and any of these calls are in the same transaction without any untrusted external calls.

The nextEpoch function withdraws liquidity from the DEX, and if necessary, makes a swap from token0 to token1 or vice versa, depending on the initial and final balances of the pool and swap fees accrued during the period. It then updates the current exchange rate for "Day 0 Tokens". For example, if someone deposited 100 TOKEN0 in the first epoch when the exchange rate was 1:1, and at the end of this epoch the new exchange rate is 10:11, the user would have a claim on 110 TOKEN0 if they would choose to withdraw. We store the historical exchange rate for each epoch, for both token0, and token1, so that requests can be claimed in the future.

Then it calculates the amount of each token being withdrawn during this epoch, calculated as the total amount of "Day 0 Tokens" withdrawn times the current exchange rate. It aggregates that with the total amount of deposits requests for each token. Now we know how much of each token is currently available (after withdraws and deposits) to be paired up in the DEX. The Vault contract now redeposits the available tokens into the DEX.

There are 5 functions that are left undefined in the Vault contract. These functions are specific to the DEX type that the instance of the vault interacts with.

  • getPoolBalances: returns the reserve amounts of each token currently in the DEX pool
  • calcAmountIn: calculates the amount of tokenA that must be swapped to get some amount of tokenB given the current reserves of the DEX pool
  • withdrawLiquidity: withdraws all LP tokens from the DEX pool
  • depositLiqudity: deposits tokens into the DEX pool and receives LP tokens
  • swap: swaps some amount of tokenA for tokenB in the DEX.

Vault Types

Uniswap Vault

The Uniswap Vault inherits the Vault parent contract, and simply defines these 5 virtual functions so that they interact with the Uniswap Router. It can also be used for Sushiswap, because there is no dependency on the UniswapV2Library with a different init code hash.

MasterChef Vault

The MasterChef Vault inherits from the Uniswap Vault and is used for token pairs that receive rewards from Sushi's MasterChef contract. Upon depositing liquidity into the DEX, it takes the received LP Tokens and stakes them in the MasterChef contract to receive SUSHI staking rewards. Before withdrawing liquidity, it unstakes its tokens from the MasterChef, harvests Sushi rewards, then removes its liquidity from the DEX pool.

MasterChefV2 Vault

The MasterChefV2 Vault inherits from the Uniswap Vault and is used for token pairs that receive rewards from Sushi's MasterChefV2 contract. Upon depositing liquidity into the DEX, it takes the received LP Tokens and stakes them in the MasterChefV2 contract to receive both SUSHI and MasterChefV2 staking rewards, which are typically denominated as the token paired with ETH. For example, a DAO may incentivize its Pool 2 by providing liquidity mining rewards of its own token for users who provide liquidity and stake with MasterChefV2. Before withdrawing liqudity, the contract unstakes its tokens from the MasterChefV2, harvests Sushi and MasterChefV2 rewards, then removes its liquidity from the DEX pool.

Other

New vault types can be added easily by inheriting the Vault class and defining the 5 function listed above.

rift-protocol's People

Contributors

ttarsi avatar balasan avatar kevinhalliday avatar pegahcarter avatar mrod502 avatar

Stargazers

geoffhorwitz.eth  avatar  avatar rake avatar Taisuke Mino avatar  avatar BappleBauce avatar Koda avatar abran avatar t11s avatar  avatar Charlie You avatar  avatar Dustin Brickwood avatar  avatar Austin King avatar

Watchers

 avatar haishan avatar  avatar

Forkers

jedusor1

rift-protocol's Issues

Potentially remove `registeredVaults`

Although it may be convenient in some cases, don't actually need to track registeredVaults in Core.sol.
Emitting events is enough to reproduce the list of vaults from the UI.
A partial optimization may include removing dependency on costly EnumerableSet.sol

Additional Vault tests

Possible test additions:

  • add some fuzz tests to ensure robustness around edge cases

  • test different deposit / active amounts

  • test a range of price movements

  • ensure we hit all the nextEpoch branches

  • test the MIN_LP (prev 1 gwei) deposit logic

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.