# BalanceSheet

## Introduction

The BalanceSheet is the global debt registry of Hifi. All users who borrow fyTokens have to first open a vault bespoke to that fyToken contract. All vaults are recorded in and managed via the BalanceSheet.

## Gas Costs

Gas usage is not deterministic due to requisite calls to third-party Erc20 tokens. We provide the table below for guidance only:

| Action              | Typical Gas Cost                 |
| ------------------- | -------------------------------- |
| Deposit Collateral  | <70K                             |
| Free Collateral     | <110K if partial, <40K otherwise |
| Lock Collateral     | <40K                             |
| Open Vault          | <50K                             |
| Withdraw Collateral | <40K                             |

## Storage Properties

### Fintroller

The unique Fintroller associated with this contract.

```javascript
FintrollerInterface public fintroller;
```

## Constant Functions <a href="#constant-functions" id="constant-functions"></a>

### Get Clutchable Collateral <a href="#getstream" id="getstream"></a>

Determines the amount of collateral that can be clutched when liquidating a borrow according to the formula:

$$
clutchedCollateral = \frac {repayAmount \* liquidationIncentive \* underlyingPriceUsd} {collateralPriceUsd}
$$

```javascript
function getClutchableCollateral(FyTokenInterface fyToken, uint256 repayAmount) external view returns (uint256)
```

* `fyToken`: The fyToken to make the query against.
* `repayAmount`: The amount of fyTokens to repay (must be non-zero).
* `RETURN`: The amount of clutchable collateral as uint256, specified in the collateral's decimal system.

#### Solidity <a href="#solidity-5" id="solidity-5"></a>

```javascript
‌BalanceSheet balanceSheet = BalanceSheet(0xabcd...);
FyTokenInterface fyToken = FyTokenInterface(0xbcde...);
uint256 repayAmount = 10000000000000000000;
uint256 clutchableCollateral = balanceSheet.getClutchableCollateral(fyToken, repayAmount);
```

#### Ethers.js <a href="#ethers-js-5" id="ethers-js-5"></a>

```javascript
const balanceSheet = new ethers.Contract(0xabcd..., balanceSheetABI, signer);
const fyToken = new ethers.Contract(0xbcde..., fyTokenInterfaceABI, signer);
const repayAmount = "10000000000000000000";
const clutchableCollateral = await balanceSheet.getClutchableCollateral(fyToken, repayAmount);‌
```

### Get Current Collateralization Ratio <a href="#cancel-stream" id="cancel-stream"></a>

Determines the current collateralization ratio for the given borrower account.

```javascript
function getCurrentCollateralizationRatio(FyTokenInterface fyToken, address borrower) public view returns (uint256)
```

* `fyToken`: The fyToken to make the query against.
* `borrower`: The borrower account to make the query against.
* `RETURN`: A quotient if locked collateral is non-zero, otherwise zero.

#### Solidity <a href="#solidity-5" id="solidity-5"></a>

```javascript
‌BalanceSheet balanceSheet = BalanceSheet(0xabcd...);
FyTokenInterface fyToken = FyTokenInterface(0xbcde...);
address borrower = 0x1234;
uint256 currentCollateralizationRatio = balanceSheet.getCurrentCollateralizationRatio(fyToken, borrower);
```

#### Ethers.js <a href="#ethers-js-5" id="ethers-js-5"></a>

```javascript
const balanceSheet = new ethers.Contract(0xabcd..., balanceSheetABI, signer);
const fyToken = new ethers.Contract(0xbcde..., fyTokenInterfaceABI, signer);
const borrower = 0x1234;
const currentCollateralizationRatio = await balanceSheet.getCurrentCollateralizationRatio(fyToken, borrower);‌
```

### Get Hypothetical Collateralization Ratio <a href="#cancel-stream" id="cancel-stream"></a>

Determines the hypothetical collateralization ratio for the given locked collateral and debt, at the current prices provided by the oracle according to the formula:

$$
collateralizationRatio = \frac {lockedCollateralValueUsd} {debtValueUsd}
$$

```javascript
function getHypotheticalCollateralizationRatio(FyTokenInterface fyToken, address borrower, uint256 lockedCollateral, uint256 debt) public view returns (uint256)
```

* `fyToken`: The fyToken to make the query against.
* `borrower`: The borrower account to make the query against.
* `lockedCollateral`: The hypothetical locked collateral.
* `debt`: The hypothetical debt.
* `RETURN`: The hypothetical collateralization ratio as a percentage mantissa if locked collateral is non-zero, otherwise zero.

{% hint style="warning" %}
Requirements

* The vault must be open.
* "debt" must be non-zero.
* The oracle prices must be non-zero.
  {% endhint %}

#### Solidity <a href="#solidity-5" id="solidity-5"></a>

```javascript
‌BalanceSheet balanceSheet = BalanceSheet(0xabcd...);
FyTokenInterface fyToken = FyTokenInterface(0xbcde...);
address borrower = 0x1234;
address lockedCollateral = 10000000000000000000;
address debt = 5000000000000000000;
uint256 hypotheticalCollateralizationRatio = balanceSheet.getHypotheticalCollateralizationRatio(fyToken, borrower, lockedCollateral, debt);
```

#### Ethers.js <a href="#ethers-js-5" id="ethers-js-5"></a>

```javascript
const balanceSheet = new ethers.Contract(0xabcd..., balanceSheetABI, signer);
const fyToken = new ethers.Contract(0xbcde..., fyTokenInterfaceABI, signer);
const borrower = 0x1234;
const lockedCollateral = "10000000000000000000";
const debt = "5000000000000000000";
const hypotheticalCollateralizationRatio = await balanceSheet.getHypotheticalCollateralizationRatio(fyToken, borrower, lockedCollateral, debt);
```

### Get Vault <a href="#cancel-stream" id="cancel-stream"></a>

Reads all the properties of a vault.

```javascript
function getVault(FyTokenInterface fyToken, address borrower) external view returns (uint256, uint256, uint256, bool)
```

* `fyToken` : The fyToken to make the query against.
* `borrower` : The borrower account to make the query against.
* `RETURN`: The vault with all its properties.

#### Solidity <a href="#solidity-5" id="solidity-5"></a>

```javascript
‌BalanceSheet balanceSheet = BalanceSheet(0xabcd...);
FyTokenInterface fyToken = FyTokenInterface(0xbcde...);
address borrower = 0x1234;
(uint256 debt, uint256 freeCollateral, uint256 lockedCollateral, bool isOpen) = balanceSheet.getVault(fyToken, borrower);
```

#### Ethers.js <a href="#ethers-js-5" id="ethers-js-5"></a>

```javascript
const balanceSheet = new ethers.Contract(0xabcd..., balanceSheetABI, signer);
const fyToken = new ethers.Contract(0xbcde..., fyTokenInterfaceABI, signer);
const borrower = 0x1234;
const vault = await balanceSheet.getVault(fyToken, borrower);‌
```

### Get Vault Debt <a href="#cancel-stream" id="cancel-stream"></a>

Reads the debt held by the given account.

```javascript
function getVaultDebt(FyTokenInterface fyToken, address borrower) external view returns (uint256)
```

* `fyToken` : The fyToken to make the query against.
* `borrower` : The borrower account to make the query against.
* `RETURN`: The debt held by the borrower, as an uint256.

#### Solidity <a href="#solidity-5" id="solidity-5"></a>

```javascript
‌BalanceSheet balanceSheet = BalanceSheet(0xabcd...);
FyTokenInterface fyToken = FyTokenInterface(0xbcde...);
address borrower = 0x1234;
uint256 vaultDebt = balanceSheet.getVaultDebt(fyToken, borrower);
```

#### Ethers.js <a href="#ethers-js-5" id="ethers-js-5"></a>

```javascript
const balanceSheet = new ethers.Contract(0xabcd..., balanceSheetABI, signer);
const fyToken = new ethers.Contract(0xbcde..., fyTokenInterfaceABI, signer);
const borrower = 0x1234;
const vaultDebt = await balanceSheet.getVaultDebt(fyToken, borrower);‌
```

### Get Vault Locked Collateral <a href="#cancel-stream" id="cancel-stream"></a>

Reads the amount of collateral that the given borrower account locked in the vault.

```javascript
function getVaultLockedCollateral(FyTokenInterface fyToken, address borrower) external view returns (uint256)
```

* `fyToken`: The fyToken to make the query against.
* `borrower`: The borrower account to make the query against.
* `RETURN`: The collateral locked in the vault by the borrower, as an uint256.

#### Solidity <a href="#solidity-5" id="solidity-5"></a>

```javascript
‌BalanceSheet balanceSheet = BalanceSheet(0xabcd...);
FyTokenInterface fyToken = FyTokenInterface(0xbcde...);
address borrower = 0x1234;
uint256 vaultLockedCollateral = balanceSheet.getVaultLockedCollateral(fyToken, borrower);
```

#### Ethers.js <a href="#ethers-js-5" id="ethers-js-5"></a>

```javascript
const balanceSheet = new ethers.Contract(0xabcd..., balanceSheetABI, signer);
const fyToken = new ethers.Contract(0xbcde..., fyTokenInterfaceABI, signer);
const borrower = 0x1234;
const vaultLockedCollateral = await balanceSheet.getVaultLockedCollateral(fyToken, borrower);‌
```

### Is Account Underwater <a href="#cancel-stream" id="cancel-stream"></a>

Checks whether the borrower account can be liquidated or not.

```javascript
function isAccountUnderwater(FyTokenInterface fyToken, address borrower) external view returns (bool)
```

* `fyToken`: The fyToken to make the query against.
* `borrower`: The borrower account to make the query against.
* `RETURN`: true = is underwater, otherwise not.

#### Solidity <a href="#solidity-5" id="solidity-5"></a>

```javascript
‌BalanceSheet balanceSheet = BalanceSheet(0xabcd...);
FyTokenInterface fyToken = FyTokenInterface(0xbcde...);
address borrower = 0x1234;
uint256 isAccountUnderwater = balanceSheet.isAccountUnderwater(fyToken, borrower);
```

#### Ethers.js <a href="#ethers-js-5" id="ethers-js-5"></a>

```javascript
const balanceSheet = new ethers.Contract(0xabcd..., balanceSheetABI, signer);
const fyToken = new ethers.Contract(0xbcde..., fyTokenInterfaceABI, signer);
const borrower = 0x1234;
const isAccountUnderwater = await balanceSheet.isAccountUnderwater(fyToken, borrower);‌
```

### Is Vault Open <a href="#cancel-stream" id="cancel-stream"></a>

Checks whether the borrower account has a vault opened for a particular fyToken.

```javascript
function isVaultOpen(FyTokenInterface fyToken, address borrower) external view returns (bool)
```

* `fyToken`: The fyToken to make the query against.
* `borrower`: The borrower account to make the query against.
* `RETURN`: true = is open, otherwise not.

#### Solidity <a href="#solidity-5" id="solidity-5"></a>

```javascript
‌BalanceSheet balanceSheet = BalanceSheet(0xabcd...);
FyTokenInterface fyToken = FyTokenInterface(0xbcde...);
address borrower = 0x1234;
uint256 isVaultOpen = balanceSheet.isVaultOpen(fyToken, borrower);
```

#### Ethers.js <a href="#ethers-js-5" id="ethers-js-5"></a>

```javascript
const balanceSheet = new ethers.Contract(0xabcd..., balanceSheetABI, signer);
const fyToken = new ethers.Contract(0xbcde..., fyTokenInterfaceABI, signer);
const borrower = 0x1234;
const isVaultOpen = await balanceSheet.isVaultOpen(fyToken, borrower);‌
```

## Non-Constant Functions <a href="#non-constant-functions" id="non-constant-functions"></a>

### Clutch Collateral <a href="#getstream" id="getstream"></a>

Transfers the collateral from the borrower's vault to the liquidator account. Emits a "ClutchCollateral" event.

```javascript
function clutchCollateral(FyTokenInterface fyToken, address liquidator, address borrower, uint256 collateralAmount ) external returns (bool)
```

* `fyToken`: The address of the fyToken contract.
* `liquidator`: The account who repays the borrower's debt and receives the collateral.
* `borrower`: The account who fell underwater and is liquidated.
* `collateralAmount`: The amount of collateral to clutch, specified in the collateral's decimal system.
* `RETURN`: true = success, otherwise it reverts

{% hint style="warning" %}
Requirements:

* Can only be called by the fyToken contract.
* There must be enough collateral in the borrower's vault.
  {% endhint %}

{% hint style="info" %}
We didn't write code snippets for this function because it is not meant to be called directly. Only the fyToken contract is allowed to call "clutchCollateral".
{% endhint %}

### Deposit Collateral <a href="#getstream" id="getstream"></a>

Deposits collateral into the account's vault. Emits a "DepositCollateral" event.

```javascript
function depositCollateral(FyTokenInterface fyToken, uint256 collateralAmount) external returns (bool)
```

* `fyToken` : The address of the fyToken contract.
* `collateralAmount` : The amount of collateral to deposit.
* `RETURN`: true = success, otherwise it reverts.

{% hint style="warning" %}
Requirements:

* The vault must be open.
* The amount to deposit cannot be zero.
* The Fintroller must allow this action to be performed.
* The caller must have allowed this contract to spend "collateralAmount" tokens.
  {% endhint %}

#### Solidity <a href="#solidity-5" id="solidity-5"></a>

```javascript
‌BalanceSheet balanceSheet = BalanceSheetInterface(0xabcd...);
FyTokenInterface fyToken = FyTokenInterface(0xbcde...);
uint256 collateralAmount = 10000000000000000000;
bool success = balanceSheet.depositCollateral(fyToken, collateralAmount);
require(success, "something went wrong");
```

#### Ethers.js <a href="#ethers-js-5" id="ethers-js-5"></a>

```javascript
const balanceSheet = new ethers.Contract(0xabcd..., balanceSheetABI, signer);
const fyToken = new ethers.Contract(0xbcde..., fyTokenInterfaceABI, signer);
const collateralAmount = "10000000000000000000";
const depositCollateralTx = await balanceSheet.depositCollateral(fyToken, collateralAmount);
await depositCollateralTx.wait();
```

### Free Collateral <a href="#getstream" id="getstream"></a>

Frees a portion or all of the locked collateral. Emits a "FreeCollateral" event.

```javascript
function freeCollateral(FyTokenInterface fyToken, uint256 collateralAmount) external returns (bool)
```

* `fyToken`: The address of the fyToken contract.
* `collateralAmount`: The amount of locked collateral to free.
* `RETURN`: true = success, otherwise it reverts.

{% hint style="warning" %}
Requirements:

* The vault must be open.
* The amount to free cannot be zero.
* There must be enough locked collateral.
* The borrower account cannot fall below the collateralization ratio.
  {% endhint %}

#### Solidity <a href="#solidity-5" id="solidity-5"></a>

```javascript
‌BalanceSheet balanceSheet = BalanceSheetInterface(0xabcd...);
FyTokenInterface fyToken = FyTokenInterface(0xbcde...);
uint256 collateralAmount = 10000000000000000000;
bool success = balanceSheet.freeCollateral(fyToken, collateralAmount);
require(success, "something went wrong");
```

#### Ethers.js <a href="#ethers-js-5" id="ethers-js-5"></a>

```javascript
const balanceSheet = new ethers.Contract(0xabcd..., balanceSheetABI, signer);
const fyToken = new ethers.Contract(0xbcde..., fyTokenInterfaceABI, signer);
const collateralAmount = "10000000000000000000";
const freeCollateralTx = await balanceSheet.freeCollateral(fyToken, collateralAmount);
await freeCollateralTx.wait();
```

### Lock Collateral <a href="#getstream" id="getstream"></a>

Locks a portion or all of the free collateral to make it eligible for borrowing. Emits a "LockCollateral" event.

```javascript
function lockCollateral(FyTokenInterface fyToken, uint256 collateralAmount) external returns (bool)
```

* `fyToken`: The address of the fyToken contract.
* `collateralAmount`: The amount of free collateral to lock.
* `RETURN`: true = success, otherwise it reverts.

{% hint style="warning" %}
Requirements:

* The vault must be open.
* The amount to lock cannot be zero.
* There must be enough free collateral.
  {% endhint %}

#### Solidity <a href="#solidity-5" id="solidity-5"></a>

```javascript
‌BalanceSheet balanceSheet = BalanceSheetInterface(0xabcd...);
FyTokenInterface fyToken = FyTokenInterface(0xbcde...);
uint256 collateralAmount = 10000000000000000000;
bool success = balanceSheet.lockCollateral(fyToken, collateralAmount);
require(success, "something went wrong");
```

#### Ethers.js <a href="#ethers-js-5" id="ethers-js-5"></a>

```javascript
const balanceSheet = new ethers.Contract(0xabcd..., balanceSheetABI, signer);
const fyToken = new ethers.Contract(0xbcde..., fyTokenInterfaceABI, signer);
const collateralAmount = "10000000000000000000";
const lockCollateralTx = await balanceSheet.lockCollateral(fyToken, collateralAmount);
await lockCollateralTx.wait();
```

### Open Vault <a href="#getstream" id="getstream"></a>

Opens a Vault for the caller. Emits an "OpenVault" event.

```javascript
function openVault(FyTokenInterface fyToken) external returns (bool)
```

* `fyToken`: The address of the fyToken contract for which to open the vault.
* `RETURN`: true = success, otherwise it reverts.

{% hint style="warning" %}
Requirements:

* The vault cannot be already open.
* The fyToken must pass the inspection.
  {% endhint %}

#### Solidity <a href="#solidity-5" id="solidity-5"></a>

```javascript
‌BalanceSheet balanceSheet = BalanceSheetInterface(0xabcd...);
FyTokenInterface fyToken = FyTokenInterface(0xbcde...);
bool success = balanceSheet.openVault(fyToken);
require(success, "something went wrong");
```

#### Ethers.js <a href="#ethers-js-5" id="ethers-js-5"></a>

```javascript
const balanceSheet = new ethers.Contract(0xabcd..., balanceSheetABI, signer);
const fyToken = new ethers.Contract(0xbcde..., fyTokenInterfaceABI, signer);
const openVaultTx = await balanceSheet.openVault(fyToken);
await openVaultTx.wait();
```

### Set Vault Debt <a href="#getstream" id="getstream"></a>

Updates the debt accrued by a particular borrower account. Emits a "SetVaultDebt" event.

```javascript
function setVaultDebt(FyTokenInterface fyToken, address borrower, uint256 newVaultDebt) external returns (bool)
```

* `fyToken`: The address of the fyToken contract.
* `borrower`: The borrower account for which to update the debt.
* `newVaultDebt`: The new debt to assign to the borrower account.
* `RETURN`: true = success, otherwise it reverts.

{% hint style="warning" %}
Requirements:

* Can only be called by the fyToken.
  {% endhint %}

{% hint style="info" %}
We didn't write code snippets for this function because it is not meant to be called directly. Only the fyToken contract is allowed to call "setVaultDebt".
{% endhint %}

### Withdraw Collateral <a href="#getstream" id="getstream"></a>

Withdraws a portion or all of the free collateral. Emits a "WithdrawCollateral" event.

```javascript
function withdrawCollateral(FyTokenInterface fyToken, uint256 collateralAmount) external returns (bool)
```

* `fyToken`: The address of the fyToken contract.
* `collateralAmount`: The amount of collateral to withdraw.
* `RETURN`: true = success, otherwise it reverts.

{% hint style="warning" %}
Requirements

* The vault must be open.
* The amount to withdraw cannot be zero.
* There must be enough free collateral in the vault.
  {% endhint %}

#### Solidity <a href="#solidity-5" id="solidity-5"></a>

```javascript
‌BalanceSheet balanceSheet = BalanceSheet(0xabcd...);
FyTokenInterface fyToken = FyTokenInterface(0xbcde...);
uint256 collateralAmount = 10000000000000000000;
bool success = balanceSheet.withdrawCollateral(fyToken, collateralAmount);
require(success, "something went wrong");
```

#### Ethers.js <a href="#ethers-js-5" id="ethers-js-5"></a>

```javascript
const balanceSheet = new ethers.Contract(0xabcd..., balanceSheetABI, signer);
const fyToken = new ethers.Contract(0xbcde..., fyTokenInterfaceABI, signer);
const collateralAmount = "10000000000000000000";
const withdrawCollateralTx = await balanceSheet.withdrawCollateral(fyToken, collateralAmount);
await withdrawCollateralTx.wait();
```


---

# 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://v0.docs.hifi.finance/smart-contracts/balancesheet.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.
