# Silo

> ISilo

Silo is the main component of the protocol. It implements lending logic, manages and isolates risk, acts as a vault for assets, and performs liquidations. Each Silo is composed of the unique asset for which it was created (ie. UNI) and bridge assets (ie. ETH and SiloDollar). There may be multiple bridge assets at any given time.

*Main Silo contact that inherits from Base contract. It implements all user/UI facing methods.*

## Methods

### ASSET\_DECIMAL\_POINTS

```solidity
function ASSET_DECIMAL_POINTS() external view returns (uint256)
```

#### Returns

| Name | Type    | Description |
| ---- | ------- | ----------- |
| \_0  | uint256 | undefined   |

### VERSION

```solidity
function VERSION() external view returns (uint256)
```

It tells us which `SiloRepository.siloFactory(version)` created this Silo

#### Returns

| Name | Type    | Description |
| ---- | ------- | ----------- |
| \_0  | uint256 | undefined   |

### accrueInterest

```solidity
function accrueInterest(address _asset) external nonpayable
```

Function to update interests for `_asset` token since the last saved state

#### Parameters

| Name    | Type    | Description                            |
| ------- | ------- | -------------------------------------- |
| \_asset | address | The address of the token to be updated |

### allSiloAssets

```solidity
function allSiloAssets(uint256) external view returns (address)
```

#### Parameters

| Name | Type    | Description |
| ---- | ------- | ----------- |
| \_0  | uint256 | undefined   |

#### Returns

| Name | Type    | Description |
| ---- | ------- | ----------- |
| \_0  | address | undefined   |

### assetInterestData

```solidity
function assetInterestData(address) external view returns (uint256 harvestedProtocolFees, uint256 protocolFees, uint64 interestRateTimestamp, enum IBaseSilo.AssetStatus status)
```

#### Parameters

| Name | Type    | Description |
| ---- | ------- | ----------- |
| \_0  | address | undefined   |

#### Returns

| Name                  | Type                       | Description |
| --------------------- | -------------------------- | ----------- |
| harvestedProtocolFees | uint256                    | undefined   |
| protocolFees          | uint256                    | undefined   |
| interestRateTimestamp | uint64                     | undefined   |
| status                | enum IBaseSilo.AssetStatus | undefined   |

### assetStorage

```solidity
function assetStorage(address _asset) external view returns (struct IBaseSilo.AssetStorage)
```

Get asset storage data

#### Parameters

| Name    | Type    | Description   |
| ------- | ------- | ------------- |
| \_asset | address | asset address |

#### Returns

| Name | Type                   | Description         |
| ---- | ---------------------- | ------------------- |
| \_0  | IBaseSilo.AssetStorage | AssetStorage struct |

### borrow

```solidity
function borrow(address _asset, uint256 _amount) external nonpayable
```

Borrow `_amount` of `_asset` tokens from the Silo to `msg.sender`

#### Parameters

| Name     | Type    | Description                        |
| -------- | ------- | ---------------------------------- |
| \_asset  | address | The address of the token to borrow |
| \_amount | uint256 | The amount of the token to borrow  |

### borrowFor

```solidity
function borrowFor(address _asset, address _borrower, address _receiver, uint256 _amount) external nonpayable
```

Router function to borrow `_amount` of `_asset` tokens from the Silo for the `_receiver`

#### Parameters

| Name       | Type    | Description                             |
| ---------- | ------- | --------------------------------------- |
| \_asset    | address | The address of the token to borrow      |
| \_borrower | address | The address of the debt tokens receiver |
| \_receiver | address | The address of the asset receiver       |
| \_amount   | uint256 | The amount of the token to borrow       |

### borrowPossible

```solidity
function borrowPossible(address _asset, address _borrower) external view returns (bool)
```

Check if borrowing an asset for given account is possible

*Borrowing an asset that has been already deposited (and vice versa) is disallowed*

#### Parameters

| Name       | Type    | Description              |
| ---------- | ------- | ------------------------ |
| \_asset    | address | asset we want to deposit |
| \_borrower | address | borrower address         |

#### Returns

| Name | Type | Description                               |
| ---- | ---- | ----------------------------------------- |
| \_0  | bool | true if asset can be borrowed by borrower |

### deposit

```solidity
function deposit(address _asset, uint256 _amount, bool _collateralOnly) external nonpayable
```

Deposit `_amount` of `_asset` tokens from `msg.sender` to the Silo

#### Parameters

| Name             | Type    | Description                         |
| ---------------- | ------- | ----------------------------------- |
| \_asset          | address | The address of the token to deposit |
| \_amount         | uint256 | The amount of the token to deposit  |
| \_collateralOnly | bool    | True if depositing collateral only  |

### depositFor

```solidity
function depositFor(address _asset, address _depositor, uint256 _amount, bool _collateralOnly) external nonpayable
```

Router function to deposit `_amount` of `_asset` tokens to the Silo for the `_depositor`

#### Parameters

| Name             | Type    | Description                                       |
| ---------------- | ------- | ------------------------------------------------- |
| \_asset          | address | The address of the token to deposit               |
| \_depositor      | address | The address of the recipient of collateral tokens |
| \_amount         | uint256 | The amount of the token to deposit                |
| \_collateralOnly | bool    | True if depositing collateral only                |

### depositPossible

```solidity
function depositPossible(address _asset, address _depositor) external view returns (bool)
```

Check if depositing an asset for given account is possible

*Depositing an asset that has been already borrowed (and vice versa) is disallowed*

#### Parameters

| Name        | Type    | Description              |
| ----------- | ------- | ------------------------ |
| \_asset     | address | asset we want to deposit |
| \_depositor | address | depositor address        |

#### Returns

| Name | Type | Description                                 |
| ---- | ---- | ------------------------------------------- |
| \_0  | bool | true if asset can be deposited by depositor |

### flashLiquidate

```solidity
function flashLiquidate(address[] _users, bytes _flashReceiverData) external nonpayable returns (address[] assets, uint256[][] receivedCollaterals, uint256[][] shareAmountsToRepay)
```

this methods does not requires to have tokens in order to liquidate user

*during liquidation process, msg.sender will be notified once all collateral will be send to him msg.sender needs to be `IFlashLiquidationReceiver`*

#### Parameters

| Name                | Type       | Description                                             |
| ------------------- | ---------- | ------------------------------------------------------- |
| \_users             | address\[] | array of users to liquidate                             |
| \_flashReceiverData | bytes      | this data will be forward to msg.sender on notification |

#### Returns

| Name                | Type          | Description                                                                                    |
| ------------------- | ------------- | ---------------------------------------------------------------------------------------------- |
| assets              | address\[]    | array of all processed assets (collateral + debt, including removed)                           |
| receivedCollaterals | uint256\[]\[] | seizedCollaterals\[userId]\[assetId] => amount amounts of collaterals send to `_flashReceiver` |
| shareAmountsToRepay | uint256\[]\[] | shareAmountsToRepaid\[userId]\[assetId] => amount required amounts of debt to be repaid        |

### getAssets

```solidity
function getAssets() external view returns (address[] assets)
```

Returns all initialized (synced) assets of Silo including current and removed bridge assets

#### Returns

| Name   | Type       | Description                         |
| ------ | ---------- | ----------------------------------- |
| assets | address\[] | array of initialized assets of Silo |

### getAssetsWithState

```solidity
function getAssetsWithState() external view returns (address[] assets, struct IBaseSilo.AssetStorage[] assetsStorage)
```

Returns all initialized (synced) assets of Silo including current and removed bridge assets with corresponding state

#### Returns

| Name          | Type                      | Description                                           |
| ------------- | ------------------------- | ----------------------------------------------------- |
| assets        | address\[]                | array of initialized assets of Silo                   |
| assetsStorage | IBaseSilo.AssetStorage\[] | array of assets state corresponding to `assets` array |

### harvestProtocolFees

```solidity
function harvestProtocolFees(address[] _assets) external nonpayable
```

*harvest protocol fees from an array of assets*

#### Parameters

| Name     | Type       | Description                                  |
| -------- | ---------- | -------------------------------------------- |
| \_assets | address\[] | array of assets we want to harvest fees from |

### initAssetsTokens

```solidity
function initAssetsTokens() external nonpayable
```

*this is exposed only for test purposes, but it is safe to leave it like that*

### interestData

```solidity
function interestData(address _asset) external view returns (struct IBaseSilo.AssetInterestData)
```

Get asset interest data

#### Parameters

| Name    | Type    | Description   |
| ------- | ------- | ------------- |
| \_asset | address | asset address |

#### Returns

| Name | Type                        | Description              |
| ---- | --------------------------- | ------------------------ |
| \_0  | IBaseSilo.AssetInterestData | AssetInterestData struct |

### isSolvent

```solidity
function isSolvent(address _user) external view returns (bool)
```

Calculates solvency of an account

#### Parameters

| Name   | Type    | Description                                     |
| ------ | ------- | ----------------------------------------------- |
| \_user | address | wallet address for which solvency is calculated |

#### Returns

| Name | Type | Description                      |
| ---- | ---- | -------------------------------- |
| \_0  | bool | true if solvent, false otherwise |

### repay

```solidity
function repay(address _asset, uint256 _amount) external nonpayable
```

Repay `_amount` of `_asset` tokens from `msg.sender` to the Silo

#### Parameters

| Name     | Type    | Description                                  |
| -------- | ------- | -------------------------------------------- |
| \_asset  | address | The address of the token to repay            |
| \_amount | uint256 | amount of asset to repay, includes interests |

### repayFor

```solidity
function repayFor(address _asset, address _borrower, uint256 _amount) external nonpayable
```

Allows to repay in behalf of borrower to execute liquidation

#### Parameters

| Name       | Type    | Description                                        |
| ---------- | ------- | -------------------------------------------------- |
| \_asset    | address | The address of the token to repay                  |
| \_borrower | address | The address of the user to have debt tokens burned |
| \_amount   | uint256 | amount of asset to repay, includes interests       |

### siloAsset

```solidity
function siloAsset() external view returns (address)
```

#### Returns

| Name | Type    | Description |
| ---- | ------- | ----------- |
| \_0  | address | undefined   |

### siloRepository

```solidity
function siloRepository() external view returns (contract ISiloRepository)
```

Get Silo Repository contract address

#### Returns

| Name | Type                     | Description |
| ---- | ------------------------ | ----------- |
| \_0  | contract ISiloRepository | undefined   |

### state

```solidity
function state(address) external view returns (contract IShareToken collateralToken, contract IShareToken collateralOnlyToken, contract IShareToken debtToken, uint256 totalDeposits, uint256 collateralOnlyDeposits, uint256 totalBorrowAmount)
```

#### Parameters

| Name | Type    | Description |
| ---- | ------- | ----------- |
| \_0  | address | undefined   |

#### Returns

| Name                   | Type                 | Description |
| ---------------------- | -------------------- | ----------- |
| collateralToken        | contract IShareToken | undefined   |
| collateralOnlyToken    | contract IShareToken | undefined   |
| debtToken              | contract IShareToken | undefined   |
| totalDeposits          | uint256              | undefined   |
| collateralOnlyDeposits | uint256              | undefined   |
| totalBorrowAmount      | uint256              | undefined   |

### syncBridgeAssets

```solidity
function syncBridgeAssets() external nonpayable
```

Synchronize current bridge assets with Silo

*This function needs to be called on Silo deployment to setup all assets for Silo. It needs to be called every time a bridged asset is added or removed. When bridge asset is removed, depositing and borrowing should be disabled during asset sync.*

### utilizationData

```solidity
function utilizationData(address _asset) external view returns (struct IBaseSilo.UtilizationData data)
```

*helper method for InterestRateModel calculations*

#### Parameters

| Name    | Type    | Description |
| ------- | ------- | ----------- |
| \_asset | address | undefined   |

#### Returns

| Name | Type                      | Description |
| ---- | ------------------------- | ----------- |
| data | IBaseSilo.UtilizationData | undefined   |

### withdraw

```solidity
function withdraw(address _asset, uint256 _amount, bool _collateralOnly) external nonpayable
```

Withdraw `_amount` of `_asset` tokens from the Silo to `msg.sender`

#### Parameters

| Name             | Type    | Description                                 |
| ---------------- | ------- | ------------------------------------------- |
| \_asset          | address | The address of the token to withdraw        |
| \_amount         | uint256 | The amount of the token to withdraw         |
| \_collateralOnly | bool    | True if withdrawing collateral only deposit |

### withdrawFor

```solidity
function withdrawFor(address _asset, address _depositor, address _receiver, uint256 _amount, bool _collateralOnly) external nonpayable
```

Router function to withdraw `_amount` of `_asset` tokens from the Silo for the `_depositor`

#### Parameters

| Name             | Type    | Description                                         |
| ---------------- | ------- | --------------------------------------------------- |
| \_asset          | address | The address of the token to withdraw                |
| \_depositor      | address | The address of the collateral tokens source account |
| \_receiver       | address | The address of the asset receiver                   |
| \_amount         | uint256 | The amount of the token to withdraw                 |
| \_collateralOnly | bool    | True if withdrawing collateral only deposit         |

## Events

### Borrow

```solidity
event Borrow(address indexed asset, address indexed user, uint256 amount)
```

Emitted on asset borrow

#### Parameters

| Name            | Type    | Description |
| --------------- | ------- | ----------- |
| asset `indexed` | address | undefined   |
| user `indexed`  | address | undefined   |
| amount          | uint256 | undefined   |

### Deposit

```solidity
event Deposit(address indexed asset, address indexed depositor, uint256 amount, bool collateralOnly)
```

Emitted when deposit is made

#### Parameters

| Name                | Type    | Description |
| ------------------- | ------- | ----------- |
| asset `indexed`     | address | undefined   |
| depositor `indexed` | address | undefined   |
| amount              | uint256 | undefined   |
| collateralOnly      | bool    | undefined   |

### Liquidate

```solidity
event Liquidate(address indexed asset, address indexed user, uint256 shareAmountRepaid, uint256 seizedCollateral)
```

Emitted on user liquidation

#### Parameters

| Name              | Type    | Description |
| ----------------- | ------- | ----------- |
| asset `indexed`   | address | undefined   |
| user `indexed`    | address | undefined   |
| shareAmountRepaid | uint256 | undefined   |
| seizedCollateral  | uint256 | undefined   |

### Repay

```solidity
event Repay(address indexed asset, address indexed user, uint256 amount)
```

Emitted on asset repay

#### Parameters

| Name            | Type    | Description |
| --------------- | ------- | ----------- |
| asset `indexed` | address | undefined   |
| user `indexed`  | address | undefined   |
| amount          | uint256 | undefined   |

### Withdraw

```solidity
event Withdraw(address indexed asset, address indexed depositor, address indexed receiver, uint256 amount, bool collateralOnly)
```

Emitted when withdraw is made

#### Parameters

| Name                | Type    | Description |
| ------------------- | ------- | ----------- |
| asset `indexed`     | address | undefined   |
| depositor `indexed` | address | undefined   |
| receiver `indexed`  | address | undefined   |
| amount              | uint256 | undefined   |
| collateralOnly      | bool    | undefined   |

## Errors

### IncorrectDataLength

```solidity
error IncorrectDataLength()
```
