# SAFE Engine

## 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.
