# Introduction to GEB

The what and how of the GEB framework

[GEB](https://en.wikipedia.org/wiki/G%C3%B6del,_Escher,_Bach) is a framework for deploying systems that can issue [stablecoins](https://medium.com/reflexer-labs/stability-without-pegs-8c6a1cbc7fbd). Stablecoins don't look like [this](https://www.coingecko.com/en/coins/usd-coin) (that's a pegged coin), but rather like [this](https://duneanalytics.com/HggqX/Reflexer-RAI). Stablecoins are a great collateral source for other DeFi protocols (compared to ETH or BTC) and are also a store of value with an embedded funding rate.\
\
This documentation is meant to explain all the components behind GEB. Before diving in the docs, we recommend reading our original [whitepaper](https://github.com/reflexer-labs/whitepapers/blob/master/English/rai-english.pdf).\
\
GEB is a modified fork of [MCD](https://github.com/makerdao/dss) that has several core differences:

* Variable names you [can actually understand](https://docs.reflexer.finance/contract-translation/naming-transition)
* An autonomous feedback mechanism that changes the incentives of system participants
* The possibility to add insurance for SAFEs
* Fixed and increasing discount auctions (instead of English auctions) used to sell off collateral
* Automatic adjustment of several parameters in the system
* A set of contracts that bound control over parameters that are governed in the long run
* The possibility to send stability fees at once to multiple addresses
* The possibility to switch between surplus auctions and other types of strategies meant to remove surplus from the system
* Two prices for each `CollateralType`: one used for generating debt, the other one used exclusively when liquidating SAFEs
* A stability fee treasury that can pay for oracle calls or other contracts that automate the system

### GEB Overview Diagram

Explore the diagram in detail [here](https://viewer.diagrams.net/?target=blank\&highlight=0000ff\&layers=1\&nav=1\&title=GEB_overview.drawio#Uhttps%3A%2F%2Fdrive.google.com%2Fuc%3Fid%3D1nIcaY8N8StVCfyAL_ztbmETJX2bvY3a9%26export%3Ddownload).

![](/files/-MZCEJv2Xvz-xIw0JAwy)

{% file src="/files/-MVRdQkiYprFv1xG82Gl" %}


# Community Resources

List of talks and articles about RAI and Reflexer

### Podcasts

* [Yield TV Episode 93 - Stefan Ionescu Interview](https://www.youtube.com/watch?v=usKEpLUukW8) March 2021
* [Defiant - Ameen Soleimani Interview](https://thedefiant.substack.com/p/we-were-idiots-and-we-were-poor-then-037) March 2021
* [Bankless - Stefan Ionescu Interview](https://www.youtube.com/watch?v=5Fm5xNwfqNo) July 2020

### Articles&#x20;

* [Reflexer and RAI Explained, defiprime.com](https://defiprime.com/reflexer) April 2021
* [Solange Gueiros - Reflexer.finance tutorial for beginners: how to get started](https://solangegueiros.medium.com/reflexer-finance-tutorial-how-to-create-an-account-and-a-safe-on-kovan-testnet-f5aa2fdc2092) March 2021
* [Ameen Soleimani - A Money God RAIses](https://ameensol.medium.com/a-money-god-raises-rai-is-live-on-ethereum-mainnet-f9aff2b1d331) February 2021
* [Defi Pulse - Crypto-Native Stability Built for DeFi](https://defipulse.com/blog/reflexer/) Febrary 2021
* [Bankless - DeFi needs trust minimized money - Stefan Ionescu](https://newsletter.banklesshq.com/p/defi-needs-trust-minimized-money) February 2021
* [Crypto AMA by Spencer Noon](https://crypto-ama.herokuapp.com/messages_reflexer.html) - February 2021

### Talks

* [EthCC 2021 - Control Theory & Cryptoeconomics](https://www.youtube.com/watch?v=Gr_8p2IpT8A) - Guillaume Felley July 2021
* [ETH Denver - The Centralized Risk of DeFi - Guillaume Felley](https://www.youtube.com/watch?v=AvtJ6P60r4w) February 2021
* [ETH Online - Rai: Building a Money God - Ameen Soleimani](https://www.youtube.com/watch?v=kDCqiZd4xkI) October 2020

### Press

* [Messari - The Art of Central Banking on Blockchains: Non Pegged Stablecoins March](https://messari.io/article/the-art-of-central-banking-on-blockchains-non-pegged-stablecoins) 2021
* [Decrypt - Reflexer Launches Alternative to Ethereum Stablecoin DAI, Called RAI](https://decrypt.co/58101/reflexer-launches-alternative-to-ethereum-stablecoin-dai-called-rai) February 2021
* [TheBlock - Reflex indexes for more stable collateral assets in DeFi](https://www.theblockcrypto.com/genesis/90930/reflex-indexes-for-more-stable-collateral-assets-in-defi) January 2021
* [Coindesk - Reflexer Labs Raises $1.7M to Build a Somewhat-Stable Coin for DeFi](https://www.coindesk.com/eth-lite-reflexer-labs-raises-1-7m-to-build-a-somewhat-stable-coin-for-defi) August 2021


# FLX Mechanics

## 1. Overview

The FLX token has two main functions inside the RAI protocol:

* Backstop mechanism: FLX stakers are the first line of defense in case the RAI protocol goes underwater. The second line of defense is with debt auctions that mint new FLX and auction it in exchange for RAI
* Ungovernance: once governance minimization is finalized, FLX holders will be able to remove control from any remaining components in RAI or, if needed, continue to manage components that may be challenging to ungovern (such as oracles or any other component interacting with other protocols)

## 2. RAI Resource Flow

Before the protocol is governance minimized, RAI will be set up so that stability fees (borrow rate charged to Safes that mint RAI) flow in three places:

* The stability fee treasury, which is a smart contract in charge with paying for oracle updates or any other contract meant to automate RAI parameters
* FLX stakers, which are the first line of defense for the protocol
* Buyback and burn, which is meant to auction RAI in exchange for FLX which is subsequently burned

In the case of FLX stakers, the RAI that accrues for them is auctioned in exchange for FLX. The FLX proceeds from the auction are then sent to the staking pool.\
\
As for buyback and burn, RAI is first accrued in the protocol's balance sheet. Once there's enough RAI in the balance sheet, the protocol can start to auction some of it in exchange for FLX that is then burned.

To visualize all this, you can check the diagram below:

![](/files/-MgQbThRT20MvC16AqVK)

**NOTE**: RAI only flows to the stability fee treasury, to stakers and in the protocol's balance sheet when the borrow rate charged to Safes is positive. When the borrow rate is negative, the protocol only uses funds from the balance sheet to repay RAI debt from all Safes.

## 3. FLX and the Money God League

FLX is also at the core of the Money God League as seen [here](https://community.reflexer.finance/t/another-new-money-god-introducing-h2o/131) and [here](https://community.reflexer.finance/t/a-new-money-god-introducing-volt/120). The Money God League is presented on [this page](https://docs.reflexer.finance/the-money-god-league/intro-to-the-league).


# FAQ

Frequently asked questions about RAI and GEB

### What is RAI?

RAI is an ETH backed stable asset with a [managed float regime](https://en.wikipedia.org/wiki/Managed_float_regime). The RAIUSD exchange rate is determined by supply and demand while the protocol that issues RAI tries to stabilize its price by constantly de or revaluing it.

The supply and demand mechanic plays out between two parties: SAFE users (those who generate RAI with their ETH) and RAI holders.

Compared to protocols that try to defend a [fixed exchange rate](https://www.investopedia.com/terms/f/fixedexchangerate.asp) between their native stable asset (pegged coin) and fiat (DAI/USD, sUSD/USD etc), RAI's monetary policy offers a couple of advantages:

* Flexibility: the protocol can devalue or revalue RAI in response to changes in RAI's market price. This process transfers value between SAFE users and RAI holders and incentivizes both parties to bring the market price back to a target chosen by the protocol. The mechanism is similar to countries [devaluing](https://www.investopedia.com/terms/d/devaluation.asp) or [revaluing](https://www.investopedia.com/terms/r/revaluation.asp) their currencies in order to combat a trade imbalance. The "trade imbalance" in RAI's case happens between RAI and SAFE users
* Discretion: the protocol itself is free to change the target exchange rate to its own advantage. It can attract or repel capital whenever it wants.

At the same time, a managed float can cause uncertainty due to the fact that the price varies day by day.

### How does RAI work/behave?

The long term price trajectory of RAI is determined by the demand for ETH leverage. RAI tends to appreciate if SAFE users deleverage and/or RAI users long and it depreciates in case SAFE users leverage and/or RAI users short.

To better understand how RAI behaves, we need to analyze its monetary policy which is made out of four elements:

* Redemption price: this is the price that the protocol wants RAI to have on the secondary market (e.g on Uniswap). The redemption price is used by SAFE users to mint RAI against ETH and it is also used during Global Settlement in order to allow both SAFE and RAI users to redeem collateral from the system. The redemption price almost always floats and it does not target any specific peg.
* Market price: this is the price that RAI is traded at on the secondary market (on exchanges).
* Redemption rate: this is the rate at which RAI is being devalued or revalued. The process of devaluing/revaluing RAI consists in the redemption rate changing the redemption price.
* Global Settlement: settlement consists in shutting down the protocol and allowing both SAFE and RAI users to redeem collateral from the system. Settlement uses the redemption (and not the market) price to calculate how much collateral can be redeemed by each user.

Let's walk through an example of how RAI is revalued in case of ETH capital inflow (aka people are bullish on ETH):

* At time T1: ETH price is $500, RAI's market and redemption prices are both $5
* At time T2: ETH price surges to $1000. RAI SAFE users suddenly have more borrowing power and generate more RAI against their collateral. SAFE users sell RAI on the secondary market (Uniswap), causing RAI's market price to crash to $4.
* At time T3: ETH remains at $1000 and RAI's market price is still $4. The system wants the market price to get close to the redemption price. In order to eliminate the imbalance between the market/redemption prices, the system starts to revalue RAI. Revaluing consists in setting a positive redemption rate which makes the redemption price grow every second.
* At time T4: ETH remains at $1000. RAI's redemption price is now $5.1. SAFE users are starting to realize that they can now borrow less RAI per one ETH, they can redeem less ETH during Settlement (because RAI is now more expensive) and that it will be more expensive to close their SAFE once the market price follows the redemption price. At the same time, RAI holders are starting to realize that they can redeem more and more ETH during settlement
* At time T5: ETH remains at $1000. RAI's redemption price is now $5.2. RAI's market price surged to $5.2 as a result of SAFE users buying RAI in order to close their positions as soon as possible instead of later on when RAI is more expensive

When RAI is devalued (in case of ETH capital outflow), the opposite thing happens:

* SAFE users realize that they can mint more RAI against their ETH and that they will be able to buy cheap RAI once the market price tanks
* Token holders realize that they can redeem less ETH during Settlement and they need to short RAI

### Is RAI a rebase token?

No. The protocol doesn't change the amount of tokens you have. Rather, it changes the target price that the protocol wants RAI to have on exchanges.

### Why would I hold RAI when the system devalues the token?

This is exactly what the system wants you to ask yourself when it charges a negative redemption rate. The system is trying to incentivize RAI holders to sell and bring the market price down and close to the redemption price.

### Isn't RAI growth bounded by ETH growth?

Short answer: yes. Nevertheless, we decided to build a pure ETH system for several reasons:

* Social scalability: we believe the most successful DeFi protocols will be the ones that act as a trust minimized operating system. You can build on top of them without the fear that the rules will drastically change and break your application. For this reason we also want to progressively remove control over RAI.
* Simplicity: it is easier to explain RAI's behaviour in contrast to ETH as opposed to a basket of assets.
* Proof of concept: a system backed by a single collateral type is easier to manage than a multi-collateral one. It allows us to test our hypotheses without layering extra risk and overhead

### Can you summarize the behavior of the RAI redemption rate?

1. When RAI's market price > redemption price for a sustained period of time, the redemption rate will become negative
2. When RAI's market price < redemption price for a sustained period of time, the redemption rate will become positive
3. When RAI's market price = redemption price for a sustained period of time, the redemption rate will settle at a steady state (that may be non zero)

### What is the difference between the redemption rate and the borrow rate?

A system like RAI has two types of rates:

* The borrow rate which is an interest rate charged on open SAFEs. The borrow rate will usually be fixed or bounded
* The redemption rate: this is the rate at which RAI (or RAI-like assets) are devalued or revalued

### Why would I want to mint RAI?

* Getting paid for opening and managing SAFEs: when RAI is devalued, SAFE users are "paid" because the value of their debt shrinks compared to the value of their collateral
* Capped borrow rate: in the long run, RAI will have a capped (and small) borrow rate which makes the cost of maintaining a SAFE more predictable. Governance can, in theory, set the borrow rate to 0% although this prevents the system from accruing surplus that's [used to incentivize keepers](https://docs.reflexer.finance/system-contracts/sustainability-module/stability-fee-treasury) to update core components such as oracles and the PID. A 0% borrow rate would also prevent the protocol from building a surplus buffer meant to settle bad debt that couldn't be covered by collateral auctions
* Insurance for SAFEs: in the long run we can allow SAFE users to attach a wide variety of insurance contracts meant to protect their positions against liquidation
* No exposure to assets with counterparty risk: RAI will only be backed by ETH. Borrowers are not exposed to riskier crypto assets or real world collateral
* Superior collateral factors: as we improve the efficiency of our [collateral auctions](https://docs.reflexer.finance/system-contracts/auction-module/fixed-discount-collateral-auction-house) and add insurance contracts for SAFEs, we can lower the collateral requirements for borrowing RAI

### What are RAI's use-cases?

The following is a non-exhaustive list of use-cases we envision for RAI:

* Portfolio diversification: RAI offers dampened exposure to ETH's price moves
* DeFi collateral: RAI can be used as an ETH supplement or alternative collateral in DeFi protocols due to the fact that it dampens ether's price moves and gives users more time to react to market shifts
* DAO reserve asset: DAOs can keep RAI on their balance sheet and get exposure to ETH without being affected by its full market swings

### Will RAI always return to the same initial value/peg?

RAI is not designed to be pegged to anything, so it may never return to the same value it started at. Similar to many fiat currencies (EUR, GBP etc), RAI will float around, being influenced by market forces (supply & demand) and by the incentives that the PID controller offers to SAFE users and RAI holders.


# RAI Use-Cases

An incomplete list of things you can build with or on top of RAI

### **Unique Money Markets**

If Alice pays 5% per year to borrow RAI from a money market and the RAI redemption rate is -10% per year, she is effectively earning 5% year. This is because of the expectation that RAI's market price will go down by 10% in one year. On the other hand, Bob might be lending RAI at 4% per year, but if the redemption rate is -10%, his net rate is -6%.\
\
There's the other scenario where Bob is lending RAI at 4% per year and the redemption rate is 10% per year. In total, Bob is earning 14% annually on his position (assuming that RAI will appreciate in value by 10% in the next year). Meanwhile, Alice, who's borrowing RAI at 5% per year, is paying a total of 15% (5% as the money market borrow rate plus the expected 10% appreciation in RAI's price over one year).

### Stacked Funding Rates

If an exchange or protocol decides to offer RAI perpetuals, they will essentially allow traders to stack funding rates on top of each other. \
\
The redemption rate is similar but not identical to a funding rate. The net funding rate on a RAI perpetual is a combination of the funding rate on the platform/exchange that lists the perpetual and the redemption rate.\
\
RAI is the first asset ever created that allows this.

### Options

A developer can build an options protocol which takes into account changes in the redemption rate in order to determine the price of puts/calls. This is because the redemption rate can be thought of as an intrinsic interest rate for RAI.

### Pegged Coins/Synthetic Assets

Projects building pegged coins can use RAI as a more stable alternative to ETH. In case of a severe ETH market crash, RAI can offer its holders more time to unwind their positions before they get liquidated.

### Yield Aggregator

Protocols that deploy capital in order to get the best yield for their users (e.g [Yearn](https://yearn.finance/)) can leverage RAI (and its intrinsic redemption rate) to boost returns. For example, combining RAI's positive redemption rate with lending on [Compound](https://compound.finance/) or [Aave](https://aave.com/) is one possible way to optimize earnings.

### **Sophisticated Arbitrageurs**

Arbitrageurs (or otherwise traders in general) can look at the redemption price behavior and combine this datapoint with others (e.g market sentiment) in order to find the ideal time when they should execute a trade.

Some arbers can offer specialized RAI trading services to pools of capital. They can be allowed to flashloan funds and split the profit with the pool.

### **Portfolio Management Strategies**

Anyone can create [Set Protocol](https://www.tokensets.com/) sets or [Balancer](https://balancer.finance/) pools that offer diversified exposure to RAI's redemption rate as well as other yield bearing assets (e.g cTokens, aTokens).


# Multi-chain RAI

## Fantom

RAI Address: [0xa71353bb71dda105d383b02fc2dd172c4d39ef8b](https://ftmscan.com/address/0xa71353bb71dda105d383b02fc2dd172c4d39ef8b)

Currently, RAI holders can port their tokens to [Fantom RAI](https://ftmscan.com/token/0xa71353bb71dda105d383b02fc2dd172c4d39ef8b) using the [Multichain.xyz](https://multichain.xyz/) bridge. RAI holders should keep in mind that they need to get FTM first in order to send transactions on Fantom. One way to [get FTM](https://fantom.foundation/where-to-buy-ftm/) is on [Sushiswap](https://app.sushi.com/swap) and then use Multichain.xyz to transfer your Ethereum FTM to Fantom FTM.

Once you have FTM and RAI on the Fantom chain, you should also make sure you have [Fantom set up](https://docs.fantom.foundation/tutorials/set-up-metamask) in Metamask (or any other wallet you're using).

The RAI address on Fantom can be found [here](https://ftmscan.com/token/0xa71353bb71dda105d383b02fc2dd172c4d39ef8b).

### Fantom RAI Integrations

The first protocol that started to support RAI on Fantom is [SpiritSwap](https://app.spiritswap.finance/#/).

## Polygon

RAI Address: [0x00e5646f60AC6Fb446f621d146B6E1886f002905](https://polygonscan.com/address/0x00e5646f60ac6fb446f621d146b6e1886f002905)\
\
RAI holders can trade on [RAI/USDC Kyber DMM](https://polygon-info.dmm.exchange/pair/0x00e5646f60ac6fb446f621d146b6e1886f002905_0x2791bca1f2de4661ed88a30c99a7a9449aa84174).&#x20;

### Polygon RAI Integrations

BaoDAO also build a synthetics platform called [Polly](https://pollyfinance.com/?ref=null) and decided to use RAI for their [incentives pools](https://gov.bao.finance/t/accelerated-polly-tokenomics-proposal/813).

## Solana

RAI Address: [XXTrSXmzS7MvjYP5QGVbFppbvF3gXBmbezsphQbVG54](https://explorer.solana.com/address/XXTrSXmzS7MvjYP5QGVbFppbvF3gXBmbezsphQbVG54).

In order to interact with Solana you can use the [Phantom wallet](https://phantom.app/).&#x20;

## Avalanche

RAI Address: [0x97Cd1CFE2ed5712660bb6c14053C0EcB031Bff7d](https://cchain.explorer.avax.network/address/0x97Cd1CFE2ed5712660bb6c14053C0EcB031Bff7d/transactions)

You can get your RAI from Ethereum to Avalanche using [Anyswap](https://anyswap.exchange/#/bridge?bridgetoken=0x97cd1cfe2ed5712660bb6c14053c0ecb031bff7d\&network=43114).

### Avalanche RAI Integrations

You can swap RAI on Avalanche using Pangolin. The main pair is [RAI/AVAX](https://info.pangolin.exchange/#/pair/0xd89dd8dcef91bee0a46d57681473b5ce824d3adf).

## Arbitrum

RAI Address: [0xaeF5bbcbFa438519a5ea80B4c7181B4E78d419f2](https://arbiscan.io/token/0xaef5bbcbfa438519a5ea80b4c7181b4e78d419f2)\
\
You can brdge RAI from Ethereum to Arbitrum using the official [Arbitrum bridge](https://bridge.arbitrum.io/).

### Arbitrum RAI Integrations

RAI can be traded on Arbitrum using [Uniswap v3](https://app.uniswap.org/#/swap).

## Optimism

RAI Address: [0x7FB688CCf682d58f86D7e38e03f9D22e7705448B](https://optimistic.etherscan.io/token/0x7FB688CCf682d58f86D7e38e03f9D22e7705448B)\
\
You can brdge RAI from Ethereum to Optimism using the official [bridge](https://gateway.optimism.io/).

### Optimism RAI Integrations

RAI can be traded on Optimism using [Uniswap v3](https://app.uniswap.org/#/swap).


# RAI Integrations

### Money Markets

Fuse - <https://app.rari.capital/fuse/pool/9>, <https://app.rari.capital/fuse/pool/24>, <https://app.rari.capital/fuse/pool/18>

Yearn - <https://yearn.finance/vaults>�

Idle - [https://beta.idle.finance/#/dashboard/best/RAI](https://idle.finance/#/dashboard/best/RAI)

Aave - <https://app.aave.com/reserve-overview/RAI?pool=AaveV2>

BarnBridge - <https://app.barnbridge.com/smart-yield/stats?m=aave/v2&t=RAI>

WePiggy - <https://app.wepiggy.com/access>

88mph - <https://88mph.app/earn>

### RAI as Collateral/Reserve Asset

Fei Protocol - <https://etherscan.io/address/0x25d60212D47Dd8F6Ff0469367E4c6C98Cd3411A5>�

Frax Finance

Metacartel Ventures

Gnosis DAO

PieDAO

dxDAO

### Spend RAI

Coinbase Card - <https://www.coinbase.com/card>

Eidoo (UK & EU members) - <https://eidoo.io/>

Uphold - <https://uphold.com/en/debit-card>

Mover - <https://viamover.com/>

### Exchanges

Curve v1 (Ethereum L1) - [curve.fi/rai](https://t.co/FyP1mD9uDa)&#x20;

mStable - <https://mstable.app/#/musd/swap>

Uniswap v3 RAI Markets - <https://info.uniswap.org/#/tokens/0x03ab458634910aad20ef5f1c8ee96f1d6ac54919>

Uniswap v2 RAI/ETH - <https://info.uniswap.org/token/0x03ab458634910aad20ef5f1c8ee96f1d6ac54919>&#x20;

Uniswap v2 RAI/DAI - <https://info.uniswap.org/pair/0x4a0ea6ad985f6526de7d1ade562e1007e9c5d757>&#x20;

Sushiswap RAI Markets - <https://sushiswap.vision/token/0x03ab458634910aad20ef5f1c8ee96f1d6ac54919>

KyberSwap Markets - <https://analytics.kyberswap.com/token/0x03ab458634910aad20ef5f1c8ee96f1d6ac54919>

KeeperDAO Trade - <https://app.keeperdao.com/trade>

CowSwap - <https://cowswap.exchange/#/swap>

Loopring - <https://exchange.loopring.io/swap/RAI-ETH>

Coinbase Pro - <https://exchange.coinbase.com/trade/RAI-USD>�

### Dashboards & Apps

DeBank - <https://debank.com/projects/reflexer?mode=stats>&#x20;

DeFi Saver - <https://app.defisaver.com/reflexer/manage>&#x20;

LoanScan - <https://loanscan.io/borrow>&#x20;

Zapper - <https://zapper.fi/protocols/reflexer>&#x20;

Zerion - <https://app.zerion.io/invest/asset/RAI-0x03ab458634910aad20ef5f1c8ee96f1d6ac54919>

Sablier - <https://sablier.finance/>��


# Intro to The League

## 1. Overview

The Money God League is an initiative meant to bring non-pegged stable assets (stablecoins) into the mainstream. The League is also devoted toward making control theory a common framework used in a wide variety of DeFi related projects.

## 2. Who Can Be in The League?

Initially, the Reflexer team will seek to work with a few established projects that have a clear idea of what they want to achieve with their stable assets and also have a roadmap with collateral assets that they want to add in the new protocols.

## 3. Entering the League

For now, you can simply join [Reflexer's Discord](https://discord.gg/QYBEw6Z) and start to talk with the core team about building a new Money God. More details will be released in the next few months.


# Governance Minimization Guide

Steps and details for minimizing governance over a GEB deployment

GEB governance minimization is a multi stage process at the end of which governance will not control or be able to upgrade most core contracts and many parameters will be set autonomously by other external contracts.

This guide will go over the requirements needed to governance minimize a GEB, infrastructure needed to automate parameter setting as well as the governance minimization stages that RAI (and possibly other stablecoins) will go through.

### &#x20;1. Requirements for Governance Minimization

In order for a GEB to be governance minimized, there are several requirements that need to be met:

* The protocol's governance must not add or plan to add any more collateral types
* All the infrastructure for governance minimization must have been audited and tested in production
* The system must accrue enough surplus in its main treasury so that it affords to pay for oracle, PID, state management etc costs for at least 6 months

### 2. How Much Can GEB Be Governance Minimized

Each component in GEB has varying degrees of governance minimization potential. The following is a (incomplete) list of contracts and which parameters will still need to be managed after governance minimization:

* **Accounting Engine** - governance may need to keep control over setting `systemStakingPool` until the pool is governance minimized; `initialDebtAuctionMintedTokens` and `debtAuctionBidSize` will need to be set by an external contract which will be connected to oracles (thus this external contract will not be fully gov minimized); an optional contract may set `surplusBuffer` so that it covers a specific percentage of the outstanding supply of system coins minus the surplus from the Accounting Engine and the one from the Stability Fee Treasury/ies; another external contract should reward addresses that call `popDebtFromQueue`
* **Collateral Token Adapters** - governance can completely remove control from these contracts
* **Coin** - governance can completely remove control from this contract
* **Collateral Auction House** - governance can completely remove control from these contracts
* **Debt Auction House** - governance can completely remove control from this contract
* **Surplus Auction House** - governance can completely remove control from this contract
* **Global Settlement** - once all the other core contracts are governance minimized, governance can remove control from this contract
* **ESM** - governance will need to set an external contract `thresholdSetter` that recomputes `triggerThreshold` according to the latest outstanding supply of protocol tokens; this can only be done once; the rest of the contract can be governance minimized
* **Liquidation Engine** - governance will keep control over connecting and disconnecting saviours; governance may optionally authorize an external contract to automatically set`onAuctionSystemCoinLimit`
* **Oracle Relayer** - governance may be allowed to set the redemption rate to 0% only; apart from this governance can completely be removed
* **SAFE Engine** - governance will need to allow an external contract to automatically set `debtCeiling`s for every collateral type once every couple of hours/days; governance should also allow a contract to adjust `debtFloor`s according to the latest redemption price; depending on how many collateral types are in a system, it may not be feasible to automatically set debt ceilings but rather manually vote on lowering/raising them
* **Stability Fee Treasury** - governance should keep maintaining this component over the long run
* **Tax Collector** - governance may optionally want to have bounded control over setting stability fees; by bounded we mean that there will be upper and lower bounds for setting each collateral's fee e.g between 1-2% annually; apart from this, the contract can be governance minimized
* **OSMs/DSMs** - governance will need to keep maintaining these components in the long run because they are connected to medianizers which are in turn connected to external components (oracles)
* **Medianizers** - governance will need to keep maintaining these components in the long run because they are connected to external components
* **FSM Governance Interface** - governance will need to keep maintaining this component in the long run because it is managing OSMs/DSMs which are not gov minimized
* **DSPause** - this components is part of the governance module and it will be, by definition, governed in the long run
* **Protocol Token Authority** - governance can completely remove control from this contract once the Debt Auction House is governance minimized
* **Protocol Token Printing Permissions** - governance can completely remove control from this contract once the Debt Auction House is governance minimized
* **Protocol Token** - governance will not have control over this component (manually minting tokens or changing allowances so other addresses can mint) once they remove control from the Protocol Token Authority and the Protocol Token Printing Permissions
* **PID Controller** - governance may need to keep some control over this component in the long run; the community will have more insight into how much control it will need after a GEB has been running for at least 1 year on mainnet; one reason for maintaining (bounded) control is the fact that the controller should be paused when the system's stablecoin doesn't have enough liquidity on exchanges; **NOTE**: even if governance keeps some control over the PID, the `OracleRelayer` will have upper and lower bounds for the redemption rate so that a potential governance attack cannot immediately destroy the protocol
* **Saviour Contracts** - governance will need to keep maintaining these contracts in the long run because they are connected to external components
* **SAFE Saviour Registry** - governance will need to keep maintaining this contract in the long run because it's meant to whitelist/blacklist saviour contracts
* Treasury Reward Adjuster & RAI Fee Reward Adjusters - governance will need to keep maintaining these contracts as they manage treasury funds used to rewards addresses that update RAI & ETH oracles,&#x20;

### 3. Infrastructure for Automation

A couple of GEB contracts will need to authorize other components to automatically set some of their parameters post governance minimization. Here is the current list of external components for every GEB contract:

* **Liquidation Engine** - an optional contract that automatically sets `onAuctionSystemCoinLimit` as a percentage of the current amount of system coins minus the surplus accrued in the Accounting Engine and in the Stability Fee Treasury/ies
* **Accounting Engine** - an optional contract may set `surplusBuffer` so that it covers a specific percentage of the outstanding supply of system coins minus the surplus from the Accounting Engine and the one from the Stability Fee Treasury/ies; a mandatory contract that sets`initialDebtAuctionMintedTokens` and `debtAuctionBidSize` every once in a while according to the protocol token and system coin market prices
* **ESM** - `thresholdSetter` which automatically sets `triggerThreshold` as a percentage of the current outstanding supply of protocol tokens
* **Stability Fee Treasury** - governance may need to create external contracts to reset `total` allowances for addresses that have a `perBlock` allowance > 0 and allow the automatic setting of params such as `minimumFundsRequired`, `pullFundsMinThreshold` etc depending on the latest `redemptionPrice`
* **SAFE Engine** - a contract that periodically adjusts `debtCeiling`s for every collateral type; another contract that adjusts `debtFloor`s according to the latest `redemptionPrice` every couple of weeks; the implementation depends on every GEB's setup (how many collateral types it has, what percentage of system coins should be covered by each collateral etc)

Lastly, contracts that pull funds from the **Stability Fee Treasury** may need to have their `baseUpdateCallerReward` and `maxUpdateCallerReward` adjusted periodically depending on the latest `redemptionPrice`.

### 4. Governance Minimization Levels

There are three levels (or stages) of governance minimization that a GEB (like the one for RAI) will go through:

#### Level 1 - Deadline 14 Months Post Launch

In this stage, governance will remove control from:

* LiquidationEngine
* DebtAuctionHouse
* SurplusAuctionHouse
* Collateral Auction Houses
* OracleRelayer
* Coin (ERC20)
* CollateralJoin contracts
* Contracts that automate param setting in the protocol (besides Auto Surplus Buffer Setter)
* TaxCollector
* ESM

#### Level 2 - Deadline 18 Months Post Launch

In this stage, governance will remove control from:

* SAFEEngine
* AccountingEngine
* GlobalSettlement
* Lender of First Resort Pool (and adjacent contracts)
* RAI Controller
* ProtocolTokenAuthority (and as a result give up on the possibility to authorize/deauthorize new or old DebtAuctionHouses to print tokens)
* ProtocolTokenPrintingPermissions
* Auto Surplus Buffer Setter

#### Level 3

At this point, all remaining governance must be in the hands of the community. The community will judge the feasibility of fully removing control from more contracts (e.g the PID).


# GEB Risks

Using a GEB deployment and/or its associated stable asset doesn't come without risk. Before you decide to deposit your assets in the protocol or acquire the stable asset, you should do your research and understand the risks involved.

This section will only give an overview of the main risks associated with GEB. If you'd like to dive deeper, you can check out every [module](https://docs.reflexer.finance/system-contracts/core) in the System Contracts section.

You can also check our original [whitepaper](https://github.com/reflexer-labs/whitepapers).

### Smart Contract Bugs

The core GEB contracts were audited by [OpenZeppelin](https://github.com/reflexer-labs/geb-audits/tree/master/open-zeppelin/core-contracts). Other helper contracts were audited by [Quantstamp](https://github.com/reflexer-labs/geb-audits/tree/master/quantstamp/helper-contracts).

However, security audits do not completely eliminate smart contract risk. We urge you not to put your life savings or money you can't afford to lose into any GEB deployment or its associated stable asset.

### Admin Keys

The very first GEB deployment will need to be fully managed in its initial stages because of the risks tied to the PID controller managing the system as well as the need for more infrastructure to be built so the protocol can be automated.

Subsequent GEB deployments may or may not be governed, depending on whether the community will want to add more collateral types as time goes by.

While a GEB is fully managed/governed, almost all of its components can be upgraded and manually set up. Once it's governance minimized, only a few components can be upgraded and fewer parameters can be changed.

You can take a look at the [Governance Minimization Guide](https://docs.reflexer.finance/governance-minimization-guide) to see what will need to be done so that a GEB can be governance minimized. Stay alert for more updates from the Reflexer team regarding a timeline for RAI governance minimization.

Until most of the RAI protocol is governance minimized, the protocol is managed by [this multisig](https://etherscan.io/address/0x427A277eA53e25143B3b509C684aA4D0EB8bA01b).

### PID Controller

PID control is still a novel concept in DeFi. No other stable asset prior to RAI has been managed by an on-chain controller and there is no historical data that can help with the controller's modelling and simulations.

If the controller is too slow it may be completely ineffective in stabilizing RAI or other stablecoins. If it's too strong, it may destabilize the system.

**NOTE**: check out more PID failure modes in [this section](https://docs.reflexer.finance/pid-failure-modes-and-responses).

### Suboptimal Parameters

Governance may set suboptimal parameters for:

* Debt auctions which can lead to an excessive amount of protocol tokens being printed
* Collateral auctions which may not give a good enough incentive for bidding
* Global Settlement which may delay SAFE processing and collateral redemption indefinitely

There are many more parameters which may be suboptimal. Check the [System Contracts modules](https://docs.reflexer.finance/system-contracts/core) for more details.


# PID Failure Modes & Responses

How to react in different scenarios where the redemption rate is ineffective

## Failure Scenarios

The following is a list of known PID failure modes and possible responses or fixes for each one of them. Note that in order to minimize the risk of the PID failing, governance should activate it only after the stablecoin has a minimum, mandatory liquidity level on exchanges as well as plenty of users interacting with the system.&#x20;

### Market Manipulation

Although improbable (in case the PID is fed a TWAP feed for the stablecoin market price) after a stablecoin gets to scale, market manipulation is always a concern that can make the PID controller destabilize the system. In this scenario, governance has two options: pause the controller until there is more liquidity on exchanges or globally settle the system.

### Lack of Liquidity on Exchanges

Governance must ensure at all times that there is enough stablecoins on exchanges vs stablecoins locked in other applications. This is why governance must specify two KPIs:

1. An absolute minimum amount of liquidity that must be on the exchanges from which the PID is pulling market price data
2. A minimum percentage of stablecoins out of the total oustanding supply that must be at all times on exchanges vs the percentage of stablecoins locked/used in other applications

In case the stablecoin liquidity drops below any of the two limits specied above, governance is advised to pause the PID and restart it only after the liquidity improves.

**NOTE**: lack of liquidity will increase the risk of market manipulation (as seen in Proto RAI).

### Skewed Incentives

In case governance sets up a system to incentivize the growth of a stablecoin, these incentives may interfere with the PID's and cause the system to become unstable. In this scenario, governance should look at the following solutions:

1. Offer less growth incentives over a longer period of time
2. Pause the controller until the growth campaign/s end
3. Completely stop growth campaigns
4. Find a way to incentivize market making alongside growth

### Negative Feedback Turning Positive

There are cases when, even if there is no market manipulation, no skewed incentives and there's plenty of liquidity on exchanges, the market might not react to the redemption rate incentives and the redemption price would continue to go in a single direction for a long period of time.

In this scenario there are three possible solutions:

1. Temporarily pause the PID and wait for the market to come closer toward redemption
2. Temporarily pause the PID and build a second controller that modifies the stability fee. In this scenario the redemption rate controller would only be used when the market price is consistently above redemption and the stability fee controller would be used when the market price is below redemption. Choosing this option means that governance may need to have long term control over the [TaxCollector](https://docs.reflexer.finance/system-contracts/money-market-module/tax-collector) and there will need to be more governance over rate setting in general.
3. Trigger global settlement and allow the system to shut down using the redemption price.

## Failure Prevention

In order to make market manipulation as expensive as possible, we propose the following liquidity thresholds for the RAI stablecoin:

* There must be at least $2M worth of liquidity on the exchange/s that the RAI oracle is pulling a price feed from
* At least 3% of the RAI supply must be on the exchange/s from which the system is pulling a price feed from

In addition to this, the PID controller should not be set to its full force right when RAI is launched as it may destabilize the system.


# RAI Uniswap V2 Mint + LP Incentives Program

## Overview

The RAI Mint + LP strategy requires that participants mint RAI **and** provide RAI/ETH liquidity on Uniswap v2 at the same time in order to accrue retroactive rewards.

## How It Works

1. Go to [app.reflexer.finance](https://app.reflexer.finance/) or [DeFi Saver](https://app.defisaver.com/reflexer/manage) and mint some RAI.
2. Go to the [RAI/ETH Uniswap v2 pool](https://app.uniswap.org/#/add/v2/ETH/0x03ab458634910AaD20eF5f1C8ee96F1D6ac54919) and add the RAI you minted as liquidity

You do **not** accrue rewards if:

* You provide RAI/ETH liquidity without minting RAI (e.g buy from the pool and LP)
* You mint RAI without adding RAI/ETH liquidity

If you mint more RAI than the amount of RAI you provide as liquidity, you only accrue rewards on the amount you minted & LPed. Likewise, if you add more RAI as liquidity than you mint, you accrue rewards only on the RAI amount that you both minted and LPed.\
\
In short, you can think of mint + LP as a formula: `RAI Eligible for Rewards = min(RAI from LP token balance of an address`, `Total RAI debt from Safes owned by the address)`.

## Important Notes

* You **must** use the same address to mint RAI and provide Uniswap v2 RAI/ETH liquidity
* The Uniswap v2 RAI/ETH LP tokens **must** stay on the same address that you used to mint RAI and provide liquidity
* To see the minimum amount of RAI you must mint on mainnet, check the first [onboarding page in the app](https://app.reflexer.finance/)
* If you open multiple Safes with the same address, your total RAI debt will be the sum of all RAI minted by each of your Safes
* If your Safe gets liquidated, the amount of minted RAI you have decreases by the amount of RAI that got confiscated
* If you would like to use a [Gnosis Safe](https://gnosis-safe.io/) to manage your RAI positions and provide liquidity on Uniswap, you can connect to the Safe using WalletConnect and then use [app.reflexer.finance](https://app.reflexer.finance/)

## Scenarios

#### 1. I already minted RAI but did not provide any liquidity

Go to the [Uniswap v2 RAI/ETH pool](https://app.uniswap.org/#/add/v2/ETH/0x03ab458634910AaD20eF5f1C8ee96F1D6ac54919) in order to provide liquidity. You should add less or the same amount of RAI you previously minted in the pool. If you provide more RAI as liquidity than the amount of RAI you minted, you only accrue rewards on the amount you both minted and LPed.

#### 2. I already added RAI/ETH liquidity but did not mint any RAI

You need to mint RAI in order to accrue rewards. To determine the maximum amount of RAI that you should mint, do the following:

* Go to the [Uniswap v2 RAI/ETH pool](https://app.uniswap.org/#/add/v2/ETH/0x03ab458634910AaD20eF5f1C8ee96F1D6ac54919) and check how much RAI you would get back if you were to withdraw all your liquidity. Take note of the amount.

![](/files/-MdrMIs46tJC5aS7GtHO)

* Go to [app.reflexer.finance](https://app.reflexer.finance/) or [DeFi Saver](https://app.defisaver.com/reflexer/manage) and mint RAI up to the amount that you already provided in the pool.
* You’re now accruing rewards on the amount of RAI that you both minted and LPed.

#### 3. I minted more RAI than the amount of RAI I added as liquidity

Currently you’re only accruing rewards for the amount you both minted and LPed. If you would like to accrue more rewards, you need to add more RAI as liquidity in the [Uniswap v2 RAI/ETH pool](https://app.uniswap.org/#/add/v2/ETH/0x03ab458634910AaD20eF5f1C8ee96F1D6ac54919).

**4. I minted less RAI than I can currently claim from the Uniswap v2 pool**

Similar to the second scenario, if you would like to be eligible for more rewards, you need to check the amount of RAI that you can currently withdraw from the RAI/ETH pool and determine how much more RAI you need to mint.

## Questions

#### If I provide X RAI as liquidity in the RAI/ETH Uniswap v2 pool, I might not get the same amount of RAI back when I withdraw liquidity later on. What should I do?

The retroactive scripts take this situation into account. You do not need to do anything.


# RAI Uniswap V3 Mint + LP Incentives Program (Inactive)

Inactive

## Overview

The RAI Mint + LP strategy requires that participants mint RAI **and** provide RAI/DAI liquidity on a certain range on Uniswap v3. The rewards will be claimable monthly around the 15th of the month.\
\
The RAI/DAI 0.05% fee pool concerned is [here](https://info.uniswap.org/#/pools/0xcb0c5d9d92f4f2f80cce7aa271a1e148c226e19d).

There are 2 important conditions:

* The position needs to be at least 5 ticks wide (5 increments on the official Uniswap v3 UI, which is 0.5% wide) **and** include the market price and the redemption price. If the position is narrower than 5 ticks, or doesn't include the market price or the redemption price, you will not accrue any rewards. If your position is larger than 5 ticks you will earn less rewards depending on your liquidity concentration.&#x20;
* The RAI debt value in USD in the Safe, needs the cover the full LP position value (RAI + DAI) to earn maximum rewards. If the RAI debt is less than the total LP position value, a proportional discount is applied to your reward amount.&#x20;

## How It Works

1. Go to [app.reflexer.finance](https://app.reflexer.finance/) or [DeFi Saver](https://app.defisaver.com/reflexer/manage) and mint some RAI.
2. Go to the [RAI/DAI Uniswap v3 pool](https://info.uniswap.org/#/pools/0xcb0c5d9d92f4f2f80cce7aa271a1e148c226e19d) and add the RAI you minted as liquidity

When choosing the range, make sure to include both the redemption and the market price:

![](/files/sHZ5JpymAgg9JEoaFAl5)

You can find the redemption price at <https://stats.reflexer.finance/>. The RAI market price will be displayed directly on the Uniswap v3 UI.

To help you to find the best range, we provide recommendations at <https://app.reflexer.finance/#/earn/incentives>.&#x20;

**Important:** both the redemption price and market price move over time. If any of the prices move outside of your LP range, you won't accrue any LP rewards. If you intend to move/rebalance your position less frequently, you can pick a wider range.&#x20;

#### Additional notes:

* We always assume 1 DAI = 1 USD for the calculations
* Rewards are calculated using [this](https://github.com/reflexer-labs/uni-v3-incentive-reward-script) script
* You **must** use the same address to mint RAI and provide Uniswap v3 RAI/ETH or RAI/DAI liquidity
* The Uniswap v3 RAI/DAI LP tokens **must** stay on the same address that you used to mint RAI and provide liquidity
* If you open multiple Safes with the same address, your total RAI debt will be the sum of all RAI minted by each of your Safes
* If you have several LP positions with the same address, the total sum of the liquidity will be considered for rewards.
* Only positions from the official Uniswap V3 NFT manager are supported (used by the official UI at <https://app.uniswap.org/#/pool>). Positions directly minted on the pool contract are **not** supported.
* If your Safe gets liquidated, the amount of minted RAI you have decreases by the amount of RAI that got confiscated

## Examples

Current redemption price: $3.0322\
Current market price: $3.03897 (DAI per RAI but we assume 1 DAI = 1 USD)

Bob: Mint 1000 RAI + LP between 3.0312 and 3.0403 for a total position value of $3038.97\
Alice: Mint 1000 RAI + LP between 3.0281 and 3.0433 for a total position value of $3038.97 \
Sophie: Mint 1000 RAI + LP between 3.0221 and 3.0524 for a total position value of $3038.97&#x20;

George: Mint 500 RAI + LP between 3.0281 and 3.0433 for a total position value of $3038.97\
Robert: Mint 1000 RAI + LP between 3.0281 and 3.0372 for a total position value of $3038.97\
Richard: Mint 1000 RAI + LP between 3.0342 and 3.0433 for a total position value of $3038.97

* Bob earns earns 0 FLX rewards because his range is narrower than 5 ticks
* Both Alice and Sophie are earning rewards. Alice earns twice more reward than Sophie because her range is half the size.&#x20;
* George earns about half the rewards that Alice gets because his debt value is only 500 RAI (= $1519.48) which is only half of his position value ($3038.97).
* Robert earns 0 FLX rewards because his range does not include the market price&#x20;
* Richard earns 0 FLX rewards because his range does not include the redemption price


# FLX Staking

## 1. Overview

Stakers are in charge with protecting the RAI protocol from insolvency. They stake [FLX/ETH Uniswap v2 LP tokens](https://v2.info.uniswap.org/pair/0xd6f3768e62ef92a9798e5a8cedd2b78907cecef9) in a smart contract that then constantly checks whether RAI is well capitalized.

In case the protocol is undercapitalized (has debt that is not backed by collateral), the staking pool will start to auction FLX/ETH LP tokens in exchange for RAI that is then used to bring the protocol above water. Stakers will get diluted in this process.\
\
In exchange for protecting the protocol, stakers receive more FLX.

## 2. Staking Pool Parameters

### Mainnet

* Exit delay (thawing period): 21 days
* Reward unlock period: 3 months. Locked rewards are unlocked linearly during a 3 month time period from the moment a staker requests that they claim their rewards
* Percentage of rewards unlocked over 3 months: 75%
* Percentage of rewards that can be claimed right away (no unlock): 25%
* Percentage of LP tokens in the pool that can be slashed/auctioned: 30% (the rest of the pool isn't auctioned/slashed)

### Kovan

* Exit delay (thawing period): 1 minute
* Reward unlock period: 10 minutes. Locked rewards are unlocked linearly during a 10 minute time period from the moment a staker requests that they claim their rewards
* Percentage of rewards unlocked over 10 minutes: 75%
* Percentage of rewards that can be claimed right away (no unlock): 25%
* Percentage of LP tokens in the pool that can be slashed/auctioned: 30% (the rest of the pool isn't auctioned/slashed)

## 3. RAI Insolvency

The RAI protocol is "insolvent" when liquidations (collateral auctions) are not successful (cannot repay a Safe's debt by selling ETH) and they leave leftover RAI which is not backed by collateral anymore.

Liquidations can be unsuccessful when:

* Only a portion of RAI is received by the liquidation out of the total amount of RAI that was requested
* The value of ETH drops during a liquidation and there isn't any incentive to bid with RAI (value of ETH is less than the value of RAI requested)
* The market price of RAI soars more than 10% above the redemption price which makes liquidations unprofitable

If there's too much unbacked RAI in the protocol, the system becomes insolvent. In case of insolvency, stakers are the first line of defense.

Anyone can call the staking pool to auction LP tokens immediately after the protocol becomes insolvent. In Section 2 above you can see the percentage of the staking pool that can be auctioned in exchange for RAI which is subsequently used to eliminate unbacked debt.

### Determining Insolvency

RAI being "insolvent" means that there must be at least `debtAuctionBidSize` unbacked RAI on the protocol's balance sheet. The `debtAuctionBidSize` can be automatically recomputed by the protocol approximately every 4 days (assuming that someone calls the protocol to recalculate the parameter). The current `debtAuctionBidSize` parameter value can be read from the [accounting engine](https://etherscan.io/address/0xcee6aa1ab47d0fb0f24f51a3072ec16e20f90fce#readContract) contract.

The staking pool can read the amount of unbacked debt that the [accounting engine](https://etherscan.io/address/0xcee6aa1ab47d0fb0f24f51a3072ec16e20f90fce#readContract) has and compare it to the `debtAuctionBidSize` value. If there's more unbacked debt than `debtAuctionBidSize`, it means that the protocol is insolvent and the staking pool can start to auction tokens.

## 4. Staking Walkthrough

First, you need to provide liquidity in this [FLX/ETH Uniswap v2 pool](https://app.uniswap.org/#/add/v2/0x6243d8cea23066d098a15582d81a598b4e8391f4/ETH) for mainnet and in [this pool](https://app.uniswap.org/#/add/v2/0x6e6eA84bb2fcE17AfCE8e1117DdC708142ef51c9/ETH) for Kovan.

![FLX/ETH Uniswap v2 Pool](/files/-MejiAOa6zHFLAQc9OZ4)

Once you receive your FLX/ETH LP tokens, head over [here](https://app.reflexer.finance/#/earn/staking) (for mainnet) and [here](https://app-kovan.reflexer.finance/earn/staking) (for Kovan) in order to see the staking dashboard.

![](/files/-MejqP0ukmeMp9qdAfvp)

In the Stake section, you can specify how many LP tokens you'd like to stake.&#x20;

![](/files/-MejuGOFE8irlquwAyug)

Once you stake, you will start to accrue rewards every block. You can claim rewards anytime using the **Claim Reward** button.

When you want to start unstaking, you can head over to the **Unstaking** section.

![](/files/-Mek0WLA-IUfLoAM0oAN)

Unstaking must be done in two stages:

* You request that a portion of your currently staked tokens should be unstaked
* You wait for the full thawing period until you can get your LP tokens back from the staking contract

![Thawing period passed and you can now withdraw your LP tokens](/files/-MekGNwasD8z0nBQrMij)

**There are also several important things you must keep in mind when you unstake:**

* The amount of tokens that are waiting to be unstaked **do not** count toward accruing rewards anymore. You only accrue rewards for the tokens that are both staked and are not waiting to be unstaked
* Take the following scenario: Alice has 10 tokens staked. She requests to unstake 5 tokens and has to wait 3 weeks to withdraw them from the contract. After 2 weeks, Alice requests that she unstakes another 3 extra tokens (so she's only earning rewards with 2 tokens now). Alice must wait 3 weeks from the moment of the **second unstake request** in order to withdraw the whole 8 tokens from the contract
* Take another scenario: Alice has 10 tokens staked. She requests to unstake 5 tokens and has to wait 4 weeks to withdraw them from the contract. After 5 weeks, Alice does not unstake the 5 tokens but rather requests that she unstakes another 3 extra tokens (so she's only earning rewards with 2 tokens now). Alice must wait 4 weeks from the moment of the **second unstake request** even if the 5 tokens could have been withdrawn from the contract

Two things to keep in mind:

* After you stake, the staking pool will mint a claim token for you called **Staked FLX (stFLX)**. **stFLX is not transferrable**
* **You can still get slashed while you're waiting to unstake from the pool**

You will notice that the amount of stFLX you receive might differ from the amount of LP tokens you stake. That is normal behaviour.


# RAI / ETH Uniswap V3 Oracle LP Incentives Program

Description coming soon

## Overview

The RAI / ETH Uniswap V3 Oracle LP strategy requires that participants provide full range liquidity.<br>

The RAI / ETH 0.05% fee pool concerned is [here](https://info.uniswap.org/#/pools/0x0dc9877f6024ccf16a470a74176c9260beb83ab6).


# Core Contracts Naming Transition

Going from cute to actual English words

The following tables show the before and after variable names from all core MCD contracts.

| MCD Units | Meaning                         |
| --------- | ------------------------------- |
| WAD       | Number with 18 decimals (10^18) |
| RAY       | Number with 27 decimals (10^27) |
| RAD       | Number with 45 decimals (10^45) |

| Vat      | SAFEEngine                            |
| -------- | ------------------------------------- |
| wards    | authorizedAccounts                    |
| rely     | addAuthorization                      |
| deny     | removeAuthorization                   |
| auth     | isAuthorized                          |
| hope     | approveSAFEModification               |
| nope     | denySAFEModification                  |
| wish     | canModifySAFE                         |
| Ilk      | CollateralType                        |
| Ilk.Art  | CollateralType.debtAmount             |
| Ilk.rate | CollateralType.accumulatedRate        |
| Ilk.spot | CollateralType.safetyPrice            |
| Ilk.line | CollateralType.debtCeiling            |
| Ilk.dust | CollateralType.debtFloor              |
| NaN      | CollateralType.liquidationPrice (NEW) |
| Urn      | SAFE                                  |
| Urn.ink  | SAFE.lockedCollateral                 |
| Urn.art  | SAFE.generatedDebt                    |
| ilks     | collateralTypes                       |
| urns     | safes                                 |
| gem      | tokenCollateral                       |
| dai      | coinBalance                           |
| sin      | debtBalance                           |
| debt     | globalDebt                            |
| vice     | globalUnbackedDebt                    |
| Line     | globalDebtCeiling                     |
| live     | contractEnabled                       |
| init     | initializeCollateralType              |
| file     | modifyParameters                      |
| cage     | disableContract                       |
| slip     | modifyCollateralBalance               |
| flux     | transferCollateral                    |
| move     | transferInternalCoins                 |
| frob     | modifySAFECollateralization           |
| dink     | deltaCollateral                       |
| dart     | deltaDebt                             |
| fork     | transferSAFECollateralAndDebt         |
| grab     | confiscateSAFECollateralAndDebt       |
| heal     | settleDebt                            |
| suck     | createUnbackedDebt                    |
| fold     | updateAccumulatedRate                 |
| NaN      | AddAuthorization (NEW)                |
| NaN      | RemoveAuthorization (NEW)             |
| NaN      | ApproveSAFEModification (NEW)         |
| NaN      | DenySAFEModification (NEW)            |
| NaN      | InitializeCollateralType (NEW)        |
| NaN      | ModifyParameters (NEW)                |
| NaN      | ModifyParameters (NEW)                |
| NaN      | DisableContract (NEW)                 |
| NaN      | ModifyCollateralBalance (NEW)         |
| NaN      | TransferCollateral (NEW)              |
| NaN      | TransferInternalCoins (NEW)           |
| NaN      | ModifySAFECollateralization (NEW)     |
| NaN      | TransferSAFECollateralAndDebt (NEW)   |
| NaN      | ConfiscateSAFECollateralAndDebt (NEW) |
| NaN      | SettleDebt (NEW)                      |
| NaN      | CreateUnbackedDebt (NEW)              |
| NaN      | UpdateAccumulatedRate (NEW)           |

| Vow     | AccountingEngine                     |
| ------- | ------------------------------------ |
| wards   | authorizedAccounts                   |
| rely    | addAuthorization                     |
| deny    | removeAuthorization                  |
| auth    | isAuthorized                         |
| vat     | safeEngine                           |
| flapper | surplusAuctionHouse                  |
| flopper | debtAuctionHouse                     |
| NaN     | postSettlementSurplusDrain (NEW)     |
| NaN     | extraSurplusReceiver (NEW)           |
| sin     | debtQueue                            |
| NaN     | debtPoppers (NEW)                    |
| Sin     | totalQueuedDebt                      |
| Ash     | totalOnAuctionDebt                   |
| NaN     | lastSurplusAuctionTime (NEW)         |
| NaN     | lastSurplusTransferTime (NEW)        |
| NaN     | surplusAuctionDelay (NEW)            |
| NaN     | surplusTransferDelay (NEW)           |
| NaN     | extraSurplusIsTransferred (NEW)      |
| wait    | popDebtDelay                         |
| dump    | initialDebtAuctionMintedTokens       |
| sump    | debtAuctionBidSize                   |
| bump    | surplusAuctionAmountToSell           |
| NaN     | surplusTransferAmount (NEW)          |
| hump    | surplusBuffer                        |
| NaN     | disableCooldown (NEW)                |
| NaN     | disableTimestamp (NEW)               |
| NaN     | protocolTokenAuthority (NEW)         |
| NaN     | systemStakingPool (NEW)              |
| live    | contractEnabled                      |
| NaN     | unqueuedUnauctionedDebt              |
| file    | modifyParameters                     |
| fess    | pushDebtToQueue                      |
| flog    | popDebtFromQueue                     |
| heal    | settleDebt                           |
| kiss    | cancelAuctionedDebtWithSurplus       |
| flop    | auctionDebt                          |
| NaN     | settleDebtAuction (NEW)              |
| flap    | auctionSurplus                       |
| NaN     | transferExtraSurplus (NEW)           |
| cage    | disableContract                      |
| NaN     | transferPostSettlementSurplus (NEW)  |
| NaN     | AddAuthorization (NEW)               |
| NaN     | RemoveAuthorization (NEW)            |
| NaN     | ModifyParameters (NEW)               |
| NaN     | ModifyParameters (NEW)               |
| NaN     | PushDebtToQueue (NEW)                |
| NaN     | PopDebtFromQueue (NEW)               |
| NaN     | SettleDebt (NEW)                     |
| NaN     | CancelAuctionedDebtWithSurplus (NEW) |
| NaN     | AuctionDebt (NEW)                    |
| NaN     | AuctionSurplus (NEW)                 |
| NaN     | DisableContract (NEW)                |
| NaN     | TransferPostSettlementSurplus (NEW)  |
| NaN     | TransferExtraSurplus (NEW)           |

| Flap/per | Burning/Recycling/PostSettlementSurplusAuctionHouse                    |
| -------- | ---------------------------------------------------------------------- |
| wards    | authorizedAccounts                                                     |
| rely     | addAuthorization                                                       |
| deny     | removeAuthorization                                                    |
| auth     | isAuthorized                                                           |
| NaN      | AUCTION\_HOUSE\_TYPE (NEW)                                             |
| Bid      | Bid                                                                    |
| Bid.bid  | Bid.bidAmount                                                          |
| Bid.lot  | Bid.amountToSell                                                       |
| Bid.guy  | Bid.highBidder                                                         |
| Bid.tic  | Bid.bidExpiry                                                          |
| Bid.end  | Bid.auctionDeadline                                                    |
| Kick     | StartAuction                                                           |
| bids     | bids                                                                   |
| vat      | safeEngine                                                             |
| gem      | protocolToken                                                          |
| NaN      | protocolTokenBidReceiver (only in the Recycling version)               |
| beg      | bidIncrease                                                            |
| ttl      | bidDuration                                                            |
| tau      | totalAuctionLength                                                     |
| kicks    | auctionsStarted                                                        |
| live     | contractEnabled                                                        |
| file     | modifyParameters                                                       |
| kick     | startAuction                                                           |
| tick     | restartAuction                                                         |
| tend     | increaseBidSize                                                        |
| deal     | settleAuction                                                          |
| cage     | disableContract                                                        |
| yank     | terminateAuctionPrematurely (only in the Burning & Recycling versions) |
| NaN      | AddAuthorization (NEW)                                                 |
| NaN      | RemoveAuthorization (NEW)                                              |
| NaN      | ModifyParameters (NEW)                                                 |
| NaN      | RestartAuction (NEW)                                                   |
| NaN      | IncreaseBidSize (NEW)                                                  |
| NaN      | StartAuction (NEW)                                                     |
| NaN      | SettleAuction (NEW)                                                    |
| NaN      | DisableContract (NEW)                                                  |
| NaN      | TerminateAuctionPrematurely (NEW)                                      |

| Flop/per | DebtAuctionHouse                  |
| -------- | --------------------------------- |
| wards    | authorizedAccounts                |
| rely     | addAuthorization                  |
| deny     | removeAuthorization               |
| auth     | isAuthorized                      |
| NaN      | AUCTION\_HOUSE\_TYPE              |
| Bid      | Bid                               |
| Bid.bid  | Bid.bidAmount                     |
| Bid.lot  | Bid.amountToSell                  |
| Bid.guy  | Bid.highBidder                    |
| Bid.tic  | Bid.bidExpiry                     |
| Bid.end  | Bid.auctionDeadline               |
| Kick     | StartAuction                      |
| bids     | bids                              |
| vat      | safeEngine                        |
| vow      | accountingEngine                  |
| gem      | protocolToken                     |
| beg      | bidDecrease                       |
| pad      | amountSoldIncrease                |
| ttl      | bidDuration                       |
| tau      | totalAuctionLength                |
| kicks    | auctionsStarted                   |
| NaN      | activeDebtAuctions                |
| live     | contractEnabled                   |
| file     | modifyParameters                  |
| kick     | startAuction                      |
| tick     | restartAuction                    |
| dent     | decreaseSoldAmount                |
| deal     | settleAuction                     |
| cage     | disableContract                   |
| yank     | terminateAuctionPrematurely       |
| NaN      | AddAuthorization (NEW)            |
| NaN      | RemoveAuthorization (NEW)         |
| NaN      | StartAuction (NEW)                |
| NaN      | ModifyParameters (NEW)            |
| NaN      | RestartAuction (NEW)              |
| NaN      | DecreaseSoldAmount (NEW)          |
| NaN      | SettleAuction (NEW)               |
| NaN      | TerminateAuctionPrematurely (NEW) |
| NaN      | DisableContract (NEW)             |

| Flip/per | English/Fixed/IncreasingDiscountCollateralAuctionHouse                                              |
| -------- | --------------------------------------------------------------------------------------------------- |
| wards    | authorizedAccounts                                                                                  |
| rely     | addAuthorization                                                                                    |
| deny     | removeAuthorization                                                                                 |
| auth     | isAuthorized                                                                                        |
| NaN      | AUCTION\_HOUSE\_TYPE (NEW)                                                                          |
| NaN      | AUCTION\_TYPE (NEW)                                                                                 |
| Bid      | Bid                                                                                                 |
| NaN      | raisedAmount (NEW) (only in the FixedDiscount version)                                              |
| NaN      | soldAmount(NEW) (only in the FixedDiscount version)                                                 |
| Bid.bid  | Bid.bidAmount (only in the English version)                                                         |
| Bid.lot  | Bid.amountToSell                                                                                    |
| Bid.guy  | Bid.highBidder (only in the English version)                                                        |
| Bid.tic  | Bid.bidExpiry (only in the English version)                                                         |
| Bid.end  | Bid.auctionDeadline                                                                                 |
| Bid.usr  | Bid.forgoneCollateralReceiver                                                                       |
| Bid.gal  | Bid.auctionIncomeRecipient                                                                          |
| Bid.tab  | Bid.amountToRaise                                                                                   |
| NaN      | Bid.currentDiscount (NEW) (only in the IncreasingDiscount version)                                  |
| NaN      | Bid.maxDiscount (NEW) (only in the IncreasingDiscount version)                                      |
| NaN      | Bid.perSecondDiscountUpdateRate (NEW) (only in the IncreasingDiscount version)                      |
| NaN      | Bid.discountIncreaseDeadline (NEW) (only in the IncreasingDiscount version)                         |
| Kick     | StartAuction                                                                                        |
| bids     | bids                                                                                                |
| vat      | safeEngine                                                                                          |
| ilk      | collateralType                                                                                      |
| NaN      | lastReadRedemptionPrice (only in the FixedDiscount version)                                         |
| NaN      | minimumBid (NEW) (only in the FixedDiscount version)                                                |
| beg      | bidIncrease (only in the English version)                                                           |
| ttl      | bidDuration (only in the English version)                                                           |
| tau      | totalAuctionLength                                                                                  |
| kicks    | auctionsStarted                                                                                     |
| NaN      | discount (NEW) (only in the FixedDiscount version)                                                  |
| NaN      | minDiscount (NEW) (only in the IncreasingDiscount version)                                          |
| NaN      | maxDiscount (NEW) (only in the IncreasingDiscount version)                                          |
| NaN      | perSecondDiscountUpdateRate (NEW) (only in the IncreasingDiscount version)                          |
| NaN      | maxDiscountUpdateRateTimeline (NEW) (only in the IncreasingDiscount version)                        |
| NaN      | lowerCollateralMedianDeviation (NEW) (only in the FixedDiscount version)                            |
| NaN      | upperCollateralMedianDeviation (NEW) (only in the FixedDiscount version)                            |
| NaN      | lowerSystemCoinMedianDeviation (NEW) (only in the FixedDiscount version)                            |
| NaN      | upperSystemCoinMedianDeviation (NEW) (only in the FixedDiscount version)                            |
| NaN      | minSystemCoinMedianDeviation (NEW) (only in the FixedDiscount version)                              |
| cut      | bidToMarketPriceRatio (only in the English version)                                                 |
| spot     | oracleRelayer                                                                                       |
| pip      | orcl/osm                                                                                            |
| NaN      | median (NEW) (only in the FixedDiscount version)                                                    |
| Kick     | StartAuction                                                                                        |
| live     | contractEnabled                                                                                     |
| file     | modifyParameters                                                                                    |
| NaN      | getDiscountedCollateralPrice (NEW) (only in the Fixed and Increasing Discount versions)             |
| NaN      | getBoughtCollateral (NEW) (only in the Fixed and Increasing Discount versions)                      |
| NaN      | getSystemCoinFloorDeviatedPrice (NEW) (only in the Fixed and Increasing Discount versions)          |
| NaN      | getSystemCoinCeilingDeviatedPrice (NEW) (only in the Fixed and Increasing Discount versions)        |
| NaN      | getCollateralFSMAndFinalSystemCoinPrices (NEW) (only in the Fixed and Increasing Discount versions) |
| NaN      | getFinalBaseCollateralPrice (NEW) (only in the Fixed and Increasing Discount versions)              |
| NaN      | getNextCurrentDiscount (NEW) (only in the IncreasingDiscount version)                               |
| NaN      | getCollateralBought (NEW) (only in the FixedDiscount version)                                       |
| NaN      | buyCollateral (NEW) (only in the FixedDiscount version)                                             |
| kick     | startAuction                                                                                        |
| tick     | restartAuction (only in the English version)                                                        |
| tend     | increaseBidSize (only in the English version)                                                       |
| dent     | decreaseSoldAmount (only in the English version)                                                    |
| deal     | settleAuction                                                                                       |
| yank     | terminateAuctionPrematurely                                                                         |
| NaN      | bidAmount (NEW)                                                                                     |
| NaN      | remainingAmountToSell (NEW)                                                                         |
| NaN      | forgoneCollateralReceiver (NEW)                                                                     |
| NaN      | amountToRaise (NEW)                                                                                 |
| NaN      | AddAuthorization (NEW)                                                                              |
| NaN      | RemoveAuthorization (NEW)                                                                           |
| NaN      | StartAuction (NEW)                                                                                  |
| NaN      | ModifyParameters (NEW)                                                                              |
| NaN      | BuyCollateral (NEW)                                                                                 |
| NaN      | SettleAuction (NEW)                                                                                 |
| NaN      | TerminateAuctionPrematurely (NEW)                                                                   |

| Join    | BasicTokenAdapters        |
| ------- | ------------------------- |
| wards   | authorizedAccounts        |
| rely    | addAuthorization          |
| deny    | removeAuthorization       |
| auth    | isAuthorized              |
| GemLike | CollateralLike            |
| GemJoin | CollateralJoin            |
| vat     | safeEngine                |
| ilk     | collateralType            |
| gem     | collateral                |
| dec     | decimals                  |
| live    | contractEnabled           |
| cage    | disableContract           |
| join    | join                      |
| exit    | exit                      |
| ETHJoin | ETHJoin                   |
| DaiJoin | CoinJoin                  |
| dai     | systemCoin                |
| NaN     | AddAuthorization (NEW)    |
| NaN     | RemoveAuthorization (NEW) |
| NaN     | DisableContract (NEW)     |
| NaN     | Join (NEW)                |
| NaN     | Exit (NEW)                |

| Cat      | LiquidationEngine                       |
| -------- | --------------------------------------- |
| wards    | authorizedAccounts                      |
| rely     | addAuthorization                        |
| deny     | removeAuthorization                     |
| auth     | isAuthorized                            |
| NaN      | safeSaviours (NEW)                      |
| NaN      | connectSAFESaviour (NEW)                |
| NaN      | disconnectSAFESaviour (NEW)             |
| Ilk      | CollateralType                          |
| Ilk.flip | CollateralType.collateralAuctionHouse   |
| Ilk.chop | CollateralType.liquidationPenalty       |
| Ilk.dunk | CollateralType.liquidationQuantity      |
| box      | onAuctionSystemCoinLimit                |
| litter   | currentOnAuctionSystemCoins             |
| ilks     | collateralTypes                         |
| NaN      | chosenSAFESaviour (NEW)                 |
| NaN      | mutex (NEW)                             |
| live     | contractEnabled                         |
| vat      | safeEngine                              |
| vow      | accountingEngine                        |
| file     | modifyParameters                        |
| flip     | collateralAuctionHouse                  |
| cage     | disableContract                         |
| NaN      | protectSAFE (NEW)                       |
| bite     | liquidateSAFE                           |
| claw     | removeCoinsFromAuction                  |
| NaN      | getLimitAdjustedDebtToCover (NEW)       |
| urn      | safe                                    |
| rate     | accumulatedRates                        |
| ink      | safeCollateral                          |
| art      | safeDebt                                |
| dust     | debtFloor                               |
| grab     | confiscateSAFECollateralAndDebt         |
| fess     | pushDebtToQueue                         |
| mink     | collateralData                          |
| gal      | initialBidder                           |
| tab      | amountToRaise                           |
| bid      | initialBid                              |
| Bite     | Liquidate                               |
| NaN      | AddAuthorization (NEW)                  |
| NaN      | RemoveAuthorization (NEW)               |
| NaN      | ConnectSAFESaviour (NEW)                |
| NaN      | DisconnectSAFESaviour (NEW)             |
| NaN      | UpdateCurrentOnAuctionSystemCoins (NEW) |
| NaN      | ModifyParameters (NEW)                  |
| NaN      | DisableContract (NEW)                   |
| NaN      | SaveSAFE (NEW)                          |
| NaN      | FailedSAFESave (NEW)                    |
| NaN      | ProtectSAFE (NEW)                       |

| Spot/ter | OracleRelayer                          |
| -------- | -------------------------------------- |
| wards    | authorizedAccounts                     |
| rely     | addAuthorization                       |
| deny     | removeAuthorization                    |
| auth     | isAuthorized                           |
| Ilk      | CollateralType                         |
| Ilk.pip  | CollateralType.orcl                    |
| Ilk.mat  | CollateralType.safetyCRatio            |
| NaN      | CollateralType.liquidationCRatio (NEW) |
| ilks     | collateralTypes                        |
| vat      | safeEngine                             |
| par      | redemptionPrice                        |
| NaN      | redemptionPriceUpdateTime (NEW)        |
| NaN      | redemptionRateUpperBound (NEW)         |
| NaN      | redemptionRateLowerBound (NEW)         |
| live     | contractEnabled                        |
| Poke     | UpdateCollateralPrice                  |
| file     | modifyParameters                       |
| NaN      | updateRedemptionPrice (NEW)            |
| poke     | updateCollateralPrice                  |
| cage     | disableContract                        |
| NaN      | AddAuthorization (NEW)                 |
| NaN      | RemoveAuthorization (NEW)              |
| NaN      | DisableContract (NEW)                  |
| NaN      | ModifyParameters (NEW)                 |
| NaN      | UpdateRedemptionPrice (NEW)            |
| NaN      | UpdateCollateralPrice (NEW)            |

| Jug      | TaxCollector                          |
| -------- | ------------------------------------- |
| wards    | authorizedAccounts                    |
| rely     | addAuthorization                      |
| deny     | removeAuthorization                   |
| auth     | isAuthorized                          |
| Ilk      | CollateralType                        |
| Ilk.duty | CollateralType.stabilityFee           |
| Ilk.rho  | CollateralType.updateTime             |
| NaN      | TaxReceiver (NEW)                     |
| NaN      | TaxReceiver.canTakeBackTax (NEW)      |
| NaN      | TaxReceiver.taxPercentage (NEW)       |
| ilks     | collateralTypes                       |
| NaN      | secondaryReceiverAllotedTax (NEW)     |
| NaN      | usedSecondaryReceiver (NEW)           |
| NaN      | secondaryReceiverAccounts (NEW)       |
| NaN      | secondaryReceiverRevenueSources (NEW) |
| NaN      | secondaryTaxReceivers (NEW)           |
| vat      | safeEngine                            |
| vow      | primaryTaxReceiver                    |
| base     | globalStabilityFee                    |
| NaN      | secondaryReceiverNonce (NEW)          |
| NaN      | maxSecondaryReceivers (NEW)           |
| NaN      | latestSecondaryReceiver (NEW)         |
| NaN      | collateralList (NEW)                  |
| NaN      | secondaryReceiverList (NEW)           |
| init     | initializeCollateralType              |
| file     | modifyParameters                      |
| NaN      | addSecondaryReceiver (NEW)            |
| NaN      | modifySecondaryReceiver (NEW)         |
| NaN      | collectedAllTax (NEW)                 |
| NaN      | taxManyOutcome (NEW)                  |
| NaN      | secondaryReceiversAmount (NEW)        |
| NaN      | isSecondaryReceiver (NEW)             |
| NaN      | collateralListLength (NEW)            |
| NaN      | taxSingleOutcome (NEW)                |
| drip     | taxMany (NEW) / taxSingle             |
| NaN      | splitTaxIncome (NEW)                  |
| NaN      | distributeTax (NEW)                   |
| NaN      | CollectTax (NEW)                      |
| NaN      | DistributeTax (NEW)                   |
| NaN      | AddAuthorization (NEW)                |
| NaN      | RemoveAuthorization (NEW)             |
| NaN      | InitializeCollateralType (NEW)        |
| NaN      | ModifyParameters (NEW)                |
| NaN      | AddSecondaryReceiver (NEW)            |
| NaN      | ModifySecondaryReceiver (NEW)         |
| NaN      | CollectTax (NEW)                      |
| NaN      | DistributeTax (NEW)                   |

| Pot   | CoinSavingsAccount          |
| ----- | --------------------------- |
| wards | authorizedAccounts          |
| rely  | addAuthorization            |
| deny  | removeAuthorization         |
| auth  | isAuthorized                |
| pie   | savings                     |
| Pie   | totalSavings                |
| dsr   | savingsRate                 |
| chi   | accumulatedRates            |
| vat   | safeEngine                  |
| file  | modifyParameters            |
| cage  | disableContract             |
| drip  | updateAccumulatedRate       |
| NaN   | nextAccumulatedRate (NEW)   |
| join  | deposit                     |
| exit  | withdraw                    |
| NaN   | AddAuthorization (NEW)      |
| NaN   | RemoveAuthorization (NEW)   |
| NaN   | RemoveAuthorization (NEW)   |
| NaN   | DisableContract (NEW)       |
| NaN   | Deposit (NEW)               |
| NaN   | Withdraw (NEW)              |
| NaN   | UpdateAccumulatedRate (NEW) |

| End   | GlobalSettlement                      |
| ----- | ------------------------------------- |
| wards | authorizedAccounts                    |
| rely  | addAuthorization                      |
| deny  | removeAuthorization                   |
| auth  | isAuthorized                          |
| vat   | safeEngine                            |
| cat   | liquidationEngine                     |
| vow   | accountingEngine                      |
| spot  | oracleRelayer                         |
| pot   | coinSavingsAccount                    |
| NaN   | stabilityFeeTreasury (NEW)            |
| live  | contractEnabled                       |
| when  | shutdownTime                          |
| wait  | shutdownCooldown                      |
| debt  | outstandingCoinSupply                 |
| tag   | finalCoinPerCollateralPrice           |
| gap   | collateralShortfall                   |
| Art   | collateralTotalDebt                   |
| fix   | collateralCashPrice                   |
| bag   | coinBag                               |
| out   | coinsUsedToRedeem                     |
| file  | modifyParameters                      |
| cage  | shutdownSystem / freezeCollateralType |
| skip  | fastTrackAuction                      |
| skim  | processSAFE                           |
| urn   | safe                                  |
| owe   | amountOwed                            |
| free  | freeCollateral                        |
| thaw  | setOutstandingCoinSupply              |
| flow  | calculateCashPrice                    |
| pack  | prepareCoinsForRedeeming              |
| cash  | redeemCollateral                      |
| NaN   | AddAuthorization (NEW)                |
| NaN   | RemoveAuthorization (NEW)             |
| NaN   | ModifyParameters (NEW)                |
| NaN   | ShutdownSystem (NEW)                  |
| NaN   | FreezeCollateralType (NEW)            |
| NaN   | FastTrackAuction (NEW)                |
| NaN   | ProcessSAFE (NEW)                     |
| NaN   | FreeCollateral (NEW)                  |
| NaN   | SetOutstandingCoinSupply (NEW)        |
| NaN   | CalculateCashPrice (NEW)              |
| NaN   | PrepareCoinsForRedeeming (NEW)        |
| NaN   | RedeemCollateral (NEW)                |

| Dai               | Coin                |
| ----------------- | ------------------- |
| wards             | authorizedAccounts  |
| rely              | addAuthorization    |
| deny              | removeAuthorization |
| auth              | isAuthorized        |
| name              | name                |
| symbol            | symbol              |
| version           | version             |
| decimals          | decimals            |
| totalSupply       | totalSupply         |
| balanceOf         | balanceOf           |
| allowance         | allowance           |
| nonces            | nonces              |
| NaN               | changeData (NEW)    |
| Approval          | Approval            |
| Transfer          | Transfer            |
| DOMAIN\_SEPARATOR | DOMAIN\_SEPARATOR   |
| PERMIT\_TYPEHASH  | PERMIT\_TYPEHASH    |
| transfer          | transfer            |
| transferFrom      | transferFrom        |
| mint              | mint                |
| burn              | burn                |
| approve           | approve             |
| push              | push                |
| pull              | pull                |
| move              | move                |
| permit            | permit              |

| DssCdpManager | GebSAFEManager              |
| ------------- | --------------------------- |
| vat           | safeEngine                  |
| cdpi          | safei                       |
| urns          | safes                       |
| list          | safeList                    |
| owns          | ownsSAFE                    |
| ilks          | collateralTypes             |
| first         | firstSAFEID                 |
| last          | lastSAFEID                  |
| count         | safeCount                   |
| cdpCan        | safeCan                     |
| urnCan        | handlerCan                  |
| List.prev     | List.prev                   |
| List.next     | List.next                   |
| NewCdp        | NewSafe                     |
| cdpAllowed    | safeAllowed                 |
| urnAllowed    | handlerAllowed              |
| cdpAllow      | allowSAFE                   |
| urnAllow      | allowHandler                |
| open          | openSAFE                    |
| give          | transferSAFEOwnership       |
| ilk           | collateralType              |
| frob          | modifySAFECollateralization |
| dink          | deltaCollateral             |
| dart          | deltaDebt                   |
| flux          | transferCollateral          |
| move          | transferInternalCoins       |
| quit          | quitSystem                  |
| enter         | enterSystem                 |
| shift         | moveSAFE                    |
| NaN           | protectSAFE (NEW)           |

| GetCdps     | GetSafes     |
| ----------- | ------------ |
| getCdpsAsc  | getSafesAsc  |
| getCdpsDesc | getSafesDesc |

| DssProxyActions    | GebProxyActions                                         |
| ------------------ | ------------------------------------------------------- |
| daiJoin\_join      | coinJoin\_join                                          |
| apt                | apt                                                     |
| urn                | safeHandler                                             |
| \_getDrawDart      | \_getGeneratedDeltaDebt                                 |
| vat                | safeEngine                                              |
| jug                | taxCollector                                            |
| urn                | safeHandler                                             |
| ilk                | collateralType                                          |
| dart               | deltaDebt                                               |
| \_getWipeDart      | \_getRepaidDeltaDebt                                    |
| \_getWipeAllWad    | \_getRepaidAlDebt                                       |
| transfer           | transfer                                                |
| ethJoin\_join      | ethJoin\_join                                           |
| gem                | collateral                                              |
| gemJoin\_join      | tokenCollateralJoin\_join                               |
| hope               | approveSAFEModification                                 |
| nope               | denySAFEModification                                    |
| open               | openSAFE                                                |
| give               | transferSAFEOwnership                                   |
| giveToProxy        | transferSAFEOwnershipToProxy                            |
| cdpAllow           | allowSAFE                                               |
| urnAllow           | allowHandler                                            |
| flux               | transferCollateral                                      |
| move               | transferInternalCoins                                   |
| frob               | modifySAFECollateralization                             |
| quit               | quitSystem                                              |
| enter              | enterSystem                                             |
| shift              | moveSAFE                                                |
| makeGemBag         | makeCollateralBag                                       |
| NaN                | protectSAFE (NEW)                                       |
| lockETH            | lockETH                                                 |
| safeLockETH        | safeLockETH                                             |
| lockGem            | lockTokenCollateral                                     |
| safeLockGem        | safeLockTokenCollateral                                 |
| freeETH            | freeETH                                                 |
| freeGem            | freeTokenCollateral                                     |
| exitETH            | exitETH                                                 |
| exitGem            | exitTokenCollateral                                     |
| draw               | generateDebt                                            |
| NaN                | generateDebtAndProtectSAFE (NEW)                        |
| wipe               | repayDebt                                               |
| safeWipe           | safeRepayDebt                                           |
| wipeAll            | repayAllDebt                                            |
| safeWipeAll        | safeRepayAllDebt                                        |
| lockETHAndDraw     | lockETHAndGenerateDebt                                  |
| openLockETHAndDraw | openLockETHAndGenerateDebt                              |
| NaN                | openLockETHGenerateDebtAndProtectSAFE (NEW)             |
| lockGemAndDraw     | lockTokenCollateralAndGenerateDebt                      |
| NaN                | lockTokenCollateralGenerateDebtAndProtectSAFE (NEW)     |
| openLockGemAndDraw | openLockTokenCollateralAndGenerateDebt                  |
| NaN                | openLockTokenCollateralGenerateDebtAndProtectSAFE (NEW) |
| openLockGNTAndDraw | openLockGNTAndGenerateDebt                              |
| NaN                | openLockGNTGenerateDebtAndProtectSAFE (NEW)             |
| wipeAndFreeETH     | repayDebtAndFreeETH                                     |
| wipeAllAndFreeETH  | repayAllDebtAndFreeETH                                  |
| wipeAndFreeGem     | repayDebtAndFreeTokenCollateral                         |
| wipeAllAndFreeGem  | repayAllDebtAndFreeTokenCollateral                      |

| DssProxyActionsEnd | GebProxyActionsGlobalSettlement |
| ------------------ | ------------------------------- |
| \_free             | \_freeCollateral                |
| end                | globalSettlement                |
| freeETH            | freeETH                         |
| freeGem            | freeTokenCollateral             |
| pack               | prepareCoinsForRedeeming        |
| cashETH            | redeemETH                       |
| cashGem            | redeemTokenCollateral           |


# Governance Contracts Naming Transition

The following tables show the before and after variable names for MCD governance contracts.

| DSPause      | DSPause/DSProtestPause                                  |
| ------------ | ------------------------------------------------------- |
| wait         | isDelayed                                               |
| setOwner     | setOwner                                                |
| setAuthority | setAuthority                                            |
| setDelay     | setDelay                                                |
| plans        | scheduledTransactions                                   |
| NaN          | transactionDelays (NEW) (DSProtestPause)                |
| proxy        | proxy                                                   |
| delay        | delay                                                   |
| NaN          | MAX\_DELAY (NEW)                                        |
| NaN          | DS\_PAUSE\_TYPE (NEW)                                   |
| hash         | getTransactionDataHash                                  |
| soul         | getExtCodeHash                                          |
| NaN          | setDelayMultiplier (NEW) (DSProtestPause)               |
| NaN          | protestWindowAvailable (NEW) (DSProtestPause)           |
| NaN          | timeUntilProposalProtestDeadline (NEW) (DSProtestPause) |
| NaN          | maxScheduledTransactions (NEW)                          |
| NaN          | protester (NEW) (DSProtestPause)                        |
| NaN          | protestEnd (NEW) (DSProtestPause)                       |
| NaN          | MAX\_DELAY\_MULTIPLIER (NEW) (DSProtestPause)           |
| plot         | scheduleTransaction                                     |
| NaN          | attachTransactionDescription (NEW)                      |
| NaN          | protestAgainstTransaction (NEW) (DSProtestPause)        |
| drop         | abandonTransaction                                      |
| exec         | executeTransaction                                      |
| eta          | earliestExecutionTime                                   |
| fax          | parameters                                              |
| tag          | codeHash                                                |
| NaN          | getTransactionDelays (NEW) (DSProtestPause)             |

| DSChief               | VoteQuorum                   |
| --------------------- | ---------------------------- |
| slates                | ballots                      |
| votes                 | votes                        |
| approvals             | approvals                    |
| deposits              | deposits                     |
| GOV                   | PROT                         |
| IOU                   | IOU                          |
| hat                   | votedAuthority               |
| MAX\_YAYS             | MAX\_CANDIDATES\_PER\_BALLOT |
| Etch                  | GroupCandidates              |
| lock                  | addVotingWeight              |
| free                  | removeVotingWeight           |
| etch                  | groupCandidates              |
| vote                  | vote                         |
| lift                  | electCandidate               |
| addWeight             | addWeight                    |
| subWeight             | subWeight                    |
| requireByteOrderedSet | requireByteOrderedSet        |
| setOwner              | setOwner                     |
| setAuthority          | setAuthority                 |
| isUserRoot            | isUserRoot                   |
| setRootUser           | setRootUser                  |

| DSAuth       | DSAuth       |
| ------------ | ------------ |
| authority    | authority    |
| owner        | owner        |
| setOwner     | setOwner     |
| setAuthority | setAuthority |
| auth         | auth         |
| isAuthorized | isAuthorized |

| DSRoles                | DSRoles/DSDelegateRoles |
| ---------------------- | ----------------------- |
| \_root\_users          | \_root\_users           |
| \_user\_roles          | \_user\_roles           |
| \_capability\_roles    | \_capability\_roles     |
| \_public\_capabilities | \_public\_capabilities  |
| getUserRoles           | getUserRoles            |
| getCapabilityRoles     | getCapabilityRoles      |
| isUserRoot             | isUserRoot              |
| isCapabilityPublic     | isCapabilityPublic      |
| hasUserRole            | hasUserRole             |
| canCall                | canCall                 |
| BITNOT                 | BITNOT                  |
| setRootUser            | setRootUser             |
| setUserRole            | setUserRole             |
| setPublicCapability    | setPublicCapability     |
| setRoleCapability      | setRoleCapability       |

| MkrAuthority | ProtocolTokenAuthority     |
| ------------ | -------------------------- |
| root         | root                       |
| NaN          | owner (NEW)                |
| sudo         | isRootCalling              |
| NaN          | isRootOrOwnerCalling (NEW) |
| LogSetRoot   | LogSetRoot                 |
| NaN          | LogSetOwner (NEW)          |
| setRoot      | setRoot                    |
| NaN          | setOwner (NEW)             |
| wards        | authorizedAccounts         |
| LogRely      | LogAddAuthorizedAccount    |
| rely         | addAuthorization           |
| LogDeny      | LogRemoveAuthorizedAccount |
| deny         | removeAuthorization        |
| burn         | burn                       |
| burnFrom     | burnFrom                   |
| mint         | mint                       |
| canCall      | canCall                    |

| VoteProxy | VoteProxy             |
| --------- | --------------------- |
| cold      | cold                  |
| hot       | hot                   |
| gov       | gov                   |
| iou       | iou                   |
| chief     | voteQuorum            |
| auth      | isAuthorized          |
| lock      | addVotingWeight       |
| free      | removeVotingWeight    |
| freeAll   | removeAllVotingWeight |
| vote      | vote                  |

| DSGuard   | DSGuard   |
| --------- | --------- |
| LogPermit | LogPermit |
| LogForbid | LogForbid |
| ANY       | ANY       |
| canCall   | canCall   |
| permit    | permit    |
| forbid    | forbid    |

| DSStop    | DSStop    |
| --------- | --------- |
| stopped   | stopped   |
| stoppable | stoppable |
| stop      | stop      |
| start     | start     |


# SAFE Management Contract Naming Transition

The following tables show the before and after variable names for SAFE management related contracts.

| DssCdpManager | GebSAFEManager              |
| ------------- | --------------------------- |
| vat           | safeEngine                  |
| cdpi          | safei                       |
| urns          | safes                       |
| list          | safeList                    |
| owns          | ownsSAFE                    |
| ilks          | collateralTypes             |
| first         | firstSAFEID                 |
| last          | lastSAFEID                  |
| count         | safeCount                   |
| cdpCan        | safeCan                     |
| urnCan        | handlerCan                  |
| List.prev     | List.prev                   |
| List.next     | List.next                   |
| NewCdp        | NewSafe                     |
| cdpAllowed    | safeAllowed                 |
| urnAllowed    | handlerAllowed              |
| cdpAllow      | allowSAFE                   |
| urnAllow      | allowHandler                |
| open          | openSAFE                    |
| give          | transferSAFEOwnership       |
| ilk           | collateralType              |
| frob          | modifySAFECollateralization |
| dink          | deltaCollateral             |
| dart          | deltaDebt                   |
| flux          | transferCollateral          |
| move          | transferInternalCoins       |
| quit          | quitSystem                  |
| enter         | enterSystem                 |
| shift         | moveSAFE                    |
| NaN           | protectSAFE (NEW)           |

| GetCdps     | GetSafes     |
| ----------- | ------------ |
| getCdpsAsc  | getSafesAsc  |
| getCdpsDesc | getSafesDesc |

| DssProxyActions    | GebProxyActions                                         |
| ------------------ | ------------------------------------------------------- |
| daiJoin\_join      | coinJoin\_join                                          |
| apt                | apt                                                     |
| urn                | safeHandler                                             |
| \_getDrawDart      | \_getGeneratedDeltaDebt                                 |
| vat                | safeEngine                                              |
| jug                | taxCollector                                            |
| urn                | safeHandler                                             |
| ilk                | collateralType                                          |
| dart               | deltaDebt                                               |
| \_getWipeDart      | \_getRepaidDeltaDebt                                    |
| \_getWipeAllWad    | \_getRepaidAlDebt                                       |
| transfer           | transfer                                                |
| ethJoin\_join      | ethJoin\_join                                           |
| gem                | collateral                                              |
| gemJoin\_join      | tokenCollateralJoin\_join                               |
| hope               | approveSAFEModification                                 |
| nope               | denySAFEModification                                    |
| open               | openSAFE                                                |
| give               | transferSAFEOwnership                                   |
| giveToProxy        | transferSAFEOwnershipToProxy                            |
| cdpAllow           | allowSAFE                                               |
| urnAllow           | allowHandler                                            |
| flux               | transferCollateral                                      |
| move               | transferInternalCoins                                   |
| frob               | modifySAFECollateralization                             |
| quit               | quitSystem                                              |
| enter              | enterSystem                                             |
| shift              | moveSAFE                                                |
| makeGemBag         | makeCollateralBag                                       |
| NaN                | protectSAFE (NEW)                                       |
| lockETH            | lockETH                                                 |
| safeLockETH        | safeLockETH                                             |
| lockGem            | lockTokenCollateral                                     |
| safeLockGem        | safeLockTokenCollateral                                 |
| freeETH            | freeETH                                                 |
| freeGem            | freeTokenCollateral                                     |
| exitETH            | exitETH                                                 |
| exitGem            | exitTokenCollateral                                     |
| draw               | generateDebt                                            |
| NaN                | generateDebtAndProtectSAFE (NEW)                        |
| wipe               | repayDebt                                               |
| safeWipe           | safeRepayDebt                                           |
| wipeAll            | repayAllDebt                                            |
| safeWipeAll        | safeRepayAllDebt                                        |
| lockETHAndDraw     | lockETHAndGenerateDebt                                  |
| openLockETHAndDraw | openLockETHAndGenerateDebt                              |
| NaN                | openLockETHGenerateDebtAndProtectSAFE (NEW)             |
| lockGemAndDraw     | lockTokenCollateralAndGenerateDebt                      |
| NaN                | lockTokenCollateralGenerateDebtAndProtectSAFE (NEW)     |
| openLockGemAndDraw | openLockTokenCollateralAndGenerateDebt                  |
| NaN                | openLockTokenCollateralGenerateDebtAndProtectSAFE (NEW) |
| openLockGNTAndDraw | openLockGNTAndGenerateDebt                              |
| NaN                | openLockGNTGenerateDebtAndProtectSAFE (NEW)             |
| wipeAndFreeETH     | repayDebtAndFreeETH                                     |
| wipeAllAndFreeETH  | repayAllDebtAndFreeETH                                  |
| wipeAndFreeGem     | repayDebtAndFreeTokenCollateral                         |
| wipeAllAndFreeGem  | repayAllDebtAndFreeTokenCollateral                      |

| DssProxyActionsEnd | GebProxyActionsGlobalSettlement |
| ------------------ | ------------------------------- |
| \_free             | \_freeCollateral                |
| end                | globalSettlement                |
| freeETH            | freeETH                         |
| freeGem            | freeTokenCollateral             |
| pack               | prepareCoinsForRedeeming        |
| cashETH            | redeemETH                       |
| cashGem            | redeemTokenCollateral           |


# Core Module

Handling SAFE state, liquidations and accounting (surplus & bad debt)

**Relevant smart contracts:**

* [**SAFEEngine**](https://github.com/reflexer-labs/geb/blob/master/src/single/SAFEEngine.sol)
* [**LiquidationEngine**](https://github.com/reflexer-labs/geb/blob/master/src/single/LiquidationEngine.sol)
* [**AccountingEngine**](https://github.com/reflexer-labs/geb/blob/master/src/single/AccountingEngine.sol)

## 1. Overview

The **Core Module** stores all the SAFE data, allows external actors to trigger liquidations in case SAFEs are underwater and also handles debt and surplus auctions.

## 2. Component Descriptions

* The `SAFEEngine`stores all SAFEs' states and system coin balances, as well as the amount of collateral and debt each address has. This contract is self-contained and has no external dependencies.
* The `LiquidationEngine` is meant to check if a SAFE is unsafe (the value of the issued debt is too high compared to the collateral value) and start a collateral auction that sells a portion of the SAFE's collateral in order to cover a share of its debt.
* The `AccountingEngine` stores the overall system surplus and debt data. It is meant to settle deficit via debt auctions and dispose off surplus via surplus auctions or basic transfers.

## 3. Risks

### Smart Contract Bugs <a href="#coding-errors" id="coding-errors"></a>

* `SAFEEngine` - A bug in the `SAFEEngine` could be fatal and would lead to collateral or debt being stuck in the system
* `LiquidationEngine` - A bug in the `LiquidationEngine` could lead debt or collateral being assigned to addresses from where they cannot be recovered. Compared to MCD, the `LiquidationEngine` can call external contracts that are meant to save SAFEs by adding more collateral in the system. These "insurance" contracts, if coded incorrectly, can change system state without actually adding any collateral and thus block the engine from starting new auctions. The `liquidateSAFE(bytes32 collateralType, address cdp)` function also uses mutexes to prevent re-entrancy. If a mutex is not unassigned at the end of the call, it can prevent the `LiquidationEngine` from liquidating a specific SAFE in the future.
* `AccountingEngine` - A bug in the `AccountingEngine` would prevent the system from reaching equilibrium (by auctioning debt or disposing off surplus).

### Price Feeds <a href="#feeds" id="feeds"></a>

Both the `SAFEEngine` and the `LiquidationEngine` rely (directly or indirectly) on the `OracleRelayer` which in turn receives price data from multiple trusted sources. If the price feed oracles fail, it's possible that SAFEs will be unfairly liquidated or that users will generate unbacked debt.

### All-Powerful Governance <a href="#governance" id="governance"></a>

* `SAFEEngine` - Malicious governance can steal collateral (`modifyCollateralBalance`) or mint unbacked debt for no apparent reason (`createUnbackedDebt`/addition of worthless collateral types).
* `LiquidationEngine` - Governance could misconfigure liquidation parameters (e.g an extremely low or high `liquidationPenalty`).
* `AccountingEngine` - Malicious governance can set null addresses as the `debtAuctionHouse` or the `surplusAuctionHouse` and thus not allow the system to reach equilibrium or even trigger settlement. The can also set a faulty `AccountingEngine.systemStakingPool` which can prevent the engine from starting new debt auctions and thus leave deficit in the system

## 4. Governance Minimization

* `SAFEEngine` (Level 2 Gov Minimization) - the `SAFEEngine` will need an external contract to automatically set the `globalDebtCeiling` and each collateral's individual `debtCeiling`s. Apart from this, governance can remove control from the `SAFEEngine`.
* `LiquidationEngine` (Level 1 Gov Minimization) - the `LiquidationEngine` may have an external contract authorized to periodically set `onAuctionSystemCoinLimit` depending on the current outstanding amount of system coins generated. Governance will also need to have control over connecting and disconnecting saviour contracts because they are external dependencies connected to other protocols/3rd parties. Apart from these, governance can remove control over this contract.
* `AccountingEngine` (Level 2 Gov Minimization) - the `AccountingEngine` must authorize an external contract to automatically set `initialDebtAuctionMintedTokens` and `debtAuctionBidSize` according to the protocol token and system coin market prices. Governance may also keep control over setting `systemStakingPool` in case the staking pool still needs to be upgraded and may cause problems in the engine.


# SAFE Engine

The SAFE, system coin and collateral database

## 1. Summary <a href="#id-1-introduction-summary" id="id-1-introduction-summary"></a>

The `SAFEEngine` stores SAFEs and tracks all debt and collateral balances. This contract is the most important system component and thus, in order to minimize the possibility of bugs, it does not have any external dependencies.

## 2. Contract Variables & Functions <a href="#id-2-contract-details" id="id-2-contract-details"></a>

**Variables**

* `debtBalance[user: address]` - unbacked coins (system debt, not belonging to any `cdp`).
* `collateralTypes[collateralType: bytes32]` - a mapping of `CollateralType`s.
* `safes[collateralType: bytes32`, `safeHandler: address]` - a mapping of `SAFE` types.
* `tokenCollateral[user: address]` - collateral token balances.
* `coinBalance[user: address]` - how many coins an account has. This number is **not** reflected in the [external ERC20 token contract](https://reflexer-labs.gitbook.io/geb/system-contracts/token-module/system-coin).
* `globalDebt` - total amount of debt currently issued.
* `globalDebtCeiling` - the limit on total amount of debt that can be issued.
* `globalUnbackedDebt` - amount of bad debt in the system.
* `authorizedAccounts[usr: address]` - stores addresses that are able to `modifyParameters`, disable the contract, `modifyCollateralBalance`s, `createUnbackedDebt` and `confiscateSAFECollateralAndDebt`.
* `contractEnabled` - global settlement flag.

**Data Structures**

* `CollateralType`:
  * `debtAmount` - total normalized system coin debt.
  * `accumulatedRate` - system coin debt multiplier (accumulated stability fees).
  * `safetyPrice` - collateral price with safety margin. Used to limit the amount of debt that can be generated per one unit of collateral.
  * `debtCeiling` - the total amount of debt that can be generated using this collateral type.
  * `debtFloor` - the minimum amount of debt that must be generated by a SAFE with this collateral type.
  * `liquidationPrice` - collateral price with safety margin. Used only in `LiquidationEngine` when a SAFE is liquidated.
* `SAFE`:
  * `lockedCollateral` - SAFE collateral balance.
  * `generatedDebt` - normalized outstanding system coin debt.

**Modifiers**

* `canModifySAFE` - modifier that checks whether an address is allowed to modify another address's collateral or system coin balance.
* `isAuthorized` \*\*\*\* - checks whether an address is part of `authorizedAddresses`.

**Functions**

* `disableContract()` - disable the SAFEEngine.
* `modifyParameters(parameter: bytes32`, `data: uint256)` - modify general `uint256` parameters.
* `modifyParameters(collateralType: bytes32`, `parameter: bytes32`, `data: uint256)` - modify collateral type `uint256` parameters.
* `initializeCollateralType(collateralType: bytes32)` - create a new collateral type.
* `modifyCollateralBalance(parameter: bytes32`, `usr: address`, `wad: int256)` - modify a user's collateral balance.
* `transferCollateral(collateralType: bytes32`, `src: address`, `dst: address`, `wad: uint256)` - transfer collateral between users.
* `transferInternalCoins(src: address`, `dst: address`, `rad: uint256)` - transfer system coins between users. This action does not transfer coins between users in the ERC20 contract but only in the CDPEngine.
* `confiscateSAFECollateralAndDebt(collateralType: bytes32`,`cdp: address`, `collateralCounterparty: address`, `debtCounterparty: address`, `deltaCollateral: int256`, `deltaDebt: int256)` - called by the `LiquidationEngine` when auctioning collateral to cover bad debt.
* `settleDebt(rad: uint256)` - destroy equal quantities of system coins and system debt (`globalUnbackedDebt`).
* `updateAccumulatedRate(collateralType: bytes32`, `surplusDst: address`, `rateMultiplier: int256)` - modify a collateral's accumulated interest rates, creating / destroying corresponding debt.
* `createUnbackedDebt(debtDestination: address`, `coinDestination: address`, `rad: uint256)` - mint unbacked system coins (accounted for with `globalUnbackedDebt`).
* `modifySAFECollateralization(collateralType: bytes32`, `cdp: address`, `collateralSource: address`, `debtDestination: address`, `deltaCollateral: int256`, `deltaDebt: int256)` - modify a SAFE's CRatio \*\*\*\* by locking/unlocking collateral and/or generating/paying back debt.
* `transferSAFECollateralAndDebt(collateralType: bytes32`, `src: address`, `dst: address`, `deltaCollateral: int256`, `deltaDebt: int256)` - splitting/merging SAFEs by transferring collateral and/or debt between them.
* `approveSAFEModification(account: address)` - enable `canModifySAFE`for a pair of addresses.
* `denySAFEModification(account: address)` - disable `canModifySAFE`for a pair of addresses.

**Events**

* `AddAuthorization` - emitted when an `addAuthorization(address)` is successfully executed. Contains:
  * `account` - the account that is authorized
* `RemoveAuthorization` - emitted when a `removeAuthorization(address)` is successfully executed. Contains:
  * `account` - the account that is de-authorized
* `ApproveSAFEModification` - emitted when someone successfully approves another address to modify their SAFE. Contains:
  * `sender` - the transaction's msg.sender
  * `account` - the account that is being approved
* `DenySAFEModification` - emitted when someone successfully denies another address to modify their `SAFE`. Contains:
  * `sender` - the transaction's msg.sender
  * `account` - the account that is being denied the permission to modify a SAFE
* `InitializeCollateralType` - emitted when a new collateral type is initialized. Contains:
  * `collateralType` - the collateral type identifier (name)
* `ModifyParameters` - emitted when a parameter is successfully updated
* `DisableContract` - emitted when the `SAFEEngine` is disabled
* `ModifyCollateralBalance` - emitted when a user's collateral balance is modified (add new collateral/remove collateral). Contains:
  * `collateralType` - the collateral's identifier
  * `account` - the account that's being credited/debited collateral
  * `wad` - delta collateral amount
* `TransferCollateral` - emitted when someone transfers collateral from one account to another. Contains:
  * `collateralType` - the collateral's identifier
  * `src` - the source from which collateral is transferred
  * `dst` - the destination where collateral arrives
  * `wad` - the amount of collateral transferred
* `TransferInternalCoins` - emitted when someone transfers system coins internally. Contains:
  * `src` - the source of the system coins
  * `dst` - the destination of the system coins
  * `rad` - amount of internal coins to transfer
* `ModifySAFECollateralization` - emitted when someone modifies the collateralization ration of their `SAFE` (add/remove collateral and/or generate/repay debt). Contains:
  * `collateralType` - the collateral type added/withdrawn from the SAFE
  * `safe` - the target SAFE
  * `collateralSource` - the source from which collateral is taken and deposited in the SAFE
  * `debtDestination` - the destination of the system coins generated
  * `deltaCollateral` - the amount of collateral added/withdrawn
  * `deltaDebt` - the amount of system coins borrowed/repaid
  * `lockedCollateral` - the total amount of collateral locked in the SAFE
  * `generatedDebt` - the total amount of debt currently generated by the SAFE
  * `globalDebt` - the amount of global debt after the SAFE's collateralization ratio is modified
* `TransferSAFECollateralAndDebt` - emitted when someone transfers collateral and/or debt from one SAFE to another. Contains:
  * `collateralType` - the identifier of the collateral stored in both the source and the destination SAFEs
  * `src` - the source SAFE
  * `dst` - the destination SAFE
  * `deltaCollateral` - the amount of collateral added to/withdrawn from `src` and added to/withdrawn from `dst`
  * `deltaDebt` - the amount of debt added to/withdrawn from `src` and added to/withdrawn from `dst`
  * `srcLockedCollateral` - total amount of collateral locked in the source SAFE
  * `srcGeneratedDebt` - total amount of debt generated by the source SAFE
  * `dstLockedCollateral` - total amount of collateral locked in the destination SAFE
  * `dstGeneratedDebt` - total amount of debt generated by the destination SAFE
* `ConfiscateSAFECollateralAndDebt` - emitted when an authed address confiscates collateral and/or debt from a SAFE. Contains:
  * `collateralType` - the identifier of the collateral deposited in the target SAFE
  * `safe` - the SAFE from which to confiscate collateral/debt
  * `collateralCounterparty` - the address that will receive the confiscated collateral
  * `debtCounterparty` - the address that will receive the confiscated debt
  * `deltaCollateral` - the amount of collateral to confiscate
  * `deltaDebt` - the amount of debt to confiscate
  * `globalUnbackedDebt` - the total amount of global bad debt
* `SettleDebt` - emitted when the contract settles bad debt with an equal amount of coins (surplus). Contains:
  * `rad` - the amount of bad debt to settle
  * `debtBalance` - the resulting debt balance of `msg.sender`
  * `coinBalance` - the resulting coin balance of `msg.sender`
  * `globalUnbackedDebt` - the resulting amount of global bad debt
  * `globalDebt` - the resulting amount of total global debt
* `CreateUnbackedDebt` - emitted after creating debt out of thin air. Contains:
  * `debtDestination` - the address that will receive debt
  * `coinDestination` - the address that will receive the corresponding amount of coins
  * `rad` - the amount of debt to issue
  * `debtDstBalance` - the resulting amount of debt that the debt destination has
  * `coinDstBalance` - the resulting amount of coins that the coin destination has
  * `globalUnbackedDebt` - the resulting amount of global bad debt
  * `globalDebt` - the resulting amount of total global debt
* `UpdateAccumulatedRate` - emitted after updating the total accrued interest rate for a specific collateral type. Contains:
  * `collateralType` - the identifier of the collateral type that had its rate accumulated
  * `surplusDst` - the destination of the surplus accrued as a result of the rate being accumulated
  * `rateMultiplier` - amount to be accumulated
  * `dstCoinBalance` - coin balance of the address that received surplus
  * `globalDebt` - total amount of global debt

**Notes**

* `globalDebt` equals `globalUnbackedDebt` plus the sum of `CollateralType.debtAmount * CollateralType.accumulatedRates` across all `collateralTypes`.
* `globalUnbackedDebt` is the sum of all `debtBalance`s (the total quantity of system debt).
* `CollateralType.debtAmount` the sum of all `generatedDebt` in the `safe`s for that `CollateralType`.

## 3. Walkthrough <a href="#id-3-mechanisms-and-concepts" id="id-3-mechanisms-and-concepts"></a>

The core Safe, Coin, and collateral state is kept in the `SafeEngine`. The `SafeEngine` contract has no external dependencies and maintains the central "Accounting Invariants" of Coin. The core principles that apply to the `SafeEngine` are as follows:

1. **Coin cannot exist without collateral:**

* A `collteralType` is a particular type of collateral.
* Collateral `collateral` is assigned to users with `modifyCollateralBalance`.
* Collateral `collateral` is transferred between users with `transferCollateral`.

**2. The Safe data structure is the `SAFE`:**

* has `safeCollateral` - encumbered collateral
* has `safeDebt` - encumbered, normalized debt

**3. Similarly, a collateral is an `collateralType`:**

* has `debtAmount` - encumbered, normalized debt
* has `accumulatedRate` - debt scaling factor (discussed further below)
* has `safetyPrice` - price with safety margin
* has `debtCeiling` - debt ceiling
* has `debtFloor` - debt floor

**Note:** Above, when using the term "encumbered", this refers to being "locked in a SAFE".

### 1. SAFE Management <a href="#vault-management" id="vault-management"></a>

* Anyone can manage a SAFE via `modifySAFECollateralization`, which modifies the SAFE at address `safe`, using `tokenCollateral` from user `collateralSource` and modifying `coinBalance` for user `debtDestination`.
* `confiscateSAFECollateralAndDebt`is usually called by `LiquidationEngine` and transfers debt from the SAFE to another address' `debtBalance`.
* `debtBalance` represents bad debt and can be canceled out with an equal quantity of system coins using `settleDebt(uint rad)` where `msg.sender` is used as the address for the `coinBalance` and `debtBalance`.

### **2. Stability Fee Accrual** <a href="#rate-updates-via-fold-bytes32-ilk-address-u-int-rate" id="rate-updates-via-fold-bytes32-ilk-address-u-int-rate"></a>

The `accumulatedRates` helps convert normalized debt (`generatedDebt`) drawn against a `collateralType` to the present value of that debt (actual debt issued + interest). The rate is updated using `updateAccumulatedRate` (called by the `TaxCollector`). After every update, the newly accrued stability fees are added to the `coinBalance` of `surplusDst`.

## 4. Gotchas <a href="#id-4-gotchas" id="id-4-gotchas"></a>

The methods in the `SafeEngine` are written to be as generic as possible and as such have interfaces that can be quite verbose. Care should be taken that you have not mixed the order of parameters.

Any module that is `auth`ed against the `SafeEngine` has full root access, and can therefore steal all collateral in the system. This means that the addition of a new collateral type (and associated adapter) carries considerable risk.

## 5. Failure Modes <a href="#id-5-failure-modes" id="id-5-failure-modes"></a>

#### Coding Error

A bug in the `SafeEngine` could be catastrophic and could lead to the loss (or locking) of all Coin and Collateral in the system. It could become impossible to modify Vault's or to transfer Coin. Auctions could cease to function. Shutdown could fail.

#### Feeds

The `SafeEngine` relies upon a set of trusted oracles to provide price data. Should these price feeds fail, it would become possible for unbacked Coin to be minted, or safe Vaults could be unfairly liquidated.

#### Governance

Governance can authorize new modules against the `SafeEngine`. This allows them to steal collateral (`modifyCollateralBalance`) or mint unbacked Coin (`createUnbackedDebt` / addition of worthless collateral types). Should the cryptoeconomic protections that make doing so prohibitively expensive fail, the system may be vulnerable and left open for bad actors to drain collateral.

#### Adapters

The `SafeEngine` relies on external Adapter contracts to ensure that the collateral balances in the `SafeEngine` represent real external collateral balances. Adapter contracts are authorized to make arbitrary modifications to all collateral balances. A faulty collateral adapter could result in the loss of all collateral in the system.


# Liquidation Engine

The protocol's liquidation mechanism

## 1. Summary <a href="#id-1-introduction-summary" id="id-1-introduction-summary"></a>

The `LiquidationEngine` enables external actors to liquidate SAFEs and send their collateral to the [`CollateralAuctionHouse`](https://reflexer-labs.gitbook.io/geb/system-contracts/untitled/untitled-2) as well as send a portion of their debt to the `AccountingEngine`.

## 2. Contract Variables & Functions <a href="#id-2-contract-details" id="id-2-contract-details"></a>

**Variables**

* `contractEnabled` - must be `1` for the `LiquidationEngine` to `liquidateSAFE` s. Used to indicate whether the contract is enabled.
* `authorizedAccounts[usr: address]` - addresses allowed to call `modifyParameters()` and `disableContract()`
* `safeEngine` - address that conforms to a `SAFEEngineLike` interface. It cannot be changed after the contract is instantiated.
* `accountingEngine` - address that conforms to an `AccountingEngineLike` interface.
* `chosenSAFESaviour[collateralType: bytes32, safe: address]` - stores the `SAFESaviour` chosen by a `safe` user in order to save their position from liquidation.
* `safeSaviours[saviour: address]` - stores contract addresses that can be used as `SAFESaviour`s.
  * A `SAFESaviour` can be "attached" to a `safe` by its owner. When an external actor calls `liquidateSAFE`, the `SAFESaviour` will try to add more collateral in the targeted `safe` and thus (potentially) save it from liquidation.
* `mutex[collatralType: bytes32, safe: address]` - helps with preventing re-entrancy when `liquidateSAFE` calls a `SAFESaviour` in order to add more collateral to a position.
* `collateralTypes` **-** stores `CollateralType` structs
* `onAuctionSystemCoinLimit` - total amount of system coins that can be requested across all collateral auctions at any time
* `currentOnAuctionSystemCoins` - amount of system coins requested across all current collateral auctions

**Data Structures**

* `CollateralType`:
  * `collateralAuctionHouse` - the address of the contract that auctions a specific collateral type.
  * `liquidationPenalty` - penalty applied to a SAFE when it is liquidated (extra amount of debt that must be covered by an auction).
  * `liquidationQuantity` - maximum amount of system coins to be requested in one collateral auction.

**Modifiers**

* `isAuthorized` - checks whether an address is part of `authorizedAddresses` (and thus can call authed functions).

**Functions**

* `disableContract()` - disable the liquidation engine.
* `connectSAFESaviour(saviour: address)` - governance controlled address that whitelists a `SAFESaviour`.
* `disconnectSAFESaviour(saviour: address)` - governance controlled address that blacklists a `SAFESaviour`.
* `addAuthorization(usr: address)` - add an address to `authorizedAddresses`.
* `removeAuthorization(usr: address)` - remove an address from `authorizedAddresses`.
* `modifyParameters(parameter: bytes32`, `data: address)` - modify an `address` variable.
* `modifyParameters(collateralType: bytes32`, `parameter: bytes32`, `data: uint256)` - modify a collateral specific `uint256` parameter.
* `modifyParameters(collateralType: bytes32`, `parameter: bytes32`, `data: address)` - modify a collateral specific `address` parameter.
* `liquidateSAFE(collateralType: bytes32`, `safe: address)` - will revert if `lockedCollateral` or `generatedDebt` are larger than or equal to 2^255.
* `protectSAFE(collateralType: bytes32, address, address)` will revert if the proposed `SAFESaviour` address was not whitelisted by governance
* `removeCoinsFromAuction(rad: uint256)` - signal that an amount of system coins has been covered by a collateral auction and it can now be subtracted from `currentOnAuctionSystemCoins`
* `getLimitAdjustedDebtToCover(collateralType: bytes32`, `safe: address)` - returns the amount of debt that can currently be covered by a collateral auction for a specific safe

#### **Events** <a href="#events" id="events"></a>

* `AddAuthorization` - emitted when a new address becomes authorized. Contains:
  * `account` - the new authorized account
* `RemoveAuthorization` - emitted when an address is de-authorized. Contains:
  * account - the address that was de-authorized
* `ConnectSAFESaviour` - emitted when a new SAFE savior becomes available to protect SAFEs from liquidation. Contains:
  * `saviour` - the savior's address
* `DisconnectSAFESaviour` - emitted when a SAFE savior is not available anymore to protect SAFEs. Contains:
  * `saviour` - the savior's address
* `UpdateCurrentOnAuctionSystemCoins` - emitted when `currentOnAuctionSystemCoins` is updated. Contains:
  * `currentOnAuctionSystemCoins` - the current amount of system coins being requested across all active collateral auctions
* `ModifyParameters` - emitted when a parameter is updated by an authorized account
* `DisableContract` - emitted after the contract is disabled
* `Liquidate`- emitted when a `liquidateSAFE(bytes32, address)` is successfully executed. Contains:
  * `collateralType`- collateral
  * `safe`- SAFE address
  * `collateralAmount`- see `collateralToSell` in `liquidateSAFE`
  * `debtAmount`- see `safeDebt` in `liquidateSAFE`
  * `amountToRaise`- see `amountToRaise` in `liquidateSAFE`
  * `collateralAuctioneer`- address of the `CollateralAuctionHouse` contract
  * `auctionId`- ID of the auction in the `CollateralAuctionHouse`&#x20;
* `SaveSAFE`- emitted when the liquidated SAFE has a `SAFESaviour` attached to it and an external actor calls `liquidateSAFE(bytes32, address)`.

  Contains:

  * `collateralType`- The collateral type of the saved SAFE
  * `safe`- SAFE address
  * `collateralAdded`- amount of collateral added in the SAFE
* `FailedSAFESave` - emitted when a savior fails to rescue a SAFE. Contains:
  * `failReason` - the reason for failure
* `ProtectSAFE` - emitted when a SAFE user chooses a SAFE savior for their position. Contains:
  * `collateralType` - the collateral type locked in the protected SAFE
  * `safe` - the SAFE's address
  * `saviour` - the savior's address

**Notes**

* `liquidateSAFE`will not leave a SAFE with debt and no collateral
* `liquidateSAFE` will not leave a SAFE dusty
* `liquidateSAFE` will not start a new auction if `amountToRaise + currentOnAuctionSystemCoins` exceeds `onAuctionSystemCoinLimit`
* `protectSAFE` will revert if the chosen `SAFESaviour` address was not whitelisted by governance.

## 3. Walkthrough

`liquidateSAFE` can be called at any time but will only succeed if the target SAFE is underwater. A SAFE is underwater when the result of its collateral (`lockedCollateral`) multiplied by the collateral's liquidation price (`liquidationPrice`) is smaller than its present value debt (`generatedDebt` times the collateral's `accumulatedRates`).&#x20;

`liquidationPrice` is the oracle-reported price scaled by the collateral's liquidation ratio. There is a clear distinction between liquidation and safety ratios (even though the two can be equal in value):

* Safety ratios are the minimum collateralization ratios used when generating debt against a SAFE's collateral. They can be more conservative (higher) than liquidation ratios
* Liquidation ratios are the minimum collateralization ratios under which SAFEs are liquidated

`liquidateSAFE` may terminate early if the owner of the SAFE that's being targeted protected their position with a saviour that manages to save it from liquidation.


# Accounting Engine

The protocol's accountant, keeping track of surplus and deficit

## 1. Summary <a href="#id-1-introduction-summary" id="id-1-introduction-summary"></a>

The `AccountingEngine` receives both system surplus and system debt. It covers deficits via debt auctions and disposes off surplus via auctions (`Burning/RecyclingSurplusAuctionHouse`) or transfers (to `extraSurplusReceiver`).

## 2. Contract Variables & Functions <a href="#id-2-contract-details" id="id-2-contract-details"></a>

**Variables**

* `contractEnabled` - settlement flag (`1` or `0`).
* `authorizedAccounts[usr: address]` - addresses allowed to call `modifyParameters()` and `disableContract()`.
* `safeEngine` - address of the `SAFEEngine`.
* `surplusAuctionHouse` - address of the `PreSettlementSurplusAuctionHouse`.
* `debtAuctionHouse` - address of the `DebtAuctionHouse`.
* `systemStakingPool` - the system's staking pool acting as lender of first resort.
* `extraSurplusReceiver` - address that receives surplus in case the strategy to get rid of excessive surplus is transfer instead of auction.
* `debtQueue[timestamp: uint256]`- the system debt queue. The `LiquidationEngine` adds a new debt block every time it starts a new collateral auction. Each block can be popped out of the list after

  `popDebtDelay`seconds.
* `debtPoppers[timestamp: uint256]` - mapping that records the addresses which pop debt out of `debtQueue`.
* `lastSurplusTransferTime` - the last timestamp when the engine transferred extra surplus out.
* `lastSurplusAuctionTime` - the last timestamp when the engine auctioned extra surplus.
* `surplusTransferDelay` - the minimum delay between two consecutive extra surplus transfers.
* `surplusAuctionDelay` - the minimum delay between two consecutive extra surplus auctions.
* `extraSurplusIsTransferred` - `0` if extra surplus is auctioned, `1` if it's transferred.
* `postSettlementSurplusDrain`- contract meant to auction/dispose off any remaining surplus after the `AccountingEngine` is disabled (and in case surplus couldn't be settled with bad debt because of a bug).
* `protocolTokenAuthority` \*\*\*\* - address of \*\*\*\* authority contract that says which addresses are able to mint an burn protocol tokens.
* `totalQueuedDebt`- the total amount of debt in the queue.
* `totalOnAuctionDebt`- the total amount of debt being auctioned in the `DebtAuctionHouse`.
* `popDebtDelay`- length of time for which a debt block must stay in the `debtQueue`.
* `debtAuctionBidSize`- the fixed amount of debt to be covered by a single debt auction.
* `initialDebtAuctionMintedTokens`- the starting amount of protocol tokens offered to cover the auctioned debt.
* `surplusAuctionAmountToSell`- amount of surplus to be sold in a single surplus auction.
* `surplusTransferAmount` - the amount of extra surplus that is transferred with `transferExtraSurplus()`.
* `surplusBuffer`- threshold that must be exceeded before surplus auctions are possible.
* `disableCooldown`- time that must elapse after the `AccountingEngine` is disabled and until it can send all its remaining surplus to the `postSettlementSurplusDrain`. Must be bigger than `GlobalSettlement.shutdownCooldown`.
* `disableTimestamp`- timestamp when the `AccountingEngine` was disabled.

**Modifiers**

* `isAuthorized` \*\*\*\* - checks whether an address is part of `authorizedAddresses` (and thus can call authed functions).

**Functions**

* `modifyParameters(bytes32 parameter`, `uint256 data)` - update a `uint256` parameter.
* `modifyParameters(bytes32 parameter`, `address data)` - update an `address` parameter.
* `addAuthorization(usr: address)` - add an address to `authorizedAddresses`.
* `removeAuthorization(usr: address)` - remove an address from `authorizedAddresses`.
* `canPrintProtocolTokens() public view returns (bool)` - returns `true` if `systemStakingPool` is null or if `systemStakingPool.canPrintProtocolTokens()` reverts. Returns true or false depending on what `systemStakingPool.canPrintProtocolTokens()` returns.
* `pushDebtToQueue(debtBlock: uint256)` - adds a bad debt block to the auctions queue.
* `popDebtFromQueue(timestamp: uint256)` - release a debt block from the debt queue.
* `settleDebt(rad: uint256)` - calls `settleDebt` on the `safeEngine` in order to cancel out surplus and debt.
* `cancelAuctionedDebtWithSurplus(rad: uint256)` - cancels out surplus coming from `DebtAuctionHouse` auctions and auctioned (bad) debt.
* `auctionSurplus()` - trigger a surplus auction (`SurplusAuctionHouse.startAuction`).
* `transferExtraSurplus()` - transfers extra surplus (above the `surplusBuffer`) from the engine to `extraSurplusReceiver`.
* `auctionDebt()` - trigger a deficit auction (`DebtAuctionHouse.startAuction`).
* `settleDebtAuction(id: uint256)` - authed function meant to be called by `debtAuctionHouse` in order to signal that a specific auction settled.
* `transferPostSettlementSurplus()` - transfer any post settlement, leftover surplus to the`postSettlementSurplusDrain`. Meant to be a backup in case `GlobalSettlement.processSAFE` has a bug (cannot process a specific Safe), governance doesn't have power over the system and there's still surplus left in the `AccountingEngine` which then blocks `GlobalSettlement.setOutstandingCoinSupply`.
* `disableContract()` - set `contractEnabled` to zero and settle as much remaining debt as possible (if any)

**Events**

* `AddAuthorization` - emitted when a new address becomes authorized. Contains:
  * `account` - the new authorized account
* `RemoveAuthorization` - emitted when an address is de-authorized. Contains:
  * account - the address that was de-authorized
* `ModifyParameters` - emitted when a parameter is modified
* `PushDebtToQueue` - emitted when a new debt block is added to `debtQueue`. Contains:
  * `timestamp` - timestamp at which the debt block is pushed into `debtQueue`
  * `debtQueueBlock` - the size of the debt block
  * `totalQueuedDebt` - total amount of queued debt in the queue
* `PopDebtFromQueue` - emitted when a debt block is popped out of the `debtQueue`. Contains:
  * `timestamp` - timestamp from which all the debt is popped out of the queue
  * `debtQueueBlock` - amount of debt popped from the queue
  * `totalQueuedDebt` - total remaining amount of queued debt in the queue
* `SettleDebt` - emitted when an amount of debt that is not queued or in a debt auction is settled with an equal amount of surplus. Contains:
  * `rad` - the amount of debt to settle
  * `coinBalance` - the remaining amount of surplus after the debt is settled
  * `debtBalance` - the remaining amount of debt after `rad` debt is settled
* `CancelAuctionedDebtWithSurplus` - emitted when the contract settles debt that was in a debt auction. Contains:
  * `rad` - amount of auctioned debt to settle
  * `totalOnAuctionDebt` - remaining amount of debt being auctioned
  * `coinBalance` - the `AccountingEngine`'s coin balance after the debt is settled
  * `debtBalance` - remaining amount of debt
* `AuctionDebt` - emitted when a new debt auction starts. Contains:
  * `id` - the ID of the new debt auction
  * `totalOnAuctionDebt` - total debt being auctioned across all debt auctions
  * `debtBalance` - the `AccountingEngine`'s debt balance in the `SAFEEngine`
* `AuctionSurplus` - emitted when a new surplus auction starts. Contains:
  * `id` - the ID of the new surplus auction
  * `lastSurplusAuctionTime` - the current timestamp which is now the last time when a surplus auction was triggered
  * `coinBalance` - the `AccountingEngine`'s surplus balance
* `DisableContract` - emitted when the contract is disabled
* `TransferPostSettlementSurplus` - emitted when any remaining surplus after the contract is disabled is transferred to the `postSettlementSurplusDrain.` Contains:
  * `postSettlementSurplusDrain` - the address of the surplus drain
  * `coinBalance` - the remaining surplus balance of the `AccountingEngine`
  * `debtBalance` - the remaining debt balance of the `AccountingEngine`
* `TransferExtraSurplus` - emitted when extra surplus is transferred to `extraSurplusReceiver`. Contains:
  * `extraSurplusReceiver` - the address of the `extraSurplusReceiver`
  * `lastSurplusAuctionTime` - the current block timestamp
  * `coinBalance` - the current coin balance of the `AccountingEngine` now that some surplus has been transferred

## 3. Walkthrough

### Auctioning Debt

When a SAFE is liquidated, the seized debt is put in a queue in the `AccountingEngine`. This occurs at the block timestamp of the `liquidateSAFE` action (`debtQueue[timestamp]`). It can be released with the help of `popDebtFromQueue` once `AccountingEngine.popDebtDelay` has expired. Once released, it can be settled using the surplus gathered from the SAFE's liquidation or, if there wasn't enough surplus gathered, the debt can be auctioned using the `DebtAuctionHouse`. **NOTE**: the `AccountingEngine` can start a new debt auction only if `canPrintProtocolTokens` returns `true` and if `canPrintProtocolTokens` also doesn't unexpectedly revert.

The main risk is related to `popDebtDelay` < `CollateralAuctionHouse.totalAuctionLength` which would result in debt auctions starting before the associated collateral auctions could complete.

### Auctioning Surplus

When the `AccountingEngine` has a surplus balance above the `surplusBuffer` (`safeEngine.coinBalance[accountingEngine]` > `surplusBuffer`), if the extra surplus on top of the buffer is not reserved to nullify the engine's bad debt (`safeEngine.debtBalance[accountingEngine]`) and if `extraSurplusIsTransferred` is `0`, the extra surplus can be auctioned off using the `Burning/RecyclingSurplusAuctionHouse`. This process results in burning protocol tokens that are being offered in exchange for the auctioned surplus.

### Transferring Extra Surplus

When the `AccountingEngine` has a surplus balance above the `surplusBuffer` (`safeEngine.coinBalance[accountingEngine]` > `surplusBuffer`), if the extra surplus on top of the buffer is not reserved to nullify the engine's bad debt (`safeEngine.debtBalance[accountingEngine]`) and if `extraSurplusIsTransferred` is `1`, the extra surplus can be transferred to `extraSurplusReceiver`.

### Disabling the Accounting Engine

When an authorized address calls `AccountingEngine.disableContract` the system will try to settle as much remaining `safeEngine.debtBalance[accountingEngine]` as possible.

## 4. Gotchas (Potential source of user error)

* When the `AccountingEngine` is upgraded, there are multiple references to it that must be updated at the same time (`GlobalSettlement`, `TaxCollector`, `CoinSavingsAccount`).
* The `AccountingEngine` is the only user with a non-zero `totalQueuedDebt` balance (not a `safeEngine` invariant as there can be multiple `AccountingEngine`s).
* CollateralType storage is split across the `SafeEngine`, `TaxCollector`, `CoinSavingsAccount` and `AccountingEngine` modules. The `LiquidationEngine` also stores the liquidation penalty and maximum auction size.
* A portion of the Stability Fee is allocated for the Coin Savings Acount by increasing the amount of `totalQueuedDebt` in the `AccountingEngine` at every `CoinSavingsAccount.updateAccumulatedRate( )` call.
* Setting an incorrect value for `accountingEngine` can cause the surplus to be lost or stolen.

## 5. Failure Modes (Bounds on Operating Conditions & External Risk Factors)

#### Safe Liquidation

* A failure mode could arise when no actors call `cancelAuctionedDebtWithSurplus`, `popDebtFromQueue` or `settleDebt` to reconcile/queue the debt.

#### Auctions

* A failure mode could arise if a user does not call `auctionSurplus`or `auctionDebt` to kick off auctions.
* `AccountingEngine.popDebtDelay`, when set too high (`popDebtDelay` is too long), the `auctionDebt` auctions can no longer occur. This provides a risk of undercollateralization.
* `AccountingEngine.popDebtDelay`, when set too low, can cause too many `auctionDebt` auctions, while preventing `auctionSurplus` auctions from occurring.
* `AccountingEngine.surplusAuctionAmountToSell`, when set too high, can result in no `auctionSurplus` auctions being possible. Thus, if no `auctionSurplus` auction takes place, there will be no FLX bidding as part of that process and, accordingly, no automated FLX burn as a result of a successful auction.
* `AccountingEngine.surplusAuctionAmountToSell`, when set too low, results in `auctionSurplus` auctions not being profitable for participants (`amountToSell` size is worth less than gas cost). Thus, no FLX will be bid during a `auctionSurplus` auction and, as a result, there will be no automated FLX burn.
* `AccountingEngine.debtAuctionBidSize`, when set too high, no `auctionDebt` auctions are possible. This results in the system not being able to recover from an undercollateralized state.
* `AccountingEngine.debtAuctionBidSize`, when set too low, `auctionDebt` auctions are not profitable for participants (where the `amountToSell` size is worth less than gas cost). This results in FLX inflation due to automated FLX minting.
* `AccountingEngine.initialDebtAuctionMintedTokens`, when set too high, `auctionDebt` auctions risk not being able to close or mint a large amount of FLX, creating a risk of FLX dilution and the possibility of a governance attack.
* `AccountingEngine.initialDebtAuctionMintedTokens`, when set too low, `auctionDebt` auctions have to be `startAuction`ed many times before they will be interesting to keepers.
* `AccountingEngine.surplusBuffer`, when set too high, the `auctionSurplus` auctions would never occur. If a `auctionSurplus` auction does not occur, there is no sale of surplus, and thus, no burning of bid FLX.
* `AccountingEngine.surplusBuffer`, if set too low, can cause surplus to be auctioned off via `auctionSurplus` auctions before it is used to cancel `debtBalance` from liquidations, necessitating `auctionDebt` auctions and making the system run inefficiently.


# Auction Module

Maintaining system balance by covering shortfall and disbursing surplus

**Relevant smart contracts:**

* [**CollateralAuctionHouse**](https://github.com/reflexer-labs/geb/blob/master/src/single/CollateralAuctionHouse.sol)
* [**DebtAuctionHouse**](https://github.com/reflexer-labs/geb/blob/master/src/single/DebtAuctionHouse.sol)
* [**SurplusAuctionHouse**](https://github.com/reflexer-labs/geb/blob/master/src/single/SurplusAuctionHouse.sol)

## 1. Overview

The **Auction Module** is meant to incentivize external actors to drive the system back to a safe state by participating in collateral, debt and surplus auctions.

## 2. Component Descriptions

* The `CollateralAuctionHouse` is used to sell collateral from SAFEs that have become under-collateralized in order to preserve the overall health of the system. There are two flavours of collateral auctions: `English` and `FixedDiscount`.&#x20;
  * The `English` auction version requires that bidders compete with increasing amounts of system coins for a fixed amount of collateral and only one bidder can win. This auction type has two phases: `increaseBidSize` where bidders submit higher system coin bids and `decreaseSoldAmount` where bidders accept a lower collateral amount for the winning system coin bid.
  * On the other hand, the `FixedDiscount` and `IncreasingDiscount` auctions only have one phase (`buyCollateral`) where bidders submit system coins and the smart contract offers them collateral at a discounted price compared to its market price. These auction types are more capital efficient and user friendly compared to `English` auctions. They also allow anyone to buy collateral using [flashloans](https://blog.coincodecap.com/what-are-flash-loans-on-ethereum).

    By default, the contract will use the collateral's `OSM` price (which will lag compared to the actual collateral market price) and the system coin's `redemptionPrice` in order to calculate the amount of collateral to offer in exchange for each individual bid. There is the possibility for governance to set the contract's parameters so that it uses the collateral's medianizer price and/or the system coin's market price if they deviated within certain limits from the `FSM` price and the `redemptionPrice`.
* The `DebtAuctionHouse` is used to get rid of the `AccountingEngine`’s debt by auctioning off protocol tokens for a fixed amount of surplus (system coins). After the auction is settled, it sends the received surplus to the `AccountingEngine` in order to cancel out bad debt and it also mints protocol tokens for the winning bidder.
* The `SurplusAuctionHouse` (all of its `Burning`, `Recycling` and `PostSettlement` versions) is used to get rid of the `AccountingEngine`’s surplus by auctioning off a fixed amount of internal system coins in exchange for protocol tokens. After auction settlement, the auction house either burns the winning protocol token bid or it transfers the bid to an external address and then sends internal system coins to the winning bidder.

## 3. Risks <a href="#id-5-failure-modes-bounds-on-operating-conditions-and-external-risk-factors" id="id-5-failure-modes-bounds-on-operating-conditions-and-external-risk-factors"></a>

Governance needs to fine-tune auction parameters in order to make the bidding process as efficient as possible. In the case of `English`, `Debt` and `Surplus` auctions there are three main parameters:

* `bidIncrease`- if it's too high it will discourage bidding and if it's too low its effect will be insignificant
* `bidDuration`- if it's too high it would force the winning bidder to wait too long until they can collect their winnings. If it's too low it would not give other bidders enough time to participate
* `totalAuctionLength`- if it's too high it would only delay auction settlement without any positive impact on the outcome. If it's too low it would make the auction settle before the true price is found.
* `bidToMarketPriceRatio` (only in `English` collateral auctions) - minimum mandatory size of the first bid compared to collateral price coming from the `OSM`

In the case of `FixedDiscount` collateral auctions there's a wider range of variables:

* `totalAuctionLength`- same parameter as in the other auction types
* `discount`- discount applied to the collateral price
* `minimumBid`- minimum system coin bid that must be submitted by any bidder
* `upperCollateralMedianDeviation`- maximum upper side medianizer price deviation (compared to the `OSM` price) used by the auction contract to determine whether it will use the median or the `OSM` as a feed source
* `lowerCollateralMedianDeviation`- maximum lower side medianizer price deviation (compared to the `OSM` price) used by the auction contract to determine whether it will use the median or the `OSM` as a feed source
* `lowerSystemCoinMedianDeviation` - maximum lower side system coin market price (compared to the redemption price) used by the auction contract to determine whether it will use the market or the redemption price when determining the amount of collateral bought
* `upperSystemCoinMedianDeviation` - maximum upper side system coin market price (compared to the redemption price) used by the auction contract to determine whether it will use the market or the redemption price when determining the amount of collateral bought&#x20;
* `minSystemCoinMedianDeviation` - minimum deviation between the market and the redemption prices of the system coin in order for the contract to choose the market price (and not the redemption one) when it determines the amount of collateral bought

In the case of `IncreasingDiscount` collateral auctions, the parameter range is almost identical to the one in `FixedDiscount` auctions, with some additions:

* `minDiscount` - minimum discount (compared to the system coin's current redemption price) at which collateral is being sold
* `maxDiscount` - maximum discount (compared to the system coin's current redemption price) at which collateral is being sold
* `perSecondDiscountUpdateRate` - rate at which the discount will be updated in an auction
* `maxDiscountUpdateRateTimeline` - max time over which the discount can be updated in an auction

## 4. Governance Minimization

All of the auction contracts are in the Level 1 Gov Minimization category.


# English Collateral Auction House

English collateral auctioneer that tries to recapitalize the system

## 1. Summary <a href="#id-1-introduction-summary" id="id-1-introduction-summary"></a>

English collateral auctions are used to sell collateral from SAFEs that have become undercollateralized in order to preserve the overall system health. The `LiquidationEngine` sends collateral to the `EnglishCollateralAuctionHouse` where it is auctioned in two phases: `increaseBidSize` and `decreaseSoldAmount`.

## 2. Contract Variables & Functions <a href="#id-2-contract-details" id="id-2-contract-details"></a>

**Variables**

* `contractEnabled` - settlement flag (`1` or `0`).
* `AUCTION_HOUSE_TYPE` - flag set to `bytes32("COLLATERAL")`
* `AUCTION_TYPE` - flag set to `bytes32("ENGLISH")`.
* `authorizedAccounts[usr: address]` - addresses allowed to call `modifyParameters()` and `disableContract()`.
* `safeEngine` - storage of the `SAFEEngine`'s address.
* `bids[id: uint]` - storage of all bids.
* `collateralType` - id of the collateral type for which the `CollateralAuctionHouse` is responsible.
* `bidIncrease` - minimum bid increase (default: 5%).
* `bidDuration` - bid duration (default: 3 hours).
* `totalAuctionLength` - auction length (default: 2 days).
* `auctionsStarted` - total auction count, used to track auction `id`s.
* `bidToMarketPriceRatio` - the minimum size of the first bid compared to the latest recorded collateral price (for `collateralType`) in the system.
* `oracleRelayer` - address of the `OracleRelayer`.
* `osm` - collateral type `OSM` address
* `liquidationEngine` - the address of the `LiquidationEngine`

**Data Structures**

* `Bid` - state of a specific auction
  * `bidAmount` - paid system coins
  * `amountToSell` - quantity up for auction / collateral for sale
  * `highBidder`
  * `bidExpiry` - when a bid expires (and the auction ends)
  * `auctionDeadline` - max auction duration
  * `forgoneCollateralReceiver` - address of the SAFE being auctioned. Receives collateral during the `decreaseSoldAmount` phase
  * `auctionIncomeRecipient` - recipient of auction income / receives system coin income (this is the `AccountingEngine` contract)
  * `amountToRaise` - total system coins wanted from the auction

**Modifiers**

* `isAuthorized` - checks whether an address is part of `authorizedAddresses` (and thus can call authed functions).

**Functions**

* `modifyParameters(bytes32 parameter`, `uint256 data)` - update a `uint256` parameter.
* `modifyParameters(bytes32 parameter`, `address data)` - update an `address` parameter.
* `addAuthorization(usr: address)` - add an address to `authorizedAddresses`.
* `removeAuthorization(usr: address)` - remove an address from `authorizedAddresses`.
* `startAuction(forgoneCollateralReceiver: address`, `auctionIncomeRecipient: address`, `amountToRaise: uint256`, `amountToSell: uint256`, `initialBid: uint256 )` - function used by `LiquidationEngine` to start an auction / put collateral up for auction
* `restartAuction(id: uint256)` - restart an auction if there have been 0 bids and the `auctionDeadline` has passed
* `increaseBidSize(id: uint256`, `amountToBuy: uint256`, `rad: uint256)` - first phase of an auction. Increasing system coin `bid`s for a set `amountToSell` of collateral
* `decreaseSoldAmount(id: uint256`, `amountToBuy: uint256`, `rad: uint256)` - second phase of an auction. Set system coin `bid` for a decreasing`amountToSell`of collateral.
* `settleAuction(id: uint256)` - claim a winning bid / settles a completed auction
* `terminateAuctionPrematurely(id: uint256)` - used during `GlobalSettlement` to terminate `increaseBidSize` phase auctions and transfer the collateral to the settlement contract while repaying system coins (the winning bid) to the highest bidder.
* `bidAmount(id: uint256) public view returns (uint256)` - return the latest `bidAmount` from a specific auction
* `remainingAmountToSell(id: uint256) public view returns (uint256)` - return the remaining collateral amount to sell from a specific auction
* `forgoneCollateralReceiver(uint id) public view returns (address)` - return the`forgoneCollateralReceiver` for a specific auction
* `raisedAmount(id: uint256)` - always returns zero
* `amountToRaise(uint id) public view returns (uint256)` - return the amount of system coins to raise for a specific auction

**Events**

* `AddAuthorization` - emitted when a new address becomes authorized. Contains:
  * `account` - the new authorized account
* `RemoveAuthorization` - emitted when an address is de-authorized. Contains:
  * `account` - the address that was de-authorized
* `StartAuction`- emitted when `startAuction(address`, `address`, `uint256`, `uint256`, `uint256)` is successfully executed. Contains:
  * `id` - auction id
  * `auctionsStarted` - total amount of auctions started up until now
  * `amountToSell` - amount of collateral sold in the auction
  * `initialBid` - starting bid for the auction (usually zero).
  * `amountToRaise` - amount of system coins that should be raised by the auction.
  * `forgoneCollateralReceiver` - receiver of leftover collateral (usually the SAFE whose collateral was confiscated by the `LiquidationEngine`).
  * `auctionIncomeRecipient` - receiver of system coins (usually the `AccountingEngine`)
  * `auctionDeadline` - the auction's deadline
* `ModifyParameters` - emitted when a parameter is updated
* `RestartAuction` - emitted when an auction restarts due to a lack of bids. Contains:
  * `id` - the ID of the auction to restart
  * `auctionDeadline` - the new deadline for the auction with the ID `id`
* `IncreaseBidSize` - emitted when a bidder offers more system coins for the same amount of collateral. Contains:
  * `id` - the id of the auction being bid on
  * `highBidder` - the new high bidder (new auction winner which is set to `msg.sender`)
  * `amountToBuy` - total amount of collateral being bought from the auction
  * `rad` - the new system coin bid
  * `bidExpiry` - the timestamp after which the new bid will be considered final and `highBidder` can receive the collateral (even if `bidExpiry` < `auctionDeadline`)
* `DecreaseSoldAmount` - emitted when someone accepts a smaller amount of collateral for the same amount of `rad` system coins bid in the `increaseBidSize` phase. Contains:
  * `id` - the id of the auction being bid on
  * `highBidder` - the new high bidder (new auction winner which is set to `msg.sender`)
  * `amountToBuy` - new (and lower) amount of collateral being bought from the auction
  * `rad` - same system coin bid as the winning bid from the&#x20;
  * `bidExpiry` - the timestamp after which the new bid will be considered final and `highBidder` can receive the collateral (even if `bidExpiry` < `auctionDeadline`)
* `SettleAuction` - emitted after an auction is settled. Contains:
  * `id` - the ID of the auction that has just been settled
* `TerminateAuctionPrematurely` - emitted after an auction is terminated prematurely by an authed address. Contains:
  * `id` - the ID of the auction being terminated
  * `sender` - `msg.sender`
  * `bidAmount` - the amount of system coins that should have been raised by the auction
  * `collateralAmount` - the total amount of collateral that should have been sold by the auction

## 3. Walkthrough <a href="#id-3-key-mechanisms-and-concepts" id="id-3-key-mechanisms-and-concepts"></a>

Starting in the `increaseBidSize`-phase, bidders compete for an `amountToSell` of collateral with increasing bid amounts of system coins. The very first `bidAmount` will need to be higher than or equal to `latest collateral price in collateral OSM * bidToMarketPriceRatio / RAY.` This ensures that no bidder can submit an extremely small `bidAmount` and thus pay a negligible price for the entire `amountToSell` collateral.&#x20;

Once `amountToRaise` amount of system coins has been raised, the auction moves to the `decreaseSoldAmount`-phase. This phase is meant to incentivize bidders to returns as much collateral as possible back to the SAFE while still paying `amountToRaise` system coins.

Once the auction's last bid has expired or the auction itself has reached the `auctionDeadline` anyone can call `settleAuction` to payout the highest bidder (`Bid.highBidder`). This moves collateral from the `CollateralAuctionHouse`'s balance in the `SAFEEngine` to the winning bidder's balance.

When the auction is settled (or terminated prematurely), the contract will call the `LiquidationEngine` in order to `removeCoinsFromAuction` (subtract `bids[auctionId].amountToRaise` from `LiquidationEngine.currentOnAuctionSystemCoins`).


# Fixed Discount Collateral Auction House

Auctioneer that tries to recapitalize the system by selling collateral at a discounted price

## 1. Summary <a href="#id-1-introduction-summary" id="id-1-introduction-summary"></a>

Fixed discount collateral auctions are similar to their `English` counterpart in that they are used to preserve the overall system health by liquidating under-collateralized SAFEs and selling off collateral in exchange for system coins. This auction type automatically calculates an amount of collateral to send back to a bidder, taking into account the amount of system coins the bidder submits as well as the current system coin `redemptionPrice` (and optionally its market price) and collateral market price.

## 2. Contract Variables & Functions <a href="#id-2-contract-details" id="id-2-contract-details"></a>

**Variables**

* `contractEnabled` - settlement flag (`1` or `0`).
* `AUCTION_HOUSE_TYPE` - flag set to `bytes32("COLLATERAL")`
* `AUCTION_TYPE` - flag set to `bytes32("FIXED_DISCOUNT")`.
* `authorizedAccounts[usr: address]` - addresses allowed to call `modifyParameters()` and `disableContract()`.
* `safeEngine` - storage of the `SAFEEngine`'s address.
* `bids[id: uint]` - storage of all bids.
* `collateralType` - id of the collateral type for which the `CollateralAuctionHouse` is responsible.
* `minimumBid` - minimum amount of system coins that must be submitted by each bidder.
* `totalAuctionLength` - auction length (default: `uint48(-1)`).
* `auctionsStarted` - total auction count, used to track auction `id`s.
* `lastReadRedemptionPrice` - the last read redemption price. Can (and most probably is) be different than the latest `OracleRelayer._redemptionPrice`
* `discount` - discount compared to the collateral market price; used when calculating the amount of collateral to send to a bidder.
* `lowerCollateralMedianDeviation` - max `collateralMedian` collateral price deviation (compared to the `FSM` price) used when the median price is lower than the `collateralFSM` price and the contract needs to pick which one to use
* `upperCollateralMedianDeviation` - max `collateralMedian` collateral price deviation (compared to the `FSM` price) used when the median price is higher than the `collateralFSM` price and the contract needs to pick which one to use
* `lowerSystemCoinMedianDeviation` - max `systemCoinOracle` price deviation (compared to the `redemptionPrice`) used when the system coin's `redemptionPrice` price is higher than its market price and the contract needs to pick which one to use
* `upperSystemCoinMedianDeviation` - max `systemCoinOracle` price deviation (compared to the `redemptionPrice`) used when the system coin's `redemptionPrice` price is lower than its market price and the contract needs to pick which one to use
* `minSystemCoinMedianDeviation` - minimum deviation between the system coin's market and redemption prices that must be passed in order for the contract to use the deviated price instead of the redemption one
* `oracleRelayer` - address of the `OracleRelayer`
* `collateralFSM` - the collateral type's `FSM` address
* `collateralMedian` - collateral type medianizer address
* `systemCoinOracle` - market price oracle for the system coin
* `liquidationEngine` - the address of the `LiquidationEngine`
* `RAD` - number with 45 decimals (e.g a `safeEngine.coinBalance`)
* `WAD` - number with 18 decimals (e.g a bid submitted when someone wants to buy collateral from an auction)
* `RAY` - number with 27 decimals

**Data Structures**

* `Bid` - state of a specific auction
  * `raisedAmount` - amount of system coins raised up until this point
  * `soldAmount` - amount of collateral sold up until this point
  * `amountToSell` - quantity up for auction / collateral for sale
  * `amountToRaise` - total system coins wanted from the auction
  * `auctionDeadline` - max auction duration
  * `forgoneCollateralReceiver` - address of the SAFE being auctioned
  * `auctionIncomeRecipient` - recipient of auction income / receives system coin income (this is  the `AccountingEngine` contract)

**Modifiers**

* `isAuthorized` - checks whether an address is part of `authorizedAddresses` (and thus can call authed functions).

**Functions**

* `modifyParameters(bytes32 parameter`, `uint256 data)` - update an `uint256` parameter.
* `modifyParameters(bytes32 parameter`, `address data)` - update an `address` parameter.
* `addAuthorization(usr: address)` - add an address to `authorizedAddresses`.
* `removeAuthorization(usr: address)` - remove an address from `authorizedAddresses`.
* `getCollateralMedianPrice() public view returns (priceFeed: uint256)` - get the collateral's median price from `collateralMedian`
* `getSystemCoinMarketPrice() public view returns (priceFeed: uint256)` - get the system coin's  market price from `systemCoinOracle`
* `getFinalTokenPrices(systemCoinRedemptionPrice: uint256) public view returns (uint256`, `uint256)` - get the collateral and system coin prices that can be currently used to determine the amount of collateral bought by bidders
* `getFinalBaseCollateralPrice(collateralFsmPriceFeedValue: uint256`, `collateralMedianPriceFeedValue: uint256) public view returns (uint256)` - get the final collateral price (without the discount applied) that will be used to determine the amount of collateral bought by a bid
* `getDiscountedCollateralPrice(collateralFsmPriceFeedValue: bytes32`, `collateralMedianPriceFeedValue: bytes32`, `systemCoinPriceFeedValue: uint256`, `customDiscount: uint256) public view returns (uint256)` - get the (discounted) collateral price using either the `FSM` or median price for the collateral and the redemption/market price for the system coin
* `startAuction(forgoneCollateralReceiver: address`, `auctionIncomeRecipient: address`, `amountToRaise: uint256`, `amountToSell: uint256`, `initialBid: uint256 )` - function used by `LiquidationEngine` to start an auction / put collateral up for auction
* `getApproximateCollateralBought(id: uint256`, `wad: uint256)` - get the amount of collateral that can be bought from a specific auction by bidding `wad` and assuming that the latest system coin `redemptionPrice` is equal to `lastReadRedemptionPrice`
* `getCollateralBought(id: uint256`, `wad: uint256) returns (uint256`, `uint256)` - get the amount of collateral that can be bought from a specific auction by bidding `wad` amount of system coins (where `wad` will be scaled by `RAY` to transfer the correct amount of `RAD` system coins from `safeEngine.coinBalance`)
* `buyCollateral(id: uint256`, `wad: uint256)` - buy collateral from an auction and offer `wad` amount of system coins in return (where `wad` is scaled by `RAY` in order to transfer `RAD` amount of coins from the bidder's `safeEngine.coinBalance`)
* `settleAuction(id: uint256)` - settle an auction that has passed its `auctionDeadline` and return any unsold collateral to the `forgoneCollateralReceiver`
* `terminateAuctionPrematurely(id: uint256)` - normally used during `GlobalSettlement` to terminate an auction early and send unsold collateral to the `msg.sender` as well as call `LiquidationEngine` in order to subtract `bids[auctionId].amountToRaise` from `LiquidationEngine.currentOnAuctionSystemCoins`
* `bidAmount(id: uint256) public view returns (uint256)` - always returns zero
* `remainingAmountToSell(id: uint256) public view returns (uint256)` - return the remaining collateral amount to sell from a specific auction
* `forgoneCollateralReceiver(uint id) public view returns (address)` - returns the`forgoneCollateralReceiver` for a specific auction
* `raisedAmount(id: uint256)` - returns the currently raised amount of system coins for a specific auction.
* `amountToRaise(uint id) public view returns (uint256)` - returns the amount of system coins to raise for a specific auction

**Events**

* `AddAuthorization` - emitted when a new address becomes authorized. Contains:
  * `account` - the new authorized account
* `RemoveAuthorization` - emitted when an address is de-authorized. Contains:
  * `account` - the address that was de-authorized
* `StartAuction`- emitted when `startAuction(address`, `address`, `uint256`, `uint256`, `uint256)` is successfully executed. Contains:
  * `id` - auction id
  * `auctionsStarted` - amount of auctions started up until now
  * `amountToSell` - amount of collateral sold in the auction
  * `initialBid` - starting bid for the auction (usually zero).
  * `amountToRaise` - amount of system coins that should be raised by the auction.
  * `forgoneCollateralReceiver` - receiver of leftover collateral (usually the SAFE whose collateral was confiscated by the `LiquidationEngine`).
  * `auctionIncomeRecipient` - receiver of system coins (usually the `AccountingEngine`).
  * `auctionDeadline` - the auction's deadline
* `ModifyParameters` - emitted when a parameter is modified
* `BuyCollateral` - emitted when someone buys collateral from an auction. Contains:
  * `id` - the ID of the auction from which collateral was bought
  * `wad` - the bid size
  * `boughtCollateral` - the amount of collateral that was bought
* `SettleAuction` - emitted when someone settles an auction. Contains:
  * `id` - the ID of the auction settled
  * `leftoverCollateral` - the amount of collateral that hasn't been sold by the now settled auction
* `TerminateAuctionPrematurely` - emitted when an auction is terminated before its deadline. Contains:
  * `id` - the ID of the auction that was terminated
  * `sender` - the address that terminated the auction
  * `collateralAmount` - the amount of collateral still unauctioned

## 3. Walkthrough <a href="#id-3-key-mechanisms-and-concepts" id="id-3-key-mechanisms-and-concepts"></a>

The fixed discount auction is a straightforward way (compared to `English` auctions) to put SAFE collateral up for sale in exchange for system coins used to settle bad debt. Bidders are only required to allow the auction house to transfer their `safeEngine.coinBalance` and can then call`buyCollateral(id: uint256`, `wad: uint256)` in order to exchange their system coins for collateral which is sold at a `discount` compared to its latest recorded market price. Bidders can also review the amount of collateral they can get from a specific auction by calling `getCollateralBought(id: uint256`, `wad: uint256)` or `getApproximateCollateralBought(id: uint256`, `wad: uint256)`. Note that `getCollateralBought` is not marked as `view` because it reads (and also updates) the `redemptionPrice` from the `OracleRelayer` whereas `getApproximateCollateralBought` uses the`lastReadRedemptionPrice`.

{% hint style="info" %}
**Bids as WAD Amounts**

As opposed to `English` auctions where bidders submit bids with `RAD` amounts of system coins (using `increaseBidSize` and `decreaseSoldAmount`), `buyCollateral` requires a `WAD` amount of coins that are then multiplied by `RAY` in order to correctly scale the amount to `RAD` and transfer coins from the bidder's `safeEngine.coinBalance.`
{% endhint %}

There are several parameters that come together when the contract calculates the amount of collateral to send to a bidder:

* The amount of system coins `wad` used when calling `buyCollateral`. `wad` must be bigger than zero and bigger than or equal to `minimumBid`. In case `wad` is bigger than `minimumBid`, the contract will only request what it needs in order to fill `remainingToRaise`. Note that in order to avoid dusty auctions resulting from computing an `adjustedBid` (because of precision loss from division) the contract will automatically request `10**-18` extra system coins
* The difference between the collateral's `FSM` price (the delayed price) and the latest market price stored in the medianizer (which the `FSM` is connected to). The auction house uses the `FSM` price by default so that, in case of an oracle attack, governance can react and temporarily disable the `FSM` (in case they have power over that system component).
  * During the `FSM`'s delay, the market price (and thus the medianizer value) might change significantly and thus bidders might have to wait until a new median price feed is pushed into the `FSM` so that they can profit from auctions. In order to avoid scenarios where bidders have to wait for an `FSM` update and at the same time protect collateral auctions from an oracle attack, we added two variables: `lowerCollateralMedianDeviation`and `upperCollateralMedianDeviation`which allow the auction house to pick the medianizer price (when calculating the amount of collateral bought by a bidder) in case it deviated within certain bounds compared to the `FSM` price.
* The difference between the system coin's `redemptionPrice` and its market price (provided only if `systemCoinOracle` is not null and it returns a valid price). The auction house uses the `redemptionPrice` by default, although, during market shocks, there may be a significant difference between the system coin's redemption and market prices which will discourage bidding (if the market price is above redemption). This is why governance can set `lowerSystemCoinMedianDeviation` and `upperSystemCoinMedianDeviation` in order to allow the contract to use the system coin market price if it deviated within certain bounds from the `redemptionPrice`. Governance can also set `minSystemCoinMedianDeviation` so that the contract only chooses the market price in case it deviated above a certain threshold.

Similar to `English` auctions, when the auction is settled (or terminated prematurely), the contract will call the `LiquidationEngine` in order to `removeCoinsFromAuction` (subtract `bids[auctionId].amountToRaise` from `LiquidationEngine.currentOnAuctionSystemCoins`).

## 4. Gotchas <a href="#id-3-key-mechanisms-and-concepts" id="id-3-key-mechanisms-and-concepts"></a>

* In case someone bids an amount that is higher than the remaining amount of system coins which still need to be raised by an auction, the contract will only charge for the remaining amount plus `10**-18` extra system coins (meant to prevent dusty auctions)
* You must always submit a bid that is higher than or equal to `minimum(minimumBid`, `subtract(bids[id].amountToRaise`, `bids[id].raisedAmount))`. The contract will take care of charging only for the amount needed to cover the total remaining`amountToRaise`
* The auctions use the system coin `redemptionPrice` by default (not its market price)

## 5. Examples <a href="#id-3-key-mechanisms-and-concepts" id="id-3-key-mechanisms-and-concepts"></a>

```
// Scenario 1

minimumBid                     = 5 * WAD  // 5 coins
discount                       = 0.95E18  // 5%
lowerCollateralMedianDeviation = 0.90E18  // 10%
upperCollateralMedianDeviation = 0.95E18  // 5%
lowerSystemCoinMedianDeviation = WAD      // 0%
upperSystemCoinMedianDeviation = WAD      // 0%
minSystemCoinMedianDeviation   = 0.999E18 // 0.1%

collateralFsmPriceFeedValue    = 100 * WAD
collateralMedianPriceFeedValue = 89 * WAD

systemCoinRedemptionPrice      = 5 * RAY
systemCoinMarketPrice          = 5.01 * RAY

amountToSell                   = WAD
amountToRaise                  = 10 * RAD

submittedBid                   = 5 * WAD

/* 
    Because the collateral price fetched from the median is smaller than
    the collateral's FSM price and it is also deviated more than what
    lowerCollateralMedianDeviation permits (11%), the final collateral price 
    used by the contract will be 
    0.9 (lower collateral deviation) * 100 (collateral FSM price) = 90 USD
*/
finalCollateralPrice            = 90 * WAD

/*
    Even if the system coin market price is deviated from the redemption price,
    both the lower and the upper systemCoinMedianDeviation are 0% so the contract
    will use the redemption price
*/
finalSystemCoinPrice            = 5 * RAY

/*
    Determining the amount of collateral bought given the 5 system coin bid
*/
discountedSystemCoinCollateralPrice 
    = (finalCollateralPrice * RAY / finalSystemCoinPrice) * discount / WAD 
    = 17.1 * WAD

boughtCollateralAmount 
    = submittedBid * WAD / discountedSystemCoinCollateralPrice
    = 0.292397661 * WAD
```

```
// Scenario 2

minimumBid                     = 5 * WAD  // 5 coins
discount                       = 0.95E18  // 5%
lowerCollateralMedianDeviation = 0.90E18  // 10%
upperCollateralMedianDeviation = 0.95E18  // 5%
lowerSystemCoinMedianDeviation = 0.95E18  // 5%
upperSystemCoinMedianDeviation = 0.98E18  // 2%
minSystemCoinMedianDeviation   = 0.999E18 // 0.1%

collateralFsmPriceFeedValue    = 100 * WAD
collateralMedianPriceFeedValue = 89 * WAD

systemCoinRedemptionPrice      = 5 * RAY
systemCoinMarketPrice          = 5.1 * RAY

amountToSell                   = WAD
amountToRaise                  = 10 * RAD

submittedBid                   = 15 * WAD

/*
    Given that the submittedBid is higher than the total remaining amount to raise,
    the contract will adjust the bid (by rounding up)
*/
adjustedBid = amountToRaise / RAY + 1 = 10 * WAD + 1

/*
    Similar to Scenario 1, the final collateral price used by the contract 
    will be 90 USD
*/
finalCollateralPrice           = 90 * WAD

/*
    The system coin market price is 2% deviated compared to the redemption price
    and upperSystemCoinMedianDeviation is also 2% so the contract will pick
    5 (redemption price) * 1.02 (allowed deviation) = 5.1 USD as the system
    coin price
*/
finalSystemCoinPrice           = 5.1 * RAY

/*
    Determining the amount of collateral bought given the 10 WAD + 1 
    adjusted system coin bid
*/
discountedSystemCoinCollateralPrice 
    = (finalCollateralPrice * RAY / finalSystemCoinPrice) * discount / WAD 
    = 16.764705882 * WAD

boughtCollateralAmount 
    = adjustedBid * WAD / discountedSystemCoinCollateralPrice
    = 0.596491228082733148 * WAD
```


# Increasing Discount Collateral Auction House

Auctioneer that tries to recapitalize the system by selling collateral at an increasing discount

## 1. Summary

Increasing discount collateral auctions are similar to fixed discount ones in that they are used to preserve the overall system health by liquidating under-collateralized SAFEs and selling off collateral at a discount. This auction type automatically calculates an amount of collateral to send back to a bidder, taking into account the amount of system coins the bidder submits as well as the current system coin `redemptionPrice` (and optionally its market price) and collateral market price.

## 2. Contract Variables & Functions <a href="#id-2-contract-details" id="id-2-contract-details"></a>

**Variables**

* `contractEnabled` - settlement flag (`1` or `0`).
* `AUCTION_HOUSE_TYPE` - flag set to `bytes32("COLLATERAL")`
* `AUCTION_TYPE` - flag set to `bytes32("INCREASING_DISCOUNT")`.
* `authorizedAccounts[usr: address]` - addresses allowed to call `modifyParameters()` and `disableContract()`.
* `safeEngine` - storage of the `SAFEEngine`'s address.
* `bids[id: uint]` - storage of all bids.
* `collateralType` - id of the collateral type for which the `CollateralAuctionHouse` is responsible.
* `minimumBid` - minimum amount of system coins that must be submitted by each bidder.
* `totalAuctionLength` - auction length (default: `uint48(-1)`).
* `auctionsStarted` - total auction count, used to track auction `id`s.
* `lastReadRedemptionPrice` - the last read redemption price. Can (and most probably is) be different than the latest `OracleRelayer._redemptionPrice`
* `minDiscount` - initial discount (compared to the collateral market price) used when calculating the amount of collateral to send to a bidder.
* `maxDiscount` - maximum discount (compared to the collateral market price) used when calculating the amount of collateral to send to a bidder.
* `perSecondDiscountUpdateRate` - the rate at which the discount will be updated in an auction.
* `maxDiscountUpdateRateTimeline` - max time over which the discount can be updated in an auction.
* `lowerCollateralMedianDeviation` - max `collateralMedian` collateral price deviation (compared to the `FSM` price) used when the median price is lower than the `collateralFSM` price and the contract needs to pick which one to use
* `upperCollateralMedianDeviation` - max `collateralMedian` collateral price deviation (compared to the `FSM` price) used when the median price is higher than the `collateralFSM` price and the contract needs to pick which one to use
* `lowerSystemCoinMedianDeviation` - max `systemCoinOracle` price deviation (compared to the `redemptionPrice`) used when the system coin's `redemptionPrice` price is higher than its market price and the contract needs to pick which one to use
* `upperSystemCoinMedianDeviation` - max `systemCoinOracle` price deviation (compared to the `redemptionPrice`) used when the system coin's `redemptionPrice` price is lower than its market price and the contract needs to pick which one to use
* `minSystemCoinMedianDeviation` - minimum deviation between the system coin's market and redemption prices that must be passed in order for the contract to use the deviated price instead of the redemption one
* `oracleRelayer` - the address of the `OracleRelayer`
* `collateralFSM` - the collateral type's `FSM` address
* `collateralMedian` - collateral type medianizer address
* `systemCoinOracle` - market price oracle for the system coin
* `liquidationEngine` - the address of the `LiquidationEngine`
* `RAD` - number with 45 decimals (e.g a `safeEngine.coinBalance`)
* `WAD` - number with 18 decimals (e.g a bid submitted when someone wants to buy collateral from an auction)
* `RAY` - number with 27 decimals

**Data Structures**

* `Bid` - state of a specific auction
  * `amountToSell` - quantity up for auction / remaining collateral for sale
  * `amountToRaise` - total system coins still requested by the auction
  * `currentDiscount` - the current discount being used in the auction
  * `maxDiscount` - the max value that the `currentDiscount` can have
  * `perSecondDiscountUpdateRate` - the rate at which the `currentDiscount` grows
  * `latestDiscountUpdateTime` - last time when the `currentDiscount` was updated
  * `discountIncreaseDeadline` - deadline after which the discount cannot increase anymore
  * `forgoneCollateralReceiver` - address of the SAFE whose collateral and debt were confiscated
  * `auctionIncomeRecipient` - recipient of auction income / receives system coin income (this is  the `AccountingEngine` contract)

**Modifiers**

* `isAuthorized` - checks whether an address is part of `authorizedAddresses` (and thus can call authed functions).

**Functions**

* `modifyParameters(bytes32 parameter`, `uint256 data)` - update an `uint256` parameter.
* `modifyParameters(bytes32 parameter`, `address data)` - update an `address` parameter.
* `addAuthorization(usr: address)` - add an address to `authorizedAddresses`.
* `removeAuthorization(usr: address)` - remove an address from `authorizedAddresses`.
* `getCollateralMedianPrice() public view returns (priceFeed: uint256)` - get the collateral's median price from `collateralMedian`
* `getSystemCoinFloorDeviatedPrice(redemptionPrice: uint256) public view returns` `(floorPrice: uint256)` - get the smallest possible price that's at max `lowerSystemCoinMedianDeviation` deviated from the redemption price and at least `minSystemCoinMedianDeviation` deviated
* `getSystemCoinCeilingDeviatedPrice(redemptionPrice: uint256) public view returns` `(ceilingPrice: uint256)` - get the highest possible price that's at max `upperSystemCoinMedianDeviation` deviated from the redemption price and at least `minSystemCoinMedianDeviation` deviated
* `getCollateralFSMAndFinalSystemCoinPrices(systemCoinRedemptionPrice: uint256) public` `view returns (uint256, uint256)` - get the collateral price from the FSM and the final system coin price that will be used when bidding in an auction
* `getSystemCoinMarketPrice() public view returns (priceFeed: uint256)` - get the system coin's  market price from `systemCoinOracle`
* `getFinalTokenPrices(systemCoinRedemptionPrice: uint256) public view returns (uint256`, `uint256)` - get the collateral and system coin prices that can be currently used to determine the amount of collateral bought by bidders
* `getFinalBaseCollateralPrice(collateralFsmPriceFeedValue: uint256`, `collateralMedianPriceFeedValue: uint256) public view returns (uint256)` - get the collateral price (without the discount applied) used in bidding by picking between the raw FSM and the oracle median price and taking into account deviation limits
* `getDiscountedCollateralPrice(collateralFsmPriceFeedValue: bytes32`, `collateralMedianPriceFeedValue: bytes32`, `systemCoinPriceFeedValue: uint256`, `customDiscount: uint256) public view returns (uint256)` - get the (discounted) collateral price using either the `FSM` or median price for the collateral and the redemption/market price for the system coin
* `getNextCurrentDiscount(id: uint256) public view returns (uint256)` -  get the upcoming discount that will be used in a specific auction
* `getAdjustedBid(id: uint256`, `wad: uint256) public view returns (bool, uint256)` - get the actual bid that will be used in an auction (taking into account the bidder input)
* `startAuction(forgoneCollateralReceiver: address`, `auctionIncomeRecipient: address`, `amountToRaise: uint256`, `amountToSell: uint256`, `initialBid: uint256 )` - function used by `LiquidationEngine` to start an auction / put collateral up for auction
* `getApproximateCollateralBought(id: uint256`, `wad: uint256)` - get the amount of collateral that can be bought from a specific auction by bidding `wad` sysem coins and assuming that the latest system coin `redemptionPrice` is equal to `lastReadRedemptionPrice`
* `getCollateralBought(id: uint256`, `wad: uint256) returns (uint256`, `uint256)` - get the amount of collateral that can be bought from a specific auction by bidding `wad` amount of system coins (where `wad` will be scaled by `RAY` to transfer the correct amount of `RAD` system coins from `safeEngine.coinBalance`)
* `buyCollateral(id: uint256`, `wad: uint256)` - buy collateral from an auction and offer `wad` amount of system coins in return (where `wad` is scaled by `RAY` in order to transfer `RAD` amount of coins from the bidder's `safeEngine.coinBalance`)
* `settleAuction(id: uint256)` - settle an auction that has passed its `auctionDeadline` and return any unsold collateral to the `forgoneCollateralReceiver`
* `terminateAuctionPrematurely(id: uint256)` - normally used during `GlobalSettlement` to terminate an auction early and send unsold collateral to the `msg.sender` as well as call `LiquidationEngine` in order to subtract `bids[auctionId].amountToRaise` from `LiquidationEngine.currentOnAuctionSystemCoins`
* `bidAmount(id: uint256) public view returns (uint256)` - always returns zero.
* `remainingAmountToSell(id: uint256) public view returns (uint256)` - return the remaining collateral amount to sell from a specific auction.
* `forgoneCollateralReceiver(uint id) public view returns (address)` - returns the`forgoneCollateralReceiver` for a specific auction.
* `raisedAmount(id: uint256)` - returns zero.
* `amountToRaise(uint id) public view returns (uint256)` - returns the amount of system coins left to raise by a specific auction.

**Events**

* `AddAuthorization` - emitted when a new address becomes authorized. Contains:
  * `account` - the new authorized account
* `RemoveAuthorization` - emitted when an address is de-authorized. Contains:
  * `account` - the address that was de-authorized
* `StartAuction`- emitted when `startAuction(address`, `address`, `uint256`, `uint256`, `uint256)` is successfully executed. Contains:
  * `id` - auction id
  * `auctionsStarted` - amount of auctions started up until now
  * `amountToSell` - amount of collateral sold in the auction
  * `initialBid` - starting bid for the auction (usually zero).
  * `amountToRaise` - amount of system coins that should be raised by the auction.
  * `startingDiscount` - the initial discount offered in the auction.
  * `maxDiscount` - the max discount that can be offered in the auction.
  * `perSecondDiscountUpdateRate` - the pace at which the current discount in the auction is updated.
  * `discountIncreaseDeadline` - the deadline after which the current discount offered in the auction cannot increase anymore.
  * `forgoneCollateralReceiver` - receiver of leftover collateral (usually the SAFE whose collateral was confiscated by the `LiquidationEngine`).
  * `auctionIncomeRecipient` - receiver of system coins (usually the `AccountingEngine`).
* `ModifyParameters` - emitted when a parameter is modified
* `BuyCollateral` - emitted when someone buys collateral from an auction. Contains:
  * `id` - the ID of the auction from which collateral was bought
  * `wad` - the bid size
  * `boughtCollateral` - the amount of collateral that was bought
* `SettleAuction` - emitted when someone settles an auction. Contains:
  * `id` - the ID of the auction settled
  * `leftoverCollateral` - the amount of collateral that hasn't been sold by the now settled auction
* `TerminateAuctionPrematurely` - emitted when an auction is terminated before its deadline. Contains:
  * `id` - the ID of the auction that was terminated
  * `sender` - the address that terminated the auction
  * `collateralAmount` - the amount of collateral still unauctioned

## 3. Walkthrough <a href="#id-3-key-mechanisms-and-concepts" id="id-3-key-mechanisms-and-concepts"></a>

The bidding process in an increasing discount auction is almost identical to the one in fixed discount auctions.

The only difference is that increasing discount auctions start with a smaller discount which increases at a pace of `perSecondDiscountUpdateRate` per second. The discount will increase until it hits`maxDiscount` or until  `discountIncreaseDeadline` passes.

## 4. Gotchas

Increasing discount auctions have the same gotchas as fixed discount ones.


# Debt Auction House

Debt auctioneer that covers deficit by minting protocol tokens in exchange for system coins

## 1. Summary <a href="#id-1-introduction-summary" id="id-1-introduction-summary"></a>

Debt auctions are used to recapitalize the system by auctioning off protocol tokens for a fixed amount of system coins. In this process, bidders compete by offering to accept decreasing amounts of protocol tokens for the coins they will end up paying.

## 2. Contract Variables & Functions <a href="#id-2-contract-details" id="id-2-contract-details"></a>

**Variables**

* `contractEnabled` - settlement flag (`1` or `0`).
* `AUCTION_HOUSE_TYPE` - flag set to `bytes32("DEBT")`
* `authorizedAccounts[usr: address]` - addresses allowed to call `modifyParameters()` and `disableContract()`.
* `safeEngine` - storage of the `SAFEEngine`'s address.
* `protocolToken` - token minted in exchange for system coins.
* `accountingEngine` - address of the `AccountingEngine` (receiver of system coins).
* `bids[id: uint]` - storage of all bids.
* `bidDuration` - bid lifetime.
* `bidDecrease` - minimum bid decrease.
* `amountSoldIncrease` - increase for size of `amountToSell` during `restartAuction` (default to 50%).
* `totalAuctionLength` - maximum auction duration.
* `auctionsStarted` - number of auctions that have started up until now.

**Data Structures**

* `Bid` - state of a specific auction. Contains:
  * `bidAmount` - paid system coins
  * `amountToSell` - quantity of protocol tokens up for auction
  * `highBidder`
  * `bidExpiry` - when a bid expires (and the auction ends)
  * `auctionDeadline` - max auction duration

**Modifiers**

* `isAuthorized` \*\*\*\* - checks whether an address is part of `authorizedAddresses` (and thus can call authed functions).

**Functions**

* `modifyParameters(bytes32 parameter`, `uint256 data)` - update a `uint256` parameter.
* `modifyParameters(bytes32 parameter`, `address data)` - update an `address` parameter.
* `startAuction(incomeReceiver: address`, `amountToSell: uint256`, `initialBid: uint256)` - start a new debt auction.
* `restartAuction(id: uint256)` - restart an auction if there have been 0 bids and the `auctionDeadline` has passed.
* `decreaseSoldAmount(id: uint256`, `amountToBuy: uint256`, `bid: uint256)` - submit a fixed system coin bid with an increasingly lower amount of protocol tokens you are willing to accept in exchange.
* `disableContract()` - disable the contract.
* `settleAuction(id: uint256)` - claim a winning bid / settles a completed auction
* `terminateAuctionPrematurely(id: uint256)` - used during `GlobalSettlement` to terminate

  `decreaseSoldAmount`phase auctions and repay system coins (using `safeEngine.createUnbackedDebt` with the `accountingEngine` as the `debtDestination`) to the highest bidder.

**Events**

* `AddAuthorization` - emitted when a new address becomes authorized. Contains:
  * `account` - the new authorized account
* `RemoveAuthorization` - emitted when an address is de-authorized. Contains:
  * `account` - the address that was de-authorized
* `StartAuction`- emitted when `startAuction(address`, `uint256`, `uint256)` is successfully executed. Contains:
  * `id` - auction id
  * `auctionsStarted` - total amount of auctions that have started up until now
  * `amountToSell` - amount of protocol tokens sold in (to be minted after) the auction.
  * `initialBid` - starting bid for the auction.
  * `incomeReceiver` \*\*\*\* - address that receives the system coins from an auction (usually the `AccountingEngine`)
  * `auctionDeadline` - deadline for the auction with ID `id`
  * `activeDebtAuctions` - the current number of active debt auctions
* `ModifyParameters` - emitted after a parameter is modified
* `RestartAuction` - emitted after an auction is restarted. Contains:
  * `id` - the ID of the auction being restarted
  * `auctionDeadline` - the new auction deadline
* `DecreaseSoldAmount` - emitted when someone bids a smaller amount of protocol tokens for the same amount of system coins given in return. Contains:
  * `id` - the ID of the auction that's being bid on
  * `highBidder` - the new high bidder
  * `amountToBuy` - the protocol token bid
  * `bid` - the amount of system coins offered
  * `bidExpiry` - the timestamp when the auction will end even if it's earlier than the `auctionDeadline`
* `SettleAuction` - emitted after an auction is settled. Contains:
  * `id` - the ID of the settled auction
  * `activeDebtAuctions` - the new number of active debt auctions
* `TerminateAuctionPrematurely` - emitted after an auction is settled before its official deadline. Contains:
  * `id` - the ID of the auction that was terminated
  * `sender` - the address that terminated the auction
  * `highBidder` - the auction's high bidder
  * `bidAmount` - the auction's bid amount
  * `activeDebtAuctions` - the new number of active debt auctions
* `DisableContract` - emitted after the contract is disabled. Contains:
  * `sender` - the address that disabled the contract

## 3. Walkthrough <a href="#id-3-key-mechanisms-and-concepts" id="id-3-key-mechanisms-and-concepts"></a>

The `DebtAuctionHouse` is a reverse auction, meaning that participants bid with increasingly lower amounts of protocol tokens they are willing to accept for a fixed amount of system coins. The auction will end when the latest bid duration (`bidDuration`) has passed since the last submitted bid or when the general auction deadline (`auctionStartTime + totalAuctionLength`) has been reached.

The first bidder will pay back the system debt (that the auction tries to cover) and submit their preference for the amount of protocol tokens they would like to receive. Each subsequent bid will pay back the previous (no longer winning) bidder. When the auction is over, the process ends by cleaning up the bid and minting protocol tokens for the winning bidder.

If the auction expires without receiving any bids, anyone can restart the auction by calling `restartAuction(uint auction_id)`. This will do two things:

1. It resets `bids[id].auctionDeadline` to `now + totalAuctionLength`
2. It resets `bids[id].amountToSell` to `bids[id].amountToSell * amountSoldIncrease / ONE`

## 4. Gotchas (Potential Source of User Error)

#### **Keepers**

In the context of running a keeper (more info [here](https://github.com/reflexer-laps/geb-docs/tree/master/keepers)) to perform bids within an auction, a primary failure mode would occur when a keeper specifies an unprofitable price for FLX.

* This failure mode is due to the fact that there is nothing the system can do stop a user from paying significantly more than the fair market value for the token in an auction (this goes for all auction types, `collateral`, `debt`, and `surplus`).
* This means, in the case of Flop, that since the Coin amount is fixed for the entire auction, the risk to the keeper is that they would make a "winning" bid that pays the bid amount in Coin but does not receive any FLX (`amountToSell` == 0). Subsequent executions of this bad strategy would be limited by the amount of Coin (not FLX) in their vat balance.

## 5. Failure Modes (Bounds on Operating Conditions & External Risk Factors)

`DebtAuctionHouse` has the potential to issue an excessively huge amount of FLX and despite the mitigation efforts (the addition of the `initialDebtAuctionMintedTokens` and `amountSoldIncrease` parameters), if `initialDebtAuctionMintedTokens` is not set correctly by governance, the huge issuance of FLX could still occur.


# Surplus Auction House

Surplus auctioneer that sells extra stability fees in exchange for protocol tokens

## 1. Summary <a href="#id-1-introduction-summary" id="id-1-introduction-summary"></a>

The surplus auction is used to sell off a fixed amount of the surplus in exchange for protocol tokens. The surplus comes from the stability fees charged to SAFEs (and stored in the `AccountingEngine`). Bidders submit increasing amounts of protocol tokens and the winner receives all auctioned surplus in exchange for their coins which are burned or transferred to another address.

## 2. Contract Variables & Functions <a href="#id-2-contract-details" id="id-2-contract-details"></a>

**Variables**

* `contractEnabled` - settlement flag (available only in the pre-settlement surplus auction house)
* `AUCTION_HOUSE_TYPE` - flag set to `bytes32("SURPLUS")`
* `authorizedAccounts[usr: address]` - addresses allowed to call `modifyParameters()` and `disableContract()`.
* `bids[id: uint]` - storage of all `Bid`s by `id`
* `safeEngine` - storage of the `SAFEEngine`'s address
* `protocolToken` - address of the protocol token
* `auctionsStarted` - total auction count
* `bidDuration` - bid lifetime / max bid duration (default: 3 hours)
* `bidIncrease` - minimum bid increase (default: 5%)
* `totalAuctionLength` - maximum auction duration (default: 2 days)
* `protocolTokenBidReceiver` - receiver of protocol tokens after an auction is settled. Only present in the `RecyclingSurplusAuctionHouse`.

**Data Structures**

* `Bid` - state of a specific auction
  * `bidAmount` - quantity being offered for the `amountToSell`
  * `amountToSell`- amount of surplus sold
  * `highBidder`
  * `bidExpiry`
  * `auctionDeadline` - when the auction will finish

**Modifiers**

* `isAuthorized` \*\*\*\* - checks whether an address is part of `authorizedAddresses` (and thus can call authed functions).

**Functions**

* `modifyParameters(bytes32 parameter`, `uint256 data)` - update a `uint256` parameter.
* `modifyParameters(bytes32 parameter`, `address addr)` - update an `address` parameter. Only present in the `RecyclingSurplusAuctionHouse`.
* `startAuction(amountToSell: uint256`, `initialBid: uint256)` - start a new surplus auction.
* `restartAuction(id: uint256)` - restart an auction if there have been 0 bids and the `auctionDeadline` has passed.
* `increaseBidSize(id: uint256`, `amountToBuy: uint256`, `bid: uint256)` - submit a bid with an increasing amount of protocol tokens for a fixed amount of system coins.
* `disableContract()` - disable the contract.
* `settleAuction(id: uint256)` - claim a winning bid / settles a completed auction.
* `terminateAuctionPrematurely(id: uint256)` - is used in case Governance wishes to upgrade (only) the `PreSettlementSurplusAuctionHouse` or in case `GlobalSettlement` is triggered. It settles `increaseBidSize` phase auctions, sending back the protocol tokens submitted by the `highBidder`.

**Events**

* `AddAuthorization` - emitted when a new address becomes authorized. Contains:
  * `account` - the new authorized account
* `RemoveAuthorization` - emitted when an address is de-authorized. Contains:
  * `account` - the address that was de-authorized
* `ModifyParameters` - emitted after a parameter is modified
* `RestartAuction` - emitted after an auction is restarted. Contains:
  * `id` - the ID of the auction being restarted
  * `auctionDeadline` - the new auction deadline
* `IncreaseBidSize` - emitted when someone bids a higher amount of protocol tokens for the same amount of system coins. Contains:
  * `id` - the ID of the auction that's being bid on
  * `highBidder` - the new high bidder
  * `amountToBuy` - the amount of system coins to buy
  * `bidAmount` - the amount of protocol tokens bid
  * `bidExpiry` - the new deadline when the auction will end which can be before the original `auctionDeadline`
* `StartAuction`- emitted when `startAuction(uint256`, `uint256)` is successfully executed. Contains:
  * `id` - auction id
  * `auctionsStarted` - total amount of auctions that have started up until now
  * `amountToSell` - amount of system coins sold in the auction.
  * `initialBid` - starting bid for the auction
  * `auctionDeadline` - the auction's deadline
* `SettleAuction` - emitted after an auction is settled. Contains:
  * `id` - the ID of the auction that was settled
* `DisableContract` - emitted after the contract is disabled
* `TerminateAuctionPrematurely` - emitted after an auction is terminated before its deadline. Contains:
  * `id` - the ID of the auction that was terminated
  * `sender` - the address that terminated the auction
  * `highBidder` - the auction's high bidder
  * `bidAmount` - the latest bid amount

## 3. Walkthrough <a href="#id-3-key-mechanisms-and-concepts" id="id-3-key-mechanisms-and-concepts"></a>

In a surplus auction, bidders compete for a fixed `amountToSell` of system coins with increasing `bidAmount`s of protocol tokens.

The surplus auction ends when the last bid's duration is passed (`bidDuration`) without another bid getting placed or when the auction duration (`totalAuctionLength`) has been surpassed. When the auction settles, the protocol tokens received are burnt in the case of a `BurningSurplusAuctionHouse` or transferred to a separate address in the case of `RecyclingSurplusAuctionHouse`.

In case governance disables the surplus auction house by calling `disableContract`, anyone can call `terminateAuctionPrematurely` in order to quickly settle an auction and return the protocol token bid to the `highBidder`.

## 4. Gotchas (Potential source of user error)

#### **Keepers**

In the context of running a keeper (more info [here](https://github.com/reflexer-labs/geb-docs/tree/master/keepers)) in order to perform bids within an auction, a primary failure mode could occur when a keeper specifies an unprofitable price for FLX.

* This failure mode is due to the fact that there is nothing the system can do to stop a user from paying significantly more than the fair market value for the token in an auction (this goes for all auction types, `collateral`, `surplus`, and `debt`).
* Keepers that are performing badly in a `surplus` auction run the risk of overpaying FLX for the Coin as there is no upper limit to the `bidAmount` size other than their FLX balance.

#### **Bid Increments During an Auction**

During `increaseBidSize`, `bidAmount` amounts will increase by a `bidIncrease` percentage with each new `increaseBidSize`. The bidder must know the auction's `id`, specify the right amount of `amountToSell` for the auction, bid at least `bidIncrease` % more than the last bid and must have a sufficient FLX balance.

One risk is "front-running" or malicious miners. In this scenario, an honest keeper's bid of \[Past-bid + `bidIncrease`%] would get committed after the dishonest keeper's bid for the same, thereby preventing the honest keeper's bid from being accepted and forcing them to rebid with a higher price ((Past-bid + bidIncrease) + bidIncrease)). The dishonest keeper would need to pay higher gas fees to try to get a miner to put their transaction in first or collude with a miner to ensure their transaction is first. This could become especially important as the bid reaches the current market rate for FLX<>Coin.

**Quick** **Example**:

The `bidIncrease` could be set to 3%, meaning if the current bidder has placed a bid of 1 FLX, then the next bid must be at least 1.03 FLX. Overall, the purpose of the bid increment system is to incentivize early bidding and make the auction process move quickly.

#### Placing Bids Incorrectly

Bidders send FLX tokens from their addresses to the system/specific auction. If one bid is beat by another, the losing bid is refunded back to that bidder’s address. It’s important to note, however, that once a bid is submitted, there is no way to cancel it. The only possible way to have that bid returned is if it is outbid (or if the system goes into Global Settlement).

### **Illustration of the bidding flow:**

1. AccountingEngine `startAuction`'s a new Surplus Auction.
2. Bidder 1 sends a bid (FLX) that increases the `bidAmount` above the initial 0 value set during the `startAuction`. Bidder 1's FLX balance is decreased and the SurplusAuctionHouse's balance is increased by the bid size. `bid.highBidder` is reset from the AccountingEngine address to Bidder 1's and `bid.bidExpiry` is reset to `now + bidDuration`.
3. Next, Bidder 2 makes a bid that increases Bidder 1's bid by at least `bidIncrease`. Bidder 2's FLX balance is decreased and Bidder 1's balance is increased by Bidder 1's `bidAmount`. The difference between Bidder 2's and Bidder 1's `bidAmount` is sent from Bidder 2 to the SurplusAuctionHouse.
4. Bidder 1 then makes a bid that increases Bidder 2's `bidAmount` by at least `bidIncrease`. Bidder 1's FLX balance is decreased and Bidder 2's FLX balance is increased by Bidder 2's `bidAmount`. The amount Bidder 1 increased the bid is then sent from Bidder 1 to the SurplusAuctionHouse.
5. Bidder 2, as well as all the other bidders participating within the auction, decide it is no longer worth it to continue to bid higher `bidAmount`s, so they stop making bids. Once the `Bid.bidExpiry` expires, Bidder 1 calls `settleAuction` and the surplus Coin tokens are sent to the winning bidder's address (Bidder 1) in the `SafeEngine` and the system then burns the FLX received from the winning bidder. `gem.burn(address(this), bids[id].bid)`.

## 5. Failure Modes (Bounds on Operating Conditions & External Risk Factors)

* **Resulting from when FLX is burned**
  * There is the possibility where a situation arises where the FLX token makes the transaction revert (e.g. gets stopped or the AccountingEngine's permission to call burn() is revoked). In a case like this, deal can't succeed until someone fixes the issue with the FLX token. In the case of stoppage, this could include the deploying of a new FLX token. This new deployment could be completed by any individual using the MCD System but governance would need to add it to the system. Next, it would need to replace the old surplus and debt auctions with the new ones using the new FLX token. Lastly, it is crucial to enable the possibility to vote with the new version as well.
* **When there is massive surplus**
  * This would result in many SurplusAuctionHouse auctions occurring as the surplus over `surplusAuctionAmountToSell` + `surplusBuffer` is always auctioned off in `surplusAuctionAmountToSell` increments. However, auctions run concurrently, so this would "flood the keeper market" and possibly result in too few bids being placed on any auction. This could happen through keepers not bidding on multiple auctions at once, which would result in network congestion because all keepers are trying to bid on all of the auctions. This could also lead to possible keeper collusion (if the capital pool is large enough, they may be more willing to work together to split it evenly at the system's expense).


# Oracle Module

The "source of truth" for collateral and system coin prices

**Relevant smart contracts:**

* [DSValue](https://github.com/reflexer-labs/ds-value/blob/master/src/value.sol)
* [OSM](https://github.com/reflexer-labs/geb-fsm/blob/master/src/OSM.sol)
* [DSM](https://github.com/reflexer-labs/geb-fsm/blob/master/src/DSM.sol)
* [GovernanceLedPriceFeedMedianizer](https://github.com/reflexer-labs/geb-governance-led-median/blob/master/src/GovernanceLedPriceFeedMedianizer.sol)
* [ChainlinkPriceFeedMedianizer](https://github.com/reflexer-labs/geb-chainlink-median/blob/master/src/ChainlinkPriceFeedMedianizer.sol)
* [UniswapConsecutiveSlotsPriceFeedMedianizer](https://github.com/reflexer-labs/geb-uniswap-median/blob/master/src/UniswapConsecutiveSlotsPriceFeedMedianizer.sol)
* [OracleRelayer](https://github.com/reflexer-labs/geb/blob/master/src/single/OracleRelayer.sol)
* [FsmGovernanceInterface](https://github.com/reflexer-labs/geb-fsm-governance-interface/blob/master/src/FsmGovernanceInterface.sol)

## 1. Overview <a href="#id-1-introduction-summary" id="id-1-introduction-summary"></a>

The **Oracle Module** is in charge with ingesting and pushing price feed updates into the system. It has three core components: a medianizer that pulls a price feed for an asset, an `FSM` (Feed Security Module) that introduces a delay to prices coming from the medianizer and an `OracleRelayer` that divides the price data by the `redemptionPrice` and then divides the result again by the collateralization ratio (of the asset whose price is submitted) before pushing the final output in the `SAFEEngine`. The module may also be used to provide price feed data for the system's feedback mechanism or other contracts meant to autonomously set system parameters.

## 2. Component Descriptions

* `DSValue` is a simplified version of a medianizer. It is used for testing the oracle infrastructure. The contract creator can specify which addresses are allowed to update the price feed inside the contract.
* The `OSM` (named via acronym from Oracle Security Module) ensures that new price values propagated from the medianizers are not taken up by the system until a specified delay has passed.
* The `DSM` (named via acronym from Dampened Security Module) is an `OSM`-like contract that limits the maximum price change between two consecutive price feed updates.
* `FsmGovernanceInterface` is an abstraction meant to help governance `stop` `OSM`s.
* The `OracleRelayer` is the glue between the `OSM` and the core system (`SAFEEngine`). It divides every price feed by the latest `redemptionPrice` and then divides the output again by the collateralization ratio before saving the final result. The relayer will, in fact, store two different prices for each collateral type: a `safetyPrice` used only when SAFE users want to generate debt and a`liquidationPrice` used when someone calls `LiquidationEngine.liquidateSAFE`. The relayer is also in charge with storing the `redemptionPrice` and updating it using the `redemptionRate`.
* Both `GovernanceLedPriceFeedMedianizer` and `ChainlinkPriceFeedMedianizer` provide fresh price feeds for every token used in the system. The major difference between the two is that the governance led version maintains a whitelist of price feed contracts which are authorized (and incentivized) by token holders to push prices into the system whereas the Chainlink version does not depend on GEB's governance to function properly (apart from instances where token holders need to point to an upgraded version of the Chainlink aggregator).
* The `UniswapConsecutiveSlotsPriceFeedMedianizer` is a TWAP leveraging the Uniswap v2 infrastructure in order to provide a price feed. It needs to be connected to a separate oracle that can help translate the TWAP result into another currency (e.g USD, EUR etc).

## 3. Risks <a href="#id-5-failure-modes-bounds-on-operating-conditions-and-external-risk-factors" id="id-5-failure-modes-bounds-on-operating-conditions-and-external-risk-factors"></a>

* `OracleRelayer` - A bug would most likely result in the collateral prices not being updated anymore or in the `redemptionPrice` being set to an unusually high or low value.
* `GovernanceLedPriceFeedMedianizer` - there is no way to prevent a majority of the oracles to come together and sign a price of zero. This would result in the price being invalid and would return false on `getResultWithValidity`.
* `ChainlinkPriceFeedMedianizer` - governance may need to change the aggregator address in case there is an upgrade on the Chainlink infrastructure. Failure to do so will result in the price feed not being updated anymore and the need for settlement in case a solution is not found in a short period of time.
* `OSM` - governance can change the `priceSource` address to a malicious contract or to a source that does not adhere to the correct interface (that should otherwise contain `getResultWithValidity`). Governance may also call `stop` or `restartValue` inappropriately.
* `DSM` - can suffer from the same attacks as the `OSM`
* `FsmGovernanceInterface` - governance can maliciously stop one or more `OSM`s or `DSM`s
* `UniswapConsecutiveSlotsPriceFeedMedianizer` - governance can set a converterFeed (oracle that translates the TWAP result in another currency) to a malicious contract. Governance can also set `maxWindowSize` to an extremely large value and thus allow the TWAP to be excessively laggy.

## 4. Governance Minimization

In the long run, governance can completely remove control over the `OracleRelayer`, provided that three conditions are met:

1. Governance does not plan to add any more collateral types in the future.
2. The team that deployed the system thoroughly tested its feedback mechanism, both in simulated **and** in live environments.

The `OracleRelayer` is in the Level 1 Gov Minimization category.


# Oracle Relayer

The glue between price feeds and the SAFE Engine

## 1. Summary <a href="#id-1-introduction" id="id-1-introduction"></a>

The `OracleRelayer` functions as an interface contract between `FSM`s and the `SAFEEngine` and only stores the current `collateralType` list as well as the current `redemptionPrice` and `redemptionRate`. The relayer will depend on governance to set each collateral's safety and liquidation ratios and might also depend on an external feedback mechanism to update the `redemptionRate` which affects the `redemptionPrice`.

## 2. Contract Variables & Functions <a href="#id-2-contract-details" id="id-2-contract-details"></a>

**Variables**

* `contractEnabled` - settlement flag (`1` or `0`).
* `authorizedAccounts[usr: address]` - addresses allowed to call `modifyParameters()` and `disableContract()`.
* `collateralTypes[collateralType: bytes32]` - mapping of each collateral type
* `cdpEngine` - address of the `CDPEngine` contract
* `redemptionRate` - the current redemption rate that reprices the system coin internally and changes user incentives
* `_redemptionPrice` - virtual variable that does not reflect the latest `redemptionPrice`
* `redemptionPriceUpdateTime` - last time when the redemption price was updated
* `redemptionRateUpperBound` - maximum value that the `redemptionRate` can have
* `redemptionRateLowerBound` - minimum value that the `redemptionRate` can have
* `RAY` - number with 27 decimals

**Data Structures**

* `CollateralType` - struct with data about each collateral type
  * `orcl` - the address of a price feed, usually an `OSM`
  * `safetyCRatio` - the collateralization ratio used to compute the `safetyPrice` of a collateral type
  * `liquidationCRatio` - the collateralization ratio used to compute the `liquidationPrice` of a collateral type

**Modifiers**

* `isAuthorized` \*\*\*\* - checks whether an address is part of `authorizedAddresses` (and thus can call authed functions).

**Functions**

* `modifyParameters(parameter: bytes32`, `data: uint256)` - update a `uint256` parameter.
* `modifyParameters(parameter: bytes32`, `data: uint256)` - update a collateral related parameter.
* `modifyParameters(collateralType: bytes32`, `parameter: bytes32`, `data: address)` - update an `address` parameter.
* `addAuthorization(usr: address)` - add an address to `authorizedAddresses`.
* `removeAuthorization(usr: address)` - remove an address from `authorizedAddresses`.
* `updateRedemptionPrice()` - internal function used to update the redemption price using the `redemptionRate`
* `redemptionPrice() external view returns (uint256)` - getter function that updates and retrieves the virtual `_redemptionPrice`
* `updateCollateralPrice(collateralType: bytes32)` - update the safety and liquidation prices of a collateral price and store them in the `CDPEngine`
* `disableContract()` - disables the relayer
* `safetyCRatio(collateralType: bytes32) external view returns (uint256)` - getter for a collateral's safety CRatio
* `liquidationCRatio(collateralType: bytes32) external view returns (uint256)` - getter for a collateral's liquidation CRatio
* `orcl(collateralType: bytes32) external view returns (address)` - getter for a collateral type's oracle

**Events**

* `AddAuthorization` - emitted when a new address becomes authorized. Contains:
  * `account` - the new authorized account
* `RemoveAuthorization` - emitted when an address is de-authorized. Contains:
  * `account` - the address that was de-authorized
* `DisableContract` - emitted when the contract is disabled.
* `ModifyParameters` - emitted when a parameter is updated.
* `UpdateRedemptionPrice` - emitted when the redemption price is updated. Contains:
  * `redemptionPrice` - the latest redemption price
* `UpdateCollateralPrice` - emitted when the safety and liquidation prices of a specific collateral price are updated. Contains:
  * `collateralType` - the collateral type whose prices are updated
  * `priceFeedValue` - the new price feed coming from the collateral's oracle
  * `safetyPrice` - the price computed by dividing the feed value by the `redemptionPrice` and then dividing the result again by the collateral's `safetyCRatio`
  * `liquidationPrice` - the price computed by dividing the feed value by the `redemptionPrice` and then dividing the result again by the collateral's `liquidationCRatio`

## 3. Walkthrough <a href="#id-3-key-mechanisms-and-concepts" id="id-3-key-mechanisms-and-concepts"></a>

### UpdateCollateralPrice <a href="#poke" id="poke"></a>

`updateCollateralPrice` is a non-authenticated function. The function takes in a `bytes32` representing a `collateralType` whose (safety and liquidation) prices need to be updated. `updateCollateralPrice` has three stages:

1. `getResultWithValidity` - interacts with the `collateralType`'s `orcl` and returns a `value` and whether it `isValid` (a boolean which is false if the price is invalid). The second external call only happens if `isValid == true`.
2. When calculating the `safetyPrice` and the `liquidationPrice`, the `_redemptionPrice` is crucial as it defines the relationship between the system coin and one unit of collateral. The `value` from the `OSM` is divided by the (updated) `redemptionPrice` (to get a ratio of collateral `value` to system coins) and then the result is divided again by the `collateralType.safetyCRatio` (when calculating the `safetyPrice`) and by the `collateralType.liquidationCRatio` (when calculating the `liquidationPrice`).
3. `cdpEngine.modifyParameters` is then called to update the collateral's prices inside the system.

### Redemption Price

Every time someone wants to read the `_redemptionPrice` its value will first be updated using the `redemptionRate` and then the output will be returned. We chose this design in order to ensure a smooth `redemptionPrice` pro-ration (using the virtual variable + a state modifying getter).

### Updating the Redemption Rate

Every time the `redemptionRate` is updated, the contract makes sure to bound the value that is can be set to.

## 4. Gotchas <a href="#id-4-gotchas" id="id-4-gotchas"></a>

The methods in the `oracleRelayer` are relatively basic compared to most other portions of `geb`. There is not much room for user error in the single unauthed method `updateCollateralPrice`. If an incorrect `bytes32` is supplied the call will fail.

Any module that is authed against the `oracleRelayer` has full root access, and can, therefore, add and remove which `collateralTypes` can be "updateCollateralPrice"'d. While not completely breaking the system, this could cause considerable risk. An authed caller can also update the `redemptionRate` and `redemptionPrice`, causing considerable impact depending on the values used.

## 5. Failure Modes <a href="#id-5-failure-modes" id="id-5-failure-modes"></a>

#### Coding Error

A bug in `oracleRelayer` would most likely result in the prices for collaterals and the redemptionRate not being updated anymore. In this case, the system would need to authorize a new `oracleRelayer` which would then be able to update the prices/rate. Overall this is not a catastrophic failure as this would only pause all price fluctuation for some period.

#### Feeds

The `oracleRelayer` relies upon a set of trusted oracles to provide price data. Should these price feeds fail, it would become possible for unbacked Coin to be minted, or Safes could be unfairly liquidated.

#### Spot Price Becoming Stale

When `updateCollateralPrice` is not called frequently enough, the `SAFE`'s `safetyPrice` price will become stale. This could arise for a few reasons including tragedy of the commons or miner collusion and could lead to negative outcomes such as inappropriate liquidations, or the prevention of liquidations that should be possible.


# Medianizer

Oracle component that fetches the price of an asset

There are five types of medianizers that can be used in GEB:

1. `DSValue` - used when deploying the system on a localchain or a testnet in order to easily manipulate the price feed of a collateral type / system coin.
2. `GovernanceLedPriceFeedMedianizer`- offers more security by requiring a `quorum` of oracles to submit their prices which are then medianized on-chain.
3. `ChainlinkPriceFeedMedianizer` - relies on a Chainlink aggregator in order to fetch and push price feeds in to the system.
4. `UniswapConsecutiveSlotsPriceFeedMedianizer` - computes the average price for an asset in the last `m` seconds and can be connected to a `GovernanceLedPriceFeedMedianizer`or `ChainlinkPriceFeed` medianizer in order to translate the asset's price (e.g use the WETH/WBTC pool to get the price of WBTC in terms of WETH) in a different currency (e.g translate the WBTC/WETH Uniswap pool price into USD).


# DSValue

Simple price feed setter and getter

## 1. Summary <a href="#id-1-introduction" id="id-1-introduction"></a>

This is a simple contract where authorized addresses can set a price and anyone can read it.

## 2. Contract Variables & Functions <a href="#id-2-contract-details" id="id-2-contract-details"></a>

**Variables**

* `isValid` - boolean that signals whether the currently stored value is valid (greater than zero) or not
* `medianPrice` - the current price feed

**Modifiers**

* `auth` - modifier that checks whether an address can set the `result`. Inherited from [ds-thing](https://github.com/dapphub/ds-thing).

**Functions**

* `getResultWithValidity() external view returns (bytes32, bool)` - returns `result` and `isValid`
* `read() external view returns (uint256)` - getter that only returns the `result`
* `updateResult(newResult: bytes32)` - set a new `result`
* `restartValue()` - set `isValid` to `false`

## 3. Walkthrough <a href="#id-3-key-mechanisms-and-concepts" id="id-3-key-mechanisms-and-concepts"></a>

Authorized functions can set a new `medianPrice` by calling `updateResult`. Anyone can `read` the `medianPrice` or read both the `medianPrice` and whether it `isValid` by calling `read` or`getResultWithValidity`.

## 4. Gotchas

This oracle is entirely dependent on authed addresses to update them. They will not flag if they are stale.

## 5. Failure Modes (Bounds on Operating Conditions & External Risk Factors)

Authed address can set any arbitrary price. This will impact other components reading from the oracle.


# Governance Led Median

Medianizer that depends on governance token holders to whitelist off-chain oracles

## 1. Summary <a href="#id-1-introduction" id="id-1-introduction"></a>

The `GovernanceLedMedian` is an option to provide trusted reference prices for collateral types and for the system coin. It works by maintaining a whitelist of price feed contracts which are authorized to post price updates. Every time a new list of prices is received, the median of these is computed and used to update the stored value.

## 2. Contract Variables & Functions <a href="#id-2-contract-details" id="id-2-contract-details"></a>

**Variables**

* `contractEnabled` - settlement flag (`1` or `0`).
* `authorizedAccounts[usr: address]` - addresses allowed to call authed functions.
* `medianPrice` - the (privately) stored median price which can be read using `read()` or `getResultWithValidity()`
* `lastUpdateTime` - the block timestamp of the last `medianPrice` update.
* `symbol` - the price oracles type (ex: ETHUSD) / tells us what the type of asset the medianizer gives a price feed for.
* `quorum` - the minimum quorum which dictates how many addresses need to come together to `updateResult`
* `whitelistedOracles[oracle: uint256]` - mapping of oracles that are allowed to sign and submit prices to `updateResult`
* `oracleAddresses[oracle: address]` - addresses of oracles allowed to update the medianizer

**Modifiers**

* `isAuthorized` \*\*\*\* - checks whether an address is part of `authorizedAddresses` (and thus can call authed functions).

**Functions**

* `read() external view returns (uint256)` - gets a non-zero price or fail.
* `getResultWithValidity() external view returns (uint256, bool)` - gets the price and its validity.
* `updateResult(prices_: uint256[]`, `updateTimestamps_: uint256[]`, `v: uint8[]`, `r: bytes32[]`, `s: bytes32[])` - updates price using whitelisted providers.
* `addOracles(orcls: address[])`- adds an address to the writers whitelist.
* `removeOracles(orcls: address[])` - removes an address from the writers whitelist.
* `setQuorum(quorum_: uint256)` - sets the `quorum`.

**Events**

* `AddAuthorization` - emitted when a new address becomes authorized. Contains:
  * `account` - the new authorized account
* `RemoveAuthorization` - emitted when an address is de-authorized. Contains:
  * `account` - the address that was de-authorized
* `AddOracles` - emitted when an authed address adds new oracles that can update the price feed. Contains:
  * `orcls` - array of oracles that will be added
* `RemoveOracles` - emitted when an authed address removes previously whitelisted oracles. Contains:
  * `orcls` - array of oracles that will be removed
* `SetQuorum` - emitted when a new quorum is set. Contains:
  * `quorum` - the new median quorum
* `UpdateResult` - emitted when `updateResult` is called. Contains:
  * `medianPrice` - the new `medianPrice`
  * `lastUpdateTime` - the current block timestamp

## 3. Walkthrough

Authorization is a key component included in this medianizer. For example, the `medianPrice` is kept private because the intention is to only read it using `read` and `getResultWithValidity`(in case we ever intend to add read authorization like in MCD's `OSM`). Oracle authorization is done by calling `addOracles` or `removeOracles`.

`updateResult` is not under any kind of authorization. This means that it can be called by anyone who provides valid data. By "valid data" we mean that at least `quorum` prices must be submitted to the contract alongside the same number of `updateTimestamps` (array of Unix timestamps for every price) and the `v`, `r` and `s` values which can help prove that every price was signed by an authorized oracle. Two or more prices cannot be signed by the same oracle because the contract checks for uniqueness using a `bloom` filter.

## 4. Gotchas

#### **Emergency Oracles**

* They can shutdown the price feed but cannot bring it back up. Bringing the price feed back up requires governance to step in.

#### **Price Freeze**

* If you void the oracles Ethereum module, the idea is that you cannot interact with any SAFE that depends on that collateralType.
  * **Example:** ETHUSD shutdown (can still add collateral and pay back debt - increases safety) but you cannot do anything that increases risk (decreases safety - remove collateral, generate coin, etc.) because the system would not know if you would be undercollateralized.

#### **Governance Led Oracles Require a lot of Upkeep**

* They need to keep all relayers functioning.
* The community would need to self-police (by looking at each price signer, etc.) if any of them needs to be replaced. They would need to make sure they are constantly being called every hour (for every hour, a transaction gets sent to the OSM, which means that a few transactions have already been sent to the median to update it as well. In addition, there would need to be a transaction sent to the `oracleRelayer`, as GEB operates in a pool-type method (doesn't update the system/write to it, you tell it to read it from the OSM).

#### **There is nothing preventing from `addAuthorization`'ing two prices signers that start with the same address**

* The only thing that this prevents is that you cannot have more than 256 oracles but we don't expect to ever have that many, so it is a hard limit. However, Governance needs to be sure that whoever they are voting in anyone that they have already voting in before with the same two first characters.
* An example of what a governance proposal would look like in this case:
  * We are adding a new oracle and are proposing (the Foundation) a list of signers (that have been used in the past) and we already have an oracle but want to add someone new (e.g. Dharma or dydx). We would say that they want to be price signers, so these are their addresses and we want to auth those two addresses. They would vote for that, and we would need to keep a list of the already existing addresses and they would need to create an address that doesn't conflict with the existing ones.

## 5. Failure Modes (Bounds on Operating Conditions & External Risk Factors)

By design, there is currently no way right now to turn off the oracle (failure or returns false) if all the oracles come together and sign a price of zero. This would result in the price being invalid and would return false on `getResultWithValidity`, telling us to not trust the value.


# Chainlink Median

Chainlink integrated medianizer

## 1. Summary <a href="#id-1-introduction" id="id-1-introduction"></a>

The `ChainlinkPriceFeedMedianizer` has a similar interface to the [Governance Led Median](https://reflexer-labs.gitbook.io/geb/system-contracts/untitled-1/medianizer/governance-led) although, instead of relying on governance whitelisted oracles, it simply keeps a reference to a [Chainlink price reference contract](https://feeds.chain.link/) (price aggregator).

## 2. Contract Variables & Functions <a href="#id-2-contract-details" id="id-2-contract-details"></a>

**Variables**

* `authorizedAccounts [usr: address]` - `addAuthorization`/`removeAuthorization`/`isAuthorized` - auth mechanisms
* `staleThreshold` - time since `linkAggregatorTimestamp` after which the median value is considered stale
* `chainlinkAggregator` - address of the Chainlink price reference contract
* `rewardRelayer` - address of the contract that rewards addresses that call `updateResult`
* `medianPrice` - latest fetched price
* `lastUpdateTime` - latest timestamp when the contract pulled a price update from Chainlink
* `multiplier` - scaling factor for the Chainlink result (e.g if the price has 8 decimals and we want it to be scaled to 18 decimals, `multiplier = 10` and `medianPrice = fetchedPrice * 10 ^ multiplier`)
* `symbol` - the price oracle type (ex: ETHUSD)
* `periodSize` - the minimum delay between two consecutive updates after which the reward for updating again starts to increase
* `linkAggregatorTimestamp` - the timestamp of the Chainlink aggregator's latest price update

**Modifiers**

* `isAuthorized` \*\*\*\* - checks whether an address is part of `authorizedAddresses` (and thus can call authed functions).

**Functions**

* `modifyParameters` - allows governance to change contract parameters
* `read() public view returns (uint256)` - gets a non-zero price or fails
* `getResultWithValidity() public view returns (uint256,bool)` - gets the price and its validity
* `updateResult(feeReceiver: address)` - updates the price stored in the contract by calling the Chainlink aggregator

**Events**

* `AddAuthorization` - emitted when a new address becomes authorized. Contains:
  * `account` - the new authorized account
* `RemoveAuthorization` - emitted when an address is de-authorized. Contains:
  * `account` - the address that was de-authorized
* `ModifyParameters` \*\*\*\* - emitted when a parameter is updated
* `UpdateResult` - emitted when `updateResult` is called. Contains:
  * `medianPrice` - the latest median price
  * `lastUpdateTime` - timestamp of the call

## 3. Walkthrough

When reading the latest price feed, the contract also stores the timestamp when the price coming from Chainlink was posted on-chain. The system can incentivize anyone to call `updateResult` and update the median price regularly using a `rewardRelayer`.

## 4. Gotchas

This oracle is entirely dependent on Chainlink. If the Chainlink relayer contract is deprecated the Oracle needs to be updated accordingly.

## 5. Failure Modes (Bounds on Operating Conditions & External Risk Factors)

If the Chainlink contract is not updated the price will become stale, other contracts reading from it will revert on state changing transactions, effectively freezing the system.

If the price reported by Chainlink is wrong the system will take it as it is, possibily causing unfair liquidations, or preventing liquidations in case of higher prices reported.


# Uniswap V2 Median

A medianizer using the Uniswap V2 TWAP oracle implementation

## 1. Summary <a href="#id-1-introduction" id="id-1-introduction"></a>

The `UniswapConsecutiveSlotsPriceFeedMedianizer` is integrated with Uniswap V2 in order to provide a price feed for one of the tokens in a pool. It is also connected to a `converterFeed` in order to get the fiat value of the price quoted by the pool.

## 2. Contract Variables & Functions <a href="#id-2-contract-details" id="id-2-contract-details"></a>

**Variables**

* `defaultAmountIn` - default amount of `targetToken` used when calculating the `denominationToken` output
* `targetToken` - the token which the contract calculates the `medianPrice` for
* `denominationToken` - pair token for `targetToken`
* `uniswapPair` - the address of the Uniswap V2 pair
* `uniswapFactory` - the address of the Uniswap V2 factory
* `uniswapObservations[observation: UniswapObservation]` - array of prices taken from the Uniswap pool and the timestamps associated with each of them
* `converterPriceCumulative` - the snapshot of the latest sum of prices fetched from the `converterFeed` since the contract has been deployed
* `converterFeed` - address of the contract that offers fiat price feeds for the `denominationToken`
* `converterFeedObservations[observation: ConverterFeedObservation]` - array of fiat price feeds for the `denominationToken`
* `symbol` - the symbol of the price feed offered by the contract
* `granularity` - how many price observations are stored for the `windowSize.`As granularity increases from 1, more frequent updates are needed, but moving averages become more precise.
* `lastUpdateTime` - when the price feed was last updated
* `updates` - total number of updates up until now
* `windowSize` - the desired amount of time over which the moving average should be computed, e.g. 24 hours
* `maxWindowSize` - max window over which the moving average can be computed
* `periodSize` - this is redundant with `granularity` and `windowSize`, but stored for gas savings & informational purposes. It is the minimum amount of time that must pass between two updates.
* `converterFeedScalingFactor` - this is the denominator that correctly scales the `medianPrice` according to how many decimals the `denominationToken` has
* `medianPrice` - the latest `targetToken` median price
* `validityFlag` - flag that indicates whether the median is valid or not
* `relayer` - address of the contract that rewards others for updating the median

**Modifiers**

* `isAuthorized` \*\*\*\* - checks whether an address is part of `authorizedAddresses` (and thus can call authed functions).

**Functions**

* `modifyParameters` - allows governance to modify parameters.
* `timeElapsedSinceFirstObservation() public view returns (uint256)` - returns the time passed since the first observation in the window.
* `earliestObservationIndex() public view returns (uint256)` - returns the index of the earliest observation in the window.
* `getObservationListLength() public view returns (uint256, uint256)` - get the observation list length
* `uniswapComputeAmountOut(priceCumulativeStart: uint256`, `priceCumulativeEnd: uint256`, `timeElapsed: uint256`, `amountIn: uint256) public pure returns (amountOut: uint256)` - given the Uniswap V2 cumulative prices of the start and end of a period, and the length of the period, compute the average price in terms of how much amount out is received for the amount in.
* `converterComputeAmountOut(amountIn: uint256) public view returns (amountOut: uint256)` - calculate the price of an amount of tokens using the converter price feed. Used internally after the contract determines the amount of denomination tokens for `defaultAmountIn` target tokens.
* `updateResult(feeReceiver: address)` - update the `medianPrice` and pay the `feeReceiver` afterwards.
* `read` - gets a non-zero price or fails
* `getResultWithValidity` - gets the price and its validity

**Events**

* `AddAuthorization` - emitted when a new address becomes authorized. Contains:
  * `account` - the new authorized account
* `RemoveAuthorization` - emitted when an address is de-authorized. Contains:
  * `account` - the address that was de-authorized
* `ModifyParameters` \*\*\*\* - emitted when a parameter is updated
* `UpdateResult` - emitted when `updateResult` is called. Contains:
  * `medianPrice` - the latest median price for `targetToken`
  * `lastUpdateTime` - the current timestamp
* `FailedConverterFeedUpdate` - emitted when the contract fails to pull a price from the `converterFeed`. Contains:
  * `reason` - the failure reason
* `FailedUniswapPairSync` - emitted when the contract fails to sync the Uniswap V2 pool that it's connected to. Contains:
  * `reason` - the reason why the sync failed

## 3. Walkthrough

`updateResult` first tries to update the `converterFeed` and the Uniswap pool before it stores new observations and computes the latest median.

`read` will only return a result if the median is non-null, if `updateResult` has been successfully called at least `granularity` times, if the `validityFlag` is `1` and if `timeElapsedSinceFirstObservation() <= maxWindowSize`. `getResultWithValidity` will return the median price and its validity (determined using the same checks as `read`).

## 4. Gotchas

This oracle depends on a pinger call within a defined frequency. THe calls should be properly incentivised.

## 5. Failure Modes (Bounds on Operating Conditions & External Risk Factors)

Uniswap V2 is vulnerable to oracle manipulation attacks. A motivated attacker could push the price in the wrong direction and update the oracle. For TWAPs that is less of an issue (it would require multiple successful calls from an attacker).


# FSM

Feed security module that delays upcoming price data from being pushed in the core system

The Feed Security Module is a generalized, OSM-like framework where we experiment with different strategies to introduce a delay between a new price feed coming in a FSM contract and then being pushed in the core system.

For now we focus most of our development efforts on the OSM (that we inherited from the MCD codebase) but are also experimenting with [DSM](https://github.com/reflexer-labs/geb-fsm/blob/master/src/DSM.sol) (Dampened Security Module).


# Oracle Security Module

Basic price feed delay mechanism

## 1. Summary

The `OSM` (Oracle Security Module) ensures that new price values propagated from medianizers are not taken up by the system until a specified delay has passed. Values are updated using `updateResult` and read using `read` and `getResultWithValidity`. Each collateral type will have its own unique `OSM`. Collateral type is defined as a specific asset type (whereas `ETH-A` and `ETH-B` refer to the same asset and thus have the same `OSM`).

## 2. Contract Variables & Functions <a href="#id-2-contract-details" id="id-2-contract-details"></a>

**Variables**

* `authorizedAccounts[usr: address]` - addresses allowed to call authed functions.
* `stopped` - flag that disables price feed updates if non-zero
* `priceSource` - address of medianizer that the OSM will read from
* `ONE_HOUR` - 3600 seconds
* `updateDelay` - time delay between `updateResult` calls; defaults to `ONE_HOUR`
* `lastUpdateTime` - time of last update (rounded down to nearest multiple of `updateDelay`)
* `currentFeed` - `Feed` struct that holds the current price value
* `nextFeed` - `Feed` struct that holds the next price value

**Modifiers**

* `isAuthorized` \*\*\*\* - checks whether an address is part of `authorizedAddresses` (and thus can call authed functions).

**Functions**

* `addAuthorization`/`removeAuthorization` - add or remove authorized users (via modifications to the `authorizedAccounts` mapping)
* `stop()`/`start()` - toggle whether the OSM price feed can be updated (by changing the value of `stopped`)
* `changePriceSource(address)` - change data source for prices (by setting `priceSource`)
* `changeDelay(uint16)` - change interval between price updates (by setting `updateDelay`)
* `restartValue()` - similar to `stop`, except it also sets `currentFeed`and `nextFeed` to a `Feed` struct with zero values
* `getResultWithValidity()` - returns the current feed value and a boolean indicating whether it is valid
* `getNextResultWithValidity()` - returns the next feed value (i.e. the one that will become the current value upon the next `updateResult()` call), and a boolean indicating whether it is valid
* `read()` - returns the current feed value; reverts if it was not set by some valid mechanism
* `updateResult()` - updates the current feed value and reads the next one

**Data Structures**

* `Feed` - struct used to store price feed data. Contains:
  * `value` - the feed value
  * `isValid` - whethet the feed value is valid

## 3. Walkthrough <a href="#id-3-key-mechanisms-and-concepts" id="id-3-key-mechanisms-and-concepts"></a>

In order for the `OSM` to work properly, an external actor must regularly call `updateResult()` to update the current price and read the next one. The contract stores the timestamp of the last `updateResult()` and will not allow another update until `block.timestamp` is at least `lastUpdateTime + updateDelay`. Values are read from the `priceSource`. In case of an oracle attack, governance can call `stop()` or`restartValue()`

## 4. OSM Variations

#### SelfFundedOSM

This contract pulls funds from the [StabilityFeeTreasury](https://github.com/reflexer-labs/geb/blob/master/src/single/StabilityFeeTreasury.sol) so it can reward addresses for calling`updateResult`.

**ExternallyFundedOSM**

This contract calls an [FSMWrapper](https://github.com/reflexer-labs/geb-fsm/blob/master/src/FSMWrapper.sol) in order to reward addresses that call `updateResult`.

## 5. Gotchas (Potential Sources of User Error)

N/A

## 6. Failure Modes (Bounds on Operating Conditions & External Risk Factors)

#### `updateCollateralPrice()` is not called promptly, allowing malicious prices to be swiftly uptaken

For several reasons, `updateCollateralPrice()` is always callable as soon as `block.timestamp / updateDelay` increments, regardless of when the last `updateCollateralPrice()` call occurred (because `lastUpdateTime` is rounded down to the nearest multiple of `updateDelay`). This means the contract does not actually guarantee that a time interval of at least `updateDelay` seconds has passed since the last `updateCollateralPrice()` call before the next one; rather this is only (approximately) guaranteed if the last `updateCollateralPrice()` call occurred shortly after the previous increase of `block.timestamp / updateDelay`. Thus, a malicious price value can be acknowledged by the system in a time potentially much less than `updateDelay`.

**This was a deliberate design decision. The arguments that favoured it, roughly speaking, are:**

* Providing a predictable time at which Prot holders should check for evidence of oracle attacks (in practice, `updateDelay` is 1 hour, so checks must be performed at the top of the hour)
* Allowing all OSMs to be reliably updated at the same time in a single transaction

The fact that `updateCollateralPrice` is public, and thus callable by anyone, helps mitigate concerns, though it does not eliminate them. For example, network congestion could prevent anyone from successfully calling `updateCollateralPrice()` for a period of time. If a Prot holder observes that `updateCollateralPrice` has not been promptly called, **the actions they can take include:**

1. Call `updateCollateralPrice()` themselves and decide if the next value is malicious or not
2. Call `stop()` or `restartValue()` (the former if only `nextFeed` is malicious; the latter if the malicious value is already in `currentFeed`)
3. Trigger emergency shutdown (if the integrity of the overall system has already been compromised or if it is believed the rogue oracle(s) cannot be fixed in a reasonable length of time)

In the future, the contract's logic may be tweaked to further mitigate this (e.g. by **only** allowing `updateCollateralPrice()` calls in a short time window each `updateDelay` period).

### Authorization Attacks and Misconfigurations

Various damaging actions can be taken by authorized individuals or contracts, either maliciously or accidentally:

* Revoking access of core contracts to the methods that read values, causing mayhem as prices fail to update
* Completely revoking all access to the contract
* Changing `src` to either a malicious contract or to something that lacks a `getResultWithValidity()` interface, causing transactions that `updateCollateralPrice()` the affected OSM to revert
* Calling disruptive functions like `stop` and `restartValue` inappropriately

The only solution to these issues is diligence and care regarding the `authorizedAccounts` of the OSM.


# Dampened Security Module

An OSM-like contract that bounds price feed changes between consecutive updates

## 1. Summary

The `DSM` (Dampened Security Module) is an `OSM`-like contract that, apart from emposing a delay between prices coming from a medianizer and them being added into the system, it bounds the maximum price change between the `currentFeed` and the `nextFeed`. This ensures that in case of an oracle attack or extreme market volatility, governance has more time to react and defend the system.

## 2. Contract Variables & Functions <a href="#id-2-contract-details" id="id-2-contract-details"></a>

**Variables**

* `authorizedAccounts[usr: address]` - addresses allowed to call authed functions.
* `stopped` - flag that disables price feed updates if non-zero
* `priceSource` - address of the medianizer that the OSM will read from
* `ONE_HOUR` - 3600 seconds
* `updateDelay` - time delay between `updateResult` calls; defaults to `ONE_HOUR`
* `lastUpdateTime` - time of last update (rounded down to nearest multiple of `updateDelay`)
* `newPriceDeviation` - max deviation accepted between the current and the next feed
* `currentFeed` - `Feed` struct that holds the current price value
* `nextFeed` - `Feed` struct that holds the next price value

**Modifiers**

* `isAuthorized` - checks whether an address is part of `authorizedAddresses` (and thus can call authed functions).

**Functions**

* `addAuthorization`/`removeAuthorization` - add or remove authorized users (via modifications to the `authorizedAccounts` mapping)
* `stop`/`start` - toggle whether the OSM price feed can be updated (by changing the value of `stopped`)
* `changePriceSource(source: address)` - change data source for prices (by setting `priceSource`)
* `changeDelay(delay: uint16)` - change interval between price updates (by setting `updateDelay`)
* `changeNextPriceDeviation(deviation: uint256)` - change the `newPriceDeviation`
* `restartValue` - similar to `stop`, except it also sets `currentFeed`and `nextFeed` to a `Feed` struct with zero values
* `getResultWithValidity` - returns the current feed value and a boolean indicating whether it is valid
* `getNextResultWithValidity` - returns the next feed value (i.e. the one that will become the current value upon the next `updateResult` call), and a boolean indicating whether it is valid
* `getNextBoundedPrice` - get the next `currentFeed` price according to the current `newPriceDeviation`
* `getNextPriceLowerBound` - get the lower bound of the next `currentFeed` update
* `getNextPriceUpperBound` - get the upper bound of the next `currentFeed` update
* `read` - returns the current feed value; reverts if it was not set by some valid mechanism
* `updateResult` - updates the current feed value and reads the next one

**Data Structures**

* `Feed` - struct used to store price feed data. Contains:
  * `value` - the feed value
  * `isValid` - whether the price feed value is valid

## 3. Walkthrough <a href="#id-3-key-mechanisms-and-concepts" id="id-3-key-mechanisms-and-concepts"></a>

In order for the `DSM` to work properly, an external actor must regularly call `updateResult()` to update the current price and read the next one. The contract stores the timestamp of the last `updateResult()` and will not allow another update until `block.timestamp` is at least `lastUpdateTime + updateDelay`. Values are read from the `priceSource`. The next price accepted in the `DSM` can be at max `newPriceDeviation` deviated from the current price stored in the contract. In case of an oracle attack, governance can call `stop()` or`restartValue()`

## 4. DSM Variations

#### SelfFundedDSM

This contract pulls funds from the [StabilityFeeTreasury](https://github.com/reflexer-labs/geb/blob/master/src/StabilityFeeTreasury.sol) so it can reward addresses for calling`updateResult`.&#x20;

**ExternallyFundedDSM**

This contract calls an [FSMWrapper](https://github.com/reflexer-labs/geb-fsm/blob/master/src/FSMWrapper.sol) in order to reward addresses that call `updateResult`.


# FSM Governance Interface

Governance contract for stopping FSM-like contracts

## 1. Summary

This governance interface allows token holders to `stop()` FSM-like contracts in case of an oracle attack.

## 2. Contract Variables & Functions <a href="#id-2-contract-details" id="id-2-contract-details"></a>

**Variables**

* `owner` - the address of the contract's owner. Meant to set `FSM` addresses
* `onlyOwner` - modifier that checks whether the `owner` calls a function
* `authority` - contract authority, able only to stop an `FSM`
* `fsms[collateralType: bytes32]` - mapping of OSM-like contracts

**Modifiers**

* `isAuthorized` - modifier that checks whether msg.sender can call a specific function
* `onlyOwner` - modifiers that ensures only the `owner` can call a specific function

**Functions**

* `canCall` - checks whether an address can call a function
* `setFsm(bytes32: collateralType, address: fsm)` - set the address of an `FSM` for a specific collateral type
* `setOwner(address: owner]` - change the contract's owner
* `setAuthority(address: authority)` - change the contract's authority
* `stop(bytes32: collateralType)` - stop a collateral type's `FSM`

## 3. Walkthrough <a href="#id-2-contract-details" id="id-2-contract-details"></a>

The `owner` and the `authority` can be changed using `setOwner` and `setAuthority`. The `owner` can `setFsm`s for each collateral type and any authed address (be it the `owner`, `authority` or another address that was whitelisted in the `authority` contract) can `stop` any `FSM`.


# Token Module

ERC20 tokens, authority contracts and adapters for exiting and joining collateral in an out of the system

**Relevant smart contracts:**

* [DSDelegateToken](https://github.com/reflexer-labs/ds-token/blob/master/src/delegate.sol)
* [Coin](https://github.com/reflexer-labs/geb/blob/master/src/shared/Coin.sol)
* [BasicTokenAdapters](https://github.com/reflexer-labs/geb/blob/master/src/shared/BasicTokenAdapters.sol)
* [AdvancedTokenAdapters](https://github.com/reflexer-labs/geb-deploy/blob/master/src/AdvancedTokenAdapters.sol)
* [ProtocolTokenAuthority](https://github.com/reflexer-labs/geb-protocol-token-authority/blob/master/src/ProtocolTokenAuthority.sol)
* [GebPrintingPermissions](https://github.com/reflexer-labs/geb-printing-permissions/blob/master/src/GebPrintingPermissions.sol)

## 1. Overview <a href="#id-1-introduction-summary" id="id-1-introduction-summary"></a>

The token module has four distinct parts:

1. System Coin: token that the core system considers equal in value to its internal debt unit.
2. Protocol Token: a ds-token with delegation capabilities inherited from [UNI](https://uniswap.org/blog/uni/) which were in turn inherited from [COMP](https://compound.finance/governance/comp). It contains logic for burning and authorized minting. The token can be used to govern the system and as a recapitalization source.
3. Protocol Token Authority: authority contract that determines who is eligible to mint and burn protocol tokens.
4. Geb Printing Permissions: permissioning system to allow multiple debt auction contracts to mint protocol tokens.
5. Token Adapters:
   * Collateral Adapters: contracts that allow anyone to join or exit collateral in and out of GEB
   * Coin Join: adapter for the system coin to exit the system in the form of an ERC20 and enter the system in the form of `SAFEEngine.coinBalance`

## 2. Component Descriptions <a href="#id-5-failure-modes-bounds-on-operating-conditions-and-external-risk-factors" id="id-5-failure-modes-bounds-on-operating-conditions-and-external-risk-factors"></a>

* System Coin: this contract is the user facing ERC20 token maintaining the accounting for external system coin balances.
* Protocol Token: a token adhering to the ERC20 standard which also has [DSAuth](https://github.com/reflexer-labs/ds-auth)-protected mint and burn functions as well as delegation capabilities. The protocol token has two main use-cases:
  * **As a governance token:** tokens can be used as a representation of voting power
  * **As a recapitalization resource:** protocol tokens can autonomously be minted by the `DebtAuctionHouse` and sold for system coins which are used to recapitalize the system in times of insolvency
* Protocol Token Authority: determines who can mint and burn protocol tokens. Can be controlled directly by token holders, by the Protocol Token Authority or in some cases all control can be withdrawn from it.
* Geb Printing Permissions: forces governance to adhere to specific rules in order to allow multiple, independent `DebtAuctionHouse`s to print protocol tokens.
* Token Adapters: these are custom contracts that can allow anyone to deposit and withdraw collateral or they can have whitelisting in place to&#x20;

## 3. Risks <a href="#id-5-failure-modes-bounds-on-operating-conditions-and-external-risk-factors" id="id-5-failure-modes-bounds-on-operating-conditions-and-external-risk-factors"></a>

* The system coin is susceptible to the [ERC20 race condition](https://github.com/0xProject/0x-monorepo/issues/850)
* Emergency shutdown cannot be triggered if governance calls `PROTOCOL_TOKEN.stop` beforehand
* There is the possibility for a user to have their funds stolen by a malicious adapter which does not actually send tokens to the `SAFEEngine`, but instead to some other contract or wallet.

## 4. Governance Minimization

Governance can withdraw their voting power over all contracts, although, if they wish to allow the Protocol Token to protect multiple GEBs, they may retain influence over the Geb Printing Permissions.

All of the contracts in this module are part of Level 1 Gov Minimization.


# Token Adapters

The gateways for collateral and system coins to join or exit the system

## 1. Summary <a href="#id-1-introduction-summary" id="id-1-introduction-summary"></a>

There are three main token adapter types: `CollateralJoin`, `ETHJoin` and `CoinJoin`:

* `CollateralJoin` - allows standard ERC20 tokens to be deposited for use with the system.
* `ETHJoin` - allows native Ether to be used with the system.
* `CoinJoin` - allows users to withdraw their system coins from the protocol into a standard ERC20 token (and vice-versa).

## 2. Contract Variables & Functions <a href="#id-2-contract-details" id="id-2-contract-details"></a>

**Variables**

* `safeEngine` - storage of the `SAFEEngine`’s address.
* `collateralType` - id of the `CollateralType` for which a `CollateralJoin` is created for.
* `collateral` - the address of the `collateralType` for transferring.
* `systemCoin` - the address of the `Coin` token.
* `contractEnabled` - an access flag for the adapter.
* `decimals` - decimals for the collateral type.

**Functions**

* `join` - join tokens into the system
* `exit` - exit tokens from the system
* `disableContract` - disable the adapter and only allow `exit`s

Every `token adapter` contract has 4 public functions: a constructor, `join`, `exit`, and `disableContract`. The constructor is used on contract initialization and sets the core variables of that `token adapter` contract. `Join` and `exit` are both true to their names. `Join` provides a mechanism for users to add the given token type to the `SafeEngine`. It has slightly different logic in each variation, but generally resolves down to a `transfer` and a function call in the `SafeEngine`. `Exit` is very similar, but instead allows the the user to remove their desired token from the `SafeEngine`. `disableContract` allows the adapter to be drained (allows tokens to move out but not in).

## 3. Walkthrough <a href="#id-3-key-mechanisms-and-concepts" id="id-3-key-mechanisms-and-concepts"></a>

The `CollateralJoin` contract serves a very specified and singular purpose which is relatively abstracted away from the rest of the core smart contract system. When a user desires to enter the system and interact with the `geb` contracts, they must use one of the `CollateralJoin` contracts. After they have finished with the `geb` contracts, they must call `exit` to leave the system and take out their tokens. When the `CollateralJoin` gets `disableContract`d by an `auth`ed address, it can `exit` collateral from the SafeEngine but it can no longer `join` new collateral.

User balances for collateral tokens added to the system via `disableContract` are accounted for in the `SafeEngine` as `tokenCollateral` according to collateral type `CollateralType` until they are converted into locked collateral tokens (`Safe.lockedCollateral`) so the user can draw system coin.

The `CoinJoin` contract serves a similar purpose. It manages the exchange of Coin that is tracked in the `SafeEngine` and ERC-20 Coin that is tracked by `Coin.sol`. After a user draws Coin against their collateral, they will have a balance in `CoinJoin.coinBalance`. This Coin balance can be `exit`' ed from the SafeEngine using the `CoinJoin` contract which holds the balance of `SafeEngine.coinBalance` and mint's ERC-20 Coin. When a user wants to move their Coin back into the `SafeEngine` accounting system (to pay back debt, participate in auctions, pack `coinBag`'s in the `GlobalSettlement`, or utilize the CoinSavingsAccount, etc), they must call `CoinJoin.join`. By calling `CoinJoin.join` this effectively `burn`'s the ERC-20 Coin and transfers `SafeEngine.coinBalance` from the `CoinJoin`'s balance to the User's account in the `SafeEngine`. Under normal operation of the system, the `Coin.totalSupply` should equal the `SafEngine.coinBalance(CoinJoin)` balance. When the `CoinJoin` contract gets `disableContract`'d by an `auth`'ed address, it can move Coin back into the SafeEngine but it can no longer `exit` Coin from the SafeEngine.

## 4. Gotchas (Potential source of user error) <a href="#id-4-gotchas" id="id-4-gotchas"></a>

The main source of user error with the `TokenAdapter` contract is that Users should never `transfer` tokens directly to the contracts, they **must** use the `join` functions or they will not be able to retrieve their tokens.

There are limited sources of user error in the `TokenAdapter` contract system due to the limited functionality of the system. Barring a contract bug, should a user call `join` by accident they could always get their tokens back through the corresponding `exit` call on the given `join` contract.

The main issue to be aware of here would be a well-executed phishing attack. As the system evolves and potentially more `TokenAdapter` contracts are created, or more user interfaces are made, there is the potential for a user to have their funds stolen by a malicious `TokenAdapter` contract which does not actually send tokens to the `SafeEngine`, but instead to some other contract or wallet.

## 5. Failure Modes (Bounds on Operating Conditions & External Risk Factors) <a href="#id-5-failure-modes" id="id-5-failure-modes"></a>

**There could potentially be a `SafeEngine` upgrade that would require new `TokenAdapter` contracts to be created.**

If a `collateral` contract were to go through a token upgrade or have the tokens frozen while a user's collateral was in the system, there could potentially be a scenario in which the users were unable to redeem their collateral after the freeze or upgrade was finished. This scenario likely presents little risk though because the token going through this upgrade would more than likely want to work alongside the community to be sure this was not an issue.


# System Coin

ERC20 representation of the coins backed by system collateral

## 1. Summary <a href="#id-1-introduction-summary" id="id-1-introduction-summary"></a>

The `Coin` contract is the user-facing ERC20 token maintaining the accounting for external system coin balances. Most functions are standard for a token with changing supply, but it also has notable features such as the ability to approve transfers based on signed messages.

## 2. Contract Details & Functions <a href="#id-2-contract-details" id="id-2-contract-details"></a>

**Variables**

* `name`
* `symbol`
* `version`
* `decimals`
* `changeData` - if `1` governance can change the `name` and/or `symbol` and no one can use `permit()`; if different than `1` governance cannot change `name` or `symbol` anymore and `permit()` can be used
* `totalSupply` - total coin supply
* `balanceOf(usr: address)` - user balance
* `allowance(src: address, dst: address)` - approvals
* `nonces(usr: address)` - permit nonce
* `wad` - fixed point decimal with 18 decimals (for basic quantities, e.g. balances).

**Functions**

* `mint(usr: address`, `amount: uint256)` - mint coins to an address
* `burn(usr: address`, `amount: uint256)` - burn at an address
* `push(usr: address`, `amount: uint256)` - transfer
* `pull(usr: address`, `amount: uint256)`- transfer from
* `move(src: address`, `dst: address`, `amount: uint256)` - transfer from
* `approve(usr: address`, `amount: uint256)` - allow pulls and moves
* `modifyParameters(parameter: bytes32`, `data: uint256)` - modify the value of `changeData`
* `setName(name_: string)` - change the token's `name` if `changeData` is `1`
* `setSymbol(symbol_: string)` - change the token's `symbol` if `changeData` is `1`
* `permit(holder: address`, `spender: address`, `nonce: uint256`, `expiry: uint256`, `allowed: bool, v: uint8`, `r: bytes32`, `s: bytes32)` - approve by signature; only callable if `changeData != 1`
* `transfer(dst: address`, `amount: uint256)` - transfers coins from `msg.sender` to `dst`

## 3. Walkthrough <a href="#id-3-key-mechanisms-and-concepts" id="id-3-key-mechanisms-and-concepts"></a>

For the most part, `coin.sol` functions as a typical ERC20 token although it has a couple of core differences:

1. `push`, `pull` & `move` are aliases for `transferFrom` in the form of `transferFrom(msg.sender, usr, amount)` , `transferFrom(usr, msg.sender, amount)` & `transferFrom(src, dst, amount)` .
2. `permit` is a signature-based approval function. This allows an end-user to sign a message which can then be relayed by another party to submit their approval. This can be useful for applications in which the end-user does not need to hold ETH to pay for gas.

## 4. Gotchas (Potential Source of User Error) <a href="#id-4-gotchas" id="id-4-gotchas"></a>

Unlimited allowance is a relatively common practice. This could be something used to trick a user by a malicious contract into giving access to all their Coin. This is concerning in upgradeable contracts where the contract may appear innocent until upgraded to a malicious contract.

Coin is also susceptible to the known [ERC20 race condition](https://github.com/0xProject/0x-monorepo/issues/850), but should not normally be an issue with unlimited approval. We recommend any users using the `approval` for a specific amount be aware of this particular issue and use caution when authorizing other contracts to perform transfers on their behalf.

There is a slight deviation in `transferFrom` functionality: If the `src == msg.sender` the function does not require `approval` first and treats it as a normal `transfer` from the `msg.sender` to the `dst`.

#### Built-in meta-transaction functionality of Coin

The Coin token provides offchain approval, which means that as an owner of an ETH address, you can sign a permission (using the permit() function) which basically grants allowance to another ETH address. The ETH address that you provide permission to can then take care of the execution of the transfer but has an allowance.

## 5. Failure Modes (Bounds on Operating Conditions & External Risk Factors) <a href="#id-5-failure-modes" id="id-5-failure-modes"></a>

* N/a


# Protocol Token

The protocol's recapitalization source

## 1. Summary <a href="#id-1-introduction-summary" id="id-1-introduction-summary"></a>

The protocol token is a [DsDelegateToken](https://github.com/reflexer-labs/ds-token/blob/master/src/delegate.sol) that provides logic for burning and authorized minting of new tokens as well as delegation capabilities.

## 2. Contract Variables & Functions <a href="#id-2-contract-details" id="id-2-contract-details"></a>

**Variables**

* `guy` - user address
* `wad` - a quantity of tokens, usually as a fixed point integer with 10^18 decimal places.
* `dst` - refers to the destination address.
* `name` - returns the name of the token - e.g. "MyToken".
* `symbol` - token symbol.
* `decimals` - returns the number of decimals the token uses.
* `totalSupply` - returns the total token supply.
* `balanceOf(usr: address)` - user balance
* `delegates(usr: address)` - a record of each account's delegate
* `checkpoints(usr: address`, `checkpoint: uint32)` - a record of vote checkpoints for each account, by index
* `numCheckpoints(usr: address)` - the number of checkpoints for each account
* `nonces(usr: address)` - a record of states for signing / validating signatures
* `allowance(src: address, dst: address)` - approvals
* `balanceOf(usr: address)` - returns the account balance of another account with *address \_owner*.
* `allowance(src: address, dst: address)`- returns the amount which *\_spender* is still allowed to withdraw from *\_owner*.
* `DOMAIN_TYPEHASH` - the EIP-712 typehash for the contract's domain
* `DELEGATION_TYPEHASH` - the EIP-712 typehash for the delegation struct used by the contract

**Functions**

* `mint(usr: address`, `amount: uint256)` - mint coins to an address
* `burn(usr: address`, `amount: uint256)` - burn at an address
* `push(usr: address`, `amount: uint256)` - transfer
* `pull(usr: address`, `amount: uint256)`- transfer from
* `move(src: address`, `dst: address`, `amount: uint256)` - transfer from
* `approve(usr: address`, `amount: uint256)` - allow pulls and moves
* `transfer(dst: address`, `amount: uint256)` - transfers coins from `msg.sender` to `dst`
* `delegate(delegatee: address)` - delegate votes from `msg.sender` to `delegatee`
* `delegateBySig(delegatee: address`, `nonce: uint256`, `expiry: uint256`, `v: uint8`, `r: bytes32`, `s: bytes32)` - delegates votes from signatory to `delegatee`
* `getCurrentVotes(account: address) external view returns (uint256)` - gets the current votes balance for `account`
* `getPriorVotes(account: address`, `blockNumber: uint256) public view returns (uint256)` - determine the prior number of votes for an account as of a block number

**Data Structures**

* `Checkpoint` - stores a checkpoint's data. Contains:
  * `fromBlock` - the block from which that amount of votes has been marked
  * `votes` - the amount of votes

**Events**

* `Mint` - emitted when new tokens are minted. Contains:
  * `guy` - the address for which the contract prints tokens
  * `wad` - the amount of tokens printed
* `Burn` - emitted when tokens are burned. Contains:
  * `guy` - the address whose tokens are burned
  * `wad` - the amount of tokens that were burned
* `DelegateChanged` - emitted when an address changes its delegate. Contains:
  * `delegator` - the address that changes its delegate
  * `fromDelegate` - the old delegate
  * `toDelegate` - the new delegate
* `DelegateVotesChanged` - emitted when a delegate account's vote balance changes. Contains:
  * `delegate` - the delegate account
  * `previousBalance` - the delegate's previous vote balance
  * `newBalance` - the delegate's new vote balance

## 3. Walkthrough <a href="#id-3-key-mechanisms-and-concepts" id="id-3-key-mechanisms-and-concepts"></a>

Along with the standard ERC20 token interface, the protocol token also has [DSAuth](https://github.com/reflexer-labs/ds-auth)-protected mint and burn functions.


# Protocol Token Authority

The guardian that decides who can mint or burn protocol tokens

## 1. Summary <a href="#id-1-introduction-summary" id="id-1-introduction-summary"></a>

The `ProtocolTokenAuthority` allows governance to specify which addresses are allowed to `mint` or `burn` protocol tokens. This is done by either setting an address as the `root` of the contract, the `owner` of the contract or by whitelisting an address in the `authorizedAccounts` mapping.

## 2. Contract Variables & Functions <a href="#id-2-contract-details" id="id-2-contract-details"></a>

**Variables**

* `root` - contract's root controlling address.
* `owner` - the second most powerful address controlling the contract. It cannot set the `root` but it can set another `owner`.
* `authorizedAccounts[account: address]` - mapping of addresses that are allowed to print protocol tokens.

**Modifiers**

* `isRootCalling` - modifier checking if the `msg.sender` is the `root`
* `isRootOrOwnerCalling` - modifier checking if the `msg.sender` is the `root` or the `owner`

**Functions**

* `setRoot(usr: address)` - sets a new root
* `setOwner(usr: address)` - sets a new owner
* `addAuthorization(usr: address)` - authorize a new address to print tokens
* `removeAuthorization(usr: address)` - de-authorize an address from printing tokens
* `canCall(src: address, address, sig: bytes4)` - checks whether an address can call `mint`, `burn` or `burnFrom` inside the protocol token

## 3. Walkthrough <a href="#id-2-contract-details" id="id-2-contract-details"></a>

`auth`ed accounts, `owner` and `root` are the ones who pass the `canCall` check and thus, are able `mint`, `burn` and `burnFrom`. `root` and `owner` can add or remove authorized addresses. `owner` cannot set a new `root` but can only change the `owner`. `root` has complete power and can change both the `root` and the `owner`.&#x20;


# Protocol Token Printing Permissions

Contract allowing multiple independent debt auction houses to print protocol tokens

## 1. Summary <a href="#id-1-introduction-summary" id="id-1-introduction-summary"></a>

`GebPrintingPermissions` allows governance to whitelist multiple independent GEBs to print the same protocol token. It imposes delays for adding and removing permissions and it can also allow specific systems to print tokens indefinitely.&#x20;

## 2. Contract Variables & Functions <a href="#id-2-contract-details" id="id-2-contract-details"></a>

**Variables**

* `authorizedAccounts[usr: address]` - addresses allowed to cover or uncover systems
* `allowedSystems[system: address]` - data about a system that is allowed to print protocol tokens
* `usedAuctionHouses[house: address]` - mapping that shows whether a `DebtAuctionHouse` is allowed to print tokens or not
* `unrevokableRightsCooldown` - minimum time (in seconds) after which as system will have indefinite permission to print protocol tokens
* `denyRightsCooldown` - cooldown that must pass between calling `startUncoverSystem` and `endUncoverSystem`
* `addRightsCooldown` - cooldown for quickly removing cover from a freshly added system&#x20;
* `coveredSystems` - the current number of systems covered by the protocol token
* `protocolTokenAuthority` - the authority contract dictating who can print tokens
* `AUCTION_HOUSE_TYPE` - debt auction house identifier

**Data Structures**

* `SystemRights` - struct that stores data about each `AccountingEngine` (system). Contains:
  * `covered` - whether this system is covered or not
  * `revokeRightsDeadline` - deadline after which governance can no longer remove printing permissions from the system
  * `uncoverCooldownEnd` - cooldown after which governance can call `endUncoverSystem` and uncover this system
  * `withdrawAddedRightsDeadline` - cooldown during which governance can uncover a system without having to wait until `uncoverCooldownEnd` passed
  * `previousDebtAuctionHouse` - the previous `DebtAuctionHouse` connected to the `AccountingEngine`
  * `currentDebtAuctionHouse` - the current `DebtAuctionHouse` connected to the `AccountingEngine`

**Modifiers**

* `isAuthorized` - checks whether an address is part of `authorizedAddresses`.

**Functions**

* `addAuthorization(usr: address)` - add an address to `authorizedAddresses`.
* `removeAuthorization(usr: address)` - remove an address from `authorizedAddresses`.
* `modifyParameters(parameter: bytes32, data: uint256)` - modify a `uint256` parameter
* `giveUpAuthorityRoot()` - give up the perinting permission's position of `root` inside the `ProtocolTokenAuthority`
* `giveUpAuthorityOwnership` - give up the perinting permission's position of `owner` inside the `ProtocolTokenAuthority`
* `coverSystem(accountingEngine: address)` - cover a new system / allow the `DebtAuctionHouse` set inside `accountingEngine` to print protocol tokens
* `startUncoverSystem(accountingEngine: address)` - start to uncover a system / withdraw the permission of the previous and current `DebtAuctionHouse`s that were associated with `accountingEngine`
* `abandonUncoverSystem(accountingEngine: address)` - abandon the uncovering of a specific system
* `endUncoverSystem(accountingEngine: address)` - end the uncovering process for a system
* `updateCurrentDebtAuctionHouse(accountingEngine: address)` - update the `currentDebtAuctionHouse` of a specific system and set the old current auction house as the&#x20;

  `previousDebtAuctionHouse`
* `removePreviousDebtAuctionHouse(accountingEngine: address)` - remove the permission to print protocol tokens from an `accountingEngine`'s `previousDebtAuctionHouse`
* `proposeIndefinitePrintingPermissions(accountingEngine: address`, `freezeDelay: uint256)` - propose a deadline after which the `accountingEngine` / system cannot be denied printing permissions

**Events**

* `AddAuthorization` - emitted when a new address becomes authorized. Contains:
  * `account` - the new authorized account
* `RemoveAuthorization` - emitted when an address is de-authorized. Contains:
  * `account` - the address that was de-authorized
* `ModifyParameters` - emitted when a `uint256` parameter is updated.
* `GiveUpAuthorityRoot` - emitted when `giveUpAuthorityRoot` is called.
* `GiveUpAuthorityOwnership` -  emitted when `giveUpAuthorityOwnership` is called.
* `RevokeDebtAuctionHouses` - emitted when both the current and the previous `DebtAuctionHouse`s are denied printing permissions. Contains:
  * `accountingEngine` - the accounting engine whose debt auction houses are denied permissions
  * `currentHouse` - the current debt auction house
  * `previousHouse` - the previous debt auction house
* `CoverSystem` - emitted when a new system is covered / allowed to print tokens. Contains:
  * `accountingEngine` - the accounting engine from the system that is being covered
  * `debtAuctionHouse` - the debt auction house set inside the `accountingEngine`
  * `coveredSystems` - the new number of systems being covered
  * `withdrawAddedRightsDeadline` - the deadline after which governance can no longer quickly uncover a system without calling `startUncoverSystem` and `endUncoverSystem`
* `StartUncoverSystem` - emitted when governance starts to uncover a system. Contains:
  * `accountingEngine` - the address of the accounting engine whose debt auction houses are uncovered
  * `currentDebtAuctionHouse` - the current debt auction house connected to the accounting engine
  * `previousDebtAuctionHouse` - the previous debt auction house that was connected to the accounting engine
  * `coveredSystems` - the latest amount of covered systems
  * `revokeRightsDeadline` - the deadline after which governance will not be able to remove this system's printing rights
  * `uncoverCooldownEnd` - the deadline after which governance can call `endUncoverSystem` and finish the uncover process
  * `withdrawAddedRightsDeadline` - cooldown during which governance could have uncovered the system without having to call `endUncoverSystem`
* `AbandonUncoverSystem` - emitted when governance abandons the uncover process for a system. Contains:
  * `accountingEngine` - address of the accounting engine who's no longer being uncovered
* `EndUncoverSystem` - emitted when the uncovering process is finished. Contains:
  * `accountingEngine` - the address of the accounting engine whose debt auction houses are denied printing permissions
  * `currentHouse` - the current debt auction house connected to the accounting engine
  * `previousHouse` - the previous debt auction house that was connected to the accounting engine
* `UpdateCurrentDebtAuctionHouse` - emitted when the current debt auction house of an accounting engine is updated. Contains:
  * `accountingEngine` - the address of the accounting engine whose current debt auction house is updated
  * `currentHouse` - the address of the new current debt auction house
  * `previousHouse` - the address of the previous debt auction house
* `RemovePreviousDebtAuctionHouse` - emitted when the previous debt auction house is removed from a covered system. Contains:
  * `accountingEngine` - the address of the accounting engine whose previous debt auction house is updated
  * `currentHouse` - the address of the new current debt auction house
  * `previousHouse` - the address of the previous debt auction house
* `ProposeIndefinitePrintingPermissions` - emitted when governance proposes a deadline after which they can no longer remove a system's permission to print tokens. Contains:
  * `accountingEngine` - the address of the accounting engine that's part of the system which will no longer be denied printing permissions
  * `freezeDelay` - the delay from the current timestamp after which the system will have indefinite printing permissions

## 3. Walkthrough <a href="#id-2-contract-details" id="id-2-contract-details"></a>

### Current and Previous Debt Auction Houses

Inside the printing permissions contract, a system is represented by an [AccountingEngine](https://github.com/reflexer-labs/geb/blob/master/src/AccountingEngine.sol). The `AccountingEngine` has one debt auction house address in it at any time. That's the `currentDebtAuctionHouse` although governance may have previously had another auction house that was buggy or had to be upgraded and so the printing permissions keep track of both the `currentDebtAuctionHouse` and `previousDebtAuctionHouse` until there's no outstanding auction left in the `previousDebtAuctionHouse`.�

### Function Descriptions

`coverSystem` : checks that the debt auction house associated with that `AccountingEngine` is not already covered. Updates the `withdrawAddedRightsDeadline` for that specific `AccountingEngine`. The deadline makes sure that governance can withdraw cover from the `AccountingEngine` without the need to wait between `startUncoverSystem` and `endUncoverSystem`

`startUncoverSystem`: it cannot uncover a system if either the current or the previous debt auction house associated with that system have outstanding debt auctions to settle. It cannot uncover a system if that system is already in the process of being uncovered. It can withdraw cover from a system either if there are at least 2 systems covered or, even if there are multiple systems covered, the `withdrawAddedRightsDeadline` for the system that governance wants to uncover was not passed. It **must** make sure that at least one system is protected at any time the exception being when all the systems added have not passed their respective `withdrawAddedRightsDeadline` s

`abandonUncoverSystem` : it can only abandon the uncover for a system that is in the process of being uncovered.

`endUncoverSystem` : it must check again that neither the current nor the previous debt auction house has any outstanding auctions left. Similar to `startUncoverSystem` , it can withdraw cover from a system either if there are at least 2 systems covered or, even if there are multiple systems covered, the `withdrawAddedRightsDeadline` for the system that governance wants to uncover was not passed (same exception to the rule applies as for `startUncoverSystem`).

`updateCurrentDebtAuctionHouse`: it cannot update the `currentDebtAuctionHouse` if the new auction house is the same as the current one. It also cannot update the current auction house if `previousDebtAuctionHouse` is non null. It must allow the new auction house to print tokens and set `previousDebtAuctionHouse` as the last `currentDebtAuctionHouse`

`removePreviousDebtAuctionHouse` : it cannot remove the permission of the `previousDebtAuctionHouse` to print protocol tokens unless there are no outstanding auctions in that auction house.

`proposeIndefinitePrintingPermissions` : it sets a time after which governance can never remove cover from a specific accounting engine (and thus it's associated debt auction house). `updateCurrentDebtAuctionHouse` and `removePreviousDebtAuctionHouse` should still work even if `now > allowedSystems[accountingEngine].revokeRightsDeadline`�


# Money Market Module

Interest rate setters and collectors

**Relevant smart contracts:**

* [TaxCollector](https://github.com/reflexer-labs/geb/blob/master/src/single/TaxCollector.sol)

## 1. Overview

The **Money Market Module** contains the components that governance (or an autonomous rate setter) can use to set and collect stability fees.

## 2. Component Descriptions

* The `TaxCollector` imposes fees on all collateral types and distributes them to various parties. Each collateral's stability fee is composed out of a `globalStabilityFee` (a base fee applied to all collateral types) and its own, unique `CollateralType.stabilityFee`.

## 3. Risks

### Smart Contract Bugs <a href="#coding-errors" id="coding-errors"></a>

A bug in the `TaxCollector` would make it so that the system could no longer accrue surplus (which is used to settle bad debt and pay for other system operations) and thus components that depend on a constant stream of fees would likely stop working properly.

### Improper Maintenance

The `TaxCollector` depends on external actors that call `taxSingle` or `taxMany` in order to collect stability fees. Protocol token holders are incentivized to call the collector as often as possible, although in the early days of the system the calls may be more infrequent. The main caveat is that any SAFE that is opened and closed between two fee collections will not be subject to taxation.

Another major risk is related to malicious governance setting extremely high or extremely low stability fees. If the fees are extremely high, SAFEs may be unjustly liquidated. On the other hand, if they are too low, the system may not be able to collect enough fees to become sustainable.

## 4. Governance Minimization

The `TaxCollector` is part of the Level 1 Gov Minimization.

{% hint style="info" %}
**Bounded Stability Fee Control**

Governance can choose to keep bounded control over setting rates by clearly specifying upper and lower values. For example, the ETH-A rate may only be set to a value between 1-3% per year.

This is to ensure that the protocol offers more advantageous rates during some periods while it can also collect more surplus when needed.
{% endhint %}


# Tax Collector

The protocol's taxman

## 1. Summary <a href="#id-1-introduction-summary" id="id-1-introduction-summary"></a>

The `TaxCollector` stores data about each `CollateralType`'s stability fee. It also collects fees from currently opened SAFEs and distributes them to the `AccountingEngine` and to other auxiliary system components such as the `StabilityFeeTreasury`.

## 2. Contract Variables & Functions <a href="#id-2-contract-details" id="id-2-contract-details"></a>

**Variables**

* `authorizedAccounts[usr: address]` - `addAuthorization`/`removeAuthorization`/`isAuthorized` - auth mechanisms
* `collateralTypes[collateralType: bytes32]` - mapping with data about each collateral type
* `secondaryReceiverAllotedTax[collateralType: bytes32]` - total percentage of a `CollateralType`'s fees that goes to secondary tax receivers
* `usedSecondaryReceiver[receiver: address]` - whether an address is already used as a secondary receiver
* `secondaryReceiverAccounts[receiver: address]` - whether an address is already marked as a secondary tax receiver
* `secondaryReceiverRevenueSources[receiver: address]` - number of collateral types that give part of their stability fees to secondary receivers
* `secondaryTaxReceivers[bytes32: collateralType, uint256: receiverId]` - data about a secondary receiver for a specific collateral type
* `safeEngine` - address of the `SAFEEngine`. Cannot be changed after contract deployment
* `primaryTaxReceiver` - main receiver of stability fees (usually the `AccountingEngine`)
* `globalStabilityFee` - base stability fee applied to all collateral types
* `secondaryReceiverNonce` - total amount of secondary receivers ever added
* `maxSecondaryReceivers` - maximum amount of secondary receivers that can receive fees from one collateral type
* `latestSecondaryReceiver` - the first secondary receiver the contract starts to loop from when distributing fees
* `collateralList` - list of all collateral types added to the collector
* `secondaryReceiverList` - list of all secondary tax receivers who receive fees from at least one collateral type

**Data Structures**

* `CollateralType`:
  * `stabilityFee` - per second fee applied to SAFEs backed by a specific asset
  * `updateTime` - latest timestamp of when the system collected fees from SAFEs backed by a specific collateral
* `TaxReceiver` - struct containing data about an auxiliary address that receives stability fees. It cannot be the `AccountingEngine` (because it is already considered a primary tax receiver). Contains:
  * `canTakeBackTax` - whether the system can impose a penalty on the receiver and take back previously distributed stability fees (in case the stability fee is negative)
  * `taxPercentage` - percentage of a collateral's stability fees distributed to this receiver

**Functions**

* `initializeCollateralType(collateralType: bytes32)` - add a new collateral type
* `modifyParameters()` - add/remove tax receivers, set stability fees etc
* `addSecondaryReceiver(collateralType: bytes32, percentage: uint256, receiver: address)`- add a new secondary receiver
* `modifySecondaryReceiver(collateral: bytes32, position: uint256, percentage: uint256)` - modify a receiver's data or remove them from the receiver list
* `collectedManyTax(start: uint256`, `end: uint256)` - check if the contract is up to date with taxation (on multiple collateral types)
* `taxManyOutcome(start: uint256, end: uint256) public view returns (bool ok, int rad)` - check how many fees would be collected if multiple collateral types (between indexes `start` and `end` in `collateralList`) would be taxed at once
* `taxSingleOutcome(collateralType: bytes32) public view returns (uint, int)` - check the amount of fees that would be collected if a single collateral type was taxed
* `secondaryReceiversAmount() public view returns (uint)` - return the amount of unique secondary receivers added to the collector
* `collateralListLength() public view returns (uint)` - return the length of `collateralList`
* `isSecondaryReceiver(receiverId: uint256) public view returns (uint)` - check if an id in the `secondaryReceiverList` was allocated to a receiver
* `taxMany(start: uint256, end: uint256)` - collect tax from multiple collateral types that are between `start` and `end` in `collateralList`
* `taxSingle(collateralType: bytes32) public returns (uint)` - collect fees from a single collateral type
* `splitTaxIncome(collateral: bytes32, debt: uint256, deltaRate: int256)` - loop through tax receivers in order to distribute tax

#### **Events** <a href="#events" id="events"></a>

* `AddAuthorization` - emitted when a new address becomes authorized. Contains:
  * `account` - the new authorized account
* `RemoveAuthorization` - emitted when an address is de-authorized. Contains:
  * `account` - the address that was de-authorized
* `CollectTax`: emitted when a collateral type is taxed (the system collects stability fees from SAFEs backed by a specific asset). Contains:
  * `collateralType` - collateral type being taxed
  * `latestAccumulatedRate` - accumulator of total stability fees that have been applied to`collateralType` SAFEs since the taxed collateral has been accepted into the system
  * `deltaRate` - difference between the new (`latestAccumulatedRate`) and the old accumulated rate for the currently taxed collateral type
* `DistributeTax` - emitted when the system distributes fees to a specific recipient. Contains:
  * `collateralType` - collateral type being taxed
  * `target` - stability fee receiver
  * `taxCut` - portion of the total tax to be distributed that goes to `target`

## 3. Walkthrough <a href="#id-2-contract-details" id="id-2-contract-details"></a>

The taxation process starts with governance setting up the `globalStabilityFee` and every collateral's `stabilityFee`. Governance also needs to set a `primaryTaxReceiver` (usually the `AccountingEngine`) and add `secondaryReceiver`s for each collateral type (e.g the `StabilityFeeTreasury`).

To collect stability fees, external actors (such as protocol token holders or keepers) can call `taxMany` (to collect stability fees from multiple collateral types) or `taxSingle`. The `primaryTaxReceiver` is guaranteed to receive a non zero amount of stability fees. If there are any `secondaryReceivers` set up for a specific collateral, each one will get `TaxReceiver.taxPercentage` percentage of the distributed fees.

### `rpow`

`rpow(uint x, uint n, uint b)`, used for exponentiation in `taxSingle/taxMany`, is a fixed-point arithmetic function that raises `x` to the power `n`. It is implemented in Solidity assembly as a repeated squaring algorithm. `x` and the returned value are to be interpreted as fixed-point integers with scaling factor `b`. For example, if `b == 100`, this specifies two decimal digits of precision and the normal decimal value 2.1 would be represented as 210; `rpow(210, 2, 100)` returns 441 (the two-decimal digit fixed-point representation of 2.1^2 = 4.41). In the current implementation, 10^27 is passed for `b`, making `x` and the `rpow` result both of type `ray` in standard GEB fixed-point terminology. `rpow`'s formal invariants include "no overflow" as well as constraints on gas usage.

### Parameters Can Only Be Set By Governance

TaxCollector stores some sensitive parameters, particularly the base rate and collateral-specific risk premiums that determine the overall stability fee rate for each collateral type. Its built-in authorization mechanisms need to allow only authorized governance contracts/actors to set these values. See "Failure Modes" for a description of what can go wrong if parameters are set to unsafe values.

## 4. Gotchas (Potential Sources of User Error)

### Collateral Initialization

`initializeCollateralType(bytes32 collateral)` must called when a new collateral is added (setting `stabilityFee` via `modifyParameters()` is not sufficient)—otherwise `updateTime` will be uninitialized and fees will accumulate based on a start date of January 1st, 1970 (start of Unix epoch).

### `globalStabilityFee + CollateralType.stabilityFee` imbalance in `taxSingle()`

A call to `taxSingle(bytes32 collateral)`will add the `globalStabilityFee` rate to the `CollateralType.stabilityFee` rate. The rate is a calculated compounded rate, so `rate(globalStabilityFee + CollateralType.stabilityFee) != rate(globalStabilityFee) + rate(CollateralType.stabilityFee)`. This means that if globalStabilityFee is set, the CollateralType.stabilityFee will need to be set factoring the existing compounding factor in globalStabilityFee, otherwise the result will be outside of the rate tolerance. Updates to the `globalStabilityFee` value will require all of the `CollateralTypes` to be updated as well.

## 5. Failure Modes (Bounds on Operating Conditions & External Risk Factors)

### Tragedy of the Commons

If `taxSingle()` is called very infrequently for some collateral types (due, for example, to low overall system usage or extremely stable collateral types that have essentially zero liquidation risk), then the system will fail to collect fees on SAFES opened and closed between `taxSingle()` calls. As the system achieves scale, this becomes less of a concern, as both Keepers and FLX holders are have an incentive to regularly call taxSingle (the former to trigger liquidation auctions, the latter to ensure that surplus accumulates to decrease FLX supply); however, a hypothetical asset with very low volatility yet high risk premium might still see infrequent taxSingle calls at scale (there is not at present a real-world example of this—the most realistic possibility is `globalStabilityFee` being large, elevating rates for all collateral types).

### Malicious or Careless Parameter Setting

Various parameters of TaxCollector may be set to values that damage the system. While this can occur by accident, the greatest concern is malicious attacks, especially by an entity that somehow becomes authorized to make calls directly to TaxCollector's administrative methods, bypassing governance. Setting `stabilityFee` (for at least one collateral) or `globalStabilityFee` too low can lead to Dai oversupply; setting either one too high can trigger excess liquidations and therefore unjust loss of collateral. Setting a value for `accountingEngine` other than the true AccountingEngine's address can cause surplus to be lost or stolen.


# Sustainability Module

The protocol's resource management engine

**Relevant smart contracts:**

* [StabilityFeeTreasury](https://github.com/reflexer-labs/geb/blob/master/src/single/StabilityFeeTreasury.sol)
* [FSM Wrapper](https://github.com/reflexer-labs/geb-fsm/blob/master/src/FSMWrapper.sol)
* [Increasing Treasury Reimbursement](https://github.com/reflexer-labs/geb-treasury-reimbursement/blob/master/src/reimbursement/single/IncreasingTreasuryReimbursement.sol)
* [Mandatory Fixed Treasury Reimbursement](https://github.com/reflexer-labs/geb-treasury-reimbursement/blob/master/src/reimbursement/single/MandatoryFixedTreasuryReimbursement.sol)
* [Increasing Reward Relayer](https://github.com/reflexer-labs/geb-treasury-reimbursement/blob/master/src/relayer/IncreasingRewardRelayer.sol)

## 1. Overview

The **Sustainability Module** allocates resources to actors that update critical system components such as oracles, even in the absence of governance power over the protocol.

## 2. Component Descriptions

* `StabilityFeeTreasury` - this contract tries to keep an "optimum" amount of stability fees for itself in order to make sure it can provide funds to other contracts (or in some cases, people) that maintain the protocol's well-being. Anyone can periodically call a function to recalculate the optimum amount of funds to keep in the treasury. Any surplus above optimum values is transferred to the `extraSurplusReceiver`.
* `FSMWrapper` - this contract is meant to act as a funding source for FSM-like contracts as well as an interface that allows other contracts to read data from the FSM integrated with the wrapper.
* `IncreasingTreasuryReimbursement` - this contract is meant to be inherited from and used as a way to offer an increasing stability fee reward (pulled from the SF treasury) to any address.
* `MandatoryFixedTreasuryReimbursement` - this is a contract meant to be inherited from and used as a way to offer a fixed stability fee reward (pulled from the SF treasury) to any address.
* `IncreasingRewardRelayer` - this is a contract meant to pull funds from the `StabilityFeeTreasury` and send them to a custom address. It inherits functionality from the&#x20;

  `IncreasingTreasuryReimbursement` contract

## 3. Risks

### Smart Contract Bugs <a href="#coding-errors" id="coding-errors"></a>

* A bug in the `StabilityFeeTreasury` would potentially block other contracts from pulling funds or would incorrectly calculate the optimum amount of funds to keep in the contract (`SAFEEngine.coinBalance[stabilityFeeTreasury]`). A bug could also prevent the treasury from sending extra unused resources to another address using `transferSurplusFunds()`
* A bug in the `IncreasingTreasuryReimbursement` contract could block the execution of&#x20;

  `rewardCaller()` or it would make it impossible for someone to call `getCallerReward`
* Similar to the `IncreasingTreasuryReimbursement` contract, a bug in`MandatoryFixedTreasuryReimbursement` could block the execution of `rewardCaller()`

### Misconfiguration

* Governance might set an incorrect address as the `extraSurplusReceiver` in the `StabilityFeeTreasury` or could maliciously withdraw the permission of core contracts to pull funds. Governance could also allow malicious contracts to drain the treasury.
* Governance might set high values for `maxRewardIncreaseDelay` and `perSecondCallerRewardIncrease` inside `IncreasingTreasuryReimbursement` and thus make&#x20;

  `getCallerReward` revert

## 4. Governance Minimization

Governance can withdraw their power over the `StabilityFeeTreasury` if two conditions are satisfied:

1. All treasury dependent contracts were set up correctly (can withdraw enough funds to function properly).
2. All external actors (if any) have the necessary permissions to pull funds from the treasury.

The `StabilityFeeTreasury` is part of the Level 2 Gov Minimization. That being said, governance should maintain control only over setting `total` allowances to their initial values for every address that's currently authorized to `pullFunds` from the treasury.

The `FSMWrapper` may need to have leftover governance (depending on how much governance wants to automate reward setting).

`IncreasingRewardRelayer` can have governance in the long run, depending on how much governance wants to remove themselves from the contract and also on what the contract is requesting rewards for.

`IncreasingTreasuryReimbursement` and `MandatoryFixedTreasuryReimbursement` are meant to be inherited by other contracts and so the contracts that inherit them will determine how much they can be governance minimized.

{% hint style="info" %}
**Keeping Governance Over** `takeFunds`

Given that `StabilityFeeTreasury.takeFunds` has very simple and clearly defined behaviour, it can be governed in the long run.&#x20;
{% endhint %}


# Stability Fee Treasury

The protocol's invoice processor

## 1. Summary <a href="#id-1-introduction-summary" id="id-1-introduction-summary"></a>

The `StabilityFeeTreasury` is meant to allow other contracts or EOAs to pull funds (stability fees) in order to finance their operations. The treasury is set up as a `secondaryReceiver` in the `TaxCollector`. Anyone can periodically call the contract in order to recompute an optimal amount of fees that should be kept in the treasury and send any additional surplus to the `extraSurplusReceiver`.

## 2. Contract Variables & Functions <a href="#id-2-contract-details" id="id-2-contract-details"></a>

**Variables**

* `authorizedAccounts[usr: address]` - `addAuthorization`/`removeAuthorization` - auth mechanisms
* `allowance[receiver: address]` - total withdrawal allowance
* `pulledPerBlock[usr: address`, `blockNr: uint256]` - total amount pulled by a user on a specific block
* `safeEngine` - address of the `SAFEEngine`
* `systemCoin` - system coin address ([Coin.sol](https://github.com/reflexer-labs/geb/blob/master/src/Coin.sol))
* `coinJoin` - system coin adapter address
* `extraSurplusReceiver` - address that receives extra unused funds from the treasury
* `treasuryCapacity` - maximum amount of stability fees should be kept in the treasury
* `minimumFundsRequired` - minimum amount of stability fees that must be kept in the treasury at all times
* `expensesMultiplier` - multiplier for the expenses incurred since the last `transferSurplusFunds` call. Ensures there's a buffer of funds on top of the expected expenses until the next&#x20;

  `transferSurplusFunds` call
* `surplusTransferDelay` - delay between two `transferSurplusFunds` calls
* `expensesAccumulator` - total expenses incurred since treasury deployment
* `accumulatorTag` - latest snapshot of `expensesAccumulator`
* `latestSurplusTransferTime` - last timestamp when `transferSurplusFunds` was called
* `contractEnabled` - global settlement flag

**Data Structures**

* `Allowance` - struct that specifies the total and the per-block withdrawal allowance for an address. Contains:
  * `total` - the total allowance (in `RAD`)
  * `perBlock` - the per-block allowance (in `RAD`)

**Modifiers**

* `isAuthorized` - checks whether an address is part of `authorizedAddresses` (and thus can call authed functions).
* `accountNotTreasury` - checks that the receiver account for treasury funds is not the treasury itself

**Functions**

* `modifyParameters()` - authorized function for changing treasury parameters
* `disableContract()` - disable the treasury and transfer all of its funds to the`extraSurplusReceiver`
* `joinAllCoins()` - join any ERC20 system coins that the treasury has into internal coin form (`SAFEEngine.coinBalance`)
* `getAllowance(account: address)` - get the total and the per-block allowance for a user
* `setTotalAllowance(account: address`, `rad: uint256)` - authorized function that changes the total allowed amount an address can withdraw from the treasury
* `setPerBlockAllowance(account: address`, `rad: uint256)` - authorized function that changes the amount that an address can withdraw from the treasury every block
* `giveFunds(account: address`, `rad: uint256)` - governance controlled function that transfers stability fees from the treasury to a destination address
* `takeFunds(account: address`, `rad: uint256)` - governance controlled function that transfers stability fees from a target address to the treasury
* `pullFunds(dstAccount: address`, `token: address`, `wad: uint256)` - take funds from the treasury. Reverts if the caller is not allowed to withdraw or if their per-block allowance doesn't allow it
* `transferSurplusFunds()` - recalculate the amount of stability fees that should remain in the treasury and transfer additional funds to the `extraSurplusReceiver`

**Events**

* `AddAuthorization` - emitted when a new address becomes authorized. Contains:
  * `account` - the new authorized account
* `RemoveAuthorization` - emitted when an address is de-authorized. Contains:
  * `account` - the address that was de-authorized
* `ModifyParameters` - emitted when a parameter is updated.
* `DisableContract` - emitted when the contract is disabled.
* `SetTotalAllowance` - emitted when the total allowance for an address is set. Contains:
  * `account` - the account whose allowance was changed
  * `rad` - the new total allowance for the `account`
* `SetPerBlockAllowance` - emitted when the per-block allowance for an address is set. Contains:
  * `account` - the account whose per-block allowance was changed
  * `rad` - the new total allowance for the `account`
* `GiveFunds` - emitted when governance offers funds to an address. Contains:
  * `account` - the account that received funds
  * `rad` - the amount of funds that were given
  * `expensesAccumulator` - the sum of all the expenses incurred since the contract was deployed
* `TakeFunds` - emitted when governance calls the treasury to take funds from an address. Contains:
  * `account` - the account the treasury takes system coins from
  * `rad` - the amount of (internal) system coins to take (expressed as `RAD`)
* `PullFunds` - emitted when an approved address pulls funds from the treasury. Contains:
  * `sender` - the `msg.sender` that called `pullFunds`
  * `dstAccount` - the address that received funds
  * `token` - the address of the token being transferred (in this case it's always the address of the ERC20 system coin)
  * `rad` - the total amount of internal system coins transferred
  * `expensesAccumulator` - the sum of all the expenses incurred since the contract was deployed
* `TransferSurplusFunds` - emitted when surplus funds above the optimum amount are sent to the accounting engine. Contains:
  * `extraSurplusReceiver` - the address that received the extra funds
  * `fundsToTransfer` - the amount of funds sent

## 3. Walkthrough <a href="#id-2-contract-details" id="id-2-contract-details"></a>

The treasury is funded by stability fees coming from the `TaxCollector` or by anyone who is willing to send system coins (either internally or as ERC20 tokens) to it. Governance can also use `takeFunds` to transfer internal system coins from a source address to the treasury.\
\
Governance is in charge with setting up authorized addresses that can `pullFunds` out of the treasury (if their total or per-block `allowance` permits) as well as setting treasury parameters in order to determine the optimum amount of funds that should remain in the contract at any time. We define "optimum" as a multiplier (`expensesMultiplier`) of the latest expenses incurred by the treasury since the last `transferSurplusFunds` call.&#x20;

`transferSurplusFunds` is the way the treasury recalculates the amount of funds it should keep in reserves and transfers any surplus to the `extraSurplusReceiver`. Note that there is a `surplusTransferDelay` time delay between recalculating the optimum and transferring surplus out of the contract.

{% hint style="info" %}
**Sending Funds to** `extraSurplusReceiver`**or to the Treasury Itself**

In case governance wants to send funds to `extraSurplusReceiver` using `giveFunds`, `expensesAccumulator` will not increase. In case an address wants to `pullFunds` and send them to the `extraSurplusReceiver`, `pullFunds` will revert.\
\
`pullFunds` will silently fail if the `dstAccount` is the treasury contract itself, whereas `giveFunds` will revert.
{% endhint %}


# FSM Wrapper

Wrapper for FSM-like contracts

## 1. Summary <a href="#id-1-introduction-summary" id="id-1-introduction-summary"></a>

The `FSMWrapper` is meant to act as a funding source for FSM-like contracts as well as an interface that allows other contracts to read data from the FSM integrated with the wrapper.

## 2. Contract Variables & Functions <a href="#id-2-contract-details" id="id-2-contract-details"></a>

**Variables**

* `authorizedAccounts[usr: address]` - `addAuthorization`/`removeAuthorization` - auth mechanisms
* `lastReimburseTime` - last timestamp when the wrapper sent stability fee rewards to the address that called `fsm.updateResult()`
* `reimburseDelay` - enforced delay between consecutive `renumerateCaller` calls
* `fsm` - the FSM contract that's being wrapped; this contract is the only allowed caller for `renumerateCaller`

**Functions**

* `modifyParameters` - modify contract parameters
* `renumerateCaller(feeReceiver: address)` - called by the `fsm` in order to send stability fees from the [StabilityFeeTreasury](https://github.com/reflexer-labs/geb/blob/master/src/single/StabilityFeeTreasury.sol) to the `feeReceiver`
* `stopped() public view returns (uint256)` - read and return `stopped` from the `fsm`
* `priceSource() public view returns (address)` - read and return `priceSource` from the `fsm`
* `updateDelay() public view returns (uint16)` - read and return `updateDelay` from the `fsm`
* `lastUpdateTime() public view returns (uint64)` - read and return `lastUpdateTime` from the `fsm`
* `newPriceDeviation() public view returns (uint256)` - read and return the `newPriceDeviation` from the `fsm`
* `passedDelay() public view returns (bool)` - read and return `passedDelay` from the `fsm`
* `getNextBoundedPrice() public view returns (uint128)` - read and return the value calculated by `getNextBoundedPrice` from the `fsm`
* `getNextPriceLowerBound() public view returns (uint128)` - read and return the value calculated by `getNextPriceLowerBound` from the `fsm`
* `getNextPriceUpperBound() public view returns (uint128)` - read and return the value calculated by `getNextPriceUpperBound` from the `fsm`
* `getResultWithValidity() external view returns (uint256, bool)` - read and return the current result and its validity from the `fsm`
* `getNextResultWithValidity() external view returns (uint256, bool)` - read and return the next result and its validity from the `fsm`
* `read() external view returns (uint256)` - read and return (or revert) the current result from the `fsm`&#x20;

## 3. Walkthrough <a href="#id-2-contract-details" id="id-2-contract-details"></a>

Anyone can read values from the `fsm` contract by calling the wrapper `view` functions. The `fsm` contract is allowed to call `renumerateCaller` and thus send stability fee rewards to an address.


# Increasing Treasury Reimbursement

Integration contract meant to offer an increasing reward pulled from the SF treasury

## 1. Summary <a href="#id-1-introduction-summary" id="id-1-introduction-summary"></a>

The `IncreasingTreasuryReimbursement` is a contract meant to be inherited from and used as a way to offer an increasing stability fee reward (pulled from the SF treasury) to any address.

## 2. Contract Variables & Functions <a href="#id-2-contract-details" id="id-2-contract-details"></a>

**Variables**

* `authorizedAccounts[usr: address]` - `addAuthorization`/`removeAuthorization` - auth mechanisms
* `baseUpdateCallerReward` - starting reward offer to a fee receiver
* `maxUpdateCallerReward` - max possible reward for a fee receiver
* `maxRewardIncreaseDelay` - max delay taken into consideration when calculating the adjusted reward
* `perSecondCallerRewardIncrease` - rate applied to `baseUpdateCallerReward` every extra second passed beyond a certain date (e.g next time when a specific function needs to be called)
* `treasury` - stability fee treasury contract

**Functions**

* `treasuryAllowance() public view returns (uint256)` - this returns the stability fee treasury allowance for the reimbursement contract by taking the minimum between the per block and the total allowances
* `getCallerReward(uint256 timeOfLastUpdate`, `uint256 defaultDelayBetweenCalls) public` `view returns (uint256)` - get the SF reward that can be sent to an address right now
* `rewardCaller(proposedFeeReceiver: address, reward: uint256) internal` - internal function that's meant to send a SF reward to a `proposedFeeReceiver`

**Modifiers**

* `isAuthorized` - checks whether an address is part of `authorizedAddresses` (and thus can call authed functions)

**Events**

* `AddAuthorization` - emitted when a new address becomes authorized. Contains:
  * `account` - the new authorized account
* `RemoveAuthorization` - emitted when an address is de-authorized. Contains:
  * `account` - the address that was de-authorized
* `ModifyParameters` - emitted when a parameter is updated.
* `FailRewardCaller` - emitted when the contract cannot reward an address. Contains:
  * `revertReason` - the reason why the contract could not send the reward
  * `feeReceiver` - the address that was supposed to get the reward
  * `amount` - the reward that had to be sent

## 3. Walkthrough <a href="#id-2-contract-details" id="id-2-contract-details"></a>

`rewardCaller` is the most important function in this contract. It takes care of pulling the SF reward from the treasury and then sending it to a `proposedFeeReceiver`.

`getCallerReward` can be used to retrieve the current SF fee that can be pulled from the treasury. If `baseUpdateCallerReward` and `maxUpdateCallerReward` are both zero or if `timeOfLastUpdate >= now`, `getCallerReward` will return zero.

{% hint style="warning" %}
**Large `maxRewardIncreaseDelay` and `perSecondCallerRewardIncrease`can make `getCallerReward` revert**

If `perSecondCallerRewardIncrease` is set to a large value and `maxRewardIncreaseDelay` is also large, `getCallerReward` may revert. In most scenarios,  `maxRewardIncreaseDelay` should be set to a very conservative value (a couple of hours at most) in order to avoid this scenario.
{% endhint %}

## 4. Increasing Treasury Reimbursement Flavours

There are two alternative Increasing Treasury Reimbursement contract flavours aside from the core one:

* `NoSetupIncreasingTreasuryReimbursement` - this contract has the exact same logic as the core one but it does not set any parameters in its constructor
* `NoSetupNoAuthIncreasingTreasuryReimbursement` - this contract has the same logic as the core one but it does not set any parameters in its constructor and it also does not have any authorization logic (`addAuthorization`/`removeAuthorization`)


# Mandatory Fixed Treasury Reimbursement

Integration contract meant to offer a fixed reward pulled from the SF treasury

## 1. Summary <a href="#id-1-introduction-summary" id="id-1-introduction-summary"></a>

The `MandatoryFixedTreasuryReimbursement` is a contract meant to be inherited from and used as a way to offer a fixed stability fee reward (pulled from the SF treasury) to any address.

## 2. Contract Variables & Functions <a href="#id-2-contract-details" id="id-2-contract-details"></a>

**Variables**

* `authorizedAccounts[usr: address]` - `addAuthorization`/`removeAuthorization` - auth mechanisms
* `fixedReward` - the fixed reward sent by the `treasury` to a fee receiver
* `treasury` - stability fee treasury contract

**Functions**

* `treasuryAllowance() public view returns (uint256)` **-** return the amount of SF that the treasury can transfer in one transaction when called by the reimbursement contract
* `getCallerReward() public view returns (uint256 reward)` - get the actual reward that can be pulled from the SF treasury by taking the minimum value between the `fixedReward`and the total amount that can be sent by the `treasury` in one block
* `rewardCaller(proposedFeeReceiver: address) internal` - internal function to send a SF reward to a fee receiver by calling the `treasury`

**Modifiers**

* `isAuthorized` - checks whether an address is part of `authorizedAddresses` (and thus can call authed functions)

**Events**

* `AddAuthorization` - emitted when a new address becomes authorized. Contains:
  * `account` - the new authorized account
* `RemoveAuthorization` - emitted when an address is de-authorized. Contains:
  * `account` - the address that was de-authorized
* `ModifyParameters` - emitted when a parameter is updated.
* `RewardCaller` - emitted when the contract rewards an address with SF coming from the `treasury`. Contains:
  * `finalFeeReceiver` - the address that got the reward
  * `fixedReward` - the reward that was sent

## 3. Walkthrough <a href="#id-2-contract-details" id="id-2-contract-details"></a>

`rewardCaller` is the most important function in this contract. It takes care of pulling a fixed SF reward from the treasury and then sending it to a `proposedFeeReceiver`.

`getCallerReward` can be used to retrieve the current SF fee that can be pulled from the treasury.


# Increasing Reward Relayer

Contract that relays SF rewards from the treasury to any other address

## 1. Summary <a href="#id-1-introduction-summary" id="id-1-introduction-summary"></a>

The `IncreasingRewardRelayer` is a contract meant to pull funds from the `StabilityFeeTreasury` and send them to a custom address. The relayer can only be called by a specific address that requests payments.

This contract inherits functionality from the [IncreasingTreasuryReimbursement](https://docs.reflexer.finance/system-contracts/sustainability-module/increasing-treasury-reimbursement) contract.

## 2. Contract Variables & Functions <a href="#id-2-contract-details" id="id-2-contract-details"></a>

**Variables**

* `refundRequestor` - address that can request funds
* `lastReimburseTime` - timestamp of the last reimbursement
* `reimburseDelay` - enforced gap between reimbursements

**Functions**

* `modifyParameters` - modify contract parameters
* `reimburseCaller(feeReceiver: address)` - send SF rewards from the treasury to the `feeReceiver`

## 3. Walkthrough <a href="#id-2-contract-details" id="id-2-contract-details"></a>

`refundRequestor` is the only address that can call `reimburseCaller` and request a stability fee payment from the treasury.

`reimburseCaller` can only be called again after at least `reimburseDelay` seconds have passed since the last call.


# Automation Module

A set of contracts in charge with automating a GEB

**Relevant smart contracts:**

* [CollateralAuctionThrottler](https://github.com/reflexer-labs/geb-collateral-auction-throttler/blob/master/src/CollateralAuctionThrottler.sol)
* [SingleSpotDebtCeilingSetter](https://github.com/reflexer-labs/geb-debt-ceiling-setter/blob/master/src/SingleSpotDebtCeilingSetter.sol)
* [ESMThresholdSetter](https://github.com/reflexer-labs/geb-esm-threshold-setter/blob/master/src/ESMThresholdSetter.sol)

## 1. Overview

The **Automation Module** is a set of contracts that automate parameter setting in a GEB deployment. They are meant to ease the burden of managing a system and allow the community to focus their efforts on other areas.

## 2. Component Descriptions

* `CollateralAuctionThrottler` - this contract bounds the amount of bad debt that's waiting to be covered by collateral auctions at any given time
* `SingleSpotDebtCeilingSetter` - this contract recomputes the debt ceiling for a specific collateral type by looking at the current `globalDebt` in the `SAFEEngine`
* `ESMThresholdSSetter` - this contract recomputes the threshold needed to burn and trigger settlement using the `ESM`

## 3. Risks

### Smart Contract Bugs <a href="#coding-errors" id="coding-errors"></a>

* A bug in the `CollateralAuctionThrottler` could prevent the `LiquidationEngine` from liquidating any SAFE by setting `onAuctionSystemCoinLimit` to an extremely low value
* A bug in the `SingleSpotDebtCeilingSetter` could set an extremely low ceiling or it could block any further ceiling updates and thus not allow the system to issue more system coins
* A bug in the `ESMThresholdSetter` could set the `ESM` threshold to an extremely low value which would make shutdown extremely easy to execute or to a very high value which would make shutdown almost impossible to execute

### Misconfiguration

* Governance can misconfigure the throttler and make it compute extremely low values for the`onAuctionSystemCoinLimit`
* Governance can also misconfigure the `SingleSpotDebtCeilingSetter` to the point where it stops calculating new ceilings (by setting a large delay between recalculations) or it can calculate large or low ceilings (compared to the current amount of debt in the system)
* `ESMThresholdSetter` can be misconfigured and it can set extremely high or extremely low thresholds in the `ESM`

## 4. Governance Minimization

All the automation contracts are part of Level 2 governance minimization.


# Collateral Auction Throttler


# Single Spot Debt Ceiling Setter

Setter for a single collateral's debt ceiling

## 1. Summary <a href="#id-1-introduction-summary" id="id-1-introduction-summary"></a>

The `SingleSpotDebtCeilingSetter` is meant to recompute the `debtCeiling` for a single collateral type inside the `SAFEEngine`.\
\
The setter inherits functionality from the [IncreasingTreasuryReimbursement](https://docs.reflexer.finance/system-contracts/sustainability-module/increasing-treasury-reimbursement).

## 2. Contract Variables & Functions <a href="#id-2-contract-details" id="id-2-contract-details"></a>

**Variables**

* `manualSetters[usr: address]` - `addManualSetter`/`removeManualSetter` - auth mechanism for addresses that can call `manualUpdateCeiling`
* `maxCollateralCeiling` - the max amount of system coins that can be generated using the collateral type with `collateralName`
* `minCollateralCeiling` - the min amount of system coins that must be generated using the collateral type with `collateralName`
* `ceilingPercentageChange` - premium on top of the current amount of debt (backed by the collateral type with `collateralName`) minted. This is used to calculate a new ceiling
* `lastUpdateTime` - when the debt ceiling was last updated
* `updateDelay` - enforced time gap between calls
* `lastManualUpdateTime` - last timestamp of a manual update
* `blockIncreaseWhenRevalue` - flag that blocks an increase in the debt ceiling when the redemption rate is positive
* `blockDecreaseWhenDevalue` - flag that blocks a decrease in the debt ceiling when the redemption rate is negative
* `collateralName` - the targeted collateral's name
* `safeEngine` - the `SAFEEngine` contract
* `oracleRelayer` - the `OracleRelayer` contract

**Functions**

* `modifyParameters` - modifies contract parameters
* `autoUpdateCeiling(feeReceiver: address) external` - periodically updates the debt ceiling for the collateral type with `collateralName`. Can be called by anyone
* `manualUpdateCeiling()` - authed function that allows `manualSetters` to update the debt ceiling whenever they want
* `getNextCollateralCeiling() public view returns (uint256)` - view function meant to return the new and upcoming debt ceiling. It also checks for `allowsIncrease` and `allowsDecrease`
* `getRawUpdatedCeiling() external view returns (uint256)` - view function meant to return the new and upcoming debt ceiling. It does not perform checks for `allowsIncrease` and `allowsDecrease`
* `allowsIncrease(redemptionRate: uint256`, `currentDebtCeiling: uint256`, `updatedCeiling: uint256) public view returns (allowsIncrease: bool)` - view function meant to return whether an increase in the debt ceiling is currently allowed
* `allowsDecrease(redemptionRate: uint256`, `currentDebtCeiling: uint256`, `updatedCeiling: uint256) public view returns (allowsDecrease: bool)` - view function meant to return whether a decrease in the debt ceiling is currently allowed

**Modifiers**

* `isManualSetter` - checks whether an address is part of `manualSetters`.

**Events**

* `AddManualSetter` - emitted when a new manual setter is added. Contains:
  * `account` - new manual setter address
* `RemoveManualSetter` - emitted when a manual setter address is removed/blacklisted. Contains:
  * `account` - the setter address that's removed
* `UpdateCeiling` - emitted when a new ceiling is computed and set. Contains:
  * `nextCeiling` - the new ceiling

## 3. Walkthrough <a href="#id-2-contract-details" id="id-2-contract-details"></a>

`autoUpdateCeiling` and `manualUpdateCeiling` can both be used to recompute the debt ceiling for the collateral type with `collateralName, although manualUpdateCeiling` can only be called by whitelisted `manualSetters`. Both `autoUpdateCeiling` and `manualUpdateCeiling` call `getNextCollateralCeiling` to calculate the new ceiling.

`getNextCollateralCeiling` takes into account `allowsIncrease` and `allowsDecrease` to determine whether it is allowed to computed a higher or a lower ceiling (compared to the current one).

Both `allowsIncrease` and `allowsDecrease` look at the current `redemptionRate` as well as at `blockIncreaseWhenRevalue` and `blockDecreaseWhenDevalue` to see whether they should allow or disallow an increase or decrease in the debt ceiling. `blockIncreaseWhenRevalue` and `blockDecreaseWhenDevalue` are by default set to zero so increases or decreases are always allowed, no matter what sign the redemption rate has.


# ESM Threshold Setter

Setter that periodically recomputes the threshold in the ESM

## 1. Summary <a href="#id-1-introduction-summary" id="id-1-introduction-summary"></a>

The `ESMThresholdSetter` is meant to recompute the `threshold` of protocol tokens needed to burn and trigger settlement through the `ESM`.

## 2. Contract Variables & Functions <a href="#id-2-contract-details" id="id-2-contract-details"></a>

**Variables**

* `authorizedAccounts[usr: address]` - addresses allowed to call `modifyParameters()` and `disableContract()`.
* `minAmountToBurn` - the minimum amount of protocol tokens that must be burned to trigger settlement using the ESM
* `supplyPercentageToBurn` - the percentage of outstanding protocol tokens to burn in order to trigger settlement using the ESM
* `protocolToken` - The address of the protocol token
* `esm` - the address of the ESM contract

**Functions**

* `modifyParameters` - modify contract parameters
* `recomputeThreshold` - calculate and set a new protocol token threshold in the ESM

**Modifiers**

* `isAuthorized` - checks whether an address is part of `authorizedAddresses` (and thus can call authed functions).

**Events**

* `AddAuthorization` - emitted when a new address becomes authorized. Contains:
  * `account` - the new authorized account
* `RemoveAuthorization` - emitted when an address is de-authorized. Contains:
  * `account` - the address that was de-authorized
* `ModifyParameters` - emitted when a parameter is updated.

## 3. Walkthrough <a href="#id-2-contract-details" id="id-2-contract-details"></a>

`recomputeThreshold` can be called any time in order to recompute the threshold inside the `esm`. The computed threshold must be higher than or equal to `minAmountToBurn` and it should be a specific percentage of the outstanding supply of protocol tokens.


# Governance Module

Tools for achieving consensus

**Relevant smart contracts:**

* [DSPause](https://github.com/reflexer-labs/ds-pause/blob/master/src/pause.sol)

## 1. Overview

The **Governance Module** is a set of smart contracts that governance can use to modify and upgrade GEB.

## 2. Component Descriptions

* `DSPause` - the pause contract enforces a delay between scheduling a transaction (coming from a multisig or a voting contract) and executing it.

## 3. Risks

### Governance Attack

Malicious governance may want to extract all the collateral from the system or generate a high amount of debt that is not backed by collateral. There are two possible solutions to this problem:

1. Eliminate governance over most core system components (especially the ones that handle collateral balances).
2. Use `DSPause` and add a delay to every schedule governance proposal.

### Smart Contract Bugs

* An attacker could bypass the `delay` or, if the authorization logic is flawed, propose and execute transactions that were not approved by token holders or by a multisig.

## 4. Governance Minimization

The governance module is meant to be controlled by the community (with the use of protocol tokens) or by the core team (in the initial stages post launch). Governance minimization is done at the protocol level by removing or bounding human control.


# DSPause

Delegatecall based proxy with an enforced delay

## 1. Summary <a href="#id-1-introduction-summary" id="id-1-introduction-summary"></a>

`DSPause` allows authorized users to schedule function calls that can only be executed once some predetermined waiting period has elapsed. The configurable `delay` attribute sets the minimum wait time between scheduling and executing a transaction.

## 2. Contract Variables & Functions <a href="#id-2-contract-details" id="id-2-contract-details"></a>

**Variables**

* `scheduledTransactions[hashedTx: bytes32]` - mapping with all scheduled transactions. A

  `hashedTx` consists of an address `usr` to `delegatecall` into, the expected codehash of `usr`, `calldata` to use and the first possible time of execution
* `proxy` - the proxy contract that will execute `scheduledTransactions` in an isolated environment. It can only be called by `DSPause`
* `delay` - the delay applied to every `scheduledTransaction`
* `currentlyScheduledTransactions` - the current number of concurrently scheduled transactions
* `maxScheduledTransactions` - the max number of transactions that can be scheduled at the same time
* `MAX_DELAY` - the maximum delay for a transaction from the moment it is scheduled
* `DS_PAUSE_TYPE` - the type of the `DSPause` contract (can be `BASIC` or `PROTEST`)

**Modifiers**

* `isDelayed` - checks if `msg.sender` is `DSPause` itself

**Functions**

* `setOwner(owner: address)` - set a new contract owner. Overriden from `DSAuth`
* `setAuthority(authority: DSAuthority)` - set an authority contract. Overriden from `DSAuth`
* `setDelay(delay: uint256)` - set a delay applied to all `scheduledTransactions`
* `scheduleTransaction(usr:address`, `codeHash: bytes32`, `parameters: bytes`, `earliestExecutionTime: uint)` - schedule a new transaction by providing `usr`, `usr`'s codehash, the calldata and the first possible time of execution
* `scheduleTransaction(usr: address`, `codeHash: bytes32`, `parameters: bytes`, `earliestExecutionTime: uint`, `description: string)` - schedule a new transaction and attach a description to it
* `attachTransactionDescription(usr: address`, `codeHash: bytes32`, `parameters: bytes`, `earliestExecutionTime: uint`, `description: string)` - attach a description for an already scheduled transaction
* `abandonTransaction(usr:address`, `codeHash: bytes32`, `parameters: bytes`, `earliestExecutionTime: uint)`- delete a scheduled transaction
* `executeTransaction(usr:address`, `codeHash: bytes32`, `parameters: bytes`, `earliestExecutionTime: uint)`- execute a scheduled transaction. Throws if the `scheduledTransaction`'s `delay` has not yet passed

**Events**

* `SetDelay` - emitted when the `delay` is changed. Contains:
  * `delay` - the new delay
* `ScheduleTransaction` - emitted when a new transaction is scheduled. Contains:
  * `sender` - the `msg.sender` that scheduled the transaction
  * `usr` - the target contract
  * `codeHash` - the code hash of `usr`
  * `parameters` - parameters for the transaction
  * `earliestExecutionTime` - earliest time when the transaction can be executed
* `AbandonTransaction` - emitted when governance abandons a previously scheduled transaction. Contains:
  * `sender` - the `msg.sender` that scheduled the transaction
  * `usr` - the target contract
  * `codeHash` - the code hash of `usr`
  * `parameters` - parameters for the transaction
  * `earliestExecutionTime` - earliest time when the transaction can be executed
* `ExecuteTransaction` - emitted when a transaction is executed. Contains:
  * `sender` - the `msg.sender` that scheduled the transaction
  * `usr` - the target contract
  * `codeHash` - the code hash of `usr`
  * `parameters` - parameters for the transaction
  * `earliestExecutionTime` - earliest time when the transaction can be executed
* `AttachTransactionDescription` - emitted when governance attaches a description to a scheduled transaction. Contains:
  * `sender` - the `msg.sender` that scheduled the transaction
  * `usr` - the target contract
  * `codeHash` - the code hash of `usr`
  * `parameters` - parameters for the transaction
  * `earliestExecutionTime` - earliest time when the transaction can be executed
  * `description` - the transaction description

## 3. Walkthrough <a href="#id-3-key-mechanisms-and-concepts" id="id-3-key-mechanisms-and-concepts"></a>

`DSPause` is designed to be used as a component in a governance system, to give affected parties time to respond to decisions. If those affected by governance decisions have e.g. exit or veto rights, then the pause can serve as an effective check on governance power.

### Scheduled Transactions

A `scheduledTransaction` describes a single `delegatecall` operation and a unix timestamp `earliestExecutionTime` before which it cannot be executed.

A `scheduledTransaction` consists of:

* `usr`: address to `delegatecall` into
* `codeHash`: the expected codehash of `usr`
* `parameters`: `calldata` to use
* `earliestExecutionTime`: first possible time of execution (as seconds since unix epoch)

Each scheduled tx has a unique id, defined as `keccack256(abi.encode(usr, codeHash, parameters, earliestExecutionTime))`

### Transaction Execution

In order to protect the internal storage of the pause from malicious writes during `scheduledTransaction` execution, we perform the actual `delegatecall` operation in a seperate contract with an isolated storage context (`DSPauseProxy`). Each pause has it's own individual `proxy`.

This means that `scheduledTransactions` are executed with the identity of the `proxy`, and when integrating the pause into some auth scheme, you probably want to trust the pause's `proxy` and not the pause itself.

## 4. Gotchas (Potential source of user error) <a href="#id-4-gotchas" id="id-4-gotchas"></a>

#### **Identity & Trust**

In order to protect the internal storage of the pause from malicious writes during proposal execution, we perform the `delegatecall` operation in a separate contract with an isolated storage context (DSPauseProxy), where each pause has its own individual proxy.

This means that proposals are executed with the identity of the `proxy`. Thus when integrating the pause into some auth scheme, you will want to trust the pause's proxy and not the pause itself.

## 5. Failure Modes (Bounds on Operating Conditions & External Risk Factors) <a href="#id-5-failure-modes" id="id-5-failure-modes"></a>

**A break of any of the following would be classified as a critical issue:**

**High level**

* There is no way to bypass the delay
* The code executed by the delegatecall cannot directly modify storage on the pause
* The pause will always retain ownership of it's proxy

**Administrative**

* authority, owner, and delay can only be changed if an authorized user schedules a proposal to do so

**Schedule**

* A proposal can only be executed if its eta is after block.timestamp + delay
* A proposal can only be scheduled by authorized users

**Execute**

* A proposal can only be executed if it has previously been scheduled
* A proposal can only be executed once it's eta has passed
* A proposal can only be executed if its tag matches extcodehash(usr)
* A proposal can only be executed once
* A proposal can be executed by anyone

**Abandon**

* A proposal can only be abandoned by authorized users

#### Other Failure Modes

`DSPause.delay` - when the pause delay is set to the maximum, governance can no longer modify the system.

`DSPause.delay` - when the pause delay is set to the minimum, it is easier to pass malicious governance actions.


# Shutdown Module

Winding down system operations

**Relevant smart contracts:**

* [GlobalSettlement](https://github.com/reflexer-labs/geb/blob/master/src/single/GlobalSettlement.sol)
* [ESM](https://github.com/reflexer-labs/esm/blob/master/src/ESM.sol)

## 1. Overview

The **Shutdown Module** is in charge with winding down the system and returning all collateral back to users in case of a serious threat, such as long-term market irrationality, a hack, or a security breach.

Settlement can be triggered by the `ESM` (Emergency Shutdown Module) where governance needs to deposit (and burn) a specific amount of protocol tokens **OR** if governance has direct access to `GlobalSettlement`, they can bypass the `ESM` and settle the system.

## 2. Component Descriptions

* `GlobalSettlement` - this contract shuts down GEB and ensures that both SAFE and system coin users receive the net value of assets they are entitled to. The value of collateral that coin holders can redeem will vary depending on the system surplus or deficit at the time of settlement. It is possible that coin holders will receive less or more than [`OracleRelayer.redemptionPrice`](https://docs.reflexer.finance/system-contracts/oracle-module/oracle-relayer) worth of collateral for one coin.
* `ESM` - this contract can trigger global settlement if enough tokens are deposited (and subsequently burned) in it.

## 3. Risks

### Misconfigurations <a href="#authorization-misconfigurations" id="authorization-misconfigurations"></a>

The `ESM` may be unable to trigger shutdown (even if sufficient protocol tokens have been committed to the contract) if `GlobalSettlement` did not authorize it.

### Settlement Edge Cases

#### Oracle Attack <a href="#critical-failure-modes" id="critical-failure-modes"></a>

Since `GlobalSettlement` reads collateral prices from `FSM`s it is susceptible to reading bad data in case the oracles get attacked. Governance is not advised to use settlement as a solution to oracle attacks because the prices get added in the system too quickly in order for shutdown to help.

#### Other Failure Modes <a href="#critical-failure-modes" id="critical-failure-modes"></a>

* If `GlobalSettlement.shutdownCooldown` is set too high, it can result in the shutdown not being able to proceed.
* If `GlobalSettlement.shutdownCooldown` is too low, it can result in `setOutstandingCoinSupply` being called before all auctions have finished, resulting in debt being calculated incorrectly and setting wrong collateral prices.
* When `GlobalSettlement.shutdownSystem` is called all system coin holders may be left holding an unstable asset. This could result in a market price crash across all collateral types due to liquidations and sell-offs.
* `SAFEEngine` / `AccountingEngine` / `LiquidationEngine` / `OracleRelayer` / `StabilityFeeTreasury` - if they are set to malicious contracts (inside `GlobalSettlement`) they may cause shutdown to fail.

## 4. Governance Minimization

`GlobalSettlement` is part of Level 2 Gov Minimization. `ESM` is part of Level 1 Gov Minimization.

{% hint style="info" %}
**The** `ESMThresholdSetter`&#x20;

Before removing control from the `ESM`, governance should deploy a contract called `ESMThresholdSetter` that automatically sets the `ESM.triggerThreshold` according to the current outstanding supply of protocol tokens.
{% endhint %}


# Global Settlement

Shutting down GEB and returning collateral back to users

## 1. Summary <a href="#id-1-introduction-summary" id="id-1-introduction-summary"></a>

The `GlobalSettlement` is meant to shut down the system and reimburse SAFE users as well as system coin holders with all the collateral that's locked inside.

## 2. Contract Variables & Functions

**Variables**

* `authorizedAccounts[usr: address]`, `addAuthorization`/`removeAuthorization`/`isAuthorized` - auth mechanisms
* `safeEngine` - address of the `SAFEEngine`
* `liquidationEngine` - address of the `LiquidationEngine`
* `accountingEngine` - address of the `AccountingEngine`
* `osm` - address of the `OracleRelayer`
* `coinSavingsAccount` - address of the `CoinSavingsAccount`
* `stabilityFeeTreasury` - address of the `StabilityFeeTreasury`
* `contractEnabled` - whether settlement has been triggered or not
* `shutdownTime` - unix timestamp of the moment when settlement was triggered
* `shutdownCooldown` - cooldown post shutdown during which no on-chain processing can be done
* `outstandingCoinSupply` - outstanding system coin supply after all deficit / surplus has been taken into account
* `finalCoinPerCollateralPrice[collateralType: bytes32]` - price per collateral type at time of settlement
* `collateralShortfall[collateralType: bytes32]` - shortfall per collateral type (taking into account under-collateralised SAFEs)
* `collateralTotalDebt[collateralType: bytes32]` - outstanding debt per collateral type
* `collateralCashPrice[collateralType: bytes32]`- amount of system coins to be paid for one unit of a specific collateral type
* `coinBag[usr: address]` - system coins ready to be swapped for collateral. Coins cannot be transferred out of a bag
* `coinsUsedToRedeem[usr: address]` - the amount of already swapped system coins for a specific address

**Modifiers**

* `isAuthorized` \*\*\*\* - checks whether an address is part of `authorizedAddresses` (and thus can call authed functions).

**Functions**

* `modifyParameters()` - update parameters such as the `safeEngine`, `shutdownCooldown` etc
* `shutdownSystem()` - start the settlement process. Usually called by `ESM`
* `freezeCollateralType(collateralType: bytes32)` - sets the final price of a collateral type
* `fastTrackAuction(collateralType: bytes32, auctionId: uint256)` - cancel / terminate a live auction
* `processSAFE(collateralType: bytes32, safe: address)` - cancel a SAFE's owed debt
* `freeCollateral(collateralType: bytes32)` - remove remaining collateral from a SAFE (can occur only after there's no debt in the SAFE)
* `setOutstandingCoinSupply()` - fix the outstanding supply of system coins
* `calculateCashPrice(collateralType: bytes32)` - calculates a price for each collateral type (system coins per unit of collateral type) taking into account system surplus / deficit
* `prepareCoinsForRedeeming(coinAmount: uint256)` - add system coins in a `coinBag` and prepare them to `redemmCollateral`
* `redeemCollateral(collateralType: bytes32, coinsAmount: uint)` - swap coins from a bag with a specific collateral type

## 3. Walkthrough

### Global Settlement Properties Compared to MCD <a href="#current-implementation-properties-of-shutdown" id="current-implementation-properties-of-shutdown"></a>

**SAFE Redemption Prioritization**

We chose to give priority to SAFE users (when it comes to redeeming collateral) meaning that all users with positions above the `liquidationCRatio` (collateralization ratio under which a SAFE gets liquidated) should be allowed to retrieve surplus collateral.

### Settlement Stages <a href="#the-shutdown-mechanism-9-crucial-steps" id="the-shutdown-mechanism-9-crucial-steps"></a>

#### 1. `shutdownSystem()` : <a href="#id-1-cage" id="id-1-cage"></a>

* Freezes user entry-points
* Cancels collateral/surplus auctions
* Starts the cooldown period

#### 2. `freezeCollateralType(collateralType)` : <a href="#id-2-cage-collateraltype" id="id-2-cage-collateraltype"></a>

This step sets the final price for each `collateralType`, reading off the price feed. We must process some system state before it is possible to calculate the final systemCoin / collateral price. In particular, we need to determine:

a. `collateralShortfall` (considers under-collateralised SAFEs)

b. `outstandingCoinSupply` (after including system system surplus / deficit)

We determine (a) by processing all under-collateralised SAFEs with `processSAFE`.

#### 3. `processSAFE(collateralType, safe)` <a href="#id-3-skim-collateraltype-urn" id="id-3-skim-collateraltype-urn"></a>

This step cancels SAFE debt. Any excess collateral remains and the backing collateral is taken.

We determine the `outstandingCoinSupply` by processing ongoing coin generating processes, i.e. auctions. We need to ensure that auctions will not generate any further coin income. In the two-way auction model this occurs when all auctions are in the reverse (`decreaseSoldAmount`) phase. There are two ways of ensuring this: waiting until `shutdownCooldown` seconds have passed since the initial settlement trigger or use `fastTrackAuction`.

#### 4. `shutdownCooldown` or `fastTrackAuction` <a href="#id-4-wait-or-skip" id="id-4-wait-or-skip"></a>

1\. `shutdownCooldown`: set the cooldown period to be at least as long as the longest auction duration (which needs to be determined by the shutdown administrator). This takes a fairly predictable time to occur but with altered auction dynamics due to the now varying price of the system coin.

2\. `fastTrackAuction`: cancel all ongoing auctions and seize the collateral. This allows for faster processing at the expense of more calls. This option allows coin holders to retrieve their collateral faster. Concretely, `fastTrackAuction(collateralType, auctionId)`:

* Cancels individual collateral auctions (using `terminateAuctionPrematurely`)
* Retrieves collateral to `GlobalSettlement` and (in case the system uses `EnglishCollateralHouse`s) returns coins (the bid) to the highest bidder

In the case of an `EnglishCollateralHouse`, `reduceAuctionedAmount` (reverse) phase auctions can continue normally.

Option (1) is sufficient for processing the system settlement but option (2) will speed up auctions. Both options are available in this implementation, with `fastTrackAuction` being enabled on a per-auction basis.

When a SAFE has been processed and has no debt remaining, the remaining collateral (SAFE surplus collateral above the liquidation ratio) can be removed.

#### 5. `freeCollateral(collateralType)` : <a href="#id-5-free-collateraltype" id="id-5-free-collateraltype"></a>

Removes collateral from the caller's SAFE.

After the processing period has elapsed, we enable calculation of the final price for each collateral type.

#### 6. `setOutstandingCoinSupply()` <a href="#id-6-thaw" id="id-6-thaw"></a>

This function is only callable after the processing time period has elapsed **and** if the `AccountingEngine` has no more surplus left. `AccountingEngine.transferPostSettlementSurplus` can be called in order to drain any remaining surplus and allow `setOutstandingCoinSupply` to be executed.

`setOutstandingCoinSupply` fixes the total outstanding supply of coins.

#### 7. `calculateCashPrice(collateralType)` <a href="#id-7-flow-collateraltype" id="id-7-flow-collateraltype"></a>

Calculates `collateralCashPrice` (amount of system coins per one unit of collateral). It adjusts the cash price in the case of system deficit / surplus.

At this point we have computed the final price for each collateral type and coin holders can now turn their coin into collateral. Each unit coin can claim a fixed basket of collateral.

Coin holders must first `prepareCoinsForRedeeming` into `coinBag`s. Once prepared, coins cannot be transferred out of the bag. More coins can be added to a bag later.

#### 8. `prepareCoinsForRedeeming(coinAmount)` <a href="#id-8-pack-wad" id="id-8-pack-wad"></a>

Put some coins into a `coinBag` in order to `redeemCollateral`. The bigger the bag, the more collateral the user can claim.

#### 9. `redeemCollateral(collateralType, collateralAmount)` <a href="#id-9-cash-collateraltype-wad" id="id-9-cash-collateraltype-wad"></a>

* Exchange some coins from a bag for a specific `collateralType`
* The amount of collateral available to redeem is limited by how big a bag is

## 4. Gotchas (Potential source of user error)

#### Keepers

We expect Keepers to buy up Coin from smallholders in order to claim collateral.

* This is because a majority of Coin holders are uncertain on how to do perform specific actions during the `GlobalSettlement` process. Due to this fact, we depend on third parties to buy up post-cage Coin to use for reclaiming large portions of Coin. Overall, there will be large amounts of Coin leftover in the system.

#### Note regarding `redeemCollateral`

At the end of the Global Settlement process, users will get a share of each collateral type. This will require them to call `redeemCollateral` through each collateralType in the system to completely cash out their Coin.

* **Example:** Users will need to call `redeemCollateral(collateralType, wad)` to redeem the proportional amount of the specified collateral that corresponds to the amount of Coin that was `prepareCoinsForRedeeming`’ ed, where the prepareCoinsForRedeeming function is used to aid with the redeeming of the different collaterals in different transactions. For example, let’s say you have 1000 Coin. You first prepareCoinsForRedeeming for the respective collateral types (`collateralTypes`), then for each `redeemCollateral` call, you will redeem what the 1000 Coin represents from the total Coin supply. In return, you will get the same proportion of that same collateral that was locked for all Coin holders. Therefore, the best approach a Coin holder can take is to `redeemCollateral` every collateral type (`collateralType`).
* An additional thing to note is that if any `collateralTypes` are undercollateralized, Coin holders will end up taking a bit of a cut as a result. This is because other `collateralTypes` will not be used to "cover for" an underwater collateral type.

#### DOS Attack

In order to prevent a DOS attack, whatever entity calls the `setOutstandingCoinSupply` function should ensure that `AccountingEngine.settleDebt()` is called within the same transaction.

* **Example:** An attacker can send small amounts of Coin in the `safeEngine` to the `accountingEngine`. This would prevent `setOutstandingCoinSupply` from being called and thus, GlobalSettlement from progressing. To prevent this, we would call `settleDebt` to clear out that excess Coin and proceed with `setOutstandingCoinSupply`.

#### Governance

It is important to set the correct `shutdownCooldown` period. If you set an incorrect `shutdownCooldown` period (if this is set early on) then auctions are later extended and this is not reset.

* It is important to note that the main problem to point out here is that if the `shutdownCooldown` allows `setOutstandingCoinSupply` to be called too early, all the `collateral` auctions may not have completed and the system may have an incorrect accounting of total `debt`.

#### **Other**

* The Cooldown period's purpose is so that auctions can be `fastTrackAuction`'d and `processSAFE`'d applies to all SAFES (not just the undercollateralized ones).
* Once the time period between global settlement and the cool-down period has passed, Coin holders are exposed to the ability to redeem their Coin for collateral.
  * Therefore the `shutdownCooldown` value should not be too large, so governance should advise for this at least.
* SAFE (processSAFE/GlobalSettlement) Keeper - is a tool to process underwater SAFEs if not all undercollateralized SAFES are accounted for. This Keeper could be used by GEB Stakeholders such as large Coin holders/custodians, FLX governors, Redemption keepers and more.

## 5. Failure Modes (Bounds on Operating Conditions & External Risk Factors)

Since `GlobalSettlement` will read the Collateral price from the `osm`, this can result in the collateral price being only as accurate as the last recorded price. If `osm` returns a bad price due to oracles getting hacked, the `GlobalSettlement` will be affected.

* **For example:** Calling Global Settlement because an oracle is getting attacked, we must make sure the oracles attack won’t affect the Global Settlement price because `GlobalSettlement` reads the price off of the `osm`.

If a bad price is queued up in the OSM, we need to make sure to fix the `finalCoinPerCollateralPrice` before the price is called on Global Settlement.

* **Example Scenario:** If a bad price goes through the `oracle`, it takes approximately 30 min for the OSM, and then the Global Settlement process takes over an hour to work. Therefore, by the time it triggers, you will have a bad price in the `osm` and this will cause the system to fail.
  * Saving this from happening depends on how quickly you react when it comes to an oracles attack as well as overall **governance** decisions.
  * **We do not believe Global Settlement is a viable solution to bad Oracles. They impact the system too quickly for Global Settlement to help.**

**An Oracle attack can be caused by two main events:**

* Low prices, which makes liquidations easy.
  * During Global Settlement, setting fake low prices would allow Coin holders to get too much collateral for their Coin, making this attack profitable.
* High prices, which helps with buying a lot of Coin.
  * When paired with a subsequent Global Settlement, this could be used to steal a lot / all of the collateral as that Coin would then be used to cash out.
    * **Example:** If a user is able to push up the price of a collateral type, it would allow them to mint a larger amount of Coin, resulting in a larger share of the Coin pool. Thus, they could claim a larger proportional share of the collateral whether it was of one type or a slice of all types. They could then readjust the manipulated prices before that collateral slice was fixed in the `GlobalSettlement`.

#### Critical Failure Modes

* `GlobalSettlement.withdraw` when set to maximum can result in it not being possible to call `setOutstandingCoinSupply` and therefore resulting in the GlobalSettlement not being able to proceed.
* `GlobalSettlement.withdraw`, when set to the minimum, can result in `setOutstandingCoinSupply` being called before all auctions have finished, resulting in debt being calculated incorrectly and ultimately setting a wrong collateral price.
* When `GlobalSettlement.shutdownSystem` is called, all Coin holders are left holding an unstable asset in place of their desired stable asset. This could result in a market price crash across all collateral due to liquidations & sell-offs. GlobalSettlement.oracleRelayer - when set to attacker (`address`: set to attacker-controlled address), can cause global settlement to fail. This is unfixable. For this scenario to occur, the malicious entity (governance or otherwise) would need to be `auth`'ed on the `GlobalSettlement`.


# ESM

Trigger global settlement by burning protocol tokens

## 1. Summary <a href="#id-1-introduction-summary" id="id-1-introduction-summary"></a>

The Emergency Shutdown Module (ESM) is a contract with the ability to settle a GEB. Settlement is triggered after at least `triggerThreshold` protocol tokens are deposited in the contract and subsequently burned.

## 2. Contract Variables & Functions

**Variables**

* `authorizedAccounts[usr: address]`, `addAuthorization`/`removeAuthorization`/`isAuthorized` - auth mechanisms
* `protocolToken` - address of the token that must be deposited in the `ESM` in order to settle the system
* `globalSettlement` - address of the global settlement contract
* `thresholdSetter` - address (different from `authorizedAccounts`) that is able to set the`triggerThreshold`
* `tokenBurner` - contract that will receive all deposited protocol tokens and will then burn them
* `triggerThreshold` - minimum amount of tokens that need to be deposited in order to shut down the system
* `settled` - flag that indicates whether global settlement has already been trigerred

**Modifiers**

* `isAuthorized` \*\*\*\* - checks whether an address is part of `authorizedAddresses` (and thus can call authed functions).

**Functions**

* `modifyParameters` - change the `triggerThreshold` as well as the `thresholdSetter`.
* `shutdown` - burns `triggerThreshold` protocol tokens and triggers settlement

## 3. Walkthrough <a href="#id-2-contract-details" id="id-2-contract-details"></a>

The `ESM`is meant to be used in order to prevent an attacker from exploiting a vulnerability in the system (e.g stealing all the collateral) or to mitigate malicious governance.

If governance wishes to trigger shutdown, they must burn at least`triggerThreshold` protocol tokens and then automatically trigger settlement. Both actions are executed using `shutdown()` which can be called by anyone. `shutdown()` calls `GlobalSettlement.shutdownSystem()` which in turn starts the settlement procedure.

**Note:** `triggerThreshold` can be changed using `modifyParameters` either by governance or by `thresholdSetter` which can be an autonomous smart contract. This ensures that the threshold is always set to a specific percentage of the outstanding supply of protocol tokens.

**The ESM is intended to be used in a few potential scenarios:**

* To mitigate malicious governance
* To prevent the exploitation of a critical bug (for example one that allows collateral to be stolen)

In the case of a malicious governance attack (if the system is overned), the users will have no expectation of recovering their funds (as that would require a malicious majority to pass the required vote), and their only option is to set up an alternative fork in which the majority's funds are slashed and their funds are restored.

In other cases, the remaining FLX holders may choose to refund the ESM joiners by minting new tokens.

**Note:** Governance can disarm the ESM by calling `disableContract()`.

## 4. Gotchas (Potential Source of User Error)

### Unrecoverable of Funds

It is important for users to keep in mind that joining FLX into the ESM is irreversible—they lose it forever, regardless of whether they successfully trigger Shutdown. While it is possible that the remaining FLX holders may vote to mint new tokens for those that lose them triggering the ESM, there is no guarantee of this. In ungoverned systems this might be impossible.

### Game Theory of Funding and Firing the ESM

An entity wishing to trigger the ESM but possessing insufficient FLX to do so independently must proceed with caution. The entity could simply send FLX to the ESM to signal its desire and hope others join in; this, however, is poor strategy. Governance, whether honest or malicious, will see this, and likely move to de-authorize the ESM before the tipping point can be reached. It is clear why malicious governance would do so, but honest governance might act in a similar fashion—e.g. to prevent the system from being shut down by trolls or simply to maintain a constant threshold for ESM activation. (The ESM threshold setter automates the threshold so it reflects a pre set percentage of the protocol token's supply) If governance succeeds in this, the entity has simply lost FLX without accomplishing anything.

If an entity with insufficient FLX wishes to trigger the ESM, it is better off first coordinating with others either off-chain or ideally via a trustless smart contract. If a smart contract is used, it would be best if it employed zero-knowledge cryptography and other privacy-preserving techniques (such as transaction relayers) to obscure information such as the current amount of FLX committed and the addresses of those in support.

If an entity thinks others will join in before governance can react (e.g. if the delay for governance actions is very long), it is still possible that directly sending insufficient FLX to the ESM may work, but it carries a high degree of risk. Governance could even collude with miners to prevent `shutdownSystem` calls, etc if they suspect an ESM triggering is being organized and wish to prevent it.

## 5. Failure Modes (Bounds on Operating Conditions & External Risk Factors)

### Authorization Misconfigurations

The ESM itself does not have an isolated failure mode, but if the other parts of the system do not have proper authorization configurations (e.g. the GlobalSettlement contract does not authorize the ESM to call `disableContract()`), then the ESM's `shutdown()` method may be unable to trigger the GlobalSettlement process even if sufficient FLX has been committed to the contract.


# DSProxy

Execute transactions with the use of a proxy

**Smart contract code:** [**DSProxy**](https://github.com/reflexer-labs/ds-proxy/blob/master/src/proxy.sol)

## 1. Summary <a href="#id-1-introduction-summary" id="id-1-introduction-summary"></a>

A user can execute functions through this proxy by passing in the bytecode for the target contract as well as the calldata for the function they want to call.

## 2. Contract Variables & Functions <a href="#id-2-contract-details" id="id-2-contract-details"></a>

**Variables**

* `cache` - address of contract that caches the bytecode of target contracts called by the proxy

**Functions**

* `execute` - execute a function in the context of the proxy
* `setCache` - set a new `cache`


# Proxy Registry

Tracker and builder of DSProxy contracts

**Smart contract code:** [**GebProxyRegistry**](https://github.com/reflexer-labs/geb-proxy-registry/blob/master/src/GebProxyRegistry.sol)

## 1. Summary <a href="#id-1-introduction-summary" id="id-1-introduction-summary"></a>

This is a registry of already created DSProxies.

## 2. Contract Variables & Functions <a href="#id-2-contract-details" id="id-2-contract-details"></a>

**Variables**

* `proxies` - mapping of already created proxies (for different addresses)
* `factory` - contract that creates DSProxies

**Functions**

* `build` - create a new DSProxy


# SAFE Manager

A central hub for all SAFEs

**Smart contract code:** [**GebSafeManager**](https://github.com/reflexer-labs/geb-safe-manager/blob/master/src/GebSafeManager.sol)

## 1. Summary <a href="#id-1-introduction-summary" id="id-1-introduction-summary"></a>

The SAFE Manager is an abstraction around the `SAFEEngine` that allows anyone to easily manage their GEB positions.

## 2. Contract Variables & Functions <a href="#id-2-contract-details" id="id-2-contract-details"></a>

**Variables**

* `safeEngine` - the address of the `SAFEEngine`
* `safei` - auto incrementing nonce
* `cdps[safeId: uint256]` - mapping between SAFE ids and SAFE
* `cdpList[safeId: uint256]` - double linked list indicating the previous and next SAFE ids of a provided SAFE&#x20;
* `ownsCDP[cdpId: uint256]` - indicates the owner of a SAFE
* `collateralTypes[cdpId: uint256]` - the collateral type backing the SAFE with id `safeId`
* `firstSAFEID[owner: address]` - the first `safeId` of an owner
* `lastSAFEID[owner: address]` - the last `safeId` or an owner
* `safeCount[owner: address]` - the amount of SAFEs and address has
* `safeCan[owner: address`, `safeId: uint256`, `allowedAddr: address]` - whether an address is allowed to interact with a SAFE
* `handlerCan[safeHandler: address`, `allowedAddr: address]` - whether an address is allowed to interact with a SAFE's handler

**Data Structures**

* `List` - a struct containing the previous and the next SAFE ids of a specific SAFE. Contains:
  * `prev` - the previous SAFE id
  * `next` - the next SAFE id

**Functions**

* `allowSAFE(safe: uint256`, `usr: address`, `ok: uint256)` - allow an address to interact with a SAFE with a specific id
* `allowHandler(usr: address`, `ok: uint256)` - allow an address to interact with a SAFE handler
* `openSAFE(collateralType: bytes32`, `usr: address)` - create a new SAFE id and handler
* `transferSAFEOwnership(safe: uint256`, `dst: address)` - transfer a SAFE to another address
* `modifySAFECollateralization(safe: uint256`, `deltaCollateral: int256`, `deltaDebt:` `int256)` - add/remove collateral to and from a SAFE or generate/repay debt
* `transferCollateral(safe: uint256`, `dst: address`, `wad: uint256)` - transfer collateral from a SAFE to another address
* `transferInternalCoins(safe: uint256`, `dst: address`, `rad: uint256)` - transfer `SAFEEngine.coinBalance` system coins between addresses
* `quitSystem(safe: uint256`, `dst: address)` - migrate the SAFE to a destination address
* `enterSystem(safe: address`, `src: uint256)` - import a SAFE to the handler owned by an address
* `moveSAFE(safeSrc: uint256`, `safeDst: uint256)` - move a position between SAFE handlers
* `protectSAFE(safe: uint256`, `liquidationEngine: address`, `saviour: address)` - choose a `SAFESaviour` for a SAFE

**Events**

* `AllowSAFE` - emitted when `allowSafe` is called. Contains:
  * `sender` - the `msg.sender`
  * `safe` - the SAFE id
  * `usr` - the address of the user that is allowed/forbidden from managing the SAFE
  * `ok` - whether the `usr` is allowed or not to manage the SAFE
* `AllowHandler` - emitted when `allowHandler` is called. Contains:
  * `sender` - the `msg.sender`
  * `usr` - the handler
  * `ok` - whether it is allowed or not
* `TransferSAFEOwnership` - emitted when `transferSAFEOwnership` is called. Contains:
  * `sender` - the `msg.sender`
  * `safe` - the SAFE id
  * `dst` - the new owner
* `OpenSAFE` - emitted when a new SAFE is created using `openSAFE`. Contains:
  * `sender` - the `msg.sender`
  * `own` - the SAFE owner
  * `safe` - SAFE id
* `ModifySAFECollateralization` - emitted when `modifySAFECollateralization` is called. Contains:&#x20;
  * `sender` - the `msg.sender`
  * `safe` - the SAFE id
  * `deltaCollateral` - the amount of collateral to add/remove
  * `deltaDebt` - the amount of debt to repay/withdraw
* `TransferCollateral` - emitted when `transferCollateral` is called. Contains:
  * `sender` - the `msg.sender`
  * `safe` - the SAFE id
  * `dst` - the destination SAFE id
  * `wad` - amount of collateral to transfer
* `TransferInternalCoins` - emitted when `transferInternalCoins` is called. Contains:
  * `sender` - the `msg.sender`
  * `safe` - the SAFE id
  * `dst` - destination for internal coins
  * `rad` - amount of internal coins to transfer
* `QuitSystem` - emitted when `quitSystem` is called. Contains:
  * `sender` - the `msg.sender`
  * `safe` - the SAFE id
  * `dst` - the destination handler for the SAFE
* `EnterSystem` - emitted when `enterSystem` is called. Contains:
  * `sender` - the `msg.sender`
  * `src` - the source handler for the SAFE
  * `safe` - the SAFE id
* `MoveSAFE` - emitted when `moveSAFE` is called. Contains:
  * `safe` - the SAFE id
  * `safeSrc` - the source ID that has the current handler controlling the SAFE
  * `safeDst` - the destination SAFE id that has the handler which will control the `safe` from now on
* `ProtectSAFE` - emitted when `protectSAFE` is called. Contains:
  * `sender` - the `msg.sender`
  * `safe` - the SAFE id
  * `liquidationEngine` - the `LiquidationEngine` where `saviour` is and that can liquidate `safe`
  * `saviour` - the saviour that will protect the SAFE

## 3. Risks

When `openSAFE` is executed, a new `safeHandler` is created and a `safeId` is assigned to it for a specific `owner`. If the user calls `CollateralJoin.join` to add collateral to the `safeHandler` immediately after the SAFE creation transaction is mined, there is a chance that a chain reorg occurs. This would result in the user losing the ownership of the `safeHandler` and therefore lose their collateral. Users can avoid this issue when using [proxy actions](https://github.com/reflexer-labs/geb-proxy-actions/blob/master/src/GebProxyActions.sol).


# Getting Started

Library to interact with the GEB smart contracts. Manage your safes, mint stablecoins, inspect the system state, and much more.

The library is written in Typescript with full typing support. It allows access to the low level API to directly interact with the contracts.

## Install

```
npm install geb.js
```

## Dependencies

At the moment, Geb.js requires to use [Ether.js](https://www.npmjs.com/package/ethers) V5. In the future we will support Web3.

```
npm install ethers
```

## Documentation

Full API documentation is available [here](https://docs.reflexer.finance/geb-js/gettingstarted).

## Examples

This is a complete example of how you can inspect a SAFE and also open a new one using your own proxy:

```typescript
import { ethers, utils as ethersUtils } from 'ethers'
import { Geb, utils } from 'geb.js'

// Setup Ether.js
const provider = new ethers.providers.JsonRpcProvider(
    'http://kovan.infura.io/<API KEY>'
)
const wallet = new ethers.Wallet('0xdefiisawesome...', provider)

// Create the main GEB object
const geb = new Geb('kovan', provider)

// Get a SAFE
const safe = await geb.getSafe(4)
console.log(`Safe id 4 has: ${utils.wadToFixed(safe.debt).toString()} worth of debt.`)
console.log(`It will get liquidated if ETH price falls below ${(await safe.liquidationPrice())?.toString()} USD.`)

// Open a new SAFE, lock ETH and draw system coins in a single transaction using a proxy
// Note: Before doing this you need to create your own proxy

// We first need to check that the system didn't reach the debt ceiling so that we can
// mint more system coins.
const globalDebt = await geb.contracts.safeEngine.globalDebt()
const debtCeiling = await geb.contracts.safeEngine.globalDebtCeiling()
const systemCoinsToDraw = ethersUtils.parseEther('15')
if(globalDebt.add(systemCoinsToDraw).gt(debtCeiling)) {
    throw new Error('Debt ceiling too low, not possible to draw this amount of system coins.')
}

// We're good to mint some system coins! 
const proxy = await geb.getProxyAction(wallet.address)
const tx = proxy.openLockETHAndGenerateDebt(
    ethersUtils.parseEther('1'), // Lock 1 Ether
    utils.ETH_A,                 // Of collateral type ETH_A
    systemCoinsToDraw            // And draw 15 system coins
)

tx.gasPrice = ethers.BigNumber.from('80').mul('1000000000') // Set the gas price to 80 Gwei
const pending = await wallet.sendTransaction(tx) // Send the transaction
console.log(`Transaction ${pending.hash} waiting to be mined...`)
await pending.wait() // Wait for it to be mined
console.log('Transaction mined, safe opened!')
```

## Additional examples

In the examples below we assume that variables are defined like in the complete example above.

1. [Deploy a new proxy](/geb-js/getting-started#deploy-a-new-proxy)
2. [Partial repay of safe debt](/geb-js/getting-started#partial-repay-of-safe-debt)
3. [Complete repay of safe debt](/geb-js/getting-started#complete-repay-of-safe-debt)
4. [Withdraw Ether collateral](/geb-js/getting-started#withdraw-ether-collateral)
5. [Make direct contract calls](/geb-js/getting-started#make-direct-contract-calls)
6. [Multicall](/geb-js/getting-started#Multicall)

### Deploy a new proxy

```typescript
const tx = geb.deployProxy()
await wallet.sendTransaction(tx)
```

### Partial repayment of safe debt

```typescript
const proxy = await geb.getProxyAction("0xdefidream...")

// You first need to approve your proxy to spend your system coins
let tx =  geb.contracts.coin.approve(proxy.proxyAddress, ethers.constants.MaxUint256)
await wallet.sendTransaction(tx)

// Repay 1 system coin worth of debt for SAFE #4
tx = proxy.repayDebt(4, ethersUtils.parseEther('1'))
await wallet.sendTransaction(tx)
```

### Complete repayment of safe debt

```typescript
const proxy = await geb.getProxyAction("0xdefidream...")

// You first need to approve your proxy to spend your system coins
let tx =  geb.contracts.coin.approve(proxy.proxyAddress, ethers.constants.MaxUint256)
await wallet.sendTransaction(tx)

// Repay all debt of SAFE #4
tx = proxy.repayAllDebt(4)
await wallet.sendTransaction(tx)
```

### Withdraw Ether collateral

```typescript
const proxy = await geb.getProxyAction("0xdefidream...")
// Unlock 1 ETH of collateral from SAFE #4 and transfer it to its owner 
const tx = proxy.freeETH(4, ethersUtils.parseEther('1'))
await wallet.sendTransaction(tx)
```

### Repay all debt and withdraw all collateral

```typescript
const proxy = await geb.getProxyAction("0xdefidream...")
const safe = await geb.getSafe(4)

// You first need to approve your proxy to spend your system coins
let tx =  geb.contracts.coin.approve(proxy.proxyAddress, ethers.constants.MaxUint256)
await wallet.sendTransaction(tx)

// Pay back everything and get your ETH back into your wallet
const tx = proxy.repayAllDebtAndFreeETH(4, safe.collateral)
await wallet.sendTransaction(tx)
```

### Make direct contract calls

Geb.js exposes all contract APIs of all core contracts in the `Geb.contracts` object. Solidity functions that are read-only (`view` or `pure`) return asynchronously the expected value from the chain. State changing functions will return a transaction object to passed to `ether.js` or `web3`.

```typescript
// Fetch some system parameters from their respective contracts
const surplusBuffer = await geb.contracts.accountingEngine.surplusBuffer()
const { stabilityFee } = await geb.contracts.taxCollector.collateralTypes(utils.ETH_A)

// Liquidate a Safe
const tx = geb.contracts.liquidationEngine.liquidateSAFE(utils.ETH_A,"0xdefidream...");
await wallet.sendTransaction(tx)
```

### Multicall

Useful to bundle read-only calls in a single RPC call:

```typescript
const [ globalDebt, collateralInfo ] = await geb.multiCall([
    geb.contracts.safeEngine.globalDebt(true), // !! Note the last parameter set to true.
    geb.contracts.safeEngine.collateralTypes(utils.ETH_A, true),
])
```


# Global Settlement Guide

The following are examples of how you can use geb.js to facilitate the Global Settlement process and redeem your collateral which is locked in your own Safes or directly exchange system coins with collateral.

## Example Flow for Global Settlement Using GEB.js

These scripts can help you go throught the steps described on the [Global Settlement](https://docs.reflexer.finance/system-contracts/shutdown-module/global-settlement#the-shutdown-mechanism-9-crucial-steps) page.&#x20;

We first need to setup `geb.js` and `ethers.js`:

```typescript
import { ethers } from 'ethers'
import { Geb, utils } from 'geb.js'

const provider = new ethers.providers.JsonRpcProvider(
    'http://kovan.infura.io/v3/<API KEY>'
)
const wallet = new ethers.Wallet('0xdefiisawesome...', provider)
const geb = new Geb('kovan', provider)
```

Before continuing, we need to make sure that Global Settlement was triggered by checking the shutdown timestamp:&#x20;

```typescript
const shutdownTime = await geb.contracts.globalSettlement.shutdownTime()
const hasGlobalSettlementStarted = shutdownTime.gt(0)
```

### Withdraw Excess Collateral

After settlement starts, each collateral needs to be frozen ([Step 2](https://docs.reflexer.finance/system-contracts/shutdown-module/global-settlement#2-cage-ilk)). This needs to be done only once for every collateral type.&#x20;

```typescript
const tx = geb.contracts.globalSettlement.freezeCollateralType(utils.ETH_A)
await wallet.sendTransaction(tx)
```

Since a SAFE is supposed to be over-collateralized, its owner can already withdraw excess collateral. The following script assumes that the SAFE is owned by a [proxy](https://github.com/reflexer-labs/ds-proxy/blob/master/src/proxy.sol) contract. It also uses the Global Settlement Proxy Actions to pack and atomically execute multiple transactions at once.

```typescript
const proxy = await geb.getProxyAction(wallet.address)
const wethJoinAddress = geb.contracts.joinETH_A.address
// Withdraw excess collateral from the Safe with ID #3
const tx = proxy.freeTokenCollateralGlobalSettlement(wethJoinAddress, 3)
await wallet.sendTransaction(tx)
```

This fulfills [step 3](https://docs.reflexer.finance/system-contracts/shutdown-module/global-settlement#3-skim-ilk-urn) and [step 5](https://docs.reflexer.finance/system-contracts/shutdown-module/global-settlement#5-free-ilk) from the Global Settlement process.

### Set the Final COL/COIN Exchange Rates&#x20;

This part of the process consists in determining an exchange rate between the system coins that are still in circulation and each individual collateral type accepted by the system. The system needs to account for all Safes (I), terminate all ongoing collateral auctions (II) and remove all system surplus (III).

This needs to be done only once for the whole system. These steps can be taken care of by the [settlement keeper](https://github.com/reflexer-labs/settlement-keeper) bot or by anyone who is willing to pay the gas costs associated with these transactions.

```typescript
// For (I) the function `processSAFE` needs to be called for all SAFEs,
// particularly for under-collateralized ones since their owners are not 
// incentivised to call it themselves
const safes = [] // Gather some Safe handlers 
safes.push((await geb.getSafe(2)).handler)
safes.push((await geb.getSafe(3)).handler)
safes.push((await geb.getSafe(4)).handler)

// Prepare the transactions
const txs = safes.map(handler => 
    geb.contracts.globalSettlement.processSAFE(utils.ETH_A, handler)
)

// Send all transactions
txs.map(tx => await wallet.sendTransaction(tx))

// For (II) we have 2 possibilities: wait for all auctions to finish
const cooldown = await geb.contracts.globalSettlement.shutdownCooldown()
const now = BigNumber.from(Date.now()).div(1000)
const isCooldownPassed = now.gt(shutdownTime.add(cooldown))

// Or prematurely terminate each auction
const auctionId = 6
const tx = geb.contracts.globalSettlement.fastTrackAuction(utils.ETH_A, auctionId)
await wallet.sendTransaction(tx)

// (III) We need to get rid of the system surplus
const accountingEngineAddress = geb.contracts.accountingEngine.address
const coin = await  geb.contracts.safeEngine.coinBalance(accountingEngineAddress)
const debt = await geb.contracts.safeEngine.debtBalance(accountingEngineAddress)
const amountToSettle = coin.gte(debt) ? debt : coin
const tx = geb.contracts.accountingEngine.settleDebt(amountToSettle)
await wallet.sendTransaction(tx)

// In case there is a bug in the system's accounting that 
// created more surplus than debt, there is a backup function called
// transferPostSettlementSurplus() which gets rid of that extra surplus
// and allows GlobalSettlement.setOutstandingCoinSupply() to execute successfuly
const tx = geb.contracts.accountingEngine.transferPostSettlementSurplus()
await wallet.sendTransaction(tx)
```

Finally, the cash price for each collateral can be set with the following steps:

```typescript
const tx = geb.contracts.globalSettlement.setOutstandingCoinSupply()
await wallet.sendTransaction(tx)

// To be called once for each collateral type
const tx = geb.contracts.globalSettlement.calculateCashPrice(utils.ETH_A)
await wallet.sendTransaction(tx)
```

### Redeem Collateral Against System Coins

At this stage, any system coin holder can exchange their coins against a fixed basket of collateral. This is a 2 step process that consists in locking and preparing system coins and then claiming a share of a specific collateral type.

```typescript
// Prepare the system coins
const systemCoinBalance = await geb.contracts.coin.balanceOf(wallet.address)
const tx = proxy.prepareCoinsForRedeemingGlobalSettlement(systemCoinBalance)
await wallet.sendTransaction(tx)

// Redeem any collateral type you want
const tx = proxy.redeemTokenCollateralGlobalSettlement(wethJoinAddress, utils.ETH_A, systemCoinBalance)
await wallet.sendTransaction(tx)
```


# API Reference

Detailed documentation of public classes of the geb.js library.

### Overview

![](/files/-MLIwGpICwkXh9nV-MjF)


# Geb

The main package used to interact with the GEB system. Includes [helper functions](/geb-js/api-reference/geb#deployproxy) for safe management and the [contract interface object](/geb-js/api-reference/geb#contracts) to directly call smart contracts.

## Constructors

\+ **new Geb**(`network`: GebDeployment, `provider`: GebProviderInterface | Provider): [*Geb*](/geb-js/api-reference/geb)

*Defined in* [*packages/geb/src/geb.ts:89*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/geb.ts#L89)

Constructor of the main Geb.js object.

**Parameters:**

| Name       | Type                             | Description                                                                         |
| ---------- | -------------------------------- | ----------------------------------------------------------------------------------- |
| `network`  | GebDeployment                    | Either `'kovan'`, `'mainnet'` or an actual list of contract addresses.              |
| `provider` | GebProviderInterface \| Provider | Either a Ethers.js provider or a Geb provider (Soon support for Web3 will be added) |

**Returns:** [*Geb*](/geb-js/api-reference/geb)

## Properties

### contracts

• **contracts**: *ContractApis*

*Defined in* [*packages/geb/src/geb.ts:87*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/geb.ts#L87)

Object containing all GEB core smart-contracts instances for direct level interactions. All of the following contracts object are one-to-one typed API to the underlying smart-contract. Read-only functions that do not change the blockchain state return a promise of the return data. State modifying function will return synchronously a pre-filled transaction request object:

```
{
  to: "0x123abc.."
  data: "0xabab234ab..."
}
```

This object follow the [TransactionRequest model of ethers.js](https://docs.ethers.io/v5/api/providers/types/#providers-TransactionRequest) (Also similar to the [model used by web.js](https://web3js.readthedocs.io/en/v1.3.0/web3-eth.html#id84)). The object can be completed with properties such as `from`, `gasPrice`, `gas` (gas limit, web3.js ony) or `gasLimit` (gas limit, ethers.js only). The object can then be passed to the `sendTransaction` of [ehters.js](https://docs.ethers.io/v5/api/signer/#Signer-sendTransaction) or [web3.js](https://web3js.readthedocs.io/en/v1.3.0/web3-eth.html#sendtransaction)

Example:

```typescript
 // Setup geb.js an ethers
 const provider = new ethers.providers.JsonRpcProvider('http://kovan.infura.io/<API KEY>')
 const wallet = new ethers.Wallet('<Private key>', provider)
 const geb = new Geb('kovan', provider)

 // Contract read function: Fetch the debt ceiling
 const debtCeiling = await geb.contracts.safeEngine.globalDebtCeiling()

 // State changing function: manualy liquidate a SAFE
 const tx = geb.contracts.liquidationEngine.liquidateSAFE(ETH_A, '0x1234abc...')
 await wallet.sendTransaction(tx) // Send the Ethereum transaction
```

Currently the following contracts are available:

* SAFEEngine
* AccountingEngine
* TaxCollector
* LiquidationEngine
* OracleRelayer
* GlobalSettlement
* DebtAuctionHouse
* PreSettlementSurplusAuctionHouse
* PostSettlementSurplusAuctionHouse
* SettlementSurplusAuctioneer
* GebSafeManager
* GetSafes
* BasicCollateralJoin
* CoinJoin
* Coin (System coin ERC20 contract)
* GebProxyRegistry
* FixedDiscountCollateralAuctionHouse
* Weth (ERC20)

For detailed information about the functions of each contract we recommend referring directly to the smart contract [code](https://github.com/reflexer-labs/geb) and [documentation](https://docs.reflexer.finance/).

## Methods

### deployProxy

▸ **deployProxy**(): *TransactionRequest*

*Defined in* [*packages/geb/src/geb.ts:133*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/geb.ts#L133)

Deploy a new proxy owned by the sender.

**Returns:** *TransactionRequest*

### getErc20Contract

▸ **getErc20Contract**(`tokenAddress`: string): *Erc20*

*Defined in* [*packages/geb/src/geb.ts:261*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/geb.ts#L261)

Returns an object that can be used to interact with a ERC20 token. Example:

```typescript
const USDCAddress = "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
const USDC = geb.getErc20Contract(USDCAddress)

// Get 0xdefiisawesome's balance
const balance = USDC.balanceOf("0xdefiisawesome..")

// Send 1 USDC to 0xdefiisawesome (USDC has 6 decimals)
const tx = USDC.transfer("0xdefiisawesome..", "1000000")
await wallet.sendTransaction(tx)
```

**Parameters:**

| Name           | Type   | Description            |
| -------------- | ------ | ---------------------- |
| `tokenAddress` | string | Token contract address |

**Returns:** *Erc20*

Erc20

### getGebContract

▸ **getGebContract**‹**T**›(`gebContractClass`: GebContractAPIConstructorInterface‹T›, `address`: string): *T*

*Defined in* [*packages/geb/src/geb.ts:387*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/geb.ts#L387)

Returns an instance of a specific geb contract given a Geb contract API class at a specified address

```typescript
import { contracts } from "geb.js"
const safeEngine = geb.getGebContract(contracts.SafeEngine, "0xabcd123..")
const globalDebt = safeEngine.globalDebt()
```

**Type parameters:**

▪ **T**: *BaseContractAPI*

**Parameters:**

| Name               | Type                                  | Description                            |
| ------------------ | ------------------------------------- | -------------------------------------- |
| `gebContractClass` | GebContractAPIConstructorInterface‹T› | Class from contracts or adminContracts |
| `address`          | string                                | Contract address of the instance       |

**Returns:** *T*

### getIncentiveCampaignContract

▸ **getIncentiveCampaignContract**(`campaignNumber`: number): *Promise‹StakingRewards‹››*

*Defined in* [*packages/geb/src/geb.ts:271*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/geb.ts#L271)

Help function to get the contract object of an incentive campaign given its number ID

**Parameters:**

| Name             | Type   | Description                    |
| ---------------- | ------ | ------------------------------ |
| `campaignNumber` | number | incremental ID of the campaign |

**Returns:** *Promise‹StakingRewards‹››*

StakingRewards

### getProxyAction

▸ **getProxyAction**(`ownerAddress`: string): *Promise‹*[*GebProxyActions*](/geb-js/api-reference/gebproxyactions)*‹››*

*Defined in* [*packages/geb/src/geb.ts:121*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/geb.ts#L121)

Given an address returns a GebProxyActions object to execute bundled operations. Important: This requires the address to have deployed a GEB proxy through the proxy registry contract. It will throw a `DOES_NOT_OWN_HAVE_PROXY` error if the address specified does not have a proxy. Use the [deployProxy](/geb-js/api-reference/geb#deployproxy) function to get a new proxy.

**Parameters:**

| Name           | Type   | Description                                                            |
| -------------- | ------ | ---------------------------------------------------------------------- |
| `ownerAddress` | string | Externally owned user account, Ethereum address that owns a GEB proxy. |

**Returns:** *Promise‹*[*GebProxyActions*](/geb-js/api-reference/gebproxyactions)*‹››*

### getSafe

▸ **getSafe**(`idOrHandler`: string | number, `collateralType?`: string): *Promise‹*[*Safe*](/geb-js/api-reference/safe)*›*

*Defined in* [*packages/geb/src/geb.ts:141*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/geb.ts#L141)

Get the SAFE object given a `safeManager` id or a `safeEngine` handler address.

**Parameters:**

| Name              | Type             | Description             |
| ----------------- | ---------------- | ----------------------- |
| `idOrHandler`     | string \| number | Safe Id or SAFE handler |
| `collateralType?` | string           | -                       |

**Returns:** *Promise‹*[*Safe*](/geb-js/api-reference/safe)*›*

### getSafeFromOwner

▸ **getSafeFromOwner**(`address`: string): *Promise‹*[*Safe*](/geb-js/api-reference/safe)*\[]›*

*Defined in* [*packages/geb/src/geb.ts:224*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/geb.ts#L224)

Fetch the list of safes owned by an address. This function will fetch safes owned directly through the safeManager and safes owned through the safe manager through a proxy. Safes owned directly by the address at the safeEngine level won't appear here.

Note that this function will make a lot of network calls and is therefore very slow. For front-ends we recommend using pre-indexed data such as the geb-subgraph.

**Parameters:**

| Name      | Type   | Description |
| --------- | ------ | ----------- |
| `address` | string |             |

**Returns:** *Promise‹*[*Safe*](/geb-js/api-reference/safe)*\[]›*

### multiCall

▸ **multiCall**‹**O1**, **O2**, **O3**›(`calls`: \[MulticallRequest‹O1›, MulticallRequest‹O2›, MulticallRequest‹O3›]): *Promise‹\[O1, O2, O3]›*

*Defined in* [*packages/geb/src/geb.ts:293*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/geb.ts#L293)

Bundles several read only GEB contract call into 1 RPC single request. Useful for front-ends or apps that need to fetch many parameters from the contracts but want to minimize the network request and the load on the underlying Ethereum node. The function takes as input an Array of GEB view contract calls. **IMPORTANT**: You have to set the `multicall` parameter of the contract function to `true`, it is the always the last parameter of the function. Multicall works for all contracts in the `Geb.contracts` and can be use with any contract that inherit the `BaseContractApi`. Note that it does not support non-view calls (Calls that require to pay gas and change the state of the blockchain).

Example:

```typescript
import { ethers } from "ethers"
import { Geb } from "geb.js"

const provider = new ethers.providers.JsonRpcProvider("http://kovan.infura.io/...")
const geb = new Geb("kovan", provider);

const [ globalDebt, collateralInfo ] = await geb.multiCall([
    geb.contracts.safeEngine.globalDebt(true), // !! Note the last parameter set to true.
    geb.contracts.safeEngine.collateralTypes(ETH_A, true),
])

console.log(`Current global debt: ${globalDebt.toString()}`)
console.log(`Current ETH_A debt: ${collateralInfo.debtAmount}`)
```

**Type parameters:**

▪ **O1**

▪ **O2**

▪ **O3**

**Parameters:**

| Name    | Type                                                                | Description                                                                                                                                                   |
| ------- | ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `calls` | \[MulticallRequest‹O1›, MulticallRequest‹O2›, MulticallRequest‹O3›] | Call a read only GEB contract function. The GEB contract object needs to be called with the parameter `multicall` set to `true` as seen in the example above. |

**Returns:** *Promise‹\[O1, O2, O3]›*

Promise Array with the result from their respective requests.

### `Static` getGebContract

▸ **getGebContract**‹**T**›(`gebContractClass`: GebContractAPIConstructorInterface‹T›, `address`: string, `provider`: GebProviderInterface | Provider): *T*

*Defined in* [*packages/geb/src/geb.ts:355*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/geb.ts#L355)

Returns an instance of a specific geb contract given Geb contract API class constructor at a specified address

**Type parameters:**

▪ **T**: *BaseContractAPI*

**Parameters:**

| Name               | Type                                  | Description                                   |
| ------------------ | ------------------------------------- | --------------------------------------------- |
| `gebContractClass` | GebContractAPIConstructorInterface‹T› | Class from contracts or adminContracts        |
| `address`          | string                                | Contract address of the instance              |
| `provider`         | GebProviderInterface \| Provider      | Either a Ethers.js provider or a Geb provider |

**Returns:** *T*


# Safe

This object represents a GEB safe. It has the entire SAFE state and provides helper functions to calculate its liquidation price, collateralization ratio etc.

## Constructors

\+ **new Safe**(`contracts`: ContractApis, `handler`: string, `debt`: BigNumber, `collateral`: BigNumber, `collateralType`: string, `isManaged`: boolean, `safeId?`: number): [*Safe*](/geb-js/api-reference/safe)

*Defined in* [*packages/geb/src/schema/safe.ts:8*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/schema/safe.ts#L8)

**Parameters:**

| Name             | Type         |
| ---------------- | ------------ |
| `contracts`      | ContractApis |
| `handler`        | string       |
| `debt`           | BigNumber    |
| `collateral`     | BigNumber    |
| `collateralType` | string       |
| `isManaged`      | boolean      |
| `safeId?`        | number       |

**Returns:** [*Safe*](/geb-js/api-reference/safe)

## Properties

### collateral

• **collateral**: *BigNumber*

*Defined in* [*packages/geb/src/schema/safe.ts:23*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/schema/safe.ts#L23)

Amount of collateral locked in the SAFE (WAD)

### collateralType

• **collateralType**: *string*

*Defined in* [*packages/geb/src/schema/safe.ts:27*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/schema/safe.ts#L27)

SAFE collateral type

### debt

• **debt**: *BigNumber*

*Defined in* [*packages/geb/src/schema/safe.ts:19*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/schema/safe.ts#L19)

Amount of debt generated by the SAFE (WAD)

### handler

• **handler**: *string*

*Defined in* [*packages/geb/src/schema/safe.ts:15*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/schema/safe.ts#L15)

SAFE handler in the SAFE Engine

### isManaged

• **isManaged**: *boolean*

*Defined in* [*packages/geb/src/schema/safe.ts:31*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/schema/safe.ts#L31)

Whether the safe was opened using a SAFE manager

### `Optional` safeId

• **safeId**? : *number*

*Defined in* [*packages/geb/src/schema/safe.ts:35*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/schema/safe.ts#L35)

Safe incremental ID, only for managed safes

## Methods

### getCRatio

▸ **getCRatio**(): *Promise‹FixedNumber | null›*

*Defined in* [*packages/geb/src/schema/safe.ts:42*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/schema/safe.ts#L42)

Ratio used to calculate the amount of debt that can be drawn. Returns null is ratio is +Infinity. !! Uses unsafe division that can lead to precision loss.

**Returns:** *Promise‹FixedNumber | null›*

Promise CRatio

### liquidationPrice

▸ **liquidationPrice**(): *Promise‹FixedNumber | null›*

*Defined in* [*packages/geb/src/schema/safe.ts:70*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/schema/safe.ts#L70)

Price at which the SAFE will get liquidated.

**Returns:** *Promise‹FixedNumber | null›*

&#x20;Liquidation price


# Proxy Actions

Convenience class to call functions from [GebProxyActions](https://github.com/reflexer-labs/geb-proxy-actions/blob/master/src/GebProxyActions.sol) through a proxy contract registered in the [GebProxyRegistry](https://github.com/reflexer-labs/geb-proxy-registry/blob/master/src/GebProxyRegistry.sol). These actions bundle multiple actions in one (e.g: open a safe + lock some ETH + draw some system coins).

## Constructors

\+ **new GebProxyActions**(`proxyAddress`: string, `network`: GebDeployment, `chainProvider`: GebProviderInterface): [*GebProxyActions*](/geb-js/api-reference/gebproxyactions)

*Defined in* [*packages/geb/src/proxy-action.ts:57*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L57)

**Parameters:**

| Name            | Type                 |
| --------------- | -------------------- |
| `proxyAddress`  | string               |
| `network`       | GebDeployment        |
| `chainProvider` | GebProviderInterface |

**Returns:** [*GebProxyActions*](/geb-js/api-reference/gebproxyactions)

## Properties

### proxy

• **proxy**: *DsProxy*

*Defined in* [*packages/geb/src/proxy-action.ts:28*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L28)

Underlying proxy object. Can be used to make custom calls to the proxy using the `proxy.execute()` function.

### proxyActionCoreAddress

• **proxyActionCoreAddress**: *string*

*Defined in* [*packages/geb/src/proxy-action.ts:33*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L33)

Address of the base proxy action contract.

### proxyActionGlobalSettlementAddress

• **proxyActionGlobalSettlementAddress**: *string*

*Defined in* [*packages/geb/src/proxy-action.ts:38*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L38)

Address of the proxy action contract for global settlement.

### proxyActionIncentiveAddress

• **proxyActionIncentiveAddress**: *string*

*Defined in* [*packages/geb/src/proxy-action.ts:43*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L43)

Address of the proxy action contract for Uniswap LP share staking.

### proxyActionLeverageAddress

• **proxyActionLeverageAddress**: *string*

*Defined in* [*packages/geb/src/proxy-action.ts:48*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L48)

Address of the proxy action contract used for leverage with flash loans.

### proxyAddress

• **proxyAddress**: *string*

*Defined in* [*packages/geb/src/proxy-action.ts:62*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L62)

Address of the underlying proxy.

## Methods

### allowSAFE

▸ **allowSAFE**(`safe`: BigNumberish, `usr`: string, `ok`: BigNumberish): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:115*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L115)

**Parameters:**

| Name   | Type         |
| ------ | ------------ |
| `safe` | BigNumberish |
| `usr`  | string       |
| `ok`   | BigNumberish |

**Returns:** *TransactionRequest*

### approveSAFEModification

▸ **approveSAFEModification**(`obj`: string, `usr`: string): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:130*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L130)

**Parameters:**

| Name  | Type   |
| ----- | ------ |
| `obj` | string |
| `usr` | string |

**Returns:** *TransactionRequest*

### coinJoin\_join

▸ **coinJoin\_join**(`apt`: string, `safeHandler`: string, `wad`: BigNumberish): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:136*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L136)

**Parameters:**

| Name          | Type         |
| ------------- | ------------ |
| `apt`         | string       |
| `safeHandler` | string       |
| `wad`         | BigNumberish |

**Returns:** *TransactionRequest*

### denySAFEModification

▸ **denySAFEModification**(`obj`: string, `usr`: string): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:146*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L146)

**Parameters:**

| Name  | Type   |
| ----- | ------ |
| `obj` | string |
| `usr` | string |

**Returns:** *TransactionRequest*

### enterSystem

▸ **enterSystem**(`src`: string, `safe`: BigNumberish): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:152*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L152)

**Parameters:**

| Name   | Type         |
| ------ | ------------ |
| `src`  | string       |
| `safe` | BigNumberish |

**Returns:** *TransactionRequest*

### exitETH

▸ **exitETH**(`safe`: BigNumberish, `wad`: BigNumberish): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:162*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L162)

**Parameters:**

| Name   | Type         |
| ------ | ------------ |
| `safe` | BigNumberish |
| `wad`  | BigNumberish |

**Returns:** *TransactionRequest*

### exitTokenCollateral

▸ **exitTokenCollateral**(`collateralJoin`: string, `safe`: BigNumberish, `amt`: BigNumberish): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:173*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L173)

**Parameters:**

| Name             | Type         |
| ---------------- | ------------ |
| `collateralJoin` | string       |
| `safe`           | BigNumberish |
| `amt`            | BigNumberish |

**Returns:** *TransactionRequest*

### flashDeleverage

▸ **flashDeleverage**(`uniswapV2Pair`: string, `callbackProxy`: string, `collateralType`: BytesLike, `safe`: BigNumberish): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:815*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L815)

**Parameters:**

| Name             | Type         |
| ---------------- | ------------ |
| `uniswapV2Pair`  | string       |
| `callbackProxy`  | string       |
| `collateralType` | BytesLike    |
| `safe`           | BigNumberish |

**Returns:** *TransactionRequest*

### flashDeleverageFreeETH

▸ **flashDeleverageFreeETH**(`uniswapV2Pair`: string, `callbackProxy`: string, `collateralType`: BytesLike, `safe`: BigNumberish, `amountToFree`: BigNumberish): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:836*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L836)

**Parameters:**

| Name             | Type         |
| ---------------- | ------------ |
| `uniswapV2Pair`  | string       |
| `callbackProxy`  | string       |
| `collateralType` | BytesLike    |
| `safe`           | BigNumberish |
| `amountToFree`   | BigNumberish |

**Returns:** *TransactionRequest*

### flashLeverage

▸ **flashLeverage**(`uniswapV2Pair`: string, `callbackProxy`: string, `collateralType`: BytesLike, `safe`: BigNumberish, `leverage`: BigNumberish): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:859*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L859)

**Parameters:**

| Name             | Type         |
| ---------------- | ------------ |
| `uniswapV2Pair`  | string       |
| `callbackProxy`  | string       |
| `collateralType` | BytesLike    |
| `safe`           | BigNumberish |
| `leverage`       | BigNumberish |

**Returns:** *TransactionRequest*

### freeETH

▸ **freeETH**(`safe`: BigNumberish, `wad`: BigNumberish): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:188*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L188)

**Parameters:**

| Name   | Type         |
| ------ | ------------ |
| `safe` | BigNumberish |
| `wad`  | BigNumberish |

**Returns:** *TransactionRequest*

### freeTokenCollateral

▸ **freeTokenCollateral**(`collateralJoin`: string, `safe`: BigNumberish, `amt`: BigNumberish): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:199*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L199)

**Parameters:**

| Name             | Type         |
| ---------------- | ------------ |
| `collateralJoin` | string       |
| `safe`           | BigNumberish |
| `amt`            | BigNumberish |

**Returns:** *TransactionRequest*

### freeTokenCollateralGlobalSettlement

▸ **freeTokenCollateralGlobalSettlement**(`collateralJoin`: string, `safe`: BigNumberish): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:765*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L765)

**Parameters:**

| Name             | Type         |
| ---------------- | ------------ |
| `collateralJoin` | string       |
| `safe`           | BigNumberish |

**Returns:** *TransactionRequest*

### generateDebt

▸ **generateDebt**(`safe`: BigNumberish, `wad`: BigNumberish): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:214*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L214)

**Parameters:**

| Name   | Type         |
| ------ | ------------ |
| `safe` | BigNumberish |
| `wad`  | BigNumberish |

**Returns:** *TransactionRequest*

### generateDebtAndProtectSAFE

▸ **generateDebtAndProtectSAFE**(`safe`: BigNumberish, `wad`: BigNumberish, `saviour`: string): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:226*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L226)

**Parameters:**

| Name      | Type         |
| --------- | ------------ |
| `safe`    | BigNumberish |
| `wad`     | BigNumberish |
| `saviour` | string       |

**Returns:** *TransactionRequest*

### lockETH

▸ **lockETH**(`ethValue`: BigNumberish, `safe`: BigNumberish): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:244*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L244)

**Parameters:**

| Name       | Type         |
| ---------- | ------------ |
| `ethValue` | BigNumberish |
| `safe`     | BigNumberish |

**Returns:** *TransactionRequest*

### lockETHAndGenerateDebt

▸ **lockETHAndGenerateDebt**(`ethValue`: BigNumberish, `safe`: BigNumberish, `deltaWad`: BigNumberish): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:255*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L255)

**Parameters:**

| Name       | Type         |
| ---------- | ------------ |
| `ethValue` | BigNumberish |
| `safe`     | BigNumberish |
| `deltaWad` | BigNumberish |

**Returns:** *TransactionRequest*

### lockETHLeverage

▸ **lockETHLeverage**(`ethValue`: BigNumberish, `uniswapV2Pair`: string, `callbackProxy`: string, `collateralType`: BytesLike, `safe`: BigNumberish, `leverage`: BigNumberish): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:882*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L882)

**Parameters:**

| Name             | Type         |
| ---------------- | ------------ |
| `ethValue`       | BigNumberish |
| `uniswapV2Pair`  | string       |
| `callbackProxy`  | string       |
| `collateralType` | BytesLike    |
| `safe`           | BigNumberish |
| `leverage`       | BigNumberish |

**Returns:** *TransactionRequest*

### lockTokenCollateral

▸ **lockTokenCollateral**(`collateralJoin`: string, `safe`: BigNumberish, `amt`: BigNumberish, `transferFrom`: boolean): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:273*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L273)

**Parameters:**

| Name             | Type         |
| ---------------- | ------------ |
| `collateralJoin` | string       |
| `safe`           | BigNumberish |
| `amt`            | BigNumberish |
| `transferFrom`   | boolean      |

**Returns:** *TransactionRequest*

### lockTokenCollateralAndGenerateDebt

▸ **lockTokenCollateralAndGenerateDebt**(`collateralJoin`: string, `safe`: BigNumberish, `collateralAmount`: BigNumberish, `deltaWad`: BigNumberish, `transferFrom`: boolean): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:290*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L290)

**Parameters:**

| Name               | Type         |
| ------------------ | ------------ |
| `collateralJoin`   | string       |
| `safe`             | BigNumberish |
| `collateralAmount` | BigNumberish |
| `deltaWad`         | BigNumberish |
| `transferFrom`     | boolean      |

**Returns:** *TransactionRequest*

### lockTokenCollateralGenerateDebtAndProtectSAFE

▸ **lockTokenCollateralGenerateDebtAndProtectSAFE**(`collateralJoin`: string, `safe`: BigNumberish, `collateralAmount`: BigNumberish, `deltaWad`: BigNumberish, `transferFrom`: boolean, `saviour`: string): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:311*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L311)

**Parameters:**

| Name               | Type         |
| ------------------ | ------------ |
| `collateralJoin`   | string       |
| `safe`             | BigNumberish |
| `collateralAmount` | BigNumberish |
| `deltaWad`         | BigNumberish |
| `transferFrom`     | boolean      |
| `saviour`          | string       |

**Returns:** *TransactionRequest*

### makeCollateralBag

▸ **makeCollateralBag**(`collateralJoin`: string): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:335*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L335)

**Parameters:**

| Name             | Type   |
| ---------------- | ------ |
| `collateralJoin` | string |

**Returns:** *TransactionRequest*

### modifySAFECollateralization

▸ **modifySAFECollateralization**(`safe`: BigNumberish, `deltaCollateral`: BigNumberish, `deltaDebt`: BigNumberish): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:341*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L341)

**Parameters:**

| Name              | Type         |
| ----------------- | ------------ |
| `safe`            | BigNumberish |
| `deltaCollateral` | BigNumberish |
| `deltaDebt`       | BigNumberish |

**Returns:** *TransactionRequest*

### moveSAFE

▸ **moveSAFE**(`safeSrc`: BigNumberish, `safeDst`: BigNumberish): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:356*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L356)

**Parameters:**

| Name      | Type         |
| --------- | ------------ |
| `safeSrc` | BigNumberish |
| `safeDst` | BigNumberish |

**Returns:** *TransactionRequest*

### openLockETHAndGenerateDebt

▸ **openLockETHAndGenerateDebt**(`ethValue`: BigNumberish, `collateralType`: BytesLike, `deltaWad`: BigNumberish): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:366*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L366)

**Parameters:**

| Name             | Type         |
| ---------------- | ------------ |
| `ethValue`       | BigNumberish |
| `collateralType` | BytesLike    |
| `deltaWad`       | BigNumberish |

**Returns:** *TransactionRequest*

### openLockETHGenerateDebtAndProtectSAFE

▸ **openLockETHGenerateDebtAndProtectSAFE**(`ethValue`: BigNumberish, `collateralType`: BytesLike, `deltaWad`: BigNumberish, `saviour`: string): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:384*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L384)

**Parameters:**

| Name             | Type         |
| ---------------- | ------------ |
| `ethValue`       | BigNumberish |
| `collateralType` | BytesLike    |
| `deltaWad`       | BigNumberish |
| `saviour`        | string       |

**Returns:** *TransactionRequest*

### openLockETHLeverage

▸ **openLockETHLeverage**(`ethValue`: BigNumberish, `uniswapV2Pair`: string, `callbackProxy`: string, `collateralType`: BytesLike, `leverage`: BigNumberish): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:907*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L907)

**Parameters:**

| Name             | Type         |
| ---------------- | ------------ |
| `ethValue`       | BigNumberish |
| `uniswapV2Pair`  | string       |
| `callbackProxy`  | string       |
| `collateralType` | BytesLike    |
| `leverage`       | BigNumberish |

**Returns:** *TransactionRequest*

### openLockGNTAndGenerateDebt

▸ **openLockGNTAndGenerateDebt**(`gntJoin`: string, `collateralType`: BytesLike, `collateralAmount`: BigNumberish, `deltaWad`: BigNumberish): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:405*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L405)

**Parameters:**

| Name               | Type         |
| ------------------ | ------------ |
| `gntJoin`          | string       |
| `collateralType`   | BytesLike    |
| `collateralAmount` | BigNumberish |
| `deltaWad`         | BigNumberish |

**Returns:** *TransactionRequest*

### openLockGNTGenerateDebtAndProtectSAFE

▸ **openLockGNTGenerateDebtAndProtectSAFE**(`gntJoin`: string, `collateralType`: BytesLike, `collateralAmount`: BigNumberish, `deltaWad`: BigNumberish, `saviour`: string): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:424*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L424)

**Parameters:**

| Name               | Type         |
| ------------------ | ------------ |
| `gntJoin`          | string       |
| `collateralType`   | BytesLike    |
| `collateralAmount` | BigNumberish |
| `deltaWad`         | BigNumberish |
| `saviour`          | string       |

**Returns:** *TransactionRequest*

### openLockTokenCollateralAndGenerateDebt

▸ **openLockTokenCollateralAndGenerateDebt**(`collateralJoin`: string, `collateralType`: BytesLike, `collateralAmount`: BigNumberish, `deltaWad`: BigNumberish, `transferFrom`: boolean): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:446*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L446)

**Parameters:**

| Name               | Type         |
| ------------------ | ------------ |
| `collateralJoin`   | string       |
| `collateralType`   | BytesLike    |
| `collateralAmount` | BigNumberish |
| `deltaWad`         | BigNumberish |
| `transferFrom`     | boolean      |

**Returns:** *TransactionRequest*

### openLockTokenCollateralGenerateDebtAndProtectSAFE

▸ **openLockTokenCollateralGenerateDebtAndProtectSAFE**(`collateralJoin`: string, `collateralType`: BytesLike, `collateralAmount`: BigNumberish, `deltaWad`: BigNumberish, `transferFrom`: boolean, `saviour`: string): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:467*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L467)

**Parameters:**

| Name               | Type         |
| ------------------ | ------------ |
| `collateralJoin`   | string       |
| `collateralType`   | BytesLike    |
| `collateralAmount` | BigNumberish |
| `deltaWad`         | BigNumberish |
| `transferFrom`     | boolean      |
| `saviour`          | string       |

**Returns:** *TransactionRequest*

### openSAFE

▸ **openSAFE**(`collateralType`: BytesLike, `usr`: string): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:491*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L491)

**Parameters:**

| Name             | Type      |
| ---------------- | --------- |
| `collateralType` | BytesLike |
| `usr`            | string    |

**Returns:** *TransactionRequest*

### prepareCoinsForRedeemingGlobalSettlement

▸ **prepareCoinsForRedeemingGlobalSettlement**(`wad`: BigNumberish): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:753*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L753)

**Parameters:**

| Name  | Type         |
| ----- | ------------ |
| `wad` | BigNumberish |

**Returns:** *TransactionRequest*

### protectSAFE

▸ **protectSAFE**(`safe`: BigNumberish, `saviour`: string): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:501*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L501)

**Parameters:**

| Name      | Type         |
| --------- | ------------ |
| `safe`    | BigNumberish |
| `saviour` | string       |

**Returns:** *TransactionRequest*

### quitSystem

▸ **quitSystem**(`safe`: BigNumberish, `dst`: string): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:512*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L512)

**Parameters:**

| Name   | Type         |
| ------ | ------------ |
| `safe` | BigNumberish |
| `dst`  | string       |

**Returns:** *TransactionRequest*

### redeemETHGlobalSettlement

▸ **redeemETHGlobalSettlement**(`ethJoin`: string, `collateralType`: BytesLike, `wad`: BigNumberish): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:779*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L779)

**Parameters:**

| Name             | Type         |
| ---------------- | ------------ |
| `ethJoin`        | string       |
| `collateralType` | BytesLike    |
| `wad`            | BigNumberish |

**Returns:** *TransactionRequest*

### redeemTokenCollateralGlobalSettlement

▸ **redeemTokenCollateralGlobalSettlement**(`collateralJoin`: string, `collateralType`: BytesLike, `wad`: BigNumberish): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:794*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L794)

**Parameters:**

| Name             | Type         |
| ---------------- | ------------ |
| `collateralJoin` | string       |
| `collateralType` | BytesLike    |
| `wad`            | BigNumberish |

**Returns:** *TransactionRequest*

### repayAllDebt

▸ **repayAllDebt**(`safe`: BigNumberish): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:522*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L522)

**Parameters:**

| Name   | Type         |
| ------ | ------------ |
| `safe` | BigNumberish |

**Returns:** *TransactionRequest*

### repayAllDebtAndFreeETH

▸ **repayAllDebtAndFreeETH**(`safe`: BigNumberish, `collateralWad`: BigNumberish): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:532*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L532)

**Parameters:**

| Name            | Type         |
| --------------- | ------------ |
| `safe`          | BigNumberish |
| `collateralWad` | BigNumberish |

**Returns:** *TransactionRequest*

### repayAllDebtAndFreeTokenCollateral

▸ **repayAllDebtAndFreeTokenCollateral**(`collateralJoin`: string, `safe`: BigNumberish, `collateralAmount`: BigNumberish): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:547*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L547)

**Parameters:**

| Name               | Type         |
| ------------------ | ------------ |
| `collateralJoin`   | string       |
| `safe`             | BigNumberish |
| `collateralAmount` | BigNumberish |

**Returns:** *TransactionRequest*

### repayDebt

▸ **repayDebt**(`safe`: BigNumberish, `wad`: BigNumberish): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:563*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L563)

**Parameters:**

| Name   | Type         |
| ------ | ------------ |
| `safe` | BigNumberish |
| `wad`  | BigNumberish |

**Returns:** *TransactionRequest*

### repayDebtAndFreeETH

▸ **repayDebtAndFreeETH**(`safe`: BigNumberish, `collateralWad`: BigNumberish, `deltaWad`: BigNumberish): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:574*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L574)

**Parameters:**

| Name            | Type         |
| --------------- | ------------ |
| `safe`          | BigNumberish |
| `collateralWad` | BigNumberish |
| `deltaWad`      | BigNumberish |

**Returns:** *TransactionRequest*

### repayDebtAndFreeTokenCollateral

▸ **repayDebtAndFreeTokenCollateral**(`collateralJoin`: string, `safe`: BigNumberish, `collateralAmount`: BigNumberish, `deltaWad`: BigNumberish): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:591*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L591)

**Parameters:**

| Name               | Type         |
| ------------------ | ------------ |
| `collateralJoin`   | string       |
| `safe`             | BigNumberish |
| `collateralAmount` | BigNumberish |
| `deltaWad`         | BigNumberish |

**Returns:** *TransactionRequest*

### safeLockETH

▸ **safeLockETH**(`ethValue`: BigNumberish, `safe`: BigNumberish, `owner`: string): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:609*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L609)

**Parameters:**

| Name       | Type         |
| ---------- | ------------ |
| `ethValue` | BigNumberish |
| `safe`     | BigNumberish |
| `owner`    | string       |

**Returns:** *TransactionRequest*

### safeLockTokenCollateral

▸ **safeLockTokenCollateral**(`collateralJoin`: string, `safe`: BigNumberish, `amt`: BigNumberish, `transferFrom`: boolean, `owner`: string): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:625*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L625)

**Parameters:**

| Name             | Type         |
| ---------------- | ------------ |
| `collateralJoin` | string       |
| `safe`           | BigNumberish |
| `amt`            | BigNumberish |
| `transferFrom`   | boolean      |
| `owner`          | string       |

**Returns:** *TransactionRequest*

### safeRepayAllDebt

▸ **safeRepayAllDebt**(`safe`: BigNumberish, `owner`: string): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:644*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L644)

**Parameters:**

| Name    | Type         |
| ------- | ------------ |
| `safe`  | BigNumberish |
| `owner` | string       |

**Returns:** *TransactionRequest*

### safeRepayDebt

▸ **safeRepayDebt**(`safe`: BigNumberish, `wad`: BigNumberish, `owner`: string): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:655*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L655)

**Parameters:**

| Name    | Type         |
| ------- | ------------ |
| `safe`  | BigNumberish |
| `wad`   | BigNumberish |
| `owner` | string       |

**Returns:** *TransactionRequest*

### tokenCollateralJoin\_join

▸ **tokenCollateralJoin\_join**(`apt`: string, `safe`: string, `amt`: BigNumberish, `transferFrom`: boolean): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:671*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L671)

**Parameters:**

| Name           | Type         |
| -------------- | ------------ |
| `apt`          | string       |
| `safe`         | string       |
| `amt`          | BigNumberish |
| `transferFrom` | boolean      |

**Returns:** *TransactionRequest*

### transfer

▸ **transfer**(`collateral`: string, `dst`: string, `amt`: BigNumberish): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:687*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L687)

**Parameters:**

| Name         | Type         |
| ------------ | ------------ |
| `collateral` | string       |
| `dst`        | string       |
| `amt`        | BigNumberish |

**Returns:** *TransactionRequest*

### transferCollateral

▸ **transferCollateral**(`safe`: BigNumberish, `dst`: string, `wad`: BigNumberish): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:697*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L697)

**Parameters:**

| Name   | Type         |
| ------ | ------------ |
| `safe` | BigNumberish |
| `dst`  | string       |
| `wad`  | BigNumberish |

**Returns:** *TransactionRequest*

### transferInternalCoins

▸ **transferInternalCoins**(`safe`: BigNumberish, `dst`: string, `rad`: BigNumberish): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:712*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L712)

**Parameters:**

| Name   | Type         |
| ------ | ------------ |
| `safe` | BigNumberish |
| `dst`  | string       |
| `rad`  | BigNumberish |

**Returns:** *TransactionRequest*

### transferSAFEOwnership

▸ **transferSAFEOwnership**(`safe`: BigNumberish, `usr`: string): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:727*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L727)

**Parameters:**

| Name   | Type         |
| ------ | ------------ |
| `safe` | BigNumberish |
| `usr`  | string       |

**Returns:** *TransactionRequest*

### transferSAFEOwnershipToProxy

▸ **transferSAFEOwnershipToProxy**(`safe`: BigNumberish, `dst`: string): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:737*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L737)

**Parameters:**

| Name   | Type         |
| ------ | ------------ |
| `safe` | BigNumberish |
| `dst`  | string       |

**Returns:** *TransactionRequest*

### uniswapV2Call

▸ **uniswapV2Call**(`_sender`: string, `_amount0`: BigNumberish, `_amount1`: BigNumberish, `_data`: BytesLike): *TransactionRequest*

*Defined in* [*packages/geb/src/proxy-action.ts:930*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb/src/proxy-action.ts#L930)

**Parameters:**

| Name       | Type         |
| ---------- | ------------ |
| `_sender`  | string       |
| `_amount0` | BigNumberish |
| `_amount1` | BigNumberish |
| `_data`    | BytesLike    |

**Returns:** *TransactionRequest*


# Geb Admin

This class extends the core `GEB` class with additional tools and contracts that are not used as often as other SAFE management tools. Here you will find utils for contracts such as DSPause, ESM etc. These contracts are scattered across several repositories. Please refer to the smart contract documentation to learn more about them.

**IMPORTANT:** To avoid bloating the main [geb.js](https://www.npmjs.com/package/geb.js) package this class is only available in a [separate package](https://www.npmjs.com/package/@reflexer-finance/geb-admin). Please install it like this:

```
npm install @reflexer-finance/geb-admin
```

And after that you are ready to use the admin tools similar to the GEB class:

```typescript
import { ethers } from 'ethers'
import { GebAdmin } from "@reflexer-finance/geb-admin"

 const provider = new ethers.providers.JsonRpcProvider('http://kovan.infura.io/<API KEY>')
 const gebAdmin = new GebAdmin('kovan', provider)
```

## Constructors

\+ **new GebAdmin**(`network`: GebDeployment, `provider`: GebProviderInterface | Provider): [*GebAdmin*](/geb-js/api-reference/gebadmin)

*Defined in* [*packages/geb-admin/src/geb-admin.ts:52*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb-admin/src/geb-admin.ts#L52)

**Parameters:**

| Name       | Type                             | Description                                                                            |
| ---------- | -------------------------------- | -------------------------------------------------------------------------------------- |
| `network`  | GebDeployment                    | Either `'kovan'`, `'mainnet'` or an actual list of contract addresses.                 |
| `provider` | GebProviderInterface \| Provider | Either a Ethers.js provider or a GEB provider. Support for Web3.js will soon be added. |

**Returns:** [*GebAdmin*](/geb-js/api-reference/gebadmin)

## Properties

### contracts

• **contracts**: *ContractApis*

*Inherited from* [*GebAdmin*](/geb-js/api-reference/gebadmin)*.*[*contracts*](/geb-js/api-reference/gebadmin#contracts)

Defined in packages/geb/lib/geb.d.ts:70

Object containing all GEB core smart-contracts instances for direct level interactions. All of the following contracts object are one-to-one typed API to the underlying smart-contract. Read-only functions that do not change the blockchain state return a promise of the return data. State modifying function will return synchronously a pre-filled transaction request object:

```
{
  to: "0x123abc.."
  data: "0xabab234ab..."
}
```

This object follow the [TransactionRequest model of ethers.js](https://docs.ethers.io/v5/api/providers/types/#providers-TransactionRequest) (Also similar to the [model used by web.js](https://web3js.readthedocs.io/en/v1.3.0/web3-eth.html#id84)). The object can be completed with properties such as `from`, `gasPrice`, `gas` (gas limit, web3.js ony) or `gasLimit` (gas limit, ethers.js only). The object can then be passed to the `sendTransaction` of [ehters.js](https://docs.ethers.io/v5/api/signer/#Signer-sendTransaction) or [web3.js](https://web3js.readthedocs.io/en/v1.3.0/web3-eth.html#sendtransaction)

Example:

```typescript
 // Setup geb.js an ethers
 const provider = new ethers.providers.JsonRpcProvider('http://kovan.infura.io/<API KEY>')
 const wallet = new ethers.Wallet('<Private key>', provider)
 const geb = new Geb('kovan', provider)

 // Contract read function: Fetch the debt ceiling
 const debtCeiling = await geb.contracts.safeEngine.globalDebtCeiling()

 // State changing function: Manualy liquidate a SAFE
 const tx = geb.contracts.liquidationEngine.liquidateSAFE(ETH_A, '0x1234abc...')
 await wallet.sendTransaction(tx) // Send the Ethereum transaction
```

Currently the following contracts ae available in this property:

* SAFEEngine
* AccountingEngine
* TaxCollector
* LiquidationEngine
* OracleRelayer
* GlobalSettlement
* DebtAuctionHouse
* PreSettlementSurplusAuctionHouse
* PostSettlementSurplusAuctionHouse
* SettlementSurplusAuctioneer
* GebSafeManager
* GetSafes
* BasicCollateralJoin
* CoinJoin
* Coin (System coin ERC20 contract)
* GebProxyRegistry
* FixedDiscountCollateralAuctionHouse
* Weth (ERC20)

For detailed information about the functions of each contract we recommend referring directly to the smart-contract [code](https://github.com/reflexer-labs/geb) and [documentation](https://docs.reflexer.finance/)

### contractsAdmin

• **contractsAdmin**: *AdminApis*

*Defined in* [*packages/geb-admin/src/geb-admin.ts:52*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb-admin/src/geb-admin.ts#L52)

Object containing all GEB admin contracts instances for low level interactions. It currently has the following contracts:

* MultiSigWallet
* DsProxy
* DsToken
* ProtocolTokenAuthority
* GebPollingEmitter
* GebPrintingPermissions
* DsDelegateRoles
* DsPause
* DsPauseProxy
* GovActions
* ESM
* TokenBurner
* FsmGovernanceInterface
* DsProxyFactory
* GebDeployPauseProxyActions
* DsProxy
* TxManager

## Methods

### deployProxy

▸ **deployProxy**(): *object*

*Inherited from* [*GebAdmin*](/geb-js/api-reference/gebadmin)*.*[*deployProxy*](/geb-js/api-reference/gebadmin#deployproxy)

Defined in packages/geb/lib/geb.d.ts:88

Deploy a new proxy owned by the sender.

**Returns:** *object*

* **chainId**? : *number*
* **data**? : *string*
* **from**? : *string*
* **gasLimit**? : *BigNumber*
* **gasPrice**? : *BigNumber*
* **nonce**? : *number*
* **to**? : *string*
* **value**? : *BigNumber*

### getErc20Contract

▸ **getErc20Contract**(`tokenAddress`: string): *Erc20*

*Inherited from* [*GebAdmin*](/geb-js/api-reference/gebadmin)*.*[*getErc20Contract*](/geb-js/api-reference/gebadmin#geterc20contract)

Defined in packages/geb/lib/geb.d.ts:123

Returns an object that can be used to interact with a ERC20 token. Example:

```typescript
const USDCAddress = "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
const USDC = geb.getErc20Contract(USDCAddress)

// Get 0xdefiisawesome's balance
const balance = USDC.balanceOf("0xdefiisawesome..")

// Send 1 USDC to 0xdefiisawesome (USDC is 6 decimals)
const tx = USDC.transfer("0xdefiisawesome..", "1000000")
await wallet.sendTransaction(tx)
```

**Parameters:**

| Name           | Type   | Description            |
| -------------- | ------ | ---------------------- |
| `tokenAddress` | string | Token contract address |

**Returns:** *Erc20*

Erc20

### getGebContract

▸ **getGebContract**‹**T**›(`gebContractClass`: GebContractAPIConstructorInterface‹T›, `address`: string): *T*

*Inherited from* [*GebAdmin*](/geb-js/api-reference/gebadmin)*.*[*getGebContract*](/geb-js/api-reference/gebadmin#static-getgebcontract)

Defined in packages/geb/lib/geb.d.ts:165

Returns an instance of a specific geb contract given a Geb contract API class at a specified address

```typescript
import { contracts } from "geb.js"
const safeEngine = geb.getGebContract(contracts.SafeEngine, "0xabcd123..")
const globalDebt = safeEngine.globalDebt()
```

**Type parameters:**

▪ **T**: *BaseContractAPI*

**Parameters:**

| Name               | Type                                  | Description                            |
| ------------------ | ------------------------------------- | -------------------------------------- |
| `gebContractClass` | GebContractAPIConstructorInterface‹T› | Class from contracts or adminContracts |
| `address`          | string                                | Contract address of the instance       |

**Returns:** *T*

### getIncentiveCampaignContract

▸ **getIncentiveCampaignContract**(`campaignNumber`: number): *Promise‹StakingRewards›*

*Inherited from* [*GebAdmin*](/geb-js/api-reference/gebadmin)*.*[*getIncentiveCampaignContract*](/geb-js/api-reference/gebadmin#getincentivecampaigncontract)

Defined in packages/geb/lib/geb.d.ts:131

Help function to get the contract object of an incentive campaign given its number ID

**Parameters:**

| Name             | Type   | Description                    |
| ---------------- | ------ | ------------------------------ |
| `campaignNumber` | number | incremental ID of the campaign |

**Returns:** *Promise‹StakingRewards›*

StakingRewards

### getProxyAction

▸ **getProxyAction**(`ownerAddress`: string): *Promise‹GebProxyActions›*

*Inherited from* [*GebAdmin*](/geb-js/api-reference/gebadmin)*.*[*getProxyAction*](/geb-js/api-reference/gebadmin#getproxyaction)

Defined in packages/geb/lib/geb.d.ts:84

Given an address returns a GebProxyActions object to execute bundled operations. Important: This requires the address to have deployed a GEB proxy through the proxy registry contract. It will throw a `DOES_NOT_OWN_HAVE_PROXY` error if the address specified does not have a proxy. Use the [deployProxy](/geb-js/api-reference/gebadmin#deployproxy) function to get a new proxy.

**Parameters:**

| Name           | Type   | Description                                                            |
| -------------- | ------ | ---------------------------------------------------------------------- |
| `ownerAddress` | string | Externally owned user account, Ethereum address that owns a GEB proxy. |

**Returns:** *Promise‹GebProxyActions›*

### getSafe

▸ **getSafe**(`idOrHandler`: string | number, `collateralType?`: string): *Promise‹Safe›*

*Inherited from* [*GebAdmin*](/geb-js/api-reference/gebadmin)*.*[*getSafe*](/geb-js/api-reference/gebadmin#getsafe)

Defined in packages/geb/lib/geb.d.ts:93

Get the SAFE object given a `safeManager` id or a `safeEngine` handler address.

**Parameters:**

| Name              | Type             | Description             |
| ----------------- | ---------------- | ----------------------- |
| `idOrHandler`     | string \| number | Safe Id or SAFE handler |
| `collateralType?` | string           | -                       |

**Returns:** *Promise‹Safe›*

### getSafeFromOwner

▸ **getSafeFromOwner**(`address`: string): *Promise‹Safe\[]›*

*Inherited from* [*GebAdmin*](/geb-js/api-reference/gebadmin)*.*[*getSafeFromOwner*](/geb-js/api-reference/gebadmin#getsafefromowner)

Defined in packages/geb/lib/geb.d.ts:104

Fetch the list of safes owned by an address. This function will fetch safes owned directly through the safeManager and safes owned through the safe manager through a proxy. Safes owned directly by the address at the safeEngine level won't appear here.

Note that this function will make a lot of network calls and is therefore very slow. For front-ends we recommend using pre-indexed data such as the geb-subgraph.

**Parameters:**

| Name      | Type   | Description |
| --------- | ------ | ----------- |
| `address` | string |             |

**Returns:** *Promise‹Safe\[]›*

### gnosisSafeThreshold1SubmitTransaction

▸ **gnosisSafeThreshold1SubmitTransaction**(`sender`: string, `to`: string, `data`: string): *TransactionRequest*

*Defined in* [*packages/geb-admin/src/geb-admin.ts:203*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb-admin/src/geb-admin.ts#L203)

Submit a transaction to a gnosis safe directly executed. Works only if the threshold on the safe is 1.

**Parameters:**

| Name     | Type   | Description                        |
| -------- | ------ | ---------------------------------- |
| `sender` | string | Proposal submitter                 |
| `to`     | string | Proposal target (Usually ds-pause) |
| `data`   | string | transaction data of the proposal   |

**Returns:** *TransactionRequest*

### multiCall

▸ **multiCall**‹**O1**, **O2**, **O3**›(`calls`: \[MulticallRequest‹O1›, MulticallRequest‹O2›, MulticallRequest‹O3›]): *Promise‹\[O1, O2, O3]›*

*Inherited from* [*GebAdmin*](/geb-js/api-reference/gebadmin)*.*[*multiCall*](/geb-js/api-reference/gebadmin#multicall)

Defined in packages/geb/lib/geb.d.ts:136

**Type parameters:**

▪ **O1**

▪ **O2**

▪ **O3**

**Parameters:**

| Name    | Type                                                                |
| ------- | ------------------------------------------------------------------- |
| `calls` | \[MulticallRequest‹O1›, MulticallRequest‹O2›, MulticallRequest‹O3›] |

**Returns:** *Promise‹\[O1, O2, O3]›*

### verifyWebScheduleCallcode

▸ **verifyWebScheduleCallcode**(`govFunctionAbi`: string, `params`: any\[], `earliestExecutionTime`: number, `calldata`: string, `description?`: string): *Promise‹boolean›*

*Defined in* [*packages/geb-admin/src/geb-admin.ts:75*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb-admin/src/geb-admin.ts#L75)

Verifies a transaction for scheduling proposals

**Parameters:**

| Name                    | Type   | Description                                                                           |
| ----------------------- | ------ | ------------------------------------------------------------------------------------- |
| `govFunctionAbi`        | string | Human readable abi from gov actions or proxy of choice -> "setDelay(address,uint256)" |
| `params`                | any\[] | Array containing all for the above function                                           |
| `earliestExecutionTime` | number | -                                                                                     |
| `calldata`              | string | to verify                                                                             |
| `description?`          | string | -                                                                                     |

**Returns:** *Promise‹boolean›*

Promise

### webExecuteProposal

▸ **webExecuteProposal**(`govFunctionAbi`: string, `params`: any\[], `earliestExecutionTime`: number): *Promise‹TransactionRequest›*

*Defined in* [*packages/geb-admin/src/geb-admin.ts:99*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb-admin/src/geb-admin.ts#L99)

Encodes executing a proposal in dspause for web GUI

**Parameters:**

| Name                    | Type   | Description                                                                           |
| ----------------------- | ------ | ------------------------------------------------------------------------------------- |
| `govFunctionAbi`        | string | Human readable abi from gov actions or proxy of choice -> "setDelay(address,uint256)" |
| `params`                | any\[] | Array containing all for the above function                                           |
| `earliestExecutionTime` | number | -                                                                                     |

**Returns:** *Promise‹TransactionRequest›*

Promise

### webScheduleProposal

▸ **webScheduleProposal**(`govFunctionAbi`: string, `params`: any\[], `earliestExecutionTime`: number, `description?`: string): *Promise‹object›*

*Defined in* [*packages/geb-admin/src/geb-admin.ts:124*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb-admin/src/geb-admin.ts#L124)

Encodes scheduling a proposal in dspause for web GUI

**Parameters:**

| Name                    | Type   | Description                                                                           |
| ----------------------- | ------ | ------------------------------------------------------------------------------------- |
| `govFunctionAbi`        | string | Human readable abi from gov actions or proxy of choice -> "setDelay(address,uint256)" |
| `params`                | any\[] | Array containing all for the above function                                           |
| `earliestExecutionTime` | number | -                                                                                     |
| `description?`          | string | -                                                                                     |

**Returns:** *Promise‹object›*

Promise

### webTestScheduleProposal

▸ **webTestScheduleProposal**(`govFunctionAbi`: string, `params`: any\[], `earliestExecutionTime`: number, `description?`: string): *Promise‹void›*

*Defined in* [*packages/geb-admin/src/geb-admin.ts:173*](https://github.com/reflexer-labs/geb.js/blob/30c41df/packages/geb-admin/src/geb-admin.ts#L173)

Test the execution of a proposal about to be schedule in dspause with web GUI

**Parameters:**

| Name                    | Type   | Description                                                                           |
| ----------------------- | ------ | ------------------------------------------------------------------------------------- |
| `govFunctionAbi`        | string | Human readable abi from gov actions or proxy of choice -> "setDelay(address,uint256)" |
| `params`                | any\[] | Array containing all for the above function                                           |
| `earliestExecutionTime` | number | -                                                                                     |
| `description?`          | string | -                                                                                     |

**Returns:** *Promise‹void›*

Promise

### `Static` getGebContract

▸ **getGebContract**‹**T**›(`gebContractClass`: GebContractAPIConstructorInterface‹T›, `address`: string, `provider`: GebProviderInterface | Provider): *T*

*Inherited from* [*GebAdmin*](/geb-js/api-reference/gebadmin)*.*[*getGebContract*](/geb-js/api-reference/gebadmin#static-getgebcontract)

Defined in packages/geb/lib/geb.d.ts:152

Returns an instance of a specific geb contract given Geb contract API class constructor at a specified address

**Type parameters:**

▪ **T**: *BaseContractAPI*

**Parameters:**

| Name               | Type                                  | Description                                   |
| ------------------ | ------------------------------------- | --------------------------------------------- |
| `gebContractClass` | GebContractAPIConstructorInterface‹T› | Class from contracts or adminContracts        |
| `address`          | string                                | Contract address of the instance              |
| `provider`         | GebProviderInterface \| Provider      | Either a Ethers.js provider or a Geb provider |

**Returns:** *T*


# API Endpoints

## RAI

### Graph Protocol Subgraphs

* Mainnet: <https://thegraph.com/explorer/subgraph/reflexer-labs/rai-mainnet>&#x20;
* Kovan: <https://thegraph.com/explorer/subgraph/reflexer-labs/rai-kovan>&#x20;
* Reflexer hosted Mainnet: <https://subgraph.reflexer.finance/subgraphs/name/reflexer-labs/rai/graphql>&#x20;
* Reflexer hosted Kovan: <https://subgraph-kovan.reflexer.finance/subgraphs/name/reflexer-labs/rai/graphql>&#x20;
* Mainnet PRAI (deprecated beta): <https://thegraph.com/explorer/subgraph/reflexer-labs/prai-mainnet>

The subgraph documentation is available on the right panel of[ thegraph.com endpoint ](< https://thegraph.com/explorer/subgraph/reflexer-labs/rai-mainnet>)

![](/files/-MTaMXwa5LbpZ5zKzrNX)


# Getting Started

Installing pyflex is simple. Open a console and type:

```
$ pip install git+https://github.com/reflexer-labs/pyflex
```

You're ready to hack!


# Configuration

Import all the necessary files:

```python
>>> from web3 import Web3, HTTPProvider
>>> from pyflex.deployment import GfDeployment
```

And then connect to an Ethereum node:

```python
>>> ETH_RPC_URL = "http://13.59.107.140:8545"
>>> web3 = Web3(HTTPProvider(endpoint_uri=ETH_RPC_URL, request_kwargs={"timeout": 60}))
```

Finally, configure a `geb` object. This object allows you to access most contracts in the `GEB` system:

```python
>>> geb = GfDeployment.from_node(web3, 'rai')
```


# GEB Basics

Examples of querying the GEB contracts

## SAFE Engine

Log the current global debt and the global debt ceiling:

```python
>>> geb.safe_engine.global_debt()
Rad(5208615869764014400330809431631271622010234720384)
>>> geb.safe_engine.global_debt_ceiling()
Rad(10200000000000000000000000000000000000000000000000)
```

Get the total debt available to generate:

```python
>>> str(geb.safe_engine.global_debt_ceiling() - geb.safe_engine.global_debt())
'4991.375324317972058031697987632361257179694960552'
```

Get a `SAFE`'s status:

```python
>>> from pyflex import Address
>>> collateral_type = geb.collaterals['ETH-A'].collateral_type
>>> safe = geb.safe_engine.safe(collateral_type, Address('0xdD1693BD8E307eCfDbe51D246562fc4109f871f8'))
>>> safe.locked_collateral
Wad(550000000000000000)
>>> safe.generated_debt
Wad(85000000000000000000)
```

Get updated `CollateralType` info:

```python
>>> collateral_type = geb.safe_engine.collateral_type('ETH-A')
>>> print(collateral_type)
CollateralType('ETH-A')[accumulated_rate=1.001032213690254860731418088 safe_collateral=0.000000000000000000 safe_debt=5203.253805869738490471 safety_price=157.366296298604006512381213706 liquidation_price=157.366296298604006512381213706 debt_ceiling=10200.000000000000000000000000000000000000000000000 debt_floor=85.000000000000000000000000000000000000000000000]
>>> collateral_type.liquidation_price
Ray(157366296298604006512381213706)
```

## Oracle Relayer

Get the `redemption_price` and the`redemption_rate` . Note that fetching the latest redemption price requires you to first update it and then return the value:

```python
>>> geb.oracle_relayer.redemption_price()
Ray(2026411234986175268208847109)
>>> geb.oracle_relayer.redemption_rate()
Ray(999999954662032624407551326)
```

## Tax Collector

Get the per-second stability fee applied to `SAFEs` :

```python
>>> geb.tax_collector.stability_fee(geb.safe_engine.collateral_type('ETH-A'))
Ray(1000000000472114805215157978)
```

## Liquidation Engine

Check if a `SAFE`can be liquidated:

```python
>>> from pyflex import Address
>>> collateral_type = geb.collaterals['ETH-A'].collateral_type
>>> safe = geb.safe_engine.safe(collateral_type, Address('0xdD1693BD8E307eCfDbe51D246562fc4109f871f8'))
>>> geb.liquidation_engine.can_liquidate(collateral_type, safe)
False
```

If the `SAFE` is underwater, you can also liquidate it:

```python
>>> geb.liquidation_engine.liquidate_safe(collateral_type, safe).transact()
```

These are just a few examples. To see all supported functions,  view the source code:

{% embed url="<https://github.com/reflexer-labs/pyflex/blob/master/pyflex/gf.py>" %}


# SAFE Management

The recommendeded way to manage `SAFE`s is through the `GebSAFEManager` contract, which allows a single address to open multiple `SAFE`s.&#x20;

{% hint style="warning" %}
Pyflex does not fully support `GebSAFEManager` and so for now you can only use it to interact directly with `SAFEEngine`. When you interact directly with `SAFEEngine`, you can only open one 'unmanaged' `SAFE` per address.

If you're not using pyflex, we recommend you to manage your `SAFE`s through the [app](https://app.reflexer.finance) or with [geb-js](https://docs.reflexer.finance/geb-js/).
{% endhint %}

The following sections show you how to manage SAFEs without the GebSAFEManager and thus interact with the `SAFEEngine` contract directly.

{% content-ref url="/pages/-MMzy6JLS3\_cNdc6aXrY" %}
[SAFE Management](/pyflex/safe-management)
{% endcontent-ref %}


# Opening a SAFE

Steps to open a SAFE and withdraw system coins

Import all the necessary dependencies:

```python
>>> from web3 import Web3, HTTPProvider
>>> from pyflex import Address
>>> from pyflex.deployment import GfDeployment
>>> from pyflex.keys import register_keys
>>> from pyflex.numeric import Wad 
```

Connect to an Ethereum node:

```python
>>> ETH_RPC_URL = "http://localhost:8545"
>>> web3 = Web3(HTTPProvider(endpoint_uri=ETH_RPC_URL, request_kwargs={"timeout": 60}))
```

Set your account and keystore file and then enter your keystore password:

```python
>>> web3.eth.defaultAccount ='0xdD1693BD8E307eCfDbe51D246562fc4109f871f8'
>>> register_keys(web3, ['key_file=key.json'])
Password for key.json: 
>>>
```

Instantiate an `Address` object to use later. Then, initialize a `GEB` object:

```python
>>> our_address = Address(web3.eth.defaultAccount)
>>> geb = GfDeployment.from_node(web3=web3)
```

Currently `ETH-A` is the only supported collateral:

```python
>>> collateral = geb.collaterals['ETH-A']
```

Setup your approvals in order to `join/exit` collateral and system coins in and out of the system.

{% hint style="info" %}
These `approve` calls only need to be done once per address!
{% endhint %}

```python
>>> collateral.approve(our_address)
>>> geb.approve_system_coin(our_address)
```

Set the amount of collateral to deposit and the amount of debt to withdraw:

```python
>>> collateral_amount = Wad.from_number(2.0)
>>> debt_amount = Wad.from_number(85)
```

`deposit` collateral and `join` it into the system:

```python
>>> collateral.collateral.deposit(collateral_amount).transact()
>>> collateral.adapter.join(our_address, collateral_amount).transact()
```

Open a `SAFE` depositing the collateral and increasing your system coin balance in the `SAFEEngine` :

```python
>>> geb.safe_engine.modify_safe_collateralization(collateral_type, our_address, delta_collateral=collateral_amount, delta_debt=debt_amount).transact()
```

Check your coin balance in the `SAFEEngine` :

```python
>>> geb.safe_engine.coin_balance(our_address)
Rad(85000000000000000000000000000000000000000000)
```

`exit` system coin in ERC20 form:

```python
>>> geb.system_coin_adapter.exit(our_address, debt_amount).transact()
```


# Closing a SAFE

Steps to close a SAFE and withdraw collateral.

`join` system coins inside the `SAFEEngine`:

```python
>>> geb.system_coin_adapter.join(our_address, Wad.from_number(40)).transact()
```

Pay back system coins to the `SAFE` and withdraw collateral:

```python
>>> geb.safe_engine.modify_safe_collateralization(collateral_type, our_address, delta_collateral=Wad.from_number(-0.2), delta_debt=Wad.from_number(-4
```

`exit` collateral from the system:

```python
>>> geb.collateral.adapter.exit(our_address, Wad.from_number(0.2)).transact()
```


# Numerics

`GEB` uses different numbers representing various levels of precision.

| Type  | Precision |
| ----- | --------- |
| `Wad` | 1E-18     |
| `Ray` | 1E-27     |
| `Rad` | 1E-45     |

You can import them from pyflex:

```python
>>> from pyflex.numeric import Wad, Ray, Rad
```

Converting `Wad`, `Ray`, `Rad` to a `str` shows the numbers in a friendly format:

```python
>>> Wad.from_number(1.2)
Wad(1200000000000000000)
>>> str(Wad.from_number(1.2))
'1.200000000000000000'
```

{% hint style="warning" %}
Constructors will add a specific precision to a number  eg. `Wad(1)` is not equal to `1` but to 10^18.
{% endhint %}

```python
>>> Wad(10) == Wad.from_number(10)
False
>>> Wad(10) == Wad.from_number(10 * 1E-18)
True
```

### Operations: Addition, Subtraction, Division

`Wad`, `Ray`, and `Rad` can only perform addition, subtraction and division with another `Wad`, `Ray`, or `Rad`

```python
>>> Rad(10) + Wad(10)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/georgekellerman/reflexer/pyflex/lib/python3.8/site-packages/pyflex/numeric.py", line 320, in __add__
    raise ArithmeticError
ArithmeticError
>>> Ray(10) - Ray(5)
Ray(5)
>>> Rad(10) / Rad.from_number(2)
Rad(5)
>>> 

```

### Operations: Multiplication

`Wad`, `Ray`, and `Rad`  can be multiplied by any `Wad`, `Ray`, and `Rad`  and `int`.

The result is the type of the first number:

```python
>>> x = Wad.from_number(1.2) * Rad.from_number(1)
>>> type(x)
<class 'pyflex.numeric.Wad'>
>>> y = Rad.from_number(1) * Wad.from_number(1.2)
>>> type(y)
<class 'pyflex.numeric.Rad'>
```

### Conversion

`Wad`, `Ray`, and `Rad` all accept `Wad`, `Ray`, and `Rad` in the constructors. This is the canonical way to convert  numbers:

```python
>>> Rad(Wad(10))
Rad(10000000000000000000000000000)
```

{% hint style="warning" %}
During conversion (`Rad` to `Ray`/`Wad` or `Ray` to `Wad`) you may lose precision!
{% endhint %}

```python
>>> Wad(Rad(10))
Wad(0)
>>> Ray(Rad(20))
Ray(0)
```


# Keeper Overview

Keepers are meant participate in collateral, surplus and debt auctions by directly interacting with GEB auction contracts deployed on a blockchain.

### Keeper Responsibilities

The keepers are responsible with:

1. Monitoring all active auctions
2. Starting new auctions&#x20;
3. Discovering new auctions&#x20;
4. Ensuring a bidding model is running for each active auction&#x20;
5. Passing auction status to each bidding model&#x20;
6. Processing each bidding model output and submitting bids

### Architecture

`auction-keeper` can read an auction's status directly from the blockchain or from a [Graph](https://thegraph.com/) node. Its unique feature is the ability to plug in external *bidding models* which tell the keeper when and how much to bid. Bid prices are received from separate *bidding models*.

*Bidding models* are simple processes that can be implemented in any programming language. They only need to pass JSON objects to and from `auction-keeper`. The simplest example of a bidding model is a shell script which echoes a fixed price.

For every new block, all auctions from `1` to `auctionsStarted` are checked for active status. If a new auction is detected, a new bidding model is started.

**NOTE**: *Bidding models* are only used for surplus and debt auctions, not collateral auctions.

## Installation

### Running on Docker (recommended)

Examples:

* [Collateral](/keepers/collateral-auction-keeper/running-in-docker)
* [Surplus](/keepers/surplus-auction-keeper/running-in-docker)
* [Debt](/keepers/debt-auction-keeper/running-in-docker)

### Running on a host

Pre-requisites: Python 3.6+

Install `auction-keeper` dependencies with:

```
git clone https://github.com/reflexer-finance/auction-keeper.git
cd auction-keeper
git submodule update --init --recursive
pip3 install -r requirements.txt
```

The keeper can now be run with `bin/auction-keeper`.

Auction specific examples:

* [Collateral](/keepers/collateral-auction-keeper/running-on-a-host)
* [Surplus](/keepers/surplus-auction-keeper/running-on-a-host)
* [Debt](/keepers/debt-auction-keeper/running-on-a-host)

## Configuration Reference

Run `bin/auction-keeper -h` to see an up-to-date list of arguments and usage information.

### General

`--type collateral|surplus|debt` A keeper can only participate in one type of auction

`--collateral-type NAME` If `--type=collateral` is passed, the `collateral_type` must also be provided. A keeper can only bid on a single collateral type auction at a time. **NOTE**: Currently, only the `ETH-A` collateral type is used.

`--eth-from ADDRESS` Address of the keeper. **Warning**: **Do not use the same `eth-from` account on multiple keepers** as it complicates `SAFEEngine` inventory management and will likely cause nonce conflicts. Using an `eth-from` account with an open SAFE is also discouraged.

`--rpc-host HOST` URI of ETH JSON-RPC node. Default `"http://localhost:8545"`

`--rpc-timeout SECS` Defaults to `10`

The keeper connects to the blockchain network using [Web3.py](https://github.com/ethereum/web3.py) and interacts with GEB using [pyflex](https://github.com/reflexer-labs/pyflex). A connection to an Ethereum node (`--rpc-host`) is required. [Parity](https://www.parity.io/ethereum/) and [Geth](https://geth.ethereum.org/) nodes are supported over HTTP. Websocket endpoints are not supported in `pyflex`. A *full* or *archive* node is required; *light* nodes are **not** supported.

If you don't want to run your own node, third-party providers are available. This software has been tested with [Infura](https://infura.io), [ChainSafe](https://chainsafe.io/) and [QuikNode](https://v2.quiknode.io/).

### Gas price strategies

The following options determine the keeper's gas strategy and are mutually exclusive:

`--ethgasstation-api-key MY_API_KEY` Use [ethgasstation.info](https://ethgasstation.info) for gas prices

`--etherchain-gas-price` Use [etherchain.org](https://etherchain.org) for gas prices

`--poanetwork-gas-price` Use [poa.network](https://gasprice.poa.network/) for gas prices

`--etherscan-gas-price` Use [etherscan.io](https://etherscan.io/) for gas prices. Optional: `--etherscan-key KEY`. Rate-limited to 1request/5sec w/o a key.

`--gasnow-gas-price` Use [gasnow.org](https://gasnow.org) for gas prices

`--fixed-gas-price GWEI` Use a fixed gas price (in GWEI)

If none of these options is given or if the gas API produces no result, the keeper will fetch the gas price from the node you connected to.

### Other gas options

`--gas-initial-multiplier MULTIPLIER` When using an API source for fetching the initial gas price, this tunes the price. It's ignored when you're using `--fixed-gas-price`. In case no strategy is specified it defaults to `1.0`

`--gas-reactive-multiplier MULTIPLIER` Every 30 seconds, a transaction's gas price will be multiplied by this value until it is mined or `--gas-maxiumum` is reached. Not used if `gasPrice` is passed from your bidding model. **NOTE**: [Parity](https://wiki.parity.io/Transactions-Queue#dropping-conditions), as of this writing, requires a minimum gas increase of `1.125` to propagate a transaction replacement; this should be treated as a minimum value unless you want replacements to happen less frequently. This multiplier defaults to `1.125` if no other value is given.

`--gas-maximum GWEI` Maximum value for gas price

### Accounting options

By default the keeper `join`s system coins to `SAFEEngine` on startup and `exit`s all system coins and collateral upon shutdown. The keeper provides options for managing `SAFEEngine` balances, which may be turned off in case you'd like to manage balances manually.

`--keep-system-coin-in-safe-engine-on-exit` Do not `exit` system coin on shutdown

`--keep-collateral-in-safe-engine-on-exit` Do not `exit` collateral on shutdown

`--return-collateral-interval SECS` How often, in seconds, the keeper `exit`s won collateral from `SAFEEngine`. Pass `0` to disable completely. Defaults to `300`

`--safe-engine-system-coin-target ALL|<integer>` Amount of system coins the keeper will try to keep in `SAFEEngine` by rebalancing with `join`s and `exit`s between its own wallet and its balance inside GEB. Defaults to `ALL` and the keeper will `join` all of an account's systems coins.

### **Rebalancing**

System coins are rebalanced per `--safe-engine-system-coin-target` when:

* The keeper starts up
* `SAFEEngine` balance is insufficient in order to place a bid
* An auction is settled

Rebalances do not account for system coins moved from the `SAFEEngine` to an auction contract for an active bid.

To avoid transaction spamming, small "dusty" system coins balances will be ignored (until the keeper exits, if so configured).

### Managing resources

#### Retrieving SAFEs

To start collateral auctions, the keeper needs a list of SAFEs and the collateralization ratio of each safe. There are two ways to retrieve the list of open SAFEs:

`--from-block BLOCK_NUMBER` Scrape the chain for `ModifySAFECollateralization` events, starting at `BLOCK_NUMBER` . Set this to the block where the first ever SAFE was created. After startup, only new blocks will be queried. The scrape process can last a significant amount of time as the system matures. **NOTE**: To manage the performance of debt auction bidding, periodically adjust `--from-block` to the block number of the oldest liquidation which has not been `popDebtFromQueue`d yet. Defaults to `geb.starting_block_number`, the block in which the system was deployed.

`--graph-endpoints NODE1,NODE2` Comma delimited list of [Graph](https://thegraph.com) endpoints used to retrieve `ModifySAFECollateralization` events. If multiple endpoints are passed, they will be pinged sequentially in the order they were specified in case one or many of them fail. **NOTE**: This flag is only supported for collateral auctions.

`--graph-block-threshold NUMBER_OF_BLOCKS` When the keeper fetches SAFE data to find critical safes, use the `--graph-endpoints` when the keeper's last processed block is older than `NUMBER_OF_BLOCKS`. The graph will be faster than a node when fetching historical data, but recent graph blocks might be slightly delayed compared to an ethereum node. This allows the keeper to to fetch historical data from the graph, but use the node for all newer blocks. Defaults to `20`

The following are the most recent Graph node endpoints for RAI:`--graph-endpoints https://subgraph.reflexer.finance/subgraphs/name/reflexer-labs/rai,https://api.thegraph.com/subgraphs/name/reflexer-labs/rai-mainnet`

#### Auctions

`--min-auction AUCTION_ID` Ignore auctions older than `AUCTION_ID`

`--max-auctions NUMBER` Limit the number of bidding models created to handle active auctions.

`--block-check-interval <integer>, default:1` How often the keeper checks for new blocks

`--bid-check-interval <integer>, default 4` How often the keeper checks model processes for new bids

**NOTE**: if you'd like to use Infura with your keeper and prefer the free-tier (you do less than 100K requests per day), `--block-check-interval` must be greater than `10` and `--bid-check-interval` must be greater than 180. However, this will make your keeper slower and it will not quickly bid in auctions.

#### Flash swaps

Flash swaps allow a keeper to participate in collateral auctions without any system coins. The flash swap borrows the system coin necessary for the collateral auctions, wins the collateral at a discount and transferred the won collateral back to the keeper, all in one transaction. Note: If the overall transaction is not profitable, the swap will fail. The keeper only needs enough ether to pay for the gas of the swap.

`--flash-swap` Turn on Uniswap flash swaps for collateral auctions. Not supported for `--type debt` or `--type surplus`

[Read more about flash swaps](https://github.com/reflexer-labs/geb-docs/tree/c027d74c487c0a715a19a415c1c97933e43a9f7d/keepers/collateral-auction-keeper/flash-swaps.md)

#### Sharding/Settling

Bid management can be sharded across multiple keepers. If you want to proceed with sharding, set these options:

`--shards NUMBER_OF_KEEPER` Number of keepers you plan to run. You must set this for all keepers

`--shard-id SHARD_ID` You must specify this for every keeper, counting from 0

For example, to configure three keepers, set `--shards 3` and assign `--shard-id 0`, `--shard-id 1`, `--shard-id 2` for the first, second and third keeper.

**NOTE**: **Auction starts are not sharded**. Only one keeper should be configured to `liquidateSAFE`s and this way `startAuction`s.

If you are sharding across multiple accounts, you may want to have a separate keeper that handles all your `settleAuction`s (in the case of English collateral, debt and surplus auctions)

`--settle-for <ACCOUNT1 ACCOUNT2>|NONE|ALL` Space-delimited list of accounts for which the keeper will settle auctions. Specify `NONE` to disable this option. If you'd like to donate your gas to settle auctions for all participants, `ALL` is also supported. Defaults to only the keeper address.

**NOTE**: **Auction settlements are already sharded**, so you should remove the sharding configuration if you're running a dedicated auction settlement keeper.

#### Transaction management

`--bid-delay FLOAT`

Many pending transactions can fill up the keeper's transaction queue, causing every subsequent transaction to be dropped. By waiting a small `--bid-delay` after each bid, multiple transactions can be submitted asynchronously while still allowing some time for older transactions to complete, freeing up the queue.

Many parameters determine the appropriate bid delay. For illustration purposes, assume the queue can hold 12 transactions, and gas prices are reasonable. In this setup, a bid delay of 1.2 seconds might provide ample time for transactions at the front of the queue to complete.

### Limitations

* If an auction started before the keeper was started, this keeper will not participate in it until the next block is mined
* This keeper does not explicitly handle Global Settlement, and may submit transactions which fail during shutdown
* Some keeper functions incur gas fees regardless of whether a bid is submitted.  This includes, but is not limited to, the following actions:
  * submitting token approvals
  * adjusting the surplus and debt balances from `AccountingEngine`
  * liquidating a SAFE or starting a surplus or debt auction
* The keeper does not check model prices until an auction exists.  When configured to create new auctions, it will `liquidateSAFE`s or start a new surplus or debt auction regardless of whether or not your system coin or protocol token balance is sufficient to bid
* Liquidating a SAFE to start a new collateral auction is a time consuming operation. To do so without a subgraph subscription, the keeper initializes a cache of SAFEs states by scraping event logs from the chain. The keeper will then continuously refresh SAFE states and detect undercollateralized SAFEs.
  * Despite batching log queries into multiple requests, Geth nodes are generally unable to initialize the SAFE state cache in a reasonable amount of time.  As such, **Geth is not recommended for liquidating SAFEs**
  * To manage resources, it is recommended to run separate keepers using separate accounts to liquidate (`--start-auctions-only`) and bid (`--bid-only`) in auctions

For some known Ubuntu and macOS issues see the [pyflex](https://github.com/reflexer-labs/pyflex) README.

### Testing

This project uses [pytest](https://docs.pytest.org/en/latest/) for unit testing. Testing depends on a dockerized local testchain included in `lib\pyflex\tests\config`.

In order to be able to run tests you should execute:

```
git clone https://github.com/reflexer-labs/auction-keeper.git
cd auction-keeper
git submodule update --init --recursive
./install.sh
source _virtualenv/bin/activate
pip3 install -r requirements-dev.txt
```

You can then run all tests with:

```
./test.sh
```


# Collateral Auction Keeper

How to run a collateral auction keeper

This mini guide will walk you through running a collateral auction keeper in Docker & also directly on a host. It will also detail the liquidation and bidding process as well as the logs shown by the keeper.


# Running in Docker

Running a collateral auction-keeper in a docker container.

## 1) Get RAI

Buy RAI from Uniswap v2 or [open a SAFE](https://app.gitbook.com/@reflexer-labs/s/geb/pyflex/safe-management/opening-a-safe) and generate it.

## 2) Create the keeper run file

Create a file called `run_auction_keeper.sh` and paste the following code in it:

```
#!/bin/bash

docker run -it \
    -v <KEYSTORE DIR>:/keystore \
    reflexer/auction-keeper:latest \
        --rpc-uri <ETH_RPC_URL> \
        --eth-from <KEEPER ADDRESS> \
        --eth-key key_file=/keystore/<KEYSTORE FILE>
```

### Then, substitute the following variables:

`KEYSTORE_DIR` - the local directory where your keystore file is

`KEYSTORE_FILE` - your Ethereum UTC JSON keystore filename

For more information about this keystore format and how to generate them:

* [Ethereum UTC / JSON Wallet Encryption](https://wizardforcel.gitbooks.io/practical-cryptography-for-developers-book/content/symmetric-key-ciphers/ethereum-wallet-encryption.html)
* [keythereum](https://github.com/ethereumjs/keythereum)

`ETH_RPC_URL` - the URL of the ethereum RPC connection

`KEEPER_ADDRESS` - the keeper's address. It must be in a checksummed format

### Finally:

`chmod +x run_auction_keeper.sh`

## 3) Start the keeper and enter your keystore file password

`./run_auction_keeper.sh`

```
$ ./run_auction_keeper.sh
latest: Pulling from reflexer/auction-keeper
Digest: sha256:7e55ec9b0a136fc903d9f7f2690538bcbde9029d957e0e6f84d0282790f9666a
Status: Downloaded newer image for reflexer/auction-keeper:latest
docker.io/reflexer/auction-keeper:latest
Password for /keystore/key.json:
```


# Running on a Host

Running a collateral auction keeper directly on a host

## Prerequisties

Python 3.6+

### Get RAI:

Buy RAI from Uniswap v2 or [open a SAFE](https://app.gitbook.com/@reflexer-labs/s/geb/pyflex/safe-management/opening-a-safe) and generate it.

### Clone:

```
git clone https://github.com/reflexer-labs/auction-keeper.git
cd auction-keeper
git submodule update --init --recursive
```

### Install:

This creates a virtual environment and installs requirements.

`./install.sh`

## 1) Start virtualenv

`source _virtualenv/bin/activate`

## 2) Create a model file

Paste the following code into `collateral_model.sh`:

```
#!/usr/bin/env bash
while true; do
  echo "{}"
  sleep 120                   
done
```

**NOTE**: Currently, collateral auctions sell collateral at a fixed discount and so the keeper doesn't use a bidding model. This empty bidding model is simply a placeholder.

## 3) Create the keeper run file

Create a file called `run_auction_keeper.sh` and paste the following code in it:

```
#!/bin/bash
bin/auction-keeper \
     --model ./collateral_model.sh \
     --rpc-uri <ETH_RPC_URL> \
     --eth-from <KEEPER_ADDRESS> \
     --eth-key key_file=<KEYSTORE_FILE>
```

### Then, substitute the following variables:

`ETH_RPC_URL` - the URL of the ethereum RPC connection

`KEEPER_ADDRESS` - the keeper's address. It should be in checksummed format(not lowercase).

`KEYSTORE_FILE` - your Ethereum UTC JSON keystore filename

For more information about this keystore format and how to generate them:

* [Ethereum UTC / JSON Wallet Encryption](https://wizardforcel.gitbooks.io/practical-cryptography-for-developers-book/content/symmetric-key-ciphers/ethereum-wallet-encryption.html)
* [keythereum](https://github.com/ethereumjs/keythereum)

### Finally:

`chmod +x run_auction_keeper.sh`

## 4) Start the keeper and enter your keystore file password

`./run_auction_keeper.sh`

```
$ ./run_auction_keeper.sh
Password for /keystore/key.json:
```


# Liquidations & Collateral Auctions

Overview of the collateral liquidation and auctioning process

## Liquidations

The collateral keeper will liquidate all critical safes it encounters. This process starts new fixed discount collateral auctions:

```
Liquidating ETH-A SAFE 0xc90F721DacfF8548777026253B8CB584426DC8C7 with locked_collateral=0.435000000000000000 liquidat
ion_price=194.362282878411910669975186104 generated_debt=85.069599661138521872 accumulatedRates=1.000357358433360132592605082
Checked 39 safes in 14 seconds
Sent transaction LiquidationEngine('0x4443d35BAEa0EeD30d9C7Fb136B8e507DC593646').liquidateSAFE('0x4554482d410000000000
00000000000000000000000000000000000000000000', '0xc90F721DacfF8548777026253B8CB584426DC8C7') with nonce=206, gas=434424, gas_price=30000000000 (tx_hash
=0x6688d6e94dc884ba294dd67626f1e0c749c76ca14fb7224b948b31a0e5286d6a)
Transaction LiquidationEngine('0x4443d35BAEa0EeD30d9C7Fb136B8e507DC593646').liquidateSAFE('0x4554482d41000000000000000000000000000000000000000000000000000000', '0xc90F721DacfF8548777026253B8CB584426DC8C7') was successful (tx_hash=0x6688d6e94dc884ba294dd67626f1e0c749c76ca14fb7224b948b31a0e5286d6a)
```

## Auctions

After an auction is started, the collateral keeper will be able to bid for and buy collateral at a discounted price:

```
Started monitoring auction #8
Instantiated model using process '../models/collateral_model.sh --id 8 --collateral_auction_house 0xF8AAD33Cb9291Da4FF51377a6F1aB165c5E7Ab69'
Process '../models/collateral_model.sh --id 8 --collateral_auction_house 0xF8AAD33Cb9291Da4FF51377a6F1aB165c5E7Ab69' (pid #36) started
Checked auctions 0 to 8 in 0 seconds
Checking if internal system coin balance needs to be rebalanced
system coin token balance: 0.000000000000000000, SAFE Engine balance: 119.768970008628887937411195000000000000000000000
Sending new bid @284.538396004218362573 for auction 8
Sent transaction FixedDiscountCollateralAuctionHouse('0xF8AAD33Cb9291Da4FF51377a6F1aB165c5E7Ab69').buyCollateral(8, 4
318147966969218961926) with nonce=230, gas=303231, gas_price=30000000000 (tx_hash=0x2f63ae43a46ae777f31a0977363a4d1ebd5fb8486d68fd70987b199281c36e3a)
Transaction FixedDiscountCollateralAuctionHouse('0xF8AAD33Cb9291Da4FF51377a6F1aB165c5E7Ab69').buyCollateral(8, 431814
7966969218961926) was successful (tx_hash=0x2f63ae43a46ae777f31a0977363a4d1ebd5fb8486d68fd70987b199281c36e3a)
```

{% hint style="info" %}
**Bidding Gotchas**

1\) By default, the keeper submits a bid using all of its available system coins. This ensures the keeper gets the maximum amount of discounted collateral in one go.

2\) If there are multiple ongoing auctions, you might see this error until the first `buyCollateral` transaction is finished:

`Bid cost 5025.307970008628887936000000000000000000000000000 exceeds reservoir level of 0.000000000000000000411195000000000000000000000; bid will not be submitted`
{% endhint %}

## Swapping Bought Collateral for System Coins

The collateral keeper can swap collateral for system coins automatically when it's exited from the system using Uniswap V2. This allows the keeper to have plenty of system coins available next time it starts.To turn this option on, use this flag inside `run_auction_keeper.sh`:

`--swap-collateral`

To set the max allowable slippage percentage on Uniswap V2, set this flag:

`--max-swap-slippage <float>, default: 0.01`

{% hint style="info" %}
Use `--swap-collateral` with `--safe-engine-system-coin-target ALL`(the default) to ensure won collateral is automatically converted to system coins
{% endhint %}

## Exiting Collateral from the System

By default, the keeper will periodically exit collateral (that was bought from auctions) from the system. &#x20;

To adjust the interval at which the keeper exits collateral, set:

`--return-collateral-interval, default:300 secs`

By default, the keeper will `exit` all of its collateral when it's shutting down.&#x20;

To leave won collateral in the system on exit, specify this inside `run_auction_keeper.sh`:\
`--keep-collateral-in-safe-engine-on-exit`

```
Exiting 0.344424752741987967 ETH-A from the SAFE Engine
Sent transaction <pyflex.gf.BasicCollateralJoin object at 0x7f0b7e92b5f8>.exit('0xdD1693BD8E307eCfDbe51D246562fc4109f871f8', 344424752741987967) with nonce=210, gas=153991, gas_price=30000000000 (tx_hash=0x88266148371a3dfea081fbc378c802ad02ef2bd9e0ccdfabfa2a53894dbffd7f)
Transaction <pyflex.gf.BasicCollateralJoin object at 0x7f0b7e92b5f8>.exit('0xdD1693BD8E307eCfDbe51D246562fc4109f871f8', 344424752741987967) was successful (tx_hash=0x88266148371a3dfea081fbc378c802ad02ef2bd9e0ccdfabfa2a53894dbffd7f)
Shutdown logic finished
Keeper terminated
```


# Collateral Auction Flash Swaps

Lightning fast bidding in collateral auctions

## Overview

Normally, the collateral [auction-keeper](https://github.com/reflexer-labs/auction-keeper) uses system coins to bid in fixed discount collateral auctions. A keeper operator must acquire system coins to be prepared for future collateral auctions. With collateral auction flash swaps, this is no longer necessary.

The auction-keeper can be configured to use Uniswap v2 or v3 flash swaps when bidding in collateral auctions. This allows the keeper to participate in collateral auctions with no upfront capital other than gas costs to execute the transaction.

## Details

The collateral auction-keeper performs flash swaps using the [geb-keeper-flash-proxy](https://github.com/reflexer-labs/geb-keeper-flash-proxy) contracts.

The flash proxy is used by the auction-keeper to:

1\) Liquidate an underwater SAFE, start a new collateral auction and bid by calling `liquidateAndSettleSAFE`

or

2\) Bid in existing auctions by calling `settleAuction`

### Uniswap Pools Used for Bidding

* [RAI/DAI Uniswap V3](https://info.uniswap.org/#/pools/0xcb0c5d9d92f4f2f80cce7aa271a1e148c226e19d)
* [RAI/ETH Uniswap V2](https://v2.info.uniswap.org/pair/0x8ae720a71622e824f576b4a8c03031066548a3b1)
* [RAI/USDC Uniswap V3](https://info.uniswap.org/#/pools/0xfa7d7a0858a45c1b3b7238522a0c0d123900c118)
* [RAI/ETH Uniswap V3](https://info.uniswap.org/#/pools/0x14de8287adc90f0f95bf567c0707670de52e3813)

## Configuration

You can enable flashswaps using the `--flash-swaps` flag when starting a collateral auction-keeper.

You can also specify multiple pools that the keeper loops through when trying to bid in an auction. You do this using the `--flash-swap-pools` flag. For example:&#x20;

```
--flash-swap-pools eth-v2, dai-v3, usdc-v3, eth-v3
```

If a flash swap for a specific pool fails, the next in order will be tried.

The default order is `dai-v3, eth-v2, usdc-v3, eth-v3`.

## Flash Swaps in Action

Below is a log output from an *auction-keeper* started with the `--flash-swap` and `--flash-swap-pools usdc-v3,dai-v3,eth-v2,eth-v3` flags.

First, the *auction-keeper* finds two undercollateralized SAFEs and successfully calls `liquidateAndSettleSAFE` using the `usdc-v3` flash proxy. The second SAFE is a large one so the call fails due to lack of liquidity in the RAI/USDC Uniswap v3 pool. The *auction-keeper* then successfully uses the RAI/DAI Uniswap v3 flash-proxy to liquidate the large SAFE.

Finally, the *auction-keeper* finds a third ciritcal SAFE and successfully uses the RAI/USDC Uniswap v3 flash proxy to `liquidateAndSettleSAFE`.

```
2021-08-26 14:25:18,258 INFO     Keeper connected to RPC connection http://172.31.46.114:8545
2021-08-26 14:25:18,259 INFO     Keeper operating as 0xdD1693BD8E306eCfDbe41D246562fc4109f871f8
2021-08-26 14:25:18,289 INFO     Executing keeper startup logic
2021-08-26 14:25:19,375 INFO     Keeper will not settle auctions
2021-08-26 14:25:19,375 INFO     Keeper will perform the following operation(s) in parallel:
2021-08-26 14:25:19,375 INFO     --> Check all safes and start new auctions if any critical safes need to be liquidated
2021-08-26 14:25:19,375 INFO     --> Check all auctions being monitored and evaluate bidding opportunity every 4.0 seconds
2021-08-26 14:25:19,375 INFO     *** When Keeper is settling/bidding, the initial evaluation of auctions will likely take > 45 minutes without setting a lower boundary via '--min-auction' ***
2021-08-26 14:25:19,375 INFO     *** When Keeper is starting auctions, initializing safe history may take > 30 minutes without using Graph via `--graph-endpoints` ***
2021-08-26 14:25:19,378 INFO     Keeper will use Node gas price (currently 2.0 Gwei, changes over time) with initial multiplier 1.0 and will multiply by 1.125 every 42s to a maximum of 2000.0 Gwei for transactions and bids unless model instructs otherwise
2021-08-26 14:25:19,658 INFO     Watching for new blocks
2021-08-26 14:25:19,664 INFO     Started 2 timer(s)
2021-08-26 14:25:20,750 INFO     Getting safe mods from https://api.thegraph.com/subgraphs/name/reflexer-labs/rai-kovan
2021-08-26 14:25:20,752 INFO     Fetching safe modes from https://api.thegraph.com/subgraphs/name/reflexer-labs/rai-kovan
2021-08-26 14:25:42,418 INFO     Using usdc-v3 flash swap to liquidate and settle safe 0xA0be17B5C408aaFF03e0E3434de199F6df94fFC7
2021-08-26 14:25:42,946 INFO     Sent transaction GebETHKeeperFlashProxy('0x8a8970c74Ca60c954b32D1015D4563908eB798Fd').liquidateAndSettleSAFE('0xA0be17B5C408aaFF03e0E3434de199F6df94fFC7') with nonce=4964, gas=2000000, gas_price=2000000000 (tx_hash=0xdf19ae2f76def32a3c797ef51b614ddf6b680ad38ecbe3910b154a4c4228eb0f)
2021-08-26 14:25:44,423 INFO     Transaction GebETHKeeperFlashProxy('0x8a8970c74Ca60c954b32D1015D4563908eB798Fd').liquidateAndSettleSAFE('0xA0be17B5C408aaFF03e0E3434de199F6df94fFC7') was successful (tx_hash=0xdf19ae2f76def32a3c797ef51b614ddf6b680ad38ecbe3910b154a4c4228eb0f)
2021-08-26 14:25:44,519 INFO     Using usdc-v3 flash swap to liquidate and settle safe 0xa46B5d01326d858856396fb80bD06654ED64770f
2021-08-26 14:25:44,820 WARNING  Transaction GebETHKeeperFlashProxy('0x8a8970c74Ca60c954b32D1015D4563908eB798Fd').liquidateAndSettleSAFE('0xa46B5d01326d858856396fb80bD06654ED64770f') will fail, refusing to send (execution reverted: failed bidding)
2021-08-26 14:25:44,821 WARNING  flash swap liquidate and settle with pool usdc-v3 failed.
2021-08-26 14:25:44,821 INFO     Using dai-v3 flash swap to liquidate and settle safe 0xa46B5d01326d858856396fb80bD06654ED64770f
2021-08-26 14:25:45,223 INFO     Sent transaction GebETHKeeperFlashProxy('0x26232B7Fe0dD0Ade6192Bd69438dBEc424EF7a59').liquidateAndSettleSAFE('0xa46B5d01326d858856396fb80bD06654ED64770f') with nonce=4965, gas=2000000, gas_price=2000000000 (tx_hash=0xb4c177c114874ee267a8e2d47a3bd075936372996eeebbf3caf1decb881f2737)
2021-08-26 14:25:52,724 INFO     Transaction GebETHKeeperFlashProxy('0x26232B7Fe0dD0Ade6192Bd69438dBEc424EF7a59').liquidateAndSettleSAFE('0xa46B5d01326d858856396fb80bD06654ED64770f') was successful (tx_hash=0xb4c177c114874ee267a8e2d47a3bd075936372996eeebbf3caf1decb881f2737)
2021-08-26 14:25:53,171 INFO     Using usdc-v3 flash swap to liquidate and settle safe 0x20aE373C782b03925413a394EE620A4BF2828a60
2021-08-26 14:25:53,744 INFO     Sent transaction GebETHKeeperFlashProxy('0x8a8970c74Ca60c954b32D1015D4563908eB798Fd').liquidateAndSettleSAFE('0x20aE373C782b03925413a394EE620A4BF2828a60') with nonce=4966, gas=2000000, gas_price=2000000000 (tx_hash=0xf4d45385753219c5a9a7fb28f7d60e0e4b4d42eb05d8d65f50deb09308cfd1ba)
2021-08-26 14:25:56,851 INFO     Transaction GebETHKeeperFlashProxy('0x8a8970c74Ca60c954b32D1015D4563908eB798Fd').liquidateAndSettleSAFE('0x20aE373C782b03925413a394EE620A4BF2828a60') was successful (tx_hash=0xf4d45385753219c5a9a7fb28f7d60e0e4b4d42eb05d8d65f50deb09308cfd1ba)
```

## Caveats

* Flash swaps are only supported for collateral auctions.
* *auction-keeper* will not do flash swaps on critical SAFEs with saviours. Read more about saviours [here](https://docs.reflexer.finance/liquidation-protection/safe-protection).

## Possible errors

When liquidity is too low, calls to flash proxys will revert *or* run out of gas. In this case, the *auction-keeper* will try to use the next Uniswap pool specified in `--flash-swap-pools`. In the unlikely case where all calls fail (none of the pools have enough liquidity), the auction-keeper can be restarted without `--flash-swap` to bid normally using the keeper’s system coin balance inside the [SAFEEngine](https://docs.reflexer.finance/system-contracts/core/safe-engine).


# Debt Auction Keeper

How to run a debt auction keeper

This mini guide will walk you through running a debt auction keeper in Docker & also directly on a host.


# Running in Docker

Running a debt auction keeper in a Docker container

## 1. Get RAI

Buy RAI or [open a SAFE](https://app.gitbook.com/@reflexer-labs/s/geb/pyflex/safe-management/opening-a-safe) to generate it.

## 2. Modify the model file as needed

A basic debt auction bidding model can be found in `models/debt_model.py`. This model retrieves the latest FLX/USD price from Coingecko and will automatically place bids in an auction.

You probably want to modify the following variables in `models/debt_model.py`:

* `MAXIMUM_FLX_MULTIPLIER`: the maximum acceptable FLX price to use when bidding. Default: `0.90` meaning the maximum price to pay when biding for FLX (with RAI) is 90% of the current FLX/USD market price from Coingecko
* `MY_BID_DECREASE`: the bid decrease (in FLX) to propose when outbidding another bidder. If the value is smaller than the debt auction house's `bidDecrease`, then it will use the value set in the debt auction house. Example: a value of `1.10` will use bid decreases of 10%. Note: the current `bidDecrease` on mainnet is `1.03`

Then, use `chmod +x debt_model.py`.

For more information about bidding models, see [this](https://docs.reflexer.finance/keepers/bidding-models).

## 3) Modify the keeper run file

Modify the following variables in `run_debt_keeper.sh`:

* `KEEPER_ADDRESS` - the keeper's address. It should be in checksummed format (not lowercase)
* `ETH_RPC_URL` - the URL of your Ethereum RPC connection
* `KEYSTORE_DIR` - the full path of the directory where your keystore file is
* `MODEL_DIR` - the full path of directory where your `surplus_model.py` file is
* `KEYSTORE_FILE` - your Ethereum UTC JSON keystore filename. For more information about the keystore format and how to generate it, check [Ethereum UTC / JSON Wallet Encryption](https://wizardforcel.gitbooks.io/practical-cryptography-for-developers-book/content/symmetric-key-ciphers/ethereum-wallet-encryption.html) or[ keythereum](https://github.com/ethereumjs/keythereum).
* `GAS_MAXIMUM` -maximum gas price, in GWEI

Then, use `chmod +x run_debt_keeper.sh`.

## 4) Start the keeper and enter your keystore file password

Use `./run_debt_keeper.sh`.

```
$ ./run_debt_keeper.sh
latest: Pulling from reflexer/auction-keeper
Digest: sha256:7e55ec9b0a136fc903d9f7f2690538bcbde9029d957e0e6f84d0282790f9666a
Status: Downloaded newer image for reflexer/auction-keeper:latest
docker.io/reflexer/auction-keeper:latest
Password for /keystore/key.json:
```

## Debt Auction Output

Sample[ debt auction output](#debt-auctioning-process)


# Running on a Host

Running a debt auction keeper directly on a host

## Prerequisites

Python 3.6+

### Get RAI

Buy RAI from Uniswap v2 or [open a SAFE](https://app.gitbook.com/@reflexer-labs/s/geb/pyflex/safe-management/opening-a-safe) and generate it.

### Clone

```
git clone https://github.com/reflexer-labs/auction-keeper.git
cd auction-keeper
git submodule update --init --recursive
```

### Install

This creates a virtual environment and installs all the keeper dependencies:

`./install.sh`

## 1) Start virtualenv

`source _virtualenv/bin/activate`

## 2) Modify model file as needed

A basic debt auction bidding model can be found in `models/debt_model.py`. This model retrieves the latest FLX/USD price from coingecko and will automatically place bids in an auction.

You probably want to modify the following variables in `models/debt_model.py`:

`MAXIMUM_FLX_MULTIPLIER`: The maximum acceptable FLX price to use when bidding. Default: `0.90` meaning the maximum price to pay when buying FLX(in RAI) is 90% of the current FLX/USD market price

`MY_BID_DECREASE`: The amount of bid decrease(in FLX) to make when outbidding another bidder. If value is less than the auction house' `bidDecrease`, then it will use the auction house setting. Example: A value of `1.10` will create bid decreases of 10%. Note: Current `bidDecrease` on mainnet is `1.03`. Default: `1.03`

### Then:

`chmod +x debt_model.py`

For more information about bidding models, see [Bidding Models](/keepers/bidding-models)

## 3) Modify keeper run file

Modify the following variables in `run_debt_keeper_host.sh`

`KEEPER_ADDRESS` - the keeper's address. It should be in checksummed format (not lowercase)

`ETH_RPC_URL` - the URL of your Ethereum RPC connection

`KEYSTORE_DIR` - the full path of the directory where your keystore file is

`MODEL_DIR` - the full path of directory where your `debt_model.py` file is

`KEYSTORE_FILE` - your Ethereum UTC JSON keystore filename

For more information about this keystore format and how to generate them, check:

* [Ethereum UTC / JSON Wallet Encryption](https://wizardforcel.gitbooks.io/practical-cryptography-for-developers-book/content/symmetric-key-ciphers/ethereum-wallet-encryption.html)
* [keythereum](https://github.com/ethereumjs/keythereum)

`GAS_MAXIMUM` -maximum gas price, in GWEI

### Then:

`chmod +x run_debt_keeper_host.sh`

## 4) Start the keeper and enter your keystore file password

`./run_debt_keeper_host.sh`

```
$ ./run_debt_keeper_host.sh
Password for /keystore/key.json:
```

## Debt Auction Output

#### Pop Debt from the Queue

If debt from collateral auctions still exists after `AccountingEngine.pop_debt_delay()`, the surplus *auction-keeper* will call `popDebtFromQueue()`

```
2021-01-20 04:16:22,462 INFO     Sent transaction AccountingEngine('0x73EC2a627655134886477D10A41275f54556E0e2').popDebtFromQueue(1611116032) with nonce=1519, gas=159390, gas_price=10000000000 (tx_hash=0x7266984842ce52d8df52a775d889bb7040e0bac742d51f369e0c23e3e89dd560)
```

#### Settle Debt

Before starting a debt auction, the keeper will use any surplus to offset any existing debt. It does this by calling `settleDebt()`

```
2021-01-20 04:16:32,983 INFO     Settling debt coin balance=192.720512165128879832575769589252154674198975198 unqueued_enauctioned_debt=686.568045684729064016811194323877100504725525932
2021-01-20 04:16:33,793 INFO     Sent transaction AccountingEngine('0x73EC2a627655134886477D10A41275f54556E0e2').settleDebt(192720512165128879832575769589252154674198975198) with nonce=1520, gas=171354, gas_price=10000000000 (tx_hash=0x92d16108db353e25b70a743eefb84568f640f3ab4241d5cfa43c147126080d4b)
```

#### Starting a Debt Auction

Finally, if debt still exists and is enough to start an auction, the *auction-keeper* will call `auctionDebt`

```
2021-01-20 04:16:40,596 INFO     Initiating a debt auction with unqueued_unauctioned_debt=493.847533519600184184235424734624945830526550734
2021-01-20 04:16:41,382 INFO     Sent transaction AccountingEngine('0x73EC2a627655134886477D10A41275f54556E0e2').auctionDebt() with nonce=1521, gas=306628, gas_price=1
0000000000 (tx_hash=0x9ff7a02e85a30c361768639729678df615eba7f10a69505c1aaa4cc88818c73d)
```

#### Full Log Output

```
[ec2-user@ip-172-31-40-135 ~]$ ./run_debt_auction_keeper.sh
upstream: Pulling from reflexer/auction-keeper
Digest: sha256:d222e4d8d948262af15fbc09e64973a6df65eb0f96023ea3ec7179674d87f28c
Status: Image is up to date for reflexer/auction-keeper:upstream
docker.io/reflexer/auction-keeper:upstream
Password for /keystore/keystore.json: 
2021-01-20 04:16:01,302 INFO     Keeper connected to RPC connection https://myparitynode.com
2021-01-20 04:16:01,302 INFO     Keeper operating as 0xdD1693BD8E307eCfDbe51D246562fc4109f871f8
2021-01-20 04:16:01,646 INFO     Executing keeper startup logic
2021-01-20 04:16:02,714 INFO     Checking if internal system coin balance needs to be rebalanced
2021-01-20 04:16:02,749 INFO     Joining 1480.613947077334748390 system coin to the SAFE Engine
2021-01-20 04:16:02,816 INFO     Sent transaction <pyflex.gf.CoinJoin object at 0x7f56f75ae358>.join('0xdD1693BD8E307eCfDbe51D246562fc4109f871f8', 1480613947077334748390) with nonce=1518, gas=159975, gas_price=10000000000 (tx_hash=0x79982c65d2aece7a71e4c475e1a90afd8056811dbec6f6a82a844e637192c47e)
2021-01-20 04:16:12,665 INFO     Transaction <pyflex.gf.CoinJoin object at 0x7f56f75ae358>.join('0xdD1693BD8E307eCfDbe51D246562fc4109f871f8', 1480613947077334748390) was successful (tx_hash=0x79982c65d2aece7a71e4c475e1a90afd8056811dbec6f6a82a844e637192c47e)
2021-01-20 04:16:12,666 INFO     Keeper will perform the following operation(s) in parallel:
2021-01-20 04:16:12,666 INFO     --> Check thresholds in Accounting Engine Contract and start new debt auctions once reached
2021-01-20 04:16:12,666 INFO     --> Check all auctions being monitored and evaluate bidding opportunity every 4.0 seconds
2021-01-20 04:16:12,667 INFO     --> Check all auctions and settle for 0xdD1693BD8E307eCfDbe51D246562fc4109f871f8
2021-01-20 04:16:12,671 INFO     Keeper will use Node gas price (currently 10.0 Gwei, changes over time) with initial multiplier 1.0 and will multiply by 1.125 every 42s to a maximum of 2000.0 Gwei for transactions and bids unless model instructs otherwise
2021-01-20 04:16:13,898 INFO     Watching for new blocks
2021-01-20 04:16:13,900 INFO     Started 2 timer(s)
2021-01-20 04:16:22,462 INFO     Sent transaction AccountingEngine('0x73EC2a627655134886477D10A41275f54556E0e2').popDebtFromQueue(1611116032) with nonce=1519, gas=159390, gas_price=10000000000 (tx_hash=0x7266984842ce52d8df52a775d889bb7040e0bac742d51f369e0c23e3e89dd560)
2021-01-20 04:16:32,881 INFO     Transaction AccountingEngine('0x73EC2a627655134886477D10A41275f54556E0e2').popDebtFromQueue(1611116032) was successful (tx_hash=0x7266984842ce52d8df52a775d889bb7040e0bac742d51f369e0c23e3e89dd560)
2021-01-20 04:16:32,983 INFO     Settling debt coin balance=192.720512165128879832575769589252154674198975198 unqueued_enauctioned_debt=686.568045684729064016811194323877100504725525932
2021-01-20 04:16:33,793 INFO     Sent transaction AccountingEngine('0x73EC2a627655134886477D10A41275f54556E0e2').settleDebt(192720512165128879832575769589252154674198975198) with nonce=1520, gas=171354, gas_price=10000000000 (tx_hash=0x92d16108db353e25b70a743eefb84568f640f3ab4241d5cfa43c147126080d4b)
2021-01-20 04:16:40,536 INFO     Transaction AccountingEngine('0x73EC2a627655134886477D10A41275f54556E0e2').settleDebt(192720512165128879832575769589252154674198975198
) was successful (tx_hash=0x92d16108db353e25b70a743eefb84568f640f3ab4241d5cfa43c147126080d4b)
2021-01-20 04:16:40,596 INFO     Initiating a debt auction with unqueued_unauctioned_debt=493.847533519600184184235424734624945830526550734
2021-01-20 04:16:41,382 INFO     Sent transaction AccountingEngine('0x73EC2a627655134886477D10A41275f54556E0e2').auctionDebt() with nonce=1521, gas=306628, gas_price=1
0000000000 (tx_hash=0x9ff7a02e85a30c361768639729678df615eba7f10a69505c1aaa4cc88818c73d)
2021-01-20 04:16:44,491 INFO     Transaction AccountingEngine('0x73EC2a627655134886477D10A41275f54556E0e2').auctionDebt() was successful (tx_hash=0x9ff7a02e85a30c36176
8639729678df615eba7f10a69505c1aaa4cc88818c73d)
2021-01-20 04:16:44,636 INFO     Started monitoring auction #7
2021-01-20 04:16:44,637 INFO     Instantiated model using process '/models/debt_model.sh --id 7 --debt_auction_house 0xBD0E4aC6061Df1eA95CaDfb04707892cCb750531'
2021-01-20 04:16:44,652 INFO     Process '/models/debt_model.sh --id 7 --debt_auction_house 0xBD0E4aC6061Df1eA95CaDfb04707892cCb750531' (pid #35) started
2021-01-20 04:16:44,664 INFO     Checked auctions 0 to 7 in 0 seconds
2021-01-20 04:16:44,977 INFO     Initiating a debt auction with unqueued_unauctioned_debt=408.847533519600184184235424734624945830526550734
2021-01-20 04:16:45,210 INFO     Sent transaction AccountingEngine('0x73EC2a627655134886477D10A41275f54556E0e2').auctionDebt() with nonce=1522, gas=276628, gas_price=1
0000000000 (tx_hash=0xd87e9c0a2c6512340602426b9530c822b6c58b30eaa61021a3c314c7c30fe41c)
2021-01-20 04:16:46,965 INFO     Sending new bid @100.000000000000000000 for auction 7
2021-01-20 04:16:47,020 INFO     Sent transaction DebtAuctionHouse('0xBD0E4aC6061Df1eA95CaDfb04707892cCb750531').decreaseSoldAmount(7, 850000000000000000, 850000000000
00000000000000000000000000000000000) with nonce=1523, gas=234777, gas_price=10000000000 (tx_hash=0xaffbe93a1f901d1a43ed331284cb76f5e01b64cddc2dc1b6978b0473021b8072)
2021-01-20 04:16:53,038 INFO     Transaction AccountingEngine('0x73EC2a627655134886477D10A41275f54556E0e2').auctionDebt() was successful (tx_hash=0xd87e9c0a2c651234060
2426b9530c822b6c58b30eaa61021a3c314c7c30fe41c)
2021-01-20 04:16:53,040 INFO     Transaction DebtAuctionHouse('0xBD0E4aC6061Df1eA95CaDfb04707892cCb750531').decreaseSoldAmount(7, 850000000000000000, 85000000000000000
000000000000000000000000000000) was successful (tx_hash=0xaffbe93a1f901d1a43ed331284cb76f5e01b64cddc2dc1b6978b0473021b8072)
2021-01-20 04:16:53,216 INFO     Started monitoring auction #8
2021-01-20 04:16:53,216 INFO     Instantiated model using process '/models/debt_model.sh --id 8 --debt_auction_house 0xBD0E4aC6061Df1eA95CaDfb04707892cCb750531'
2021-01-20 04:16:53,236 INFO     Process '/models/debt_model.sh --id 8 --debt_auction_house 0xBD0E4aC6061Df1eA95CaDfb04707892cCb750531' (pid #44) started
2021-01-20 04:16:53,252 INFO     Checked auctions 0 to 8 in 0 seconds
2021-01-20 04:16:54,094 INFO     Initiating a debt auction with unqueued_unauctioned_debt=323.847533519600184184235424734624945830526550734
```


# Staked Token Auction Keeper

How to run a staked token auction keeper

This mini guide will walk you through running a staked token (FLX/ETH LP) auction keeper in Docker & also directly on a host.


# Running in Docker

Running a staked token auction keeper in a Docker container

## 1. Get RAI

Buy RAI or [open a SAFE](https://app.gitbook.com/@reflexer-labs/s/geb/pyflex/safe-management/opening-a-safe) to generate it.

## 2. Modify the model file as needed

A basic staked token auction bidding model can be found in `models/debt_staked_model.py`. This model retrieves the latest FLX/USD price from Coingecko and will automatically place bids in an auction.

You probably want to modify the following variables in `models/debt_model.py`:

* `MAXIMUM_FLX_MULTIPLIER`: the maximum acceptable FLX price to use when bidding. Default: `0.90` meaning the maximum price to pay when biding for FLX (with RAI) is 90% of the current FLX/USD market price from Coingecko
* `MINIMUM_FLX_MULTIPLIER`: the minimum FLX price to use when bidding. This will determine your opening bid. Default: `0.50` meaning the minimumm price to pay when biding for FLX (with RAI) is 50% of the current FLX/USD market price coming from Coingecko
* `MY_BID_INCREASE`: the bid increase (in RAI) to propose when outbidding another bidder. If the value is smaller than the staked token auction house's `bidIncrease`, then it will use the value set in the staked token auction house. Example: a value of `1.10` will use bid increases of 10%. Note: the current `bidIncrease` on mainnet is `1.05`

Then, use `chmod +x debt_staked_model.py`.

For more information about bidding models, see [this](https://docs.reflexer.finance/keepers/bidding-models).

### 3) Modify the keeper run file

Modify the following variables in `run_debt_keeper.sh`:

* `KEEPER_ADDRESS` - the keeper's address. It should be in checksummed format (not lowercase)
* `ETH_RPC_URL` - the URL of your Ethereum RPC connection
* `KEYSTORE_DIR` - the full path of the directory where your keystore file is
* `MODEL_DIR` - the full path of directory where your `surplus_model.py` file is
* `KEYSTORE_FILE` - your Ethereum UTC JSON keystore filename. For more information about the keystore format and how to generate it, check [Ethereum UTC / JSON Wallet Encryption](https://wizardforcel.gitbooks.io/practical-cryptography-for-developers-book/content/symmetric-key-ciphers/ethereum-wallet-encryption.html) or[ keythereum](https://github.com/ethereumjs/keythereum).
* `GAS_MAXIMUM`- maximum gas price, in GWEI

Then, use `chmod +x run_debt_keeper.sh`.

### 4) Start the keeper and enter your keystore file password

Use `./run_debt_staked_keeper.sh`.

```
$ ./run_debt_staked_keeper.sh
latest: Pulling from reflexer/auction-keeper
Digest: sha256:7e55ec9b0a136fc903d9f7f2690538bcbde9029d957e0e6f84d0282790f9666a
Status: Downloaded newer image for reflexer/auction-keeper:latest
docker.io/reflexer/auction-keeper:latest
Password for /keystore/key.json:
```


# Running on a Host

Running a staked token auction keeper directly on a host

## Prerequisites

Python 3.6+

### Get RAI

Buy RAI from Uniswap v2 or [open a SAFE](https://app.gitbook.com/@reflexer-labs/s/geb/pyflex/safe-management/opening-a-safe) and generate it.

### Clone

```
git clone https://github.com/reflexer-labs/auction-keeper.git
cd auction-keeper
git submodule update --init --recursive
```

### Install

This creates a virtual environment and installs all the keeper dependencies:

`./install.sh`

## 1) Start virtualenv

`source _virtualenv/bin/activate`

## 2) Modify model file as needed

A basic debt staked auction bidding model can be found in `models/debt_staked_model.py`. This model retrieves the latest FLX/USD price from Coingecko and will automatically place bids in an auction.

You probably want to modify the following variables in `models/debt_staked_model.py`:

* `MAXIMUM_FLX_MULTIPLIER`: the maximum acceptable FLX price to use when bidding. Default: `0.90` meaning the maximum price to pay when biding for FLX (with RAI) is 90% of the current FLX/USD market price coming from Coingecko
* `MINIMUM_FLX_MULTIPLIER`: the minimumum FLX price to use when bidding. This will determine your opening bid. Default: `0.50` meaning the minimumm price to pay when biding for FLX (with RAI) is 50% of the current FLX/USD market price from Coingecko
* `MY_BID_INCREASE`: the bid increase (in RAI) to propose when outbidding another bidder. If the value is smaller than the staked token auction house's `bidIncrease`, then it will use the value set in the staked token auction house. Example: a value of `1.10` will use bid increases of 10%. Note: the current `bidIncrease` on mainnet is `1.05`

#### Then:

`chmod +x debt_staked_model.py`

For more information about bidding models, see [Bidding Models](https://github.com/reflexer-labs/auction-keeper/blob/master/bidding-models.md).

## 3) Modify keeper run file

Modify the following variables in `run_debt_keeper_host.sh`:

* `KEEPER_ADDRESS` - the keeper's address. It should be in checksummed format (not lowercase)
* `ETH_RPC_URL` - the URL of your Ethereum RPC connection
* `KEYSTORE_DIR` - the full path of the directory where your keystore file is
* `MODEL_DIR` - the full path of directory where your `debt_model.py` file is
* `KEYSTORE_FILE` - your Ethereum UTC JSON keystore filename For more information about this keystore format and how to generate them, check [keythereum](https://github.com/ethereumjs/keythereum) or [Ethereum UTC / JSON Wallet Encryption](https://wizardforcel.gitbooks.io/practical-cryptography-for-developers-book/content/symmetric-key-ciphers/ethereum-wallet-encryption.html).
* `GAS_MAXIMUM` -maximum gas price, in GWEI

#### Then:

`chmod +x run_debt_staked_keeper_host.sh`

## 4) Start the keeper and enter your keystore file password

`./run_debt_staked_keeper_host.sh`

```
$ ./run_debt_staked_keeper_host.sh
Password for /keystore/key.json:
```

## Staked Token Auction Output

If debt from collateral auctions still exists after `AccountingEngine.pop_debt_delay()`, the debt staked *auction-keeper* will call `popDebtFromQueue()`:

```
2021-01-20 04:16:22,462 INFO     Sent transaction AccountingEngine('0x73EC2a627655134886477D10A41275f54556E0e2').popDebtFromQueue(1611116032) with nonce=1519, gas=159390, gas_price=10000000000 (tx_hash=0x7266984842ce52d8df52a775d889bb7040e0bac742d51f369e0c23e3e89dd560)
```

### Settling debt

Before starting a staked token auction, the keeper will use any surplus to offset any existing debt. It does this by calling `settleDebt()`:

```
2022-07-11 20:49:06,502 INFO     Settling debt. coin_balance=0.003849105356317367507721355548000000000000000 unqueued_enauctioned_debt=34709.319942457639191758056217752288276396399199497
2022-07-11 20:49:06,798 INFO     Sent transaction AccountingEngine('0x6073E8FE874B53732b5DdD469a2De4047f33C64B').settleDebt(3849105356317367507721355548000000000000000) with nonce=5502, gas=160806, gas_price=2500000007 (tx_hash=0x0cbf049a593cca6eaee174bb19be503736adc0562bf5837b4f2acb3e3dc37435)
2022-07-11 20:49:08,855 INFO     Transaction AccountingEngine('0x6073E8FE874B53732b5DdD469a2De4047f33C64B').settleDebt(3849105356317367507721355548000000000000000) was successful (tx_hash=0x0cbf049a593cca6eaee174bb19be503736adc0562bf5837b4f2acb3e3dc37435)
```

### Starting a Staked Token Auction

Finally, if debt still exists and is enough to start a staked token auction, the *auction-keeper* will call `auctionAncestorTokens()` in the `StakingPool`:

```
2022-07-11 20:49:09,467 INFO     Sent transaction <pyflex.gf.GebStaking object at 0x7f7bf8ddc190>.auctionAncestorTokens() with nonce=5503, gas=428111, gas_price=2500000007 (tx_hash=0xba5e1523fc60666010554b644a69e826375a28ed393a2498982db0eb2097e751)
2022-07-11 20:49:12,900 INFO     Transaction <pyflex.gf.GebStaking object at 0x7f7bf8ddc190>.auctionAncestorTokens() was successful (tx_hash=0xba5e1523fc60666010554b644a69e826375a28ed393a2498982db0eb2097e751)
```

### Bidding in a Staked Token Auction

To bid in staked token auctions, the *auction-keeper* calls `increaseBidSize()`:

```
2022-07-11 20:49:13,106 INFO     Started monitoring auction #11
2022-07-11 20:49:13,106 INFO     Instantiated model using process '/models/debt_staked_model.py --id 11 --staked_token_auction_house 0x328BCbF2d4c2D78936f52172c741456136FA7e92'
2022-07-11 20:49:13,115 INFO     Process '/models/debt_staked_model.py --id 11 --staked_token_auction_house 0x328BCbF2d4c2D78936f52172c741456136FA7e92' (pid #23) started
2022-07-11 20:49:13,204 INFO     Feeding auction 11 model input {'id': '11', 'bid_amount': '0.000000000000000000000000001000000000000000000', 'amount_to_sell': '0.001000000000000000', 'block_time': 1657572552, 'auction_deadline': 1657573452, 'price': '0.000000000000000000', 'bid_increase': '1.050000000000000000', 'high_bidder': '0x0000000000000000000000000000000000000000', 'staked_token_auction_house': '0x328BCbF2d4c2D78936f52172c741456136FA7e92'}
2022-07-11 20:49:13,238 INFO     Checked auctions 11 to 11 in 0 seconds
2022-07-11 20:49:26,756 INFO     Sending new bid @0.256000000000000000 for auction 11
2022-07-11 20:49:26,965 INFO     Sent transaction StakedTokenAuctionHouse('0x328BCbF2d4c2D78936f52172c741456136FA7e92').increaseBidSize(11, 1000000000000000, 1283356467456783863967795170000000000000000) with nonce=5504, gas=182102, gas_price=2500000007 (tx_hash=0x6b9c65ebd0b55090af120543d4024d095059ddf66542af997e1fb6543fa1e22c)
2022-07-11 20:49:29,322 INFO     Transaction StakedTokenAuctionHouse('0x328BCbF2d4c2D78936f52172c741456136FA7e92').increaseBidSize(11, 1000000000000000, 1283356467456783863967795170000000000000000) was successful (tx_hash=0x6b9c65ebd0b55090af120543d4024d095059ddf66542af997e1fb6543fa1e22c)
```

### Settling a Staked Token Auction

To settle a staked token auction, the *auction-keeper* calls `settleAuction()`:

```
2022-07-11 20:59:51,693 INFO     Sent transaction StakedTokenAuctionHouse('0x328BCbF2d4c2D78936f52172c741456136FA7e92').settleAuction(11) with nonce=55
07, gas=227887, gas_price=2500000007 (tx_hash=0x4e1d347341b9e4e1567aff93585db3fb7529b024a8282ffa6d1da2164d7264f3)
2022-07-11 20:59:52,715 INFO     Transaction StakedTokenAuctionHouse('0x328BCbF2d4c2D78936f52172c741456136FA7e92').settleAuction(11) was successful (tx
_hash=0x4e1d347341b9e4e1567aff93585db3fb7529b024a8282ffa6d1da2164d7264f3)
```

### Full Log Output

```
[ec2-user@ip-172-31-40-135 ~]$  ./run_debt_staked_keeper.sh 
Password for /keystore/keystore.json: 
2022-07-11 20:48:43,736 INFO     Keeper connected to RPC connection https://eth-kovan.alchemyapi.io/v2blahblahblah/
2022-07-11 20:48:43,736 INFO     Keeper operating as 0xdD1693BD8E307eCfDbe51D246562fc4109f871f8
2022-07-11 20:48:43,928 INFO     Executing keeper startup logic
2022-07-11 20:48:45,427 INFO     Keeper will perform the following operation(s) in parallel:
2022-07-11 20:48:45,427 INFO     --> Check thresholds in Accounting Engine Contract and start new debt_staked auctions once reached
2022-07-11 20:48:45,427 INFO     --> Check all auctions being monitored and evaluate bidding opportunity every 20.0 seconds
2022-07-11 20:48:45,427 INFO     --> Check all auctions and settle for any address
2022-07-11 20:48:45,471 INFO     Keeper will use Node gas price (currently 2.5 Gwei, changes over time) with initial multiplier 1.0 and will multiply by 1.125 every 42s to a maximum of 200.0 Gwei for transactions and bids unless model instructs otherwise
2022-07-11 20:48:45,622 INFO     Watching for new blocks
2022-07-11 20:48:45,624 INFO     Started 2 timer(s)
2022-07-11 20:49:06,502 INFO     Settling debt. coin_balance=0.003849105356317367507721355548000000000000000 unqueued_enauctioned_debt=34709.319942457639191758056217752288276396399199497
2022-07-11 20:49:06,798 INFO     Sent transaction AccountingEngine('0x6073E8FE874B53732b5DdD469a2De4047f33C64B').settleDebt(3849105356317367507721355548000000000000000) with nonce=5502, gas=160806, gas_price=2500000007 (tx_hash=0x0cbf049a593cca6eaee174bb19be503736adc0562bf5837b4f2acb3e3dc37435)
2022-07-11 20:49:08,855 INFO     Transaction AccountingEngine('0x6073E8FE874B53732b5DdD469a2De4047f33C64B').settleDebt(3849105356317367507721355548000000000000000) was successful (tx_hash=0x0cbf049a593cca6eaee174bb19be503736adc0562bf5837b4f2acb3e3dc37435)
2022-07-11 20:49:09,467 INFO     Sent transaction <pyflex.gf.GebStaking object at 0x7f7bf8ddc190>.auctionAncestorTokens() with nonce=5503, gas=428111, gas_price=2500000007 (tx_hash=0xba5e1523fc60666010554b644a69e826375a28ed393a2498982db0eb2097e751)
2022-07-11 20:49:12,900 INFO     Transaction <pyflex.gf.GebStaking object at 0x7f7bf8ddc190>.auctionAncestorTokens() was successful (tx_hash=0xba5e1523fc60666010554b644a69e826375a28ed393a2498982db0eb2097e751)
2022-07-11 20:49:13,105 INFO     Input for auction 11: {'id': '11', 'bid_amount': '0.000000000000000000000000001000000000000000000', 'amount_to_sell': '0.001000000000000000', 'block_time': 1657572552, 'auction_deadline': 1657573452, 'price': '0.000000000000000000', 'bid_increase': '1.050000000000000000', 'high_bidder': '0x0000000000000000000000000000000000000000', 'staked_token_auction_house': '0x328BCbF2d4c2D78936f52172c741456136FA7e92'}
2022-07-11 20:49:13,106 INFO     Auction 11 deleted: False
2022-07-11 20:49:13,106 INFO     Started monitoring auction #11
2022-07-11 20:49:13,106 INFO     Instantiated model using process '/models/debt_staked_model.py --id 11 --staked_token_auction_house 0x328BCbF2d4c2D78936f52172c741456136FA7e92'
2022-07-11 20:49:13,115 INFO     Process '/models/debt_staked_model.py --id 11 --staked_token_auction_house 0x328BCbF2d4c2D78936f52172c741456136FA7e92' (pid #23) started
2022-07-11 20:49:13,204 INFO     Feeding auction 11 model input {'id': '11', 'bid_amount': '0.000000000000000000000000001000000000000000000', 'amount_to_sell': '0.001000000000000000', 'block_time': 1657572552, 'auction_deadline': 1657573452, 'price': '0.000000000000000000', 'bid_increase': '1.050000000000000000', 'high_bidder': '0x0000000000000000000000000000000000000000', 'staked_token_auction_house': '0x328BCbF2d4c2D78936f52172c741456136FA7e92'}
2022-07-11 20:49:13,238 INFO     Checked auctions 11 to 11 in 0 seconds
2022-07-11 20:49:26,756 INFO     Sending new bid @0.256000000000000000 for auction 11
2022-07-11 20:49:26,965 INFO     Sent transaction StakedTokenAuctionHouse('0x328BCbF2d4c2D78936f52172c741456136FA7e92').increaseBidSize(11, 1000000000000000, 1283356467456783863967795170000000000000000) with nonce=5504, gas=182102, gas_price=2500000007 (tx_hash=0x6b9c65ebd0b55090af120543d4024d095059ddf66542af997e1fb6543fa1e22c)
2022-07-11 20:49:27,084 INFO     Sent transaction <pyflex.gf.GebStaking object at 0x7f7bf8ddc190>.auctionAncestorTokens() with nonce=5505, gas=393911, gas_price=2500000007 (tx_hash=0x191649561ef51dfee298f397e0234c5ad10ecf388416328f965bbcd556ff0e78)
2022-07-11 20:49:29,322 INFO     Transaction StakedTokenAuctionHouse('0x328BCbF2d4c2D78936f52172c741456136FA7e92').increaseBidSize(11, 1000000000000000, 1283356467456783863967795170000000000000000) was successful (tx_hash=0x6b9c65ebd0b55090af120543d4024d095059ddf66542af997e1fb6543fa1e22c)
2022-07-11 20:49:29,439 INFO     Transaction <pyflex.gf.GebStaking object at 0x7f7bf8ddc190>.auctionAncestorTokens() was successful (tx_hash=0x191649561ef51dfee298f397e0234c5ad10ecf388416328f965bbcd556ff0e78)
2022-07-11 20:49:29,619 INFO     Input for auction 11: {'id': '11', 'bid_amount': '0.001283356467456783863967795170000000000000000', 'amount_to_sell': '0.001000000000000000', 'block_time': 1657572568, 'auction_deadline': 1657573452, 'price': '0.255999805335068288', 'bid_increase': '1.050000000000000000', 'high_bidder': '0xdD1693BD8E307eCfDbe51D246562fc4109f871f8', 'bid_expiry': '1657573168', 'staked_token_auction_house': '0x328BCbF2d4c2D78936f52172c741456136FA7e92'}
2022-07-11 20:49:29,619 INFO     Auction 11 deleted: False
2022-07-11 20:49:29,768 INFO     Input for auction 12: {'id': '12', 'bid_amount': '0.000000000000000000000000001000000000000000000', 'amount_to_sell': '0.001000000000000000', 'block_time': 1657572568, 'auction_deadline': 1657573468, 'price': '0.000000000000000000', 'bid_increase': '1.050000000000000000', 'high_bidder': '0x0000000000000000000000000000000000000000', 'staked_token_auction_house': '0x328BCbF2d4c2D78936f52172c741456136FA7e92'}
2022-07-11 20:49:29,768 INFO     Auction 12 deleted: False
2022-07-11 20:49:29,768 WARNING  Processing auctions [11]; ignoring [12]
2022-07-11 20:49:29,798 INFO     Checked auctions 11 to 12 in 0 seconds
2022-07-11 20:49:47,145 INFO     Sent transaction <pyflex.gf.GebStaking object at 0x7f7bf8ddc190>.auctionAncestorTokens() with nonce=5506, gas=393911, 
gas_price=2500000007 (tx_hash=0x03e820d3536bce35eaf6f22f51d8132499bb6695ac16732c31ad1ff65f48a29e)
2022-07-11 20:49:48,861 INFO     Transaction <pyflex.gf.GebStaking object at 0x7f7bf8ddc190>.auctionAncestorTokens() was successful (tx_hash=0x03e820d3
536bce35eaf6f22f51d8132499bb6695ac16732c31ad1ff65f48a29e)
2022-07-11 20:49:49,058 INFO     Input for auction 11: {'id': '11', 'bid_amount': '0.001283356467456783863967795170000000000000000', 'amount_to_sell': '0.001000000000000000', 'block_time': 1657572588, 'auction_deadline': 1657573452, 'price': '0.255998832012630103', 'bid_increase': '1.050000000000000000', 'high_bidder': '0xdD1693BD8E307eCfDbe51D246562fc4109f871f8', 'bid_expiry': '1657573168', 'staked_token_auction_house': '0x328BCbF2d4c2D78936f52172c741456136FA7e92'}
2022-07-11 20:49:49,058 INFO     Auction 11 deleted: False
2022-07-11 20:49:49,220 INFO     Input for auction 12: {'id': '12', 'bid_amount': '0.000000000000000000000000001000000000000000000', 'amount_to_sell': '0.001000000000000000', 'block_time': 1657572588, 'auction_deadline': 1657573468, 'price': '0.000000000000000000', 'bid_increase': '1.050000000000000000', 'high_bidder': '0x0000000000000000000000000000000000000000', 'staked_token_auction_house': '0x328BCbF2d4c2D78936f52172c741456136FA7e92'}
2022-07-11 20:49:49,220 INFO     Auction 12 deleted: False
2022-07-11 20:49:49,361 INFO     Input for auction 13: {'id': '13', 'bid_amount': '0.000000000000000000000000001000000000000000000', 'amount_to_sell': '0.001000000000000000', 'block_time': 1657572588, 'auction_deadline': 1657573488, 'price': '0.000000000000000000', 'bid_increase': '1.050000000000000000', 'high_bidder': '0x0000000000000000000000000000000000000000', 'staked_token_auction_house': '0x328BCbF2d4c2D78936f52172c741456136FA7e92'}
2022-07-11 20:49:49,361 INFO     Auction 13 deleted: False
2022-07-11 20:49:49,361 WARNING  Processing auctions [11]; ignoring [12, 13]
2022-07-11 20:49:49,400 INFO     Checked auctions 11 to 13 in 0 seconds
2022-07-11 20:50:06,979 INFO     Can't start staked_token auction as there are already 3 active auctions
2022-07-11 20:50:07,179 INFO     Input for auction 11: {'id': '11', 'bid_amount': '0.001283356467456783863967795170000000000000000', 'amount_to_sell': '0.001000000000000000', 'block_time': 1657572604, 'auction_deadline': 1657573452, 'price': '0.255998053357343998', 'bid_increase': '1.050000000000000000', 'high_bidder': '0xdD1693BD8E307eCfDbe51D246562fc4109f871f8', 'bid_expiry': '1657573168', 'staked_token_auction_house': '0x328BCbF2d4c2D78936f52172c741456136FA7e92'}
2022-07-11 20:50:07,179 INFO     Auction 11 deleted: False
2022-07-11 20:50:07,316 INFO     Input for auction 12: {'id': '12', 'bid_amount': '0.000000000000000000000000001000000000000000000', 'amount_to_sell': '0.001000000000000000', 'block_time': 1657572604, 'auction_deadline': 1657573468, 'price': '0.000000000000000000', 'bid_increase': '1.050000000000000000', 'high_bidder': '0x0000000000000000000000000000000000000000', 'staked_token_auction_house': '0x328BCbF2d4c2D78936f52172c741456136FA7e92'}
2022-07-11 20:50:07,316 INFO     Auction 12 deleted: False
2022-07-11 20:50:07,467 INFO     Input for auction 13: {'id': '13', 'bid_amount': '0.000000000000000000000000001000000000000000000', 'amount_to_sell': '0.001000000000000000', 'block_time': 1657572604, 'auction_deadline': 1657573488, 'price': '0.000000000000000000', 'bid_increase': '1.050000000000000000', 'high_bidder': '0x0000000000000000000000000000000000000000', 'staked_token_auction_house': '0x328BCbF2d4c2D78936f52172c741456136FA7e92'}
2022-07-11 20:50:07,467 INFO     Auction 13 deleted: False
2022-07-11 20:50:07,467 WARNING  Processing auctions [11]; ignoring [12, 13]
2022-07-11 20:50:07,504 INFO     Checked auctions 11 to 13 in 0 seconds
2022-07-11 20:50:27,228 INFO     Can't start staked_token auction as there are already 3 active auctions
2022-07-11 20:50:27,397 INFO     Input for auction 11: {'id': '11', 'bid_amount': '0.001283356467456783863967795170000000000000000', 'amount_to_sell': '0.001000000000000000', 'block_time': 1657572624, 'auction_deadline': 1657573452, 'price': '0.255997080041566909', 'bid_increase': '1.050000000000000000', 'high_bidder': '0xdD1693BD8E307eCfDbe51D246562fc4109f871f8', 'bid_expiry': '1657573168', 'staked_token_auction_house': '0x328BCbF2d4c2D78936f52172c741456136FA7e92'}
2022-07-11 20:50:27,397 INFO     Auction 11 deleted: False
2022-07-11 20:50:27,578 INFO     Input for auction 12: {'id': '12', 'bid_amount': '0.000000000000000000000000001000000000000000000', 'amount_to_sell': '0.001000000000000000', 'block_time': 1657572624, 'auction_deadline': 1657573468, 'price': '0.000000000000000000', 'bid_increase': '1.050000000000000000', 'high_bidder': '0x0000000000000000000000000000000000000000', 'staked_token_auction_house': '0x328BCbF2d4c2D78936f52172c741456136FA7e92'}
2022-07-11 20:50:27,578 INFO     Auction 12 deleted: False
2022-07-11 20:50:27,730 INFO     Input for auction 13: {'id': '13', 'bid_amount': '0.000000000000000000000000001000000000000000000', 'amount_to_sell': '0.001000000000000000', 'block_time': 1657572624, 'auction_deadline': 1657573488, 'price': '0.000000000000000000', 'bid_increase': '1.050000000000000000', 'high_bidder': '0x0000000000000000000000000000000000000000', 'staked_token_auction_house': '0x328BCbF2d4c2D78936f52172c741456136FA7e92'}
2022-07-11 20:50:27,731 INFO     Auction 13 deleted: False
2022-07-11 20:50:27,731 WARNING  Processing auctions [11]; ignoring [12, 13]
2022-07-11 20:50:27,772 INFO     Checked auctions 11 to 13 in 0 seconds


2022-07-11 20:59:51,693 INFO     Sent transaction StakedTokenAuctionHouse('0x328BCbF2d4c2D78936f52172c741456136FA7e92').settleAuction(11) with nonce=55
07, gas=227887, gas_price=2500000007 (tx_hash=0x4e1d347341b9e4e1567aff93585db3fb7529b024a8282ffa6d1da2164d7264f3)
2022-07-11 20:59:52,715 INFO     Transaction StakedTokenAuctionHouse('0x328BCbF2d4c2D78936f52172c741456136FA7e92').settleAuction(11) was successful (tx
_hash=0x4e1d347341b9e4e1567aff93585db3fb7529b024a8282ffa6d1da2164d7264f3)
2022-07-11 20:59:52,995 INFO     Terminating model using process '/models/debt_staked_model.py --id 11 --staked_token_auction_house 0x328BCbF2d4c2D7893
6f52172c741456136FA7e92'
2022-07-11 20:59:52,995 INFO     Stopped monitoring auction #11 as it's not active anymore
2022-07-11 20:59:52,999 INFO     Process '/models/debt_staked_model.py --id 11 --staked_token_auction_house 0x328BCbF2d4c2D78936f52172c741456136FA7e92'
 (pid #23) terminated


2022-07-11 21:05:01,357 INFO     Auction 13 ended without bids; resurrecting auction
2022-07-11 21:05:01,562 INFO     Sent transaction StakedTokenAuctionHouse('0x328BCbF2d4c2D78936f52172c741456136FA7e92').restartAuction(13) with nonce=5515, gas=142873, gas_price=2500000007 (tx_hash=0xbe0ea7e2997b6554c4215076e80804a8894724c830ea35c2253ee3cbf1948265)
2022-07-11 21:05:04,878 INFO     Transaction StakedTokenAuctionHouse('0x328BCbF2d4c2D78936f52172c741456136FA7e92').restartAuction(13) was successful (tx_hash=0xbe0ea7e2997b6554c4215076e80804a8894724c830ea35c2253ee3cbf1948265)
```


# Surplus Auction Keeper

How to run a surplus auction keeper

This mini guide will walk you through running a surplus auction keeper in Docker & also directly on a host.


# Running in Docker

Running a surplus auction keeper in a Docker container

{% hint style="info" %}
In order to participate in surplus auctions you need to bid with protocol tokens
{% endhint %}

## 1. Modify the model file as needed

A basic surplus auction bidding model can be found in `models/surplus_model.py`. This model retrieves the latest FLX/USD price from Coingecko and will automatically place bids in an auction.

You probably want to modify the following variables in `models/surplus_model.py`:

* `STARTING_FLX_MULTIPLIER`: the maximum acceptable FLX price to use when bidding. This value will be used when bidding on a new auction with no previous bids. Default: `1.50` meaning the maximum price to accept for FLX (in RAI terms) is 150% of the current FLX/USD market price
* `MINIMUM_FLX_MULTIPLIER`: the minimum acceptable FLX price to use when bidding. Default: `1.10` meaning the minimum price to accept for FLX (in RAI terms) is 110% of the current FLX/USD market price

`MY_BID_INCREASE`: The amount of bid increase(in FLX) to make when outbidding another bidder. If value is less than the auction house' `bidIncrease`, then it will use the auction house setting. Example: A value of `1.10` will create bid increases of 10%. Note: Current `bidIncrease` on mainnet is `1.03`. Default: `1.03`

Then, use `chmod +x surplus_model.py`.

For more information about bidding models, see [Bidding Models](https://github.com/reflexer-labs/geb-docs/blob/master/keepers/BiddingModels.md).

## 2. Modify the keeper run file

Modify the following variables in `run_surplus_keeper.sh`:

* `KEEPER_ADDRESS` - the keeper's address. It should be in checksummed format (not lowercase)
* `ETH_RPC_URL` - the URL of your Ethereum RPC connection
* `KEYSTORE_DIR` - the full path of the directory where your keystore file is
* `MODEL_DIR` - the full path of directory where your `surplus_model.py` file is
* `KEYSTORE_FILE` - your Ethereum UTC JSON keystore filename
* `GAS_MAXIMUM` -maximum gas price, in GWEI

For more information about the keystore format and how to generate it:

* [Ethereum UTC / JSON Wallet Encryption](https://wizardforcel.gitbooks.io/practical-cryptography-for-developers-book/content/symmetric-key-ciphers/ethereum-wallet-encryption.html)
* [keythereum](https://github.com/ethereumjs/keythereum)

Finally, to run the keeper, use `chmod +x run_surplus_keeper.sh`.

## 3. Start the keeper and enter your keystore file password

`./run_surplus_keeper.sh`

```
$ ./run_auction_keeper.sh
Pulling from reflexer/auction-keeper
Digest: sha256:7e55ec9b0a136fc903d9f7f2690538bcbde9029d957e0e6f84d0282790f9666a
Status: Downloaded newer image for reflexer/auction-keeper
docker.io/reflexer/auction-keeper
Password for /keystore/key.json:
```

## Surplus Auction Output

Sample [surplus auction output](#surplus-auctioning-process)


# Running on a Host

Running a surplus auction-keeper on a host

{% hint style="info" %}
In order to participate in surplus auctions you need to bid with protocol tokens
{% endhint %}

## Prerequisites

Python 3.6+

### Clone:

```
git clone https://github.com/reflexer-labs/auction-keeper.git
cd auction-keeper
git submodule update --init --recursive
```

### Install:

This creates a virtual environment and installs requirements:

`./install.sh`

## 1. Start virtualenv

`source _virtualenv/bin/activate`

## 2. Modify model file as needed

A basic surplus auction bidding model can be found in `models/surplus_model.py`. This model retrieves the latest FLX/USD price from coingecko and will automatically place bids in an auction.

You probably want to modify the following variables in `models/surplus_model.py`:

`STARTING_FLX_MULTIPLIER`: The maximum acceptable FLX price to use when bidding. This value will be used when bidding on a new auction with no previous bids. Default: `1.50` meaning the maxiimum price to accept for FLX(in RAI) is 150% of the current FLX/USD market price

`MINIMUM_FLX_MULTIPLIER`: The minimum acceptable FLX price to use when bidding. Default: `1.10` meaning the minimum price to accept for FLX(in RAI) is 110% of the current FLX/USD market price

`MY_BID_INCREASE`: The amount of bid increase(in FLX) to make when outbidding another bidder. If value is less than the auction house' `bidIncrease`, then it will use the auction house setting. Example: A value of `1.10` will create bid increases of 10%. Note: Current `bidIncrease` on mainnet is `1.03`. Default: `1.03`

### Ensure script is executable

`chmod +x surplus_model.py`

For more information about bidding models, see [Bidding Models](https://github.com/reflexer-labs/geb-docs/blob/master/keepers/BiddingModels.md)

## 3. Modify keeper run file

Modify the following variables in `run_surplus_keeper_host.sh`

`KEEPER_ADDRESS` - the keeper's address. It should be in checksummed format (not lowercase).

`ETH_RPC_URL` - the URL of your ethereum RPC connection

`KEYSTORE_FILE` - your Ethereum UTC JSON keystore filename

For more information about this keystore format and how to generate them, check:

* [Ethereum UTC / JSON Wallet Encryption](https://wizardforcel.gitbooks.io/practical-cryptography-for-developers-book/content/symmetric-key-ciphers/ethereum-wallet-encryption.html)
* [keythereum](https://github.com/ethereumjs/keythereum)

`GAS_MAXIMUM` -maximum gas price, in GWEI

### Ensure script is executable

`chmod +x run_surplus_keeper_host.sh`

## 4. Start the keeper and enter your keystore file password

`./run_surplus_keeper_host.sh`

```
$ ./run_surplus_keeper_host.sh
Password for /keystore/key.json:
```

## Surplus Auction Output

#### Start a Surplus Auction

If enough surplus exists in the system, the surplus *auction-keeper* will call `auctionSurplus` to start a surplus auction.

```
2021-01-19 21:15:20,644 INFO     Initiating a surplus auction with coin balance=857.460939042493680361118426229210746756033227844
2021-01-19 21:15:21,317 INFO     Sent transaction AccountingEngine('0x73EC2a627655134886477D10A41275f54556E0e2').auctionSurplus() with nonce=771, gas=290341, gas_price=3000000000 (tx_hash=0x67fdeda8c2dedf5ba05cecf4184e38f3f0353c750a5f466ebf340730e0aa330e)
```

#### Bid on a Surplus Auction

If the surplus *auction-keeper* has FLX, it will bid on surplus auctions by calling `increaseBidSize`

```
2021-01-19 21:15:33,578 INFO     Sending new bid @100.000000000000000000 for auction 16
2021-01-19 21:15:33,688 INFO     Sent transaction PreSettlementSurplusAuctionHouse('0xE04ccD802E5e37bE1A64036ce8E7e514E4DBE475').increaseBidSize(16, 2000000000000000000000000000000000000000000000, 20000000000000000) with nonce=773, gas=214285, gas_price=3000000000
```

#### Full Log Output

```
2021-01-19 21:15:07,178 INFO     Keeper connected to RPC connection https://myparitynode.com
2021-01-19 21:15:07,179 INFO     Keeper operating as 0xdD1693BD8E307eCfDbe51D246562fc4109f871f8
2021-01-19 21:15:07,203 INFO     Executing keeper startup logic
2021-01-19 21:15:08,241 INFO     Checking if internal system coin balance needs to be rebalanced
2021-01-19 21:15:08,274 INFO     Joining 1000.613947077334748390 system coin to the SAFE Engine
2021-01-19 21:15:08,334 INFO     Sent transaction <pyflex.gf.CoinJoin object at 0x7fed8cc27208>.join('0xdD1693BD8E307eCfDbe51D246562fc4109f871f8', 10006139470773347483
90) with nonce=770, gas=159975, gas_price=3000000000 (tx_hash=0x996585d78c2ee40536cb575be0492c888e1603dad01b571ec805ad5e3bde231f)
2021-01-19 21:15:12,496 INFO     Transaction <pyflex.gf.CoinJoin object at 0x7fed8cc27208>.join('0xdD1693BD8E307eCfDbe51D246562fc4109f871f8', 1000613947077334748390) w
as successful (tx_hash=0x996585d78c2ee40536cb575be0492c888e1603dad01b571ec805ad5e3bde231f)
2021-01-19 21:15:12,506 INFO     Prot balance is 4.800000000000000000
2021-01-19 21:15:12,507 INFO     Keeper will perform the following operation(s) in parallel:
2021-01-19 21:15:12,507 INFO     --> Check thresholds in Accounting Engine Contract and start new surplus auctions once reached
2021-01-19 21:15:12,507 INFO     --> Check all auctions being monitored and evaluate bidding opportunity every 4.0 seconds
2021-01-19 21:15:12,508 INFO     --> Check all auctions and settle for 0xdD1693BD8E307eCfDbe51D246562fc4109f871f8
2021-01-19 21:15:12,511 INFO     Keeper will use Node gas price (currently 3.0 Gwei, changes over time) and will multiply by 1.125 every 30s to a maximum of 2000.0 Gwe
i for transactions and bids unless model instructs otherwise
2021-01-19 21:15:12,512 INFO     Watching for new blocks
2021-01-19 21:15:12,514 INFO     Started 2 timer(s)
2021-01-19 21:15:20,644 INFO     Initiating a surplus auction with coin balance=857.460939042493680361118426229210746756033227844
2021-01-19 21:15:21,317 INFO     Sent transaction AccountingEngine('0x73EC2a627655134886477D10A41275f54556E0e2').auctionSurplus() with nonce=771, gas=290341, gas_price=3000000000 (tx_hash=0x67fdeda8c2dedf5ba05cecf4184e38f3f0353c750a5f466ebf340730e0aa330e)
2021-01-19 21:15:29,370 INFO     Transaction AccountingEngine('0x73EC2a627655134886477D10A41275f54556E0e2').auctionSurplus() was successful (tx_hash=0x67fdeda8c2dedf5ba05cecf4184e38f3f0353c750a5f466ebf340730e0aa330e)
2021-01-19 21:15:29,641 INFO     Started monitoring auction #16
2021-01-19 21:15:29,642 INFO     Instantiated model using process '/models/surplus_model.sh --id 16 --surplus_auction_house 0xE04ccD802E5e37bE1A64036ce8E7e514E4DBE475'
2021-01-19 21:15:29,653 INFO     Process '/models/surplus_model.sh --id 16 --surplus_auction_house 0xE04ccD802E5e37bE1A64036ce8E7e514E4DBE475' (pid #29) started
2021-01-19 21:15:29,675 INFO     Checked auctions 0 to 16 in 0 seconds
2021-01-19 21:15:32,738 INFO     Initiating a surplus auction with coin balance=855.460939042493680361118426229210746756033227844
2021-01-19 21:15:33,430 INFO     Sent transaction AccountingEngine('0x73EC2a627655134886477D10A41275f54556E0e2').auctionSurplus() with nonce=772, gas=275341, gas_price=3000000000 (tx_hash=0xe00e3bbeeb12c23d13c52a34bbf2f5457d2ea9ae513baffd8d65133adba7b19d)
2021-01-19 21:15:33,578 INFO     Sending new bid @100.000000000000000000 for auction 16
2021-01-19 21:15:33,688 INFO     Sent transaction PreSettlementSurplusAuctionHouse('0xE04ccD802E5e37bE1A64036ce8E7e514E4DBE475').increaseBidSize(16, 2000000000000000000000000000000000000000000000, 20000000000000000) with nonce=773, gas=214285, gas_price=3000000000 (tx_hash=0x1a6e219ba11bc300e671703ae73ff5cc7f36e4be0d56fd7751c4bb24a3628106)
2021-01-19 21:15:41,040 INFO     Transaction AccountingEngine('0x73EC2a627655134886477D10A41275f54556E0e2').auctionSurplus() was successful (tx_hash=0xe00e3bbeeb12c23d13c52a34bbf2f5457d2ea9ae513baffd8d65133adba7b19d)
```


# Bidding Models

Information about bidding models for debt and surplus auction keepers

`auction-keeper` maintains a collection of child processes, as each bidding model is its own dedicated process. New processes (new *bidding model* instances) are spawned by executing the command passed to `--model`. These processes are automatically terminated (via `SIGKILL`) by the keeper shortly after their associated auctions expire.

Whenever the *bidding model* process dies, it gets automatically respawned by the keeper.

Example:

```bash
bin/auction-keeper --model '../my-bidding-model.sh' [...]
```

## Pass the auction status to each bidding model

`auction-keeper` communicates with bidding models via their standard input and output. When the auction state changes, the keeper sends a one-line JSON document to the **standard input** of the bidding model process.

A sample message sent from the keeper to the model looks like:

```javascript
{"id": "6", "surplus_auction_house": "0xf0afc3108bb8f196cf8d076c8c4877a4c53d4e7c", "bid_amount": "7.142857142857142857", "amount_to_sell": "10000.000000000000000000", "bid_increase": "1.050000000000000000", "high_bidder": "0x00531a10c4fbd906313768d277585292aa7c923a", "block_time": 1530530620, "bid_expiry": 1530541420, "auction_deadline": 1531135256, "price": "1400.000000000000000028"}
```

Bidding models should never make an assumption that messages will be sent only when auction state changes.

At the same time, the `auction-keeper` reads one-line messages from the **standard output** of the bidding model process and tries to parse them as JSON documents. It then extracts two fields from that document:

* `price` - the maximum (for debt auctions) or the minimum (for surplus auctions) price

  the model is willing to bid. This value is ignored for fixed discount collateral auctions
* `gasPrice` (optional) - gas price in WEI to use when sending the bid

## Processing each bidding model output and submitting bids

### Sample model output for a debt auction bidding model

A sample message sent from the debt model to the keeper may look like `price` is `PROT/System Coin` price.

```javascript
{"price": "250.0", "gasPrice": 70000000000}
```

### Sample model output for a surplus auction bidding model

A sample message sent from the debt model to the keeper may look like:

`price` is `PROT/System Coin` price

```javascript
{"price": "150.0"}
```

Any messages written by a *bidding model* to **stderr** will be passed through by the keeper to its logs. This is the most convenient way of implementing logging from *bidding models*.

{% hint style="danger" %}
**Currently there's no mechanism that prevents a keeper from bidding at an unprofitable price**
{% endhint %}

## Simplest possible bidding model

```
#!/usr/bin/env bash
while true; do
  echo "{\"price\": \"723.0\"}"
  sleep 120                   
done
```

Specifying a gas price is optional. If you want to start with a fixed gas price, you can add it like this:

```
#!/usr/bin/env bash

while true; do
  echo "{\"price\": \"723.0\", \"gasPrice\": \"70000000000\"}"    # put your desired gas price in Wei here
  sleep 120                                                       # locking the gas price for n seconds
done
```

The model produces price(s) for the keeper. After the `sleep` period, the keeper will restart the price model and read new price(s).

## Collateral bidding models

**Note:** Currently, collateral keepers buy collateral at a fixed discount (specified in the auction house smart contract) and don't bid prices. So they should use a blank model file like this:

```
#!/usr/bin/env bash
while true; do
  echo "{}"
  sleep 120
done
```

## Other bidding models

* *banteg*'s [Python boilerplate model](https://gist.github.com/banteg/93808e6c0f1b9b6b470beaba5a140813)


# SAFE Protection

Building and integrating saviour contracts for SAFEs

## 1. Overview

The GEB [LiquidationEngine](https://github.com/reflexer-labs/geb/blob/master/src/LiquidationEngine.sol) allows governance to [whitelist](https://github.com/reflexer-labs/geb/blob/a49e4486682b787571475821ec66bfa025e5183f/src/LiquidationEngine.sol#L88) external insurance contracts for `SAFE`s. `SAFE` users can [attach](https://github.com/reflexer-labs/geb/blob/a49e4486682b787571475821ec66bfa025e5183f/src/LiquidationEngine.sol#L290) insurance contracts to their positions and this way have an extra layer of protection against liquidation.

Anyone can build and propose new insurance contracts, assuming that the contracts abide by the requirements and principles outlined below. A central repository with `SAFE` insurance contracts (also called saviours) and interfaces can be found [here](https://github.com/reflexer-labs/geb-safe-saviours).

## 2. Contract Interface

Every insurance contract must implement one of the official interfaces (the oldest interface can be found [here](https://github.com/reflexer-labs/geb-safe-saviours/blob/master/src/interfaces/SafeSaviourLike.sol)):

```javascript
abstract contract SafeSaviourLike is ReentrancyGuard {
    // Checks whether a saviour contract has been approved by governance in the LiquidationEngine
    modifier liquidationEngineApproved(address saviour) {
        require(liquidationEngine.safeSaviours(saviour) == 1, "SafeSaviour/not-approved-in-liquidation-engine");
        _;
    }
    // Checks whether someone controls a safe handler inside the GebSafeManager
    modifier controlsSAFE(address owner, uint256 safeID) {
        require(owner != address(0), "SafeSaviour/null-owner");
        require(either(owner == safeManager.ownsSAFE(safeID), safeManager.safeCan(safeManager.ownsSAFE(safeID), safeID, owner) == 1), "SafeSaviour/not-owning-safe");

        _;
    }

    // --- Variables ---
    LiquidationEngineLike   public liquidationEngine;
    OracleRelayerLike       public oracleRelayer;
    GebSafeManagerLike      public safeManager;
    SAFEEngineLike          public safeEngine;
    SAFESaviourRegistryLike public saviourRegistry;

    // The amount of tokens the keeper gets in exchange for the gas spent to save a SAFE
    uint256 public keeperPayout;          // [wad]
    // The minimum fiat value that the keeper must get in exchange for saving a SAFE
    uint256 public minKeeperPayoutValue;  // [wad]
    /*
      The proportion between the keeperPayout (if it's in collateral) and the amount of collateral or debt that's in a SAFE to be saved.
      Alternatively, it can be the proportion between the fiat value of keeperPayout and the fiat value of the profit that a keeper
      could make if a SAFE is liquidated right now. It ensures there's no incentive to intentionally put a SAFE underwater and then
      save it just to make a profit that's greater than the one from participating in collateral auctions
    */
    uint256 public payoutToSAFESize;

    // --- Constants ---
    uint256 public constant ONE               = 1;
    uint256 public constant HUNDRED           = 100;
    uint256 public constant THOUSAND          = 1000;
    uint256 public constant WAD_COMPLEMENT    = 10**9;
    uint256 public constant WAD               = 10**18;
    uint256 public constant RAY               = 10**27;
    uint256 public constant MAX_UINT          = uint(-1);

    // --- Boolean Logic ---
    function both(bool x, bool y) internal pure returns (bool z) {
        assembly{ z := and(x, y) }
    }
    function either(bool x, bool y) internal pure returns (bool z) {
        assembly{ z := or(x, y)}
    }

    // --- Events ---
    event SaveSAFE(address indexed keeper, bytes32 indexed collateralType, address indexed safeHandler, uint256 collateralAddedOrDebtRepaid);

    // --- Functions to Implement ---
    function saveSAFE(address,bytes32,address) virtual external returns (bool,uint256,uint256);
    function getKeeperPayoutValue() virtual public returns (uint256);
    function keeperPayoutExceedsMinValue() virtual public returns (bool);
    function canSave(bytes32,address) virtual external returns (bool);
    function tokenAmountUsedToSave(bytes32,address) virtual public returns (uint256);
}
```

## 3. Implementation Guidelines

In order to get an idea of how a saviour contract should be implemented and what checks must be in place, let's analyze the components of a [demo contract](https://github.com/reflexer-labs/geb-safe-saviours/blob/master/src/saviours/GeneralTokenReserveSafeSaviour.sol) that allows `SAFE` users to deposit & withdraw collateral used to save their positions.

### Constructor Requirements:

* Sanitize every parameter (`address`es must be non null, `uint` values are non null and within expected bounds etc)
* In case of a saviour that adds more collateral in Safes, you must set the [CollateralJoin](https://github.com/reflexer-labs/geb-deploy/blob/master/src/AdvancedTokenAdapters.sol) contract of the specific collateral type you're targeting
* In case of a saviour that repays debt instead of adding collateral, you must set the [CoinJoin](https://github.com/reflexer-labs/geb/blob/dc6ad8302080cb2912f8d5fb258cdcae13601982/src/BasicTokenAdapters.sol#L225) contract
* Every saviour type should also have the [LiquidationEngine](https://github.com/reflexer-labs/geb/blob/master/src/LiquidationEngine.sol), [OracleRelayer](https://github.com/reflexer-labs/geb/blob/master/src/OracleRelayer.sol), [SAFEEngine](https://github.com/reflexer-labs/geb/blob/master/src/SAFEEngine.sol), [GebSafeManager](https://github.com/reflexer-labs/geb-safe-manager/blob/master/src/GebSafeManager.sol), [SAFESaviourRegistry](https://github.com/reflexer-labs/geb-safe-saviours/blob/master/src/SAFESaviourRegistry.sol) and [SaviourCRatioSetter](https://github.com/reflexer-labs/geb-safe-saviours/blob/master/src/SaviourCRatioSetter.sol) set
* You must set:&#x20;
  * `keeperPayout` - amount of collateral awarded to the address that initially called [LiquidationEngine.liquidateSAFE](https://github.com/reflexer-labs/geb/blob/a49e4486682b787571475821ec66bfa025e5183f/src/LiquidationEngine.sol#L309)
  * `minKeeperPayoutValue` - the minimum fiat value of the `keeperPayout` which makes it compelling for keepers to save the `SAFE` instead of waiting even more to liquidate it
  * `defaultDesiredCollateralizationRatio` - the default CRatio that a `SAFE` will have after it's saved; this CRatio must be greater than the liquidation ratio stored in the [OracleRelayer](https://github.com/reflexer-labs/geb/blob/a49e4486682b787571475821ec66bfa025e5183f/src/OracleRelayer.sol#L60) and that is associated with `collateralToken`
* Optionally, you can set:
  * `payoutToSAFESize` - how many times more collateral there must be in a `SAFE` compared to `keeperPayout`; this prevents keepers from purposefully liquidating `SAFE`s so they get a reward that is bigger than the one offered in a collateral auction
* When comparing a `liquidationCRatio` from the `OracleRelayer` with a desired collateralization ratio, you must first divide `liquidationCRatio` by `CRATIO_SCALE_DOWN` so you have the same scale for both numbers
* You must integrate your saviour with [GebSafeManager](https://github.com/reflexer-labs/geb-safe-manager/blob/master/src/GebSafeManager.sol) in order to take advantage of its modularity and friendlier interface compared to core contracts (such as `SAFEEngine`)

### Covering & Uncovering SAFEs:

There is no specific way in which users should cover a `SAFE`. They can store collateral in the saviour, they can also store [aTokens](https://docs.aave.com/developers/the-core-protocol/atokens) or [cTokens](https://compound.finance/docs/ctokens) that are then used to redeem the underlying assets and add them in the SAFE or they can use a protocol similar to [Nexus Mutual](https://nexusmutual.gitbook.io/docs/users/docs) which automatically fulfils claims and saves positions. There are, though, certain things that a saviour developer must take into account:

* The function used to add more cover for a `SAFE` (like [deposit](https://github.com/reflexer-labs/geb-safe-saviours/blob/6b8a89e1f6e7c7d210cb68f684ac1c6a5fb6e0c5/src/saviours/GeneralTokenReserveSafeSaviour.sol#L85)) must revert if the saviour contract is not whitelisted inside the [LiquidationEngine](https://github.com/reflexer-labs/geb/blob/a49e4486682b787571475821ec66bfa025e5183f/src/LiquidationEngine.sol#L83)
* Users can only add cover if their SAFEs [have generated debt](https://github.com/reflexer-labs/geb-safe-saviours/blob/6b8a89e1f6e7c7d210cb68f684ac1c6a5fb6e0c5/src/saviours/GeneralTokenReserveSafeSaviour.sol#L95)
* Users can withdraw cover (with something like [withdraw](https://github.com/reflexer-labs/geb-safe-saviours/blob/6b8a89e1f6e7c7d210cb68f684ac1c6a5fb6e0c5/src/saviours/GeneralTokenReserveSafeSaviour.sol#L109)) even if the saviour contract is not whitelisted inside the [LiquidationEngine](https://github.com/reflexer-labs/geb/blob/a49e4486682b787571475821ec66bfa025e5183f/src/LiquidationEngine.sol#L83)
* Only the `SAFE`'s owner or an authorized address inside the [GebSafeManager](https://github.com/reflexer-labs/geb-safe-manager/blob/7da11a4638a994fb0a58e7c1330f69ce897844f9/src/GebSafeManager.sol#L49) can withdraw cover

{% hint style="danger" %}
**Reentrancy**

Make sure to protect your cover/uncover functions against re-entrancy.
{% endhint %}

### View Function Requirements:

[keeperPayoutExceedsMinValue](https://github.com/reflexer-labs/geb-safe-saviours/blob/6b8a89e1f6e7c7d210cb68f684ac1c6a5fb6e0c5/src/saviours/GeneralTokenReserveSafeSaviour.sol#L214):

* It must verify if the fiat value of `keeperPayout` exceeds or is equal to `minKeeperPayoutValue`
* It must read the collateral's price from the [same oracle](https://github.com/reflexer-labs/geb-safe-saviours/blob/6b8a89e1f6e7c7d210cb68f684ac1c6a5fb6e0c5/src/saviours/GeneralTokenReserveSafeSaviour.sol#L215) used inside `OracleRelayer` in order to maintain consistency between the core system and the saviour
* It must return `false` if the oracle price is invalid

[getKeeperPayoutValue](https://github.com/reflexer-labs/geb-safe-saviours/blob/6b8a89e1f6e7c7d210cb68f684ac1c6a5fb6e0c5/src/saviours/GeneralTokenReserveSafeSaviour.sol#L227):

* It must read the collateral's price from the [same oracle](https://github.com/reflexer-labs/geb-safe-saviours/blob/6b8a89e1f6e7c7d210cb68f684ac1c6a5fb6e0c5/src/saviours/GeneralTokenReserveSafeSaviour.sol#L228) used inside `OracleRelayer` in order to maintain consistency between the core system and the saviour
* It must return `0` if the oracle price is invalid
* It must return the fiat value of `keeperPayout` collateral tokens used to pay keepers for saving `SAFE`s

[tokenAmountUsedToSave](https://github.com/reflexer-labs/geb-safe-saviours/blob/6b8a89e1f6e7c7d210cb68f684ac1c6a5fb6e0c5/src/saviours/GeneralTokenReserveSafeSaviour.sol#L256):

* It must return the amount of collateral tokens that will be used to save a `SAFE` and bring its CRatio to the desired ratio
* It must read the collateral's price from the [same oracle](https://github.com/reflexer-labs/geb-safe-saviours/blob/6b8a89e1f6e7c7d210cb68f684ac1c6a5fb6e0c5/src/saviours/GeneralTokenReserveSafeSaviour.sol#L259) used inside `OracleRelayer` in order to maintain consistency between the core system and the saviour
* It must return early if the targeted `SAFE` has no debt or if the oracle feed is invalid

[canSave](https://github.com/reflexer-labs/geb-safe-saviours/blob/6b8a89e1f6e7c7d210cb68f684ac1c6a5fb6e0c5/src/saviours/GeneralTokenReserveSafeSaviour.sol#L242):

* It must return `true` if a `SAFE` can currently be saved, `false` if not
* It must check that, when the `SAFE` is saved, the contract has enough tokens to both reward the keeper that called `LiquidationEngine.liquidateSAFE` and also bring the `SAFE`'s CRatio to the desired level

### Saving a SAFE:

The process of saving a `SAFE` has its own requirements:

* You must implement and use `saveSAFE(address keeper`, `bytes32 collateralType`, `address safeHandler) external returns (bool`, `uint256`, `uint256)` in order to save `SAFE`s
* `saveSAFE` must check that `msg.sender` is the `LiquidationEngine`
* The `keeper` parameter must not be null
* There is a special condition you must add where, if the `collateralType` is null, the `keeper` is the `LiquidationEngine` itself and the `safeHandler` is null, you return a tuple like `(true`, `uint(-1)`, `uint(-1))`. This condition will help the `LiquidationEngine` to check that you implemented `saveSAFE`. You can see an example of this condition [here](https://github.com/reflexer-labs/geb-safe-saviours/blob/6b8a89e1f6e7c7d210cb68f684ac1c6a5fb6e0c5/src/saviours/GeneralTokenReserveSafeSaviour.sol#L157)
* You must check that `keeperPayoutExceedsMinValue` returns `true`. If it returns `false`, you must return early
* You must check that the `SAFE` has debt in it
* You must check that the saviour can both reward the keeper for saving the SAFE and also add enough collateral in the SAFE so its CRatio goes to the desired level
* You must **not** add any collateral in the `SAFE` or repay the `SAFE`'s debt in case it **cannot** be saved (its CRatio cannot be increased to the desired level). You must revert in case the `SAFE` cannot be saved
* You must call `saviourRegistry.markSave(collateralType`, `safeHandler)` so that the `SAFESaviourRegistry` knows a specific `SAFE` has just been saved. The registry enforces a delay between two consecutive save actions for a specific `SAFE`. The delay is there to make sure that `SAFE` users don't solely rely on saviours to protect their positions. This way we avoid a scenario where one or a couple of popular saviours fail (e.g bugs, lack of sufficient cover) and most positions in the system are liquidated at once
* You must emit a `SaveSAFE` event before you return
* The last thing you have to do is to return a tuple in the form of `(true`, `tokenAmountUsed`, `keeperPayout)` where:
  * `tokenAmountUsed` is the amount of collateral that was used to save the `SAFE`
  * `keeperPayout` is a non null amount of collateral that was used to reward the keeper&#x20;

You can check an example implementation for `saveSAFE` [here](https://github.com/reflexer-labs/geb-safe-saviours/blob/6b8a89e1f6e7c7d210cb68f684ac1c6a5fb6e0c5/src/saviours/GeneralTokenReserveSafeSaviour.sol#L153).

## 4. Monetizing a Saviour

In some cases, saviour builders may want to monetize the service they provide and charge some sort of fee for protecting `SAFE`s.

If you would like to submit a proposal for implementing a monetized saviour, you must keep in mind several things:

* Monetization should happen outside of the saviour contract. This keeps concerns separated, simplifies the saviour implementation and gives you more flexibility when it comes to updating your business model
* You must mention that your saviour will be monetized and you should give a detailed description of how you plan to charge `SAFE` users. You must include the description in your GIP as outlined in the section below
* Assuming you plan to use a smart contract to charge users, your should attach a detailed overview or implementation of your model inside your GIP

## 5. Launching on Mainnet

In order to launch and integrate a saviour with a mainnet deployed GEB, the saviour must first pass several checks:

1. You must first create a new [GEB Improvement Proposal](https://github.com/reflexer-labs/GIPs). Once you create the GIP you must ask for feedback on [Reflexer's Discord server](https://discord.gg/kB4vcYs) (in the development channel). To maximize your chances of having your idea accepted:
   * Your saviour must only do one thing. For example, you should only handle aTokens or cTokens, not both
   * Your saviour should only take into account a single collateral type (e.g ETH-A **or** ETH-B, **not** ETH-A and ETH-B) in case it's meant to add collateral. If the saviour repays debt, it can be generalized to handle any Safe with any collateral type
   * You should have a draft implementation of your saviour with estimated gas amounts for calling each function
   * You should give an initial estimate of the `keeperPayout`, `minKeeperPayoutValue` and `payoutToSAFESize` values you plan to set
   * You must specify if you plan to monetize the saviour service you're building and how you plan to do it
2. Once you receive feedback (and assuming it's positive), you can start to fully implement the saviour. Keep in mind that, aside from the saviour, you will need to create a proxy actions contract (like [this one](https://github.com/reflexer-labs/geb-proxy-actions/blob/f7b4cdb0cde25683dc7bb04cf96f25ebe25a1853/src/GebProxyActions.sol#L746)) that will be used by others to connect your saviour to Safes and also add cover.
3. Before you submit your full implementation and update the GIP, you must make sure that you have 100% test coverage for your code and also do several integration tests between the `LiquidationEngine`, `SAFESaviourRegistry` and the saviour code. In order to submit your implementation, update your GIP with a link to your code and a new summary of the gas amounts required to call each function, as well as updated values for `keeperPayout`, `minKeeperPayoutValue`, `payoutToSAFESize` and `defaultDesiredCollateralizationRatio`

   . After you update the GIP, ping the community on Discord.
4. Once your implementation is accepted and reviewed by the community, your code must also be audited twice. Each audit must be done by an independent party.
5. After your code gets audited, you should send a new message on Discord and let the community know that it's ready to be integrated in production. You must link to the audit reports.
6. Governance may decide to first try out your saviour on a testnet. In this case, you must deploy an instance of your saviour on a testnet GEB and liquidate a `SAFE` which can then be saved
7. Assuming that you pass all previous steps, you can deploy your saviour on mainnet so that governance can whitelist it in `LiquidationEngine` and in `SAFESaviourRegistry`

## 6. Integration Ideas

To help you get started, here are a couple of ideas for building RAI saviours:

* Allow users to deposit [Aave aETH](https://aave.com/aTokens/) in a saviour which can then be used to redeem ETH that is then added in a `SAFE`
* Allow users to deposit [Compound cETH](https://compound.finance/docs/ctokens) in a saviour which can then be used to redeem ETH&#x20;

  that is then added in a `SAFE`
* [Opyn](https://opyn.co/#/) or [Hegic](https://www.hegic.co/) options which can be exercised when `saveSAFE` is called


# Liquidation Protection Guide

A guide to help you protect your SAFEs from liquidation

## 1. What is Liquidation Protection? Why Should I Use It?

Liquidation Protection is a unique feature that (as of the date of this guide) no other DeFi protocol has besides RAI. It forces liquidators to try and save your RAI SAFEs before they are liquidated. This is especially useful during a sharp price drop (e.g Black Thursday from March 2020) when gas prices explode and no one, not even you, can save your capital.

There are two key advantages in protecting your SAFE:

* Capital efficiency - protecting your SAFE means that you can mint more RAI with the same amount of ETH and have a higher guarantee that your capital will stay safe
* Peace of mind - an extra layer of cover for your SAFE means you can sleep better knowing that your capital is in a safer place

## 2. Walkthrough to Protect a SAFE

In order to protect a SAFE, you first need to create one using the [Reflexer official app](https://app.reflexer.finance/).

![A safe SAFE :D](/files/-M_vtJJgMdTBQJ3Srp8h)

Then, you need to go to the detail page of your SAFE by clicking on **Manage Safe**:

![](/files/-M_vtqgSLPvOa5ZbOH_E)

Your SAFE can be protected from liquidation by what we call a "saviour". A saviour is a smart contract that watches over SAFEs. When someone starts to liquidate a SAFE that's watched by a saviour, the saviour will first try to increase the SAFE's collateralization ratio by adding more ETH in it or repaying some of its debt.

To start connecting a saviour to your SAFE, you can click on **Add a Saviour** which is on every SAFE's details page:

![](/files/-M_w08gZgDEtiOaOd3fX)

You should see the onboarding page for saviours:

![](/files/-M_w0QQ7_xc3JSjr-vT-)

Once you click on **Configure**, you should see the configuration screen:

![](/files/-M_w4ia4q9HInXjff_5o)

You will notice a couple of things:

* You can deposit LP tokens in a saviour that protects your SAFE. During a liquidation, the saviour will first try to pull your liquidity from a DEX (in this case, Uniswap v2) and repay some of your debt or add more ETH in the SAFE
* There is a Target Rescue CRatio. This is the collateralization ratio that your SAFE will have in case it is successfully saved. If the saviour cannot bring the SAFE's collateralization ratio to the target that you specify, it will not save the SAFE at all (the SAFE will end up getting liquidated)
* The Protected Liquidation Point is the minimum collateralization ratio at which your SAFE can get liquidated and the saviour still manages to save it. If the SAFE gets liquidated below this threshold, these is a high chance it will not be saved
* There is a Rescue Fee. This is a flat fee that has to be paid to the address that initially wanted to liquidate your SAFE but ended up saving it. The saviour must both pay this fee and manage to bring the CRatio of your SAFE to the Target Rescue CRatio that you picked, otherwise your SAFE will end up getting liquidated. The Rescue Fee can be changed by governance

Once you pick an amount of tokens to deposit in the saviour and a Target Rescue CRatio, you can click on **Review Transaction** and then on **Confirm Transaction**. After your transaction is confirmed, you should see a screen like this:

![](/files/-M_wIGio59HCJYu1Q6VT)

Congrats, your SAFE is now being protected! 🎉

Let's see what happens after one of your SAFEs gets saved. If you go to the SAFE details page, you'll see a button called **Collect Saviour Balance**:

![](/files/-M_wO5gIogXrKGyHO4wG)

Sometimes, the saviour doesn't need to use all the tokens you deposited in order to save your SAFE. You can collect these unused tokens (e.g ETH & RAI withdrawn from Uniswap) by clicking on **Collect Saviour Balance**.

## 3. Best Practices

* Avoid minting more RAI after you protect your SAFE. If you do mint more after you protect it (regardless of whether you add more ETH or not), try to add more LP tokens in the saviour to make sure your SAFE can still be saved now that it has more debt
* Liquidation Protection is **not** a completely set and forget system. You should still watch your SAFE. The idea for protection is that it makes RAI more capital efficient (you can mint more RAI with the same amount of ETH) and liquidators are forced to try and save your SAFEs before they liquidate you
* You should deposit more LP tokens than the minimum recommended amount (which can be found in the app when you deposit cover for a SAFE). By depositing more tokens than the minimum, you take into account the fact that your SAFE accrues debt over time (because of the interest rate), meaning that you will slowly need more and more tokens to save it&#x20;

## 4. Gotchas

* If the saviour you're using cannot bring the collateralization ratio of a protected SAFE to the **Target Rescue CRatio** you picked, the saviour will not save the SAFE at all
* When a saviour saves a SAFE, it will withdraw all your liquidity from a DEX using the LP tokens you deposited. If you want your SAFE to be protected after it's saved, you need to deposit tokens again in the saviour
* You must have enough tokens deposited in the saviour so that it can both save your SAFE and also reimburse the liquidator that ended up paying for the save action
* Once a SAFE is saved, there are probably leftover tokens that were withdrawn from Uniswap and not used for anything. You can redeem these extra tokens at any time by going back to the SAFE's details page and clicking on **Collect Saviour Balance**

## 5. Why Use Liquidation Protection Instead of DeFi Saver?

Liquidation Protection is not meant to replace platforms such as DeFi Saver. Rather, it is meant as an extra cover layer for your SAFEs in cases where not even DeFi Saver might be able to protect you (e.g network congestion during sharp ETH price drops when few people can get a transaction through).

## 6. How does the saviour work under the hood?

When someone starts to liquidate a Safe and the saviour steps in, it will try to do the following:

* Withdraw all the Uniswap liquidity using the LP tokens allocated to save the liquidated Safe
* Calculate how much RAI would need to be repaid in order to bring the Safe's collateralization ratio above the **Target Rescue CRatio**
* If the amount of RAI calculated is higher than the amount of RAI withdrawn from Uniswap and calculate the amount of ETH that would need to be added in the Safe (besides the amount of RAI withdrawn from Uniswap which will be used to repay debt)
* If the calculated ETH amount is higher than the ETH amount withdrawn from Uniswap, the saviour will revert and the Safe will continue to be liquidated. The saviour will also revert if there isn't enough ETH and/or RAI to reimburse the liquidator (who is spending gas to save the Safe) for saving the Safe
* On the other hand, if the calculated ETH amount is lower than the ETH amount withdrawn from Uniswap, the saviour will successfuly save the Safe (by repaying some of the debt and adding the ETH in the Safe). Any amount of ETH and/or RAI that we not used to save will be kept in the saviour until the owner of the Safe will withdraw them

Note that because the saviours withdraws all the liquidity from Uniswap when it saves, the Safe owner will need to deposit LP tokens again if they want to be protected moving forward.


# Uni-V2 RAI/ETH Savior Details

The Uniswap V2 RAI/ETH savior allows users to deposit LP shares to protect their safe. Upon a liquidation attempt from a keeper, the savior will withdraw all RAI and ETH liquidity from Uniswap.&#x20;

The saviour will then repay as much RAI debt as possible. If the Safe's collateralization ratio is still not at the target ratio that the Safe owner picked, the saviour will also add more ETH in the Safe. The keeper that triggered the saviour will then take a flat fee as reward for saving the Safe.&#x20;

The savior does **not** guarantee that the safe will be saved. The user needs to make sure that they deposited enough LP tokens so the saviour can both reward the keeper that saves their position and bring the Safe's collateralization ratio to the target they picked.

### Minimum Savior Balance Formula

In order to derive the formula for the minimum LP balance that can bring your Safe to a target CRatio, we use the following variables:

**Liquidation price**: $$P\_{liq}$$

**Redemption price**: $$P\_{RP}$$

**Asset price**: $$P\_{RAI}$$ , $$P\_{ETH}$$

**Debt**: $$D$$

**Collateral**: $$C$$

**Accumulated rate**: $$A\_{cc}$$

**CRatio**: $$R\_{liq}$$ , $$R\_{targ}$$

**Uniswap reserves**: $$S\_{RAI}$$ , $$S\_{ETH}$$

We first need to use the liquidation price formula:

$$
P\_{liq} = \frac{DA\_{cc}R\_{liq}P\_{rp}}{C}
$$

​From here, we can reorganize the formula to isolate the debt and collateral amount in the Safe. We also use the Target Rebalance CRatio $$R\_{tar}$$ instead of the liquidation CRatio to know how much debt and collateral we need to save the Safe:

$$
\frac{C\_{sav}}{D\_{save}}  = \frac{A\_{cc}R\_{tar}P\_{rp}}{P\_{liq}}
$$

The savior will be withdrawing an amount of LP tokens to get $$D\_{lp}$$ RAI and $$C\_{LP}$$ ETH. Therefore, the resulting debt and collateral in safe after and adding the proceeds from the LP shares will be:&#x20;

$$C\_{save} = C + C\_{lp}$$&#x20;

$$D\_{save} = C - D\_{lp}$$

Which then gives us:

$$
\frac{C + C\_{lp}}{D - D\_{lp}}  = \frac{A\_{cc}R\_{tar}P\_{rp}}{P\_{liq}}
$$

We will reuse this formula later. We now need to model the Uniswap pool dynamics to calculate the amount $$D\_{lp}$$ and $$C\_{LP}$$  we would get from the savior LP shares at a given liquidation price. We start from the standard xy=k assumptions:

$$
\begin{cases}K\_{lp} = S\_{ETH}S\_{RAI}\ S\_{ETH}P\_{ETH}= S\_{RAI}P\_{RAI}\end{cases}
$$

$$
\iff K\_{LP} P\_{ETH} = {S\_{RAI}}^2 P\_{RAI}
$$

$$
\iff S\_{RAI} = \sqrt{K\_{LP} \frac{P\_{ETH}}{P\_{RAI}}}
$$

And similarly:

$$
\iff S\_{ETH} = \sqrt{K\_{LP} \frac{P\_{RAI}}{P\_{ETH}}}
$$

We can now replace these results in the equation from the liquidation price:

$$
\frac{C + \sqrt{K\_{LP} \frac{P\_{RAI}}{P\_{ETH}}} }{D - \sqrt{K\_{LP} \frac{P\_{ETH}}{P\_{RAI}}} }  = \frac{A\_{cc}R\_{tar}P\_{rp}}{P\_{liq}}
$$

We simplify the equation using $$p = \frac{P\_{RAI}}{P\_{ETH}}$$ and $$j=\frac{A\_{cc}R\_{tar}P\_{rp}}{P\_{liq}}$$

$$
\frac{C + \sqrt{K\_{LP}p } }{D - \sqrt{K\_{LP} \frac{1}{p}} }  = j
$$

We need to solve the equation above for $$K\_{LP}$$.

Using Wolfram Alpha:

{% embed url="<https://www.wolframalpha.com/input?i=solve%5C%2840%29Divide%5Bc%2BSqrt%5Bk*p%5D%2Cd-Sqrt%5Bk*%5C%2840%29Divide%5B1%2Cp%5D%5C%2841%29%5D%5D%3Dj%5C%2844%29k%5C%2841%29&i2d=true>" %}

​We get 2 solutions:

$$
\begin{cases} K\_{LP1}= \frac{p(C-Dj)^2}{(j-p)^2} \  K\_{LP2}= \frac{p(C-Dj)^2}{(j+p)^2} \end{cases}
$$

Since we're interested in the minimum balance of LP tokens, we keep only the second solution that will give the lowest balance possible. Last, we need to take the square root of $$K\_{LP}$$ ​to get the actual LP token balance:

$$
Bal\_{LPmin}= \sqrt{\frac{p(C-Dj)^2}{(j+p)^2}}=\sqrt{p} \frac{|C-Dj|}{j+p}
$$

Done! To that we have to add the flat $2000 keeper fee. Below is a calculation example:

{% embed url="<https://docs.google.com/spreadsheets/d/1flg9LidXvxcAInw4-AtDCEFniMGoZg9fIgm-x36S3CA/edit#gid=0>" %}

The spreadsheet is available here, make a copy to test your own parameters: <https://docs.google.com/spreadsheets/d/1flg9LidXvxcAInw4-AtDCEFniMGoZg9fIgm-x36S3CA/edit#gid=0>


# Curve V1 Savior Details

**This is the math and logic that would apply in the case of a Curve V1 saviour integrated with the RAI protocol.**

### Overview

The Curve V1 savior requires SAFE owners to deposit Curve RAI/3Pool LP tokens. The RAI/3Pool contract can be found [here](https://etherscan.io/address/0x618788357D0EBd8A37e763ADab3bc575D54c2C7d).

Upon liquidation, the Curve savior will withdraw all underlying liquidity (RAI + 3Pool tokens) from the LP shares protecting the liquidated SAFE. It will then use the withdrawn RAI to pay back as much debt as possible from the SAFE. The 3Pool tokens aren't used in this process and will need to be withdrawn manually from the savior at a later date.

### Minimum Savior Balance Calculation

We reuse the variable naming and debt/collateral liquidation relationship from the [Uni-v2 savior calculation](https://docs.reflexer.finance/liquidation-protection/uni-v2-rai-eth-savior-math#minimum-savior-balance-formula).&#x20;

$$
\frac{C + C\_{lp}}{D - D\_{lp}}  = \frac{A\_{cc}R\_{tar}P\_{rp}}{P\_{liq}}
$$

In the curve savior we aren't adding any collateral, therefore $$C\_{lp}=0$$. For$$D\_{lp}$$ we have to calculate the amount of RAI withdrawn from the pool. We will assume that the USD value of the pool stays 50/50 and that RAI trades close to it redemption price. Therefore for each RAI-3Pool LP token $$K\_{RAI3Pool}$$ we are getting $$D = \frac{K\_{RAI3Pool}}{2 P\_{rp}}$$RAI which give us the following formula:

$$
\frac{2CP\_{rp}}{2P\_{rp}D - K\_{RAI3Pool}} = \frac{A\_{cc}R\_{tar}P\_{rp}}{P\_{liq}}
$$

&#x20;Which then gives us (after also replacing the liquidation price):

$$
K = 2P\_{rp}D- \frac{2CP\_{liq}}{A\_{acc}R\_{tar}} =  2P\_{rp}D-\frac{2DP\_{rp}R\_{liq}}{R\_{tar}} = 2P\_{rp}D( 1 - \frac{R\_{liq}}{R\_{tar}})
$$

To this we have to add the $2000 liquidator fee.&#x20;

To help with the whole calculation, you can use the following spreadsheet:

{% embed url="<https://docs.google.com/spreadsheets/d/1GeY8B6RW01GeQiM1FIFBIlgA5bV6Qdzv1XsvYKwVU4Y/edit#gid=0>" %}


