# Teller Protocol Diamond

### Structure

This is the main diamond contract where all facets of the protocol can talk to each other through a shared storage interface. The `ITellerDiamond` contract itself works by importing all of it's facets as dependencies. See below:

```
abstract contract ITellerDiamond is
    SettingsFacet,
    PlatformSettingsFacet,
    AssetSettingsDataFacet,
    AssetSettingsFacet,
    PausableFacet,
    PriceAggFacet,
    ChainlinkAggFacet,
    LendingFacet,
    CollateralFacet,
    CreateLoanFacet,
    LoanDataFacet,
    RepayFacet,
    SignersFacet,
    NFTFacet,
    EscrowClaimTokensFacet,
    CompoundFacet,
    UniswapFacet,
    IDiamondCut,
    IDiamondLoupe
{}
```

In the Teller Protocol, each **Facet** contains function helpers that come from its respective **Library** or libraries. Each **Library** contains not only function helpers to assist the facets, but also a storage function caller. Here's an example of our `LoanDataFacet`

```
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

// Libraries
import { LibLoans } from "./libraries/LibLoans.sol";

// Storage
import { Loan, LoanDebt, LoanTerms } from "../storage/market.sol";

contract LoanDataFacet {

    function getLoan(uint256 loanID) external view returns (Loan memory loan_) {
        loan_ = LibLoans.s().loans[loanID];
    }

    function getLoanEscrowValue(uint256 loanID)
        external
        view
        returns (uint256)
    {
        return LibEscrow.calculateTotalValue(loanID);
    }
}
```

*Note: this example does not resemble our actual file on the Teller protocol, but rather a simplified version.*

In this example, our `LoanDataFacet` uses 2 functions that call from the `LibLoans` and the `LibEscrow` library, respectively:

* `getLoan` directly calls the `LibLoans` storage function `s()` which gets our `loan` data back after we pass our `loanID`
* `getLoanEscrowValue` directly calls the `LibEscrow` library function `calculateTotalValue` to calculate the loan escrow value using `loanID`

Next, we'll look at how storage works.

### Storage

The way diamond storage works is that we add or read data to a `struct` that is stored in a hashed position slot by calling a function. Let's call this function `store()`. We shall take a look at our `market.sol` storage file, since it's the most popular one in our Teller protocol.

```
struct MarketStorage {
    // Holds the index for the next loan ID
    Counters.Counter loanIDCounter;
    // Maps loanIDs to loan data
    mapping(uint256 => Loan) loans;
    // Maps loanID to loan debt (total owed left)
    mapping(uint256 => LoanDebt) loanDebt;
    // Maps loanID to loan terms
    mapping(uint256 => LoanTerms) _loanTerms; // DEPRECATED: DO NOT REMOVE
    // Maps loanIDs to escrow address to list of held tokens
    mapping(uint256 => ILoansEscrow) loanEscrows;
    // Maps loanIDs to list of tokens owned by a loan escrow
    mapping(uint256 => EnumerableSet.AddressSet) escrowTokens;
    // Maps collateral token address to a LoanCollateralEscrow that hold collateral funds
    mapping(address => ICollateralEscrow) collateralEscrows;
    // Maps accounts to owned loan IDs
    mapping(address => uint128[]) borrowerLoans;
    // Maps lending token to overall amount of interest collected from loans
    mapping(address => ITToken) tTokens;
    // Maps lending token to list of signer addresses who are only ones allowed to verify loan requests
    mapping(address => EnumerableSet.AddressSet) signers;
    // Maps lending token to list of allowed collateral tokens
    mapping(address => EnumerableSet.AddressSet) collateralTokens;
}

bytes32 constant MARKET_STORAGE_POS = keccak256("teller.market.storage");

library MarketStorageLib {
    function store() internal pure returns (MarketStorage storage s) {
        bytes32 pos = MARKET_STORAGE_POS;
        assembly {
            s.slot := pos
        }
    }
}
```

This file, like the previous file, has been compressed for ease of understanding.

* Our `MARKET_STORAGE_POS` is the hash of our position string
* The `store()` function in the `MarketStorageLib` returns our `MarketStorage` at the position we initialized before
* The `MarketStorage` is a heavy struct with multiple mappings to interfaces, primitive data types and other structs

So, now that we understand this, how do we call this function to update or read data? Well, it's simple really! Let's head to a simple function in our `LibLoans` library called `loan()`, which simply returns our loan data:

```
function s() internal pure returns (MarketStorage storage) {
        return MarketStorageLib.store();
    }

		/**
     * @notice it returns the loan
     * @param loanID the ID of the respective loan
     * @return l_ the loan 
     */
    function loan(uint256 loanID) internal view returns (Loan storage l_) {
        l_ = s().loans[loanID];
    }
```

Let's go through this step by step

* `loan()` function takes in the `loanID` as a parameter and returns a struct of type `Loan` (defined in `market.sol`) with the help of our `s()` function
* the `s()` function calls our `MarketStorageLib.store()`, which if you remember it returns our `MarketStorage` struct stored at our hashed slot
* Now that our `MarketStorage` is returned via `s()`, we also return the specific loan by adding `.loans[loanID]`

That's really our Diamond Structure and Storage in a nutshell! Since our Diamond pulls in all of its Facets via Inheritance, calling any of our facet is still calling our Diamond Contract's address.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.teller.org/teller-diamond/teller-protocol-diamond.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
