# Get started

Depending on your interests and experience, you’ll want to explore different parts of the Cozy application and corresponding documentation.

## What is Cozy?

Cozy is an open-source protocol for automated and trust-minimized [Protection Markets](/what-is-cozy/overview#what-are-protection-markets). Protection Markets allow you to provide and receive protection against predefined conditions like a loss of funds due to a smart contract hack. Anybody can create and use Protection Markets.

To learn more, visit the [Overview](/what-is-cozy/overview).

## For Users

Learn about the protocol, how to get protection, and how to provide protection.

{% content-ref url="/pages/-Mi2m5PnUOH43nO4sXzU" %}
[Overview](/what-is-cozy/overview)
{% endcontent-ref %}

{% content-ref url="/pages/-Mi2m5PoyjPc\_riPVGSW" %}
[Case study](/what-is-cozy/case-study)
{% endcontent-ref %}

{% content-ref url="/pages/-Mi2m5PpabdOphH8B4Ay" %}
[FAQ](/what-is-cozy/faq)
{% endcontent-ref %}

## For Developers

Learn how to programmatically create, provide, and purchase protections.

### Guides

{% content-ref url="/pages/-Mi2m5PvcYDlJ3JU4j12" %}
[Create a protection market](/for-developers/guides/how-do-i-create-a-protection-market)
{% endcontent-ref %}

{% content-ref url="/pages/-MQOphTEd9tfO0YuJYKd" %}
[Buy protection programmatically](/for-developers/guides/how-do-i-buy-protection-programmatically)
{% endcontent-ref %}

{% content-ref url="/pages/-MQOq1GXbIykZURx8gFq" %}
[Manage protection programmatically](/for-developers/guides/how-do-i-manage-protection-programmatically)
{% endcontent-ref %}

{% content-ref url="/pages/-M\_MCPd2wXKt0SI4j0vP" %}
[Provide protection programmatically](/for-developers/guides/providing-protection-programmatically)
{% endcontent-ref %}

{% content-ref url="/pages/-MQOq8vgS9MmY6znF2dr" %}
[Liquidate a vault](/for-developers/guides/how-do-i-liquidate-a-vault)
{% endcontent-ref %}

{% content-ref url="/pages/wfeAHWIw9z3m8yPOBDls" %}
[Create a protected investing opportunity](/for-developers/guides/create-a-protected-investing-opportunity)
{% endcontent-ref %}

{% content-ref url="/pages/StjVobS1khLwXOVdJK9c" %}
[Create an invest/divest contract](/for-developers/guides/how-do-i-create-an-invest-divest-contract)
{% endcontent-ref %}

### Reference

{% content-ref url="/pages/-MQOqJVMNHsQ1FJJC1nJ" %}
[API reference](/for-developers/api-reference)
{% endcontent-ref %}

{% content-ref url="/pages/-MXXW21R39EumU6Y61wg" %}
[Contract deployments](/for-developers/contract-deployments)
{% endcontent-ref %}


# Overview

Invest in decentralized financial markets with protection against risks like hacks and protocol vulnerabilities.

Cozy is an open-source protocol that enables investors to participate in automated and trust-minimized **protection markets**.

Protection markets mitigate the risks often associated with investing in decentralized financial (DeFi) markets and applications. Because DeFi application protocols might seem more vulnerable to hacks and exploitation than traditional financial instruments for some investors, Cozy provides a platform for protecting assets against losses programmatically. Investors with confidence in DeFi application security can use the Cozy platform to earn interest by supplying assets to a protection market.

The two key components of a protection market are:

* A money market with a **liquidity pool** of digital assets.
* A **trigger contract** that specifies a condition to protect the assets in the pool against.

There are three main ways to participate in a protection market:

* As a **protection market developer**, you create the trigger contract that protects assets if a specific **trigger condition**—such as a sudden, sharp decline in value—is met in one or more protocol markets.
* As a **protection market supplier**, you deposit assets to be used in a protection market pool and earn interest from borrowers who pay for the having their deposited asset protected against losses. If you think that a market is not likely to lose funds—that the trigger condition is unlikely to occur—you can use Cozy to earn interest by providing protection.
* As a **protection market borrower**, you deposit collateral and borrow against it with a reduced rate of return in exchange for protecting your deposit against the condition defined in the trigger contract. If you borrow from a protection market and the trigger condition is met, the collateral you deposited remains safe and any outstanding debt is cancelled.

![](https://92902368-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MQOlThYns4gV0tad8h_-887967055%2Fuploads%2Fgit-blob-2a6568ada93705239e1036fd27060be20dbbb7a4%2FGroup%209.png?alt=media)

For a closer look at how Cozy protection markets work, see [Case Study](/what-is-cozy/case-study).

## Borrowing and investing

With protected borrowing and investing, you borrow assets in a protection market to protect your position against losses if the condition contained in the trigger contract occurs. You pay interest to receive this protection. If the trigger condition occurs, the collateral you deposited is safe. If you have any outstanding debt for borrowed assets, you no longer have to pay it back.

Participants in a protection market pay a small fee on their potential earnings to reduce the risk of holding a particular asset. For borrowers, debt cancellation is essentially the insured event that they have paid their premiums to guard against.

To get started with protected borrowing:

1. Open the [Cozy website](https://cozy.finance) in a browser.
2. Connect to your wallet.
3. Deposit collateral on the Your Funds page.
4. Click **Protected Borrowing** and select a protection market.
5. Borrow assets from that protection market.

   Borrowed assets are transferred to the your wallet.

   Borrowers pay an interest rate until they repay their borrowed assets. If the trigger condition is met, the debts are cancelled and borrowers can withdraw their collateral.

## Supplying assets

If you are confident that a condition contained in a trigger contract is unlikely to occur, you can supply assets to a protection market and earn interest from investors who borrow from the protection market.

You continue earning interest as long as the protection market operates without having its trigger condition occur. If there is a hack, exploit, or other problem that triggers protection in the market where you have supplied assets, all outstanding debts in that market are forgiven. The interest you earn is your reward for taking on the risk associated with the trigger condition. In evaluating the risk involved, you should consider how likely it will be for a particular market's trigger condition to be satisfied.

To get started with providing protection:

1. Open the [Cozy website](https://cozy.finance) in a browser.
2. Click **Provive Protection**.
3. Select a protection market.
4. Select an Asset to supply to the protection market.

   You earn interest until you withdraw your supplied assets.

   If the trigger condition is met, debts are cancelled and you can withdraw your share of the remaining funds in the protection market.

## Creating protection markets

You must be able to write a trigger contract to develop and deploy a protection market. You can learn how to write trigger contracts using the scripts in the [Cozy Developer Guides](https://github.com/Cozy-Finance/cozy-developer-guides) repository and the [Create a protectionmarket](/for-developers/guides/how-do-i-create-a-protection-market) guide.


# Case study

How a Cozy protection market might have protected investors in the Pickle Finance DAI pool.

In November of 2020, [an exploit](https://decrypt.co/49149/pickle-finance-hack) drained nearly $20M in funds from the Pickle Finance DAI pool. Investors who had deposited funds in the Pickle DAI pool had no protection from the exploit and lost all of the funds they had deposited. If a Cozy protection market had been available, investors who chose to participate in the protection market would have been protected against the exploit. Instead of losing all of their funds, participants in the protection market would have limited their exposure and retained their original investment.

![](https://92902368-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MQOlThYns4gV0tad8h_-887967055%2Fuploads%2Fgit-blob-90da163be14f17ea0223a411b49351dd7bab40f9%2FCozy%20Case%20Study.jpg?alt=media)

Let's use the Pickle Finance DAI pool as a concrete example to illustrate how a Cozy protection market would have protected investors.

## Create a protection market

Before investors can participate in the protection market, someone needs to design, develop, and deploy a contract that protects an asset from an exploit. For this example, someone familiar with Pickle Finance decides to create a protection market for the Pickle Finance DAI pool.

The developer of the protection market must identity the condition that would trigger protection for deposited funds. In this example, the developer has decided that a 25%+ loss of funds in the pool would indicate a serious problem and should trigger protection. She expresses this condition by writing a `getPricePerFullShare()` function. If this function in the Pickle DAI pool contract returns a value less than `0.75`, the result would indicate a 25%+ loss of funds and trigger protection for the DAI pool.

In this example, there is only one trigger condition, but a protection market developer could add multiple trigger events to a trigger contract to make the protection it provides more robust or sophisticated. If any event occurs, protection is enabled. It is up to the protection market developer to identify the condition or set of conditions for which to offer protection in the trigger contract.

To learn more about creating trigger contracts and protection markets, visit [this guide](/for-developers/guides/how-do-i-create-a-protection-market).

## Provide protection by supplying assets

People who want to bet against the condition—in this case, the Pickle DAI pool losing 25% of its value—supply capital to the protection market to earn an interest rate from users seeking protection. In this example, participants supply DAI. The protection market developer wants to earn interest by making the protection market available to borrowers and protection-seekers, so she supplies DAI assets to the pool.

## Get protection by paying interest

People who want protection for the Pickle DAI pool borrow DAI from the protection market and invest those assets into the Pickle DAI that offers protection. As protection-seekers, borrowers pay an interest rate for borrowing DAI from the pool. If the condition is met—in this example, the Pickle DAI pool losing 25% of its value—their debts are forgiven and their principal deposit remains safe.

## Receive protection if an exploit occurs

If an exploit like the one in November 2020 were to occur with the protection market in place, the `getPricePerFullShare()` function would return \~0 because all of the funds in the pool were drained in an attack. However, this change satisfies the condition that the protection market is in place to guard against and triggers the cancellation of all debts in the protected Pickle DAI pool.

If you had borrowed DAI from that protection market and invested that DAI into Pickle, you would have lost all of your DAI on Pickle, but would owe zero DAI back to Cozy. Your principal would be preserved.

## Summary

Cozy allows anybody to create and use protection markets. By using protection markets, you can provide and receive protection against any condition that can be defined on chain. This case study illustrates how a protection market could have protected investors against the insolvency of the Pickle DAI pool. Instead of losing all of their deposits in the exploit, Cozy users would have kept all of their principal.


# FAQ

If you can't find an answer to your question here, contact us on discord {{TODO:LINK}}.

If you can't find an answer to your question here, contact us on [discord](https://discord.com/invite/kK84saQYyg).

{% hint style="warning" %}
Under construction
{% endhint %}

## What is Cozy?

Cozy is an open-source protocol for automated and trust-minimized [protection markets](/what-is-cozy/overview#what-are-protection-markets). Protection markets allow users to provide and receive protection against predefined conditions like loss of funds due to a smart contract hack.

## What is a protection market?

Conceptually, a **protection market** is what enables Cozy users and developers to get and provide protection against losses stemming from a specific **trigger condition**.

The main components that define a protection market are:

* A money market with a **liquidity pool** of digital assets with an **underlying token** for the market.
* A **trigger contract** that specifies an on-chain condition to protect the assets in the pool against.
* An **interest rate model** that determines the interest rate that borrowers pay.

The trigger contract for a protection market defines a **trigger condition** to check for. As long as the trigger condition has not occurred, the protection market borrowers and suppliers accrue interest. If the trigger condition occurs, the trigger contract is executed and any outstanding debts in the protection market are cancelled for protection borrowers.

To learn how to create a protection market, see [Create a protection market](/for-developers/guides/how-do-i-create-a-protection-market).

## How does protection work?

Users provide and get protection by participating in protection markets. Each protection market has a trigger contract that defines the condition users can provide and purchase protection against.

The **trigger condition** is an expression that, when evaluated, returns true if the trigger condition has occurred. If the trigger condition remains unchanged (that is, when evaluated, the trigger condition returns false), the protection market earns interest and collects payments from protection borrowers. If the trigger condition occurs, the trigger contract is executed and any outstanding debts in the protection market are cancelled for protection borrowers.

## What types of protection are available?

You can get and provide protection for any DeFi protocol that has a protection market. The specific conditions you are protected again depend on the trigger contract for the protection market in which you are interested.

If a protection market doesn't yet exist for the protocol or the type of protection you're interested in, you can create a new protection market.

## How much does protection cost?

Protection markets price protection based on utilization. Typically, the more demand there is for protection relative to supply, the higher the interest rate. However, creators of protection markets can set their own interest rate curves, so make sure to check how pricing works for the protection market you're interested in using.

## Who can create protection markets?

Anybody can create protection markets.

## What assets are supported?

You can use ETH, USDC, DAI, and WBTC.

## What fees does Cozy charge?

Each protection market takes a percentage of each interest payment. This fee is determined by the `Reserve Factor` just like in Compound. The `Reserve Factor` for each market is adjustable by governance and is held to backstop shortfall events in the protocol.

## Do you have a The Graph subgraph?

Yes. You can find our Mainnet deployment [here](https://thegraph.com/legacy-explorer/subgraph/cozy-finance/cozy?query=Market%20List) and our Rinkeby deployment [here](https://thegraph.com/explorer/subgraph/cozy-finance/cozy-rinkeby-subgraph?selected=playground).

## How is borrowing power calculated?

Borrowing power is calculated by dividing your active borrow amount by your total collateral.

* Active borrows is the USD value of all the assets you've borrowed.
* Total collateral is the USD value of all the assets you've deposited as collateral multiplied by their collateral factor.

## What oracles does Cozy use?

Cozy uses [Chainlink](https://chain.link/solutions/defi) oracles to get asset prices for ETH, DAI, and WBTC. The one exception to this is USDC, which has a hardcoded price of $1.

## What is a temporary borrow limit?

In the first phase of the protocol (alpha), each market will have a maximum amount of assets that can be borrowed. This is to limit the overall exposure users can get on the protocol as things are still relatively untested. Over time, these borrow limits will be removed.

## Why am I being asked to migrate my positions?

The Cozy protocol is implemented through a mostly immutable set of smart contracts. Protocol improvements sometimes require a complete redeployment of the smart contracts. If you are reading this, it is likely that a new version of the protocol has been deployed, which means you'll have to migrate your funds to keep using the app.

Migrating your funds is as simple as closing out your positions, withdrawing your funds, and redepositing them in the latest version of the Cozy app available on the cozy.finance website.

## Why do I need to set up a proxy wallet?

Cozy uses DSProxy, a smart wallet, to execute multiple contract calls in one transaction. Normal addresses (or [EOAs](https://ethereum.stackexchange.com/questions/5828/what-is-an-eoa-account)) are limited to interacting with only one contract per transaction, which means complex interactions would require multiple transactions. But by using DSProxy, Cozy lets users execute complex interactions with only one transaction. This allows Cozy to provide a better user experience and saves users gas in the long run.

To learn more about DSProxy, visit the [DSProxy repo](https://github.com/dapphub/ds-proxy).

## What are Estimated Balances?

If you have both an unprotected and a protected investment in the same opportunity, Cozy will estimate your balance in each type of investment based on the ratio of unprotected vs protected assets borrowed. To estimate balances on protected investments, Cozy takes your total balance and multiplies it by your protected borrow divided by total borrow. And vice versa for estimating balances on unprotected investments.

When you want to close a position, you'll have access to your total balance (across both protected and unprotected investments) to repay your debts.


# Security

Security is a top priority for the Cozy Protocol. Learn more about prior and ongoing efforts to ensure the dependability of the Cozy Protocol here.

## Audits

The Cozy Protocol has been reviewed and audited by Quantstamp and Peckshield.


# Guides

Interact with Cozy markets programmatically using samle scripts and  developer guides.

The following developer guides provide instructions and code examples to help you create programs to perform common protection market tasks programmatically.

* [Set up your development environment](/for-developers/guides/development-environment-setup)
* [Create a protection market](/for-developers/guides/how-do-i-create-a-protection-market)
* [Buy protection programmatically](/for-developers/guides/how-do-i-buy-protection-programmatically)
* [Manage protection programmatically](/for-developers/guides/how-do-i-manage-protection-programmatically)
* [Provide protection programmatically](/for-developers/guides/providing-protection-programmatically)
* [Liquidate a vault](/for-developers/guides/how-do-i-liquidate-a-vault)
* [Create a protected investing opportunity](/for-developers/guides/create-a-protected-investing-opportunity)
* [Create an invest/divest contract](/for-developers/guides/how-do-i-create-an-invest-divest-contract)


# Set up your development environment

Get everything you need to start developing using the developer guides.

All of the [developer guides](/for-developers/guides) assume that you are using a TypeScript development environment with a project structure similar to the one described here. You can follow the instructions in this section to prepare a development environment for working with the sample scripts in the [Cozy developer guide](https://github.com/Cozy-Finance/cozy-developer-guides) repository.

## Before you begin

Before you set up the development environment for creating protection markets, verify the following:

* You have an internet connection and access to a shell terminal.
* You have `node.js` and `yarn` installed.
* You can connect to a node running locally or through a service such as [Infura](https://infura.io/).
* You have access to a wallet—including its private key—and can send transactions.

## Prepare the development environment

To set up the development environment:

1. Clone the [Cozy Developer Guides](https://github.com/Cozy-Finance/cozy-developer-guides) repository by running the following command:

   ```
    git clone git@github.com:Cozy-Finance/cozy-developer-guides.git
   ```
2. Install package dependencies by running the following command:

   ```
    yarn
   ```
3. Create an environment file called `.env` to store information for connecting to the node provider and wallet.

   For example, if you are using the infura API and connecting to the Rinkeby test network, your `.env` file should look similar to the following example:

   ```bash
    RPC_URL=https://rinkeby.infura.io/v3/yourInfuraId
    PRIVATE_KEY=0xYourPrivateKey
   ```

   Be careful to never commit these secrets to a repository!
4. Test your local environment by running the following command:

   ```
    yarn test
   ```

   If your development environment is ready to use, you should see output similar to the following to indicate that tests have passed:

   ```
        Creating Typechain artifacts in directory typechain for target ethers-v5
        Successfully generated Typechain artifacts!

        MockTrigger
          Deployment
            ✓ initializes properly (52ms)
            ✓ should not deploy if market is already triggered (424ms)
          checkAndToggleTrigger
            ✓ does nothing when it should do nothing
            ✓ toggles trigger when expected to toggle trigger (58ms)
            ✓ returns a boolean with the value of isTriggered (446ms)
            5 passing (7s)
   ```

## What's next?

The settings in the `.env` file are used to initialize the wallet and send transactions when the TypeScript files such as `create-protection-market.ts` are executed.

For example:

```javascript
// Hardhat and ethers imports
import hre from 'hardhat';
import '@nomiclabs/hardhat-ethers';
import { Contract, ContractFactory } from 'ethers';

// Import some helper methods we have
import { getChainId, getContractAddress, logSuccess, logFailure, findLog, fundAccount } from '../utils/utils';

// Import any required ABIs
import comptrollerAbi from '../abi/Comptroller.json';

// STEP 0: ENVIRONMENT SETUP
// Use the default Hardhat provider
const provider = hre.ethers.provider;

// Initialize our signer using the private key from the environment variable
const signer = new hre.ethers.Wallet(process.env.PRIVATE_KEY as string, hre.ethers.provider);

// Chain ID is used to determine which contract addresses to use, and we use a 
// special helper method for getting chain ID. Normally you would get this from
// (await ethers.provider.getNetwork()).chainId, but since we are testing against
// a forked network we need to ensure we used the forked network's ID (e.g. 1 for
// mainnet) instead of the Hardhat default Chain ID of 1337
const chainId = getChainId(hre);
```

To finish setting up the development environment, you need to obtain the contract addresses and ABIs. You can find all of the contract addresses on the [Contract deployments](/for-developers/contract-deployments) page. If you cloned the [Cozy Developer Guides](https://github.com/Cozy-Finance/cozy-developer-guides) repository, you'll already have the ABIs. If you did not clone the repository, the contracts are verified on Etherscan, so you can get the ABIs from there \[NOTE: currently not true].


# Create a protection market

Learn how to create a trigger contract for a protection market.

![](https://92902368-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MQOlThYns4gV0tad8h_-887967055%2Fuploads%2Fgit-blob-4136d7a8683c525acfbd574da2643f8194f0fc5e%2FCreate%20Protection%20Market.png?alt=media)

Protection markets are intended to protect users of on-chain protocols against the kinds of smart contract or protocol failures that make investing in decentralized financial products seem riskier than investing in traditional asset classes. Some of the common problems and risks that investors in on-chain protocols face include flaws in smart contract logic, security vulnerabilities that hackers can exploit, and unscrupulous insiders.

To address these issues, the key to creating a protection market is writing and deploying a trigger contract that limits an investor's exposure if a protocol is hacked or a fund suffers a rug pull maneuver.

At a high-level, you can create a protection market by taking the following steps:‌

1. ​[Prepare a trigger contract](#step-1-trigger-contract-setup) so that it's compatible with the Cozy protocol.
2. ​[Develop the trigger contract logic](#step-2-trigger-contract-development) to detect potential problems for one or more on-chain protocols.
3. ​[Deploy the trigger contract as a protection market](#step-3-protection-market-deployment) to make protected investing and protected borrowing available for users who want purchase protection or supply assets.

{% hint style="info" %}
Everything in this guide assumes that you have experience with JavaScript, [ethers.js](https://github.com/ethers-io/ethers.js/), and [Solidity](https://docs.soliditylang.org/en/latest/).
{% endhint %}

## Prepare a trigger contract <a href="#step-1-trigger-contract-setup" id="step-1-trigger-contract-setup"></a>

Before you start creating a trigger contract of your own, let’s take a closer look at what’s involved. There are three key parts that go into creating a trigger contract for a protection market:

* The *abstract* trigger contract.
* The trigger contract that inherits the abstract trigger contract and contains the code to check for a trigger condition.
* The deployment script that provides input parameters to the trigger contract when deployed.

Let’s review what’s in each of these files and what you do with them.

### Review the abstract trigger contract

if you cloned the [Cozy Developer Guides](https://github.com/Cozy-Finance/cozy-developer-guides) repository, you have an abstract trigger contract called `ITrigger` defined in the `ITrigger.sol` file in the `contracts/interface/` folder. This abstract trigger contract serves as the base or parent contract for the trigger contract you will write for a protection market.

You don't need to make any changes to the abstract trigger contract. It's provided to make developing your own trigger contract easier. Before you start writing your own trigger contract, however, you might want to take a closer look at what’s in the `ITrigger.sol` abstract trigger contract first.

As you review the `ITrigger.sol` file, there are just a few lines to take note of:

* The `ITrigger.sol` file specifies the data types and identifiers for the basic properties of the contract and define the constructor arguments that will be passed in from a deployment script after the contract is deployed on the network.
* The `ITrigger.sol` file declares the `isTriggered` state variable and declares a `TriggerActivated()` event to emit if a condition has resulted in the `isTriggered` function returning `true`.
* The `getPlatformIds()` function is used to get an array of platform identifiers, which represent the protocols protected by this trigger contract.
* The `checkTriggerCondition()` function defines the logic that determines if the trigger condition for any of the protected protocols has occurred. This function is not implemented in the `ITrigger.sol` file. You’ll implement the `checkTriggerCondition()` function when you write the trigger contract that inherits from the abstract contract.
* The `checkAndToggleTrigger()` function sets the `isTriggered` flag to `true` if the condition defined for the `checkTriggerCondition()` function is met. This function is implemented in the abstract contract and must not be modified.

Once you are familiar with the code in the `ITrigger.sol` file, you are ready to start coding your own trigger contract.

### Prepare a trigger contract skeleton

Now that you are familiar with what's in the base trigger contract that your contract will inherit, you are ready to start writing the contract that contains the trigger logic for your protection market. Let’s start by creating a trigger contract skeleton. You can create the basic framework for the trigger contract in an empty file or you can use the `MockTrigger.sol` file in the developer-guides repository as a starting point. To illustrate what’s involved, we’ll create an empty file and copy and paste portions of the `MockTrigger` into the custom contract.

To create the basic framework for your custom trigger contract:

1. Create a new empty file. For example, create a new file called `TestTrigger.sol` by running the following command:

   ```
    touch contracts/TestTrigger.sol
   ```
2. Open the file in a text editor and insert a line with the version `pragma` to specify the compiler version this trigger contract requires. For example:

   ```
    pragma solidity ^0.8.5;
   ```
3. Import the abstract trigger contract and set the current trigger contract to inherit it. For example:

   ```
    import "./interfaces/ITrigger.sol";

    contract TestTrigger is ITrigger {
   ```

   The `shouldToggle` function in the `MockTrigger` contract is only used for example purposes in that contract, so we don’t need to include it in our contract skeleton.
4. Prepare some expected properties for the contract:

   Because the `constructor` arguments of the base contract depend on values that will be passed to the derived contract, they are defined like this in our `TestTrigger` contract:

   ```
    constructor(
      string memory _name,
      string memory _symbol,
      string memory _description,
      uint256[] memory _platformIds,
      address _recipient,
      bool _shouldToggle
   ) ITrigger(_name, _symbol, _description, _platformIds, _recipient) {

    }
   ```

   These basic properties are inherited from the base trigger contract. The values for the properties are supplied when the contract is deployed.

   We’ll get to that step in a minute, but first, let’s complete our skeleton trigger contract by adding a placeholder for the required `checkTriggerCondition()` function.
5. Add a placeholder for `checkTriggerCondition()` function. For example:

   ```
    function checkTriggerCondition() internal override returns (bool) {

    }
   ```

### Configure parameters in a deployment script

So far, we’ve reviewed the abstract contract and built a skeleton for the trigger contract. The next step in preparing the trigger contract is to configure required trigger parameters that will be supplied to the trigger contract when it is deployed:‌ These parameters provide the data to the constructor properties you saw in the abstract contract and consist of the following:

* The trigger `name` is similar to the ERC-20 name property.
* The trigger `symbol` is similar to the ERC-20 symbol property.
* The `description` of the trigger that describes what the trigger does.
* The numeric identifier for each protocol that your trigger monitors for failure conditions. For example, if this trigger covers the failure of a Yearn vault, and Yearn has an ID of 1, the `platformId` would be `[1]`. For a list of platform names and their ID numbers, see [Platform identifiers for protocols](#platform-ids).
* The trigger `recipient` to define an address to which to distribute rewards. (Use a [sybil.org](https://sybil.org/) verified address if you want users to know you created the protection.)

For example:

{% code title="create-protection-market.ts" %}

```typescript
// Define required constructor parameters
const name = 'Mock Trigger'; // trigger name
const symbol = 'MOCK'; // trigger symbol
const description = 'A mock trigger that anyone can toggle'; // trigger description
const platformIds = [3]; // array of platform IDs that this trigger protects
const recipient = '0x1234567890AbcdEF1234567890aBcdef12345678'; // address of subsidy recipient
const shouldToggle = false; // specific to our MockTrigger, which we set to not be triggered at deployment
```

{% endcode %}

## Develop the trigger contract logic <a href="#step-2-trigger-contract-development" id="step-2-trigger-contract-development"></a>

You are now ready to implement the actual trigger logic for your contract using the `checkTriggerCondition()` function that you inherited from the abstract contract. The `checkTriggerCondition()` function is where you write the core logic of your trigger contract, specifying the condition that should trigger protection for the protocol(s) defined by `getPlatformIds()` parameter.

Note that the `checkAndToggleTrigger()` and `checkTriggerCondition()` functions are crucial to ensuring your trigger behaves properly, so read the following section carefully:

* You **must** implement `checkTriggerCondition()` to execute some logic and return `true` if the trigger event has occurred, and return `false` otherwise.
* You **must** ensure that the only way to update the value of the `isTriggered` variable is through the `checkTriggerCondition()` function.
* You **must not** modify the `checkAndToggleTrigger()` function inherited from the abstract contract. This function is implemented to conform to the interface and behavior expected by Cozy protection markets. The `checkAndToggleTrigger()` function is called by a protection market to determine the trigger's state.‌

You should also note that protection market triggers are "one-way" toggles. Each protection market stores its own `isTriggered` variable—separate from the trigger contract's `isTriggered` variable—which is initialized to `false` and toggled only once, when the trigger's`checkAndToggleTrigger()` method returns `true`. Because it can only be toggled once, to avoid confusion, it's recommended that triggers themselves should also follow the same convention of only allowing "one-way" toggles.‌

The following is an example [Mock Trigger](https://github.com/Cozy-Finance/cozy-developer-guides/blob/master/contracts/MockTrigger.sol) contract that is also available in the [Cozy Developer Guides](https://github.com/Cozy-Finance/cozy-developer-guides) repository.

{% code title="MockTrigger.sol" %}

```typescript
pragma solidity ^0.8.5;

import "./interfaces/ITrigger.sol";

contract MockTrigger is ITrigger {
  /// @notice If true, checkAndToggleTrigger will toggle the trigger on its next call
  bool public shouldToggle;

  constructor(
    string memory _name,
    string memory _symbol,
    string memory _description,
    uint256[] memory _platformIds,
    address _recipient,
    bool _shouldToggle
  ) ITrigger(_name, _symbol, _description, _platformIds, _recipient) {
    shouldToggle = _shouldToggle;

    // Verify market is not already triggered.
    require(!checkTriggerCondition(), "Already triggered");
  }

  /**
   * @notice Special function for this mock trigger to set whether or not the trigger should toggle
   */
  function setShouldToggle(bool _shouldToggle) external {
    require(!isTriggered, "Cannot set after trigger event");
    shouldToggle = _shouldToggle;
  }

  /**
   * @notice Returns true if the market has been triggered, false otherwise
   */
  function checkTriggerCondition() internal view override returns (bool) {
    return shouldToggle;
  }
}
```

{% endcode %}

When testing a trigger contract, it is helpful to initialize your test suite using the test template in `test/MockTrigger.test.ts`. This file contains sample implementations of common test cases that you'll want to use when testing your trigger's functionality.

## Deploy a protection market <a href="#step-3-protection-market-deployment" id="step-3-protection-market-deployment"></a>

Once your trigger contract is complete, you are ready to deploy a new protection market that uses that trigger.‌ You deploy a protection market by defining the following properties:

* Trigger contract address.
* Interest rate model contract address.
* Underlying token that is supplied to and borrowed from that market.

### Select an interest rate model

An interest rate model is a contract that takes current market parameters as inputs and returns what the market's borrowing interest rate should be. Before you deploy your protection market, you need to decide on the interest rate model to use for it.

The simplest option is to use the "Default Protection Market Interest Rate Model". You can find the contract address for this interest rate model on the [Contract deployments](/for-developers/contract-deployments) page. This interest rate model is defined as follows:

* 0% base rate (if nothing is borrowed, the borrow rate is zero).
* At an 80% utilization ratio, the borrow rate is 20%, and the rate increases linearly between 0% and 80% utilization.
* At a 100% utilization ratio, the borrow rate is 125%, and the rate increases linearly between 80% and 100% utilization.

If you want to use a different interest rate model, the [Contract deployments](/for-developers/contract-deployments) page lists other available options. If none of the pre-deployed interest rate models suit your use case, you can deploy your own. In the [cozy-developer-guides](https://github.com/Cozy-Finance/cozy-developer-guides) repository includes an abstract contract called [`IInterestRateModel`](https://github.com/Cozy-Finance/cozy-developer-guides/blob/master/contracts/interfaces/IInterestRateModel.sol). By inheriting this contract, you'll have the correct interface and layout for building and deploying any interest rate model you would like to use.

After you have selected an interest rate model, deploy the contract for it (if necessary), and save the contract address for use in later steps.

### Set the underlying token

The next step in deploying a protection market is to choose the underlying ERC-20 token (or ETH) to use for your protection market. For example, if you are writing a trigger to protect a Yearn yUSDC vault, selecting USDC as the underlying token would enable users to borrow protected USDC from the protection market and immediately use it to mint protected yUSDC shares on Yearn. If you were to chose DAI as the underlying token, users would have to borrow protected DAI and swap it for USDC before they can get protected yUSDC shares.

{% hint style="info" %}
To use ETH as the underlying token, use an address of `0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE`‌
{% endhint %}

To deploy a protection market with a given underlying token, a money market for that underlying token must exist. After you select an underlying token, you should verify that a money market for that token exists by calling the `Comptroller.getCToken(underlying, AddressZero)` function. The Comptroller stores a mapping—called `getCToken`—that maps an underlying token address to a trigger address to a market address. Money markets use the zero address as their `trigger` address. If the `Comptroller.getCToken(underlying, AddressZero)` check returns the zero address, a money market for the underlying token token does not exist, and you'll have to wait for one to be deployed by governance before continuing. (If you try to deploy without a supported underlying token money market, protection market deployment will revert).‌

The `create-protection-market.ts` script shows how to run this check when USDC is the underlying token. If a money market does exist, you can continue to the next step to deploy the final version of your trigger contract.

### Deploy the protection market

You can now deploy your protection market in one of two ways:

* By using the default interest rate model.

  ```typescript
  // Option 1: Use the default interest rate model
  Comptroller.deployProtectionMarket(underlying, trigger);
  ```
* By specifying an interest rate model.

  ```typescript
  // Option 2: Specify an interest rate model
  Comptroller.deployProtectionMarket(underlying, trigger, interestRateModel)
  ```

where

* `underlying` is the underlying token's address for this CozyToken market.
* `trigger` is the address of your trigger contract.
* `interestRateModel` is the address of your chosen interest rate model contract.

Because `deployProtectionMarket` is an overloaded function, when using ethers.js and the sample scripts to deploy a market, we must specify which syntax we're using.

The full process for deploying a trigger and using it to create a protection market is shown in the `create-protection-market.ts` script:

{% code title="create-protection-market.ts" %}

```typescript
// Get instance of the Trigger ContractFactory with our signer attached
const MockTriggerFactory: ContractFactory = await hre.ethers.getContractFactory('MockTrigger', signer);

// Deploy the trigger contract (last constructor parameter is
// specific to the mock trigger contract)
const triggerParams = [name, symbol, description, platformIds, recipient, shouldToggle];
const trigger: Contract = await MockTriggerFactory.deploy(...triggerParams);
await trigger.deployed();
logSuccess(`MockTrigger deployed to ${trigger.address}`);

// Let's choose USDC as the underlying, so first we need to check if
// there's a USDC Money Market. We know that Money Markets have a
// trigger address of the zero address, so we use that to query the
// Comptroller for the Money Market address
const usdcAddress = getContractAddress('USDC', chainId);
const comptrollerAddress = getContractAddress('Comptroller', chainId);
const comptroller = new Contract(comptrollerAddress, comptrollerAbi, signer); // connect signer for sending transactions
const cozyUsdcAddress = await comptroller.getCToken(usdcAddress, AddressZero);

// If the returned address is the zero address, a money market does
// not exist and we cannot deploy a protection market with USDC as
// the underlying
if (cozyUsdcAddress === AddressZero) {
  logFailure('No USDC Money Market exists. Exiting script');
  return;
}
logSuccess(`Safe to continue: Found USDC Money Market at ${cozyUsdcAddress}`);

// If we're here, a USDC Money Market exists, so it's safe to create
// our new Protection Market. If we tried to create a new Protection
// Market before a USDC Money Market existed, our transaction would
// revert. Also, notice how we do not provide an `interestRateModel`
// address--this means we'll use the default interest rate model
// specified by the `ProtectionMarketFactory` contract. If you want
// to use a custom interest rate model, develop, test, and deploy your
// interest rate model, then use the commented out version below
const tx = await comptroller['deployProtectionMarket(address,address)'](usdcAddress, trigger.address);
// const tx = await comptroller['deployProtectionMarket(address,address,address)'](usdcAddress, trigger.address, interestRateModelAddress);

// This should emit a ProtectionMarketListed event on success, so
// let's check for that event. If not found, this method will throw
// and print the Failure error codes which can be looked up in
// ErrorReporter.sol
const { log, receipt } = await findLog(tx, comptroller, 'ProtectionMarketListed', provider);
logSuccess(`Success! Protection Market deployed to ${log?.args.cToken} in transaction ${receipt.transactionHash}`);
```

{% endcode %}

## Verify your protection market

After you deploy your trigger contract and interest rate model contract to create a protection market, you can verify that your protection market exists by looking at the [Cozy subgraph](https://thegraph.com/legacy-explorer/subgraph/cozy-finance/cozy).

Your protection market will be initialized with a collateral factor of zero and use the specified `trigger`, `underlying` , and `interestRateModel` addresses. Note that you can change the interest rate model by submitting a governance proposal.

## Tips for trigger contract developers

Trigger contract logic can sometimes have unintended consequences or undesirable effects. This section provides some tips and suggestions to help you avoid the pitfalls.

### Consider the gas required for computation

In a protection market, the trigger contract always calls the `checkAndToggleTrigger()` method immediately before every borrow and redeem action. This call is required to mitigate front-running. However, each call incurs a cost in gas for execution and this increases the cost of borrowing and redeeming funds.

In writing trigger contract logic, you should try to keep the gas costs for checking the trigger condition as low as possible, as users will pay the cost on every borrow and redeem action. For example, you can reduce the gas required tor checking the trigger condition by:

* Keeping trigger logic as simple as possible.
* Minimizing operations that read from or write to storage.
* Minimizing calls to external contracts or reading data from other contracts.

You can also find general guidelines for limiting gas usage in [Solidity gas optimization tips](https://mudit.blog/solidity-gas-optimization-tips/) and [Solidity tips and tricks to save gas and reduce bytecode size](https://blog.polymath.network/solidity-tips-and-tricks-to-save-gas-and-reduce-bytecode-size-c44580b218e6).

### Avoid code that encourages front-running

If it's known that a trigger condition will occur before reflected on-chain, that trigger may be susceptible to front-running. This would incentive suppliers to race to withdraw their funds immediately before a trigger is toggled, while borrowers try to max out their borrows immediately before their debt is forgiven. This is not an ideal property for triggers and consequently these types of triggers should be avoided.

Let's consider a Yearn V2 vault's `pricePerShare` as a trigger condition. Under normal operation, this value should only ever increase, though there are expected decreases immediately after each harvest. Therefore we may want to encode a trigger condition that says "if the value of `pricePerShare` drops and remains at some decreased value for X hours, toggle the trigger". This seems logical—if `pricePerShare` decreases, it may have been expected as part of a harvest, so let's wait to see if it recovers before toggling the trigger.

But this type of trigger is a prime example of a trigger that's susceptible to frontrunning. Let's say the trigger condition used a 12 hour duration. After 11 hours have elapsed, everyone knows that the trigger is likely to toggle very soon. As a result, suppliers will race to pull out their funds to remove the risk of losing funds, and borrowers will race to borrow as much as possible knowing they won't have to pay back debt. This "race" is not a desirable property for average users, so consider avoiding triggers that result in this type of scenario.

### Data availability

Every borrow and redeem calls your trigger's `checkAndToggleTrigger()` method. This method does not take any inputs, and therefore your trigger's condition cannot be dependent on function inputs or call data. This also means your trigger will not be able to use a Merkle proof to access and validate historical state. If you need access to historical state, you'll need to save data to storage on each call to `checkAndToggleTrigger()`.

### Governance

While you can initialize the parameters for your protection market, governance can change the following properties and activities:

* Interest rate model used.
* Borrowing cap.
* Mints, borrow, transfer, and liquidation operations.

## Platform identifiers for protocols

Platform identifiers are used to label DeFi protocols in Cozy applications. The protocol does not require you to use them in your trigger contracts, but they will help your protection market get proper surfacing.

The list of platform identifiers is maintained in the [Cozy-Finance/platform-ids](https://github.com/Cozy-Finance/platform-ids) repo. Please consult the list to get the proper ID for the trigger you're developing.

{% hint style="info" %}
Cozy is actively adding support for new protocols and corresponding platform identifiers. If the platform you're writing a trigger for doesn't have a platform ID assigned in the repo above, please submit a PR to add it!
{% endhint %}


# Buy protection programmatically

Learn how to buy protection programmatically on the Cozy protocol.

![](https://92902368-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MQOlThYns4gV0tad8h_-887967055%2Fuploads%2Fgit-blob-be83971e6f3a4243768f612ebb00a48bd64e2931%2FAutomatic%20purchase.png?alt=media)

Cozy provides a protected borrowing marketplace for investing in decentralized finance protocols that offer protection against a loss of funds. You pay a small premium to purchase protection for funds you deposit and can leverage your investment by borrowing against it. This guide illustrates how you can write a script using TypeScript that you can then use to buy protection from a [protection market](/what-is-cozy/faq#protection-market) programmatically,

All code snippets are from the `buy-protection.ts` script in the [Cozy Developer Guides](https://github.com/Cozy-Finance/cozy-developer-guides) repository. See that repository for more context, definitions of helper methods used, etc.

{% hint style="info" %}
Everything in this guide assumes that you have experience with JavaScript, [ethers.js](https://github.com/ethers-io/ethers.js/), and [Solidity](https://docs.soliditylang.org/en/latest/).
{% endhint %}

## Supply collateral

Before you can buy protection by borrowing protected funds from a Cozy market, you must supply collateral to borrow against.

All markets in Cozy—money markets and protection markets—have a `trigger` state variable. If the value of the `trigger` property is the [zero address](https://etherscan.io/address/0x0000000000000000000000000000000000000000), the money market does not have a trigger contract associated with it. A money market that does not have a trigger contract associated with it cannot be used for protected borrowing, but can be used for ordinary borrowing. If the value of the `trigger` property is anything except the zero address, the value of the `trigger` property represents the address of the trigger contract associated with that market. Only assets supplied to Cozy markets that have the zero address for the `trigger` property, known as money markets, can be used as collateral. Similarly, only Cozy markets with a defined trigger contract, known as protection markets, can be used for protected borrowing.

Therefore, the first step toward protected borrowing is to determine the address of the Cozy money market you intend to use as collateral. To see how to do that, let's assume that you want to buy protection for an ETH investment and you have 2 ETH to use as collateral.

### Determine address of the money market

The following code snippet illustrates how to check the `trigger` property to see if it returns the zero address and how to find the address for the Cozy ETH Money Market where you will deposit your collateral:

{% code title="buy-protection.ts" %}

```javascript
// STEP 0: ENVIRONMENT SETUP
const supplyAmount = '2'; // Supply 2 ETH as collateral
const borrowAmount = '500'; // Borrow 500 USDC

// STEP 1: SUPPLY COLLATERAL
// We need the Comptroller, so create an instance of the Comptroller contract
const comptrollerAddress = getContractAddress('Comptroller', chainId);
const comptroller = new Contract(comptrollerAddress, comptrollerAbi, signer); // connect signer for sending transactions

// Let's say we have ETH to use as collateral
// The first check is to make sure an ETH Money Market exists that we
// can supply to. We know that Money Markets have a trigger address
// of the zero address, so we use that to query the Comptroller for
// the Money Market address
const cozyEthAddress = await comptroller.getCToken(ethAddress, AddressZero);

// If the returned address is the zero address, a money market does
// not exist and we cannot supply ETH
if (cozyEthAddress === AddressZero) {
  logFailure('No ETH Money Market exists. Exiting script');
  return;
}
logSuccess(`Safe to continue: Found ETH Money Market at ${cozyEthAddress}`);
```

{% endcode %}

In this example, the `ethAddress` used as input to the `getCToken` method is the address `0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE` that Cozy uses to represent ETH.

### Supply the collateral

After verifying that there's a valid Cozy money market available for depositing your collateral, you are ready to supply the collateral to that money market. In this example, you are supplying 2 ETH, and ETH has 18 decimal places, so your script need to account for that. The process is slightly different for ETH than for ERC-20 tokens. The following code and comments describe how supplying collateral using ETH differs from supplying collateral when using ERC-20 tokens.

{% code title="buy-protection.ts" %}

```javascript
// Create a contract instance of the Cozy ETH money market
const cozyEth = new Contract(cozyEthAddress, cozyEthAbi, signer); 
// To supply ERC-20 tokens as collateral:
// const cozyToken = new Contract(cozyTokenAddress, cozyTokenAbi, signer); // for tokens

// We're now ready to supply the collateral to the market, but there's
// some preparation we need to do beforehand. For example, ETH
// has 18 decimal places, so we need to take that into account.
// `parseUnits` is a method from ethers.js
const parsedSupplyAmount = parseUnits(supplyAmount, 18); // scale amount based on number of decimals

// If using a token, here is where you'd approve the Cozy Money Market
// contract to spend your tokens. If you trust the Cozy contract,
// approve it to spend the maximum possible amount to avoid future
// approvals and save gas. Below we show a sample snippet of an
// approval transaction and verifying it was successful:
//   const approveTx = await token.approve(cozyToken.address, MaxUint256);
//   await approveTx.wait();
//   const allowance = await token.allowance(signer.address, cozyToken.address);
//   if (!allowance.eq(MaxUint256)) {
//     logFailure('CozyToken does not have sufficient allowance to spend our token. Exiting script');
//     return;
//   }
//   logSuccess('Approval transaction successful. Ready to mint CozyToken with our token');

// Ready to mint our CozyETH from ETH
const mintTx = await cozyEth.mint({ value: parsedSupplyAmount, gasLimit: '5000000' }); 
// const mintTx =await cozyToken.mint(parsedSupplyAmount); // for tokens
const { log: mintLog, receipt: mintReceipt } = await findLog(mintTx, cozyEth, 'Mint', provider);
logSuccess(`CozyETH successfully minted in transaction ${mintReceipt.transactionHash}`);
```

{% endcode %}

### Verify transaction results

In some cases, the mint transaction can appear to be successful without the mint operation actually being successful.

Because of how Cozy does error handling, transactions can be successful—and be displayed as successful on Etherscan and other block explorers—but without doing what you expected. For example, if a transaction returns an error code and emits a `Failure` event instead of reverting, it might appear as if the transaction was successful when it has actually failed. You can read more about error codes and failures in [Error codes](/for-developers/error-codes), and see information about error handling history [here](https://www.comp.xyz/t/brief-history-of-error-handling-in-the-protocol/1169).

You should manually ensure the mint transaction succeeded before continuing to the next step. You can use the `findLog()` helper method to simplify the verification process. For more details about using the `findLog()` method, see the [utils.ts](https://github.com/Cozy-Finance/cozy-developer-guides/blob/master/utils/utils.ts) file in the [Cozy developer Guides](https://github.com/Cozy-Finance/cozy-developer-guides) repository.

## Enter markets

Supplying assets does not automatically mean you can use them as collateral. To use the supplied assets as collateral, you must explicitly call the `enterMarkets` function on the Comptroller. The following code snippet illustrates how to add your collateral to the market:

{% code title="buy-protection.ts" %}

```javascript
// STEP 2: ENTER MARKETS
// Supplying assets does not automatically mean we can use them as
// collateral. To do that, we need to explicitly call enterMarkets
// on the Comptroller for each asset we want to use as collateral. For
// now, that's just ETH. (We use `em` as shorthand for `enterMarkets`
// in our variable names)
const markets = [cozyEth.address]; // array of markets to enter
const emTx = await comptroller.enterMarkets(markets);
const { log: emLog, receipt: emReceipt } = await findLog(emTx, comptroller, 'MarketEntered', provider);
logSuccess(`Markets entered successfully: ETH can now be used as collateral`);
```

{% endcode %}

## Borrow funds

Your account is now ready to borrow protected funds. Let's say there's a Yearn protection market for yUSDC, and you want to borrow protected USDC to invest in that protection market. The steps are very similar to the steps for supplying collateral, so let's jump straight to the code:

{% code title="buy-protection.ts" %}

```javascript
// STEP 3: BORROW FUNDS
// Your account is now ready to borrow funds

// We want to borrow protected USDC so we can deposit it straight into
// Yearn's yUSDC vault, so first let's verify the underlying token
// we'd borrow is in fact USDC
const usdc = new Contract(getContractAddress('USDC', chainId), erc20Abi, signer);
const yearnProtectionMarketAddress = getContractAddress('YearnProtectionMarket', chainId);
const yearnProtectionMarket = new Contract(yearnProtectionMarketAddress, cozyTokenAbi, signer);
const underlying = await yearnProtectionMarket.underlying();
if (usdc.address !== getAddress(underlying)) {
  // We use ethers' getAddress() method to ensure both addresses are
  // checksummed before comparing them. If this block executes, the
  // underlying of the protection market is not the underlying we
  // want (USDC), so we exit the script
  logFailure('USDC addresses do not match. Exiting script');
  return;
}

// Now we execute the borrow
const parsedBorrowAmount = parseUnits(borrowAmount, await usdc.decimals()); // scale amount based on number of decimals
const borrowTx = await yearnProtectionMarket.borrow(parsedBorrowAmount);
const { log: borrowLog, receipt: borrowReceipt } = await findLog(borrowTx, yearnProtectionMarket, 'Borrow', provider);
logSuccess(`Protected USDC borrowed in transaction ${borrowReceipt.transactionHash}`);

// Done! You are now supplying ETH as collateral to borrow protected
// USDC. The USDC debt will not need to be paid back if the Yearn
// trigger event occurs, so the borrowed USDC can now be safely
// supplied to Yearn
```

{% endcode %}

At this point, your account is now supplying 2 ETH as collateral to borrow 500 USDC. That USDC debt will not need to be paid back if the trigger event occurs, so you can safely deposit the 500 USDC into a Yearn vault.


# Manage protection programmatically

Learn how to view and manage positions and accounts programmatically on the Cozy protocol.

![](https://92902368-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MQOlThYns4gV0tad8h_-887967055%2Fuploads%2Fgit-blob-cf0831fe3528adc037d7db3d87ede0312279c1c7%2FProvide.png?alt=media)

This guide illustrates how you can view and manage your protection positions programmatically using a script written in TypeScript. The tasks in this section assume that you are a participant in a protection market and have supplied collateral to purchase protection as described in [Buy protection programmatically](/for-developers/guides/how-do-i-buy-protection-programmatically). If you haven't already done so, you should read the [Buy protection programmatically](/for-developers/guides/how-do-i-buy-protection-programmatically) guide or review the `buy-protection.ts` script before continuing with this guide.

All of the code snippets in this guide are from the `manage-protection.ts` script in the [Cozy developer guides](https://github.com/Cozy-Finance/cozy-developer-guides) repository. See that repository for more context, definitions of helper methods used, and related information.

{% hint style="info" %}
Everything in this guide assumes that you have experience with JavaScript, [ethers.js](https://github.com/ethers-io/ethers.js/), and [Solidity](https://docs.soliditylang.org/en/latest/).
{% endhint %}

## Prepare to manage positions

The `manage-protection.ts` script includes code to set up a your environment and buy protection so that you have an account with positions to manage. Because those steps are covered in other guides, they aren't included in this guide. For managing positions, however, you need to specify how many decimals Cozy tokens have. You can add this information to the Environment Setup section of the code with a line like this:

{% code title="manage-protection.ts" %}

```typescript
// All Cozy Tokens have 8 decimals, so we define this for convenience
const cTokenDecimals = 8;
```

{% endcode %}

After the Environment Setup instructions, the `manage-protection.ts` script includes a condensed version of the code for buying protection, which is covered in more detail in the `buy-protection.ts` script. You can view the condensed version of the code [here](https://github.com/Cozy-Finance/cozy-developer-guides/blob/9c6deb7cdad49322e82871381b146bd9c9867689/guides/manage-protection.ts#L32-L73).

## View positions

As the last step of buying protection, you borrowed funds from a protection market. In this case, you have borrowed protected USDC from a Yearn protection market. Now, let's get an array of Cozy token (cToken) addresses for each market you've entered.

{% code title="manage-protection.ts" %}

```typescript
// STEP 1: VIEWING POSITIONS
// To start, let's get an array of CToken addresses for each market
// we've entered. When you borrow from a market, you are automatically
// entered into that market
const ourAddress = signer.address; // shorthand, for convenience

 // Get an array of CozyToken addresses of markets entered
const assets = await comptroller.getAssetsIn(ourAddress);
```

{% endcode %}

{% hint style="info" %}
When you borrow from a market, you are automatically entered into that market. When you supply to a market, however, you must explicitly enter the market.
{% endhint %}

In practice, this distinction means that the `getAssetsIn` method only returns:

* Assets that you have **borrowed**.
* Assets that you have **supplied** and have used to **enter markets**.

If you have supplied assets but have not explicitly entered a market with them, those assets are not included in the results because there's no position to manage and the Comptroller does not need to be aware of those assets.

To determine whether you have borrowed from a market or supplied to the markets, you can loop through each asset and learn its current status. The comments in this code snippet explain what's happening at each step.

{% code title="manage-protection.ts" %}

```typescript
console.log('Checking status of each asset...\n');
for (const asset of assets) {
  // First we'll check balances in this loop and see if any of our
  // balances come from borrows. For brevity, we prefix all properties
  // about the underlying token with `u`
  const cToken = new Contract(asset, cozyTokenAbi, signer);
  const [name, symbol] = await Promise.all([cToken.name(), cToken.symbol()]);
  console.log(`Current asset has name "${name}" and symbol "${symbol}"`);

  // Let's also learn about the underlying token. First we determine
  // if the underlying is ETH then get a contract instance for the
  // underlying token if the underlying is not ETH
  const uAddr = await cToken.underlying();
  const isEth = uAddr === ethAddress; // true if underlying is ETH, false otherwise
  const underlying = isEth ? null : new Contract(uAddr, erc20Abi, signer);

  // Lastly we either read set the values if ETH is underlying, or
  // read the values if it's a token
  const uName = underlying ? await underlying.name() : 'Ether';
  const uSymbol = underlying ? await cToken.symbol() : 'ETH';
  const uDecimals = underlying ? await underlying.decimals() : 18;
  console.log(`  Underlying ${uName} (${uSymbol}) has ${uDecimals} decimals`);

  // Get our balance of the Cozy token
  const balance = await cToken.balanceOf(ourAddress);
  const balanceScaled = formatUnits(balance, cTokenDecimals);
  if (balance.eq(Zero)) {
    // Balance is zero, so we have not supplied the underlying token
    console.log('  No Cozy Token balance, so nothing supplied');
  } else {
    // Balance is > 0, so we have supplied some amount of underlying
    // tokens. We get exchange rate to figure out how much underlying
    // we have. The exchange rate is a mantissa (18 decimal value), so
    // the value returned is scaled by
    // 10 ** (18 + underlyingDecimals - cTokenDecimals)
    const exchangeRate = await cToken.exchangeRateStored();
    const scale = 18 + uDecimals - cTokenDecimals;
    const uBalance = balance.mul(exchangeRate);
    const uBalanceScaled = formatUnits(uBalance, scale + cTokenDecimals);
    console.log(`  Balance of ${balanceScaled} Cozy Tokens (equal to ${uBalanceScaled} underlying)`);
  }

  // Now get our balance of the underlying token
  const uBalance = underlying ? await underlying.balanceOf(ourAddress) : await signer.provider.getBalance(ourAddress);
  if (uBalance.eq(Zero)) {
    // Underlying balance is zero, so we have not borrowed the
    // underlying token
    console.log(`  No underlying ${uSymbol} balance`);
  } else {
    // Underlying balance is above zero, BUT we still may not have
    // borrowed this token -- we may have already had some
    const uBalanceScaled = formatUnits(uBalance, uDecimals);
    console.log(`  Balance of ${uBalanceScaled} underlying ${uSymbol} tokens`);

    // Read the amount borrowed
    const borrowBalance = await cToken.borrowBalanceStored(ourAddress);
    const borrowBalanceScaled = formatUnits(borrowBalance, uDecimals); // scale to human readable units

    // Now we determine if the funds were borrowed
    if (borrowBalance.eq(Zero)) console.log(`  None of the underlying ${uSymbol} tokens we have were borrowed`);
    else if (borrowBalance.eq(uBalance)) console.log(`  All the underlying ${uSymbol} tokens we have were borrowed`);
    else console.log(`  ${borrowBalanceScaled} of the ${uBalanceScaled} underlying ${uSymbol} tokens were borrowed`);
  }
  console.log('\n');
} // end for each asset
```

{% endcode %}

## Check account liquidity

The amount of collateral you have is computed by multiplying the supplied USD balance in a market by that market's collateral factor, and summing that across all markets. Total borrow balances are subtracted from that, resulting in an **account liquidity** value. Users who have negative account liquidity, i.e. a shortfall, are subject to liquidation, and are prevented from withdrawing or borrowing assets.

To avoid liquidation, you must ensure that account liquidity is always greater than zero. You can check this for an account as follows:

{% code title="manage-protection.ts" %}

```javascript
// STEP 2: CHECKING ACCOUNT LIQUIDITY

// getAccountLiquidity() returns three values. The first is an error
// code, the second is the excess liquidity, and the third is the
// shortfall. Only one of the last two will ever be positive
const [errorCode, liquidity, shortfall] = await comptroller.getAccountLiquidity(signer.address);

// Make sure there were no errors reading the data
if (errorCode.toString() !== '0') {
  logFailure(`Could not read liquidity. Received error code ${errorCode}. Exiting script`);
  return;
}

// There were no errors, so now we check if we have an excess or a
// shortfall
if (shortfall.gt(Zero)) {
  logFailure(`WARNING: Account is under-collateralized and may get liquidated! Shortfall amount: ${shortfall}`);
} else if (liquidity.gt(Zero)) {
  logSuccess(`Account has excess liquidity and is safe. Amount of liquidity: ${liquidity}`);
} else {
  logFailure('WARNING: Account has no liquidity and no shortfall');
}
```

{% endcode %}

## Manage liquidity

After checking your account liquidity, you might find that you are at risk of having your account liquidated. If you find your account liquidity is too close to the minimum required—for example, you have a shortfall or only a small amount of excess liquidity—you can adjust your position by doing the following:

* Supply additional collateral.
* Repay debt.

### Supply additional collateral

If you want to adjust your account liquidity (another way of measuring what's commonly known as your collateralization ratio) to reduce the risk of liquidation, you can supply more collateral.

To supply more collateral programmatically, follow the detailed steps in `buy-protection.ts` script (or reference the abbreviated version of the code for supplying collateral in the `manage`-`protection.ts` script).

### Repay debt

An alternate way to reduce your chance of liquidation is to pay back some, or all, of your borrowed debt.

There are two options for repaying debts:

* Repay debt you, as the transaction caller, borrowed.
* Repay debt on behalf of another borrower.

#### repayBorrow

You can repay your own borrows using the `repayBorrow()` method. As the following code snippet illustrates, you first approve the contract to spend DAI, then execute the repay.

{% code title="manage-protection.ts" %}

```typescript
// If we want to repay our own borrows, we can use the repayBorrow
// method. First we approve the contract to spend our USDC, then we
// execute the repay

// Send approval transaction and wait it to be mined
const usdcApproveTx = await usdc.approve(yearnProtectionMarket.address, MaxUint256);
await usdcApproveTx.wait();

// Define the amount to repay, taking USDC's decimals into account
const usdcDecimals = await usdc.decimals();
const repayAmount = parseUnits('25', usdcDecimals); // repay 25 USDC
const repayTx = await yearnProtectionMarket.repayBorrow(repayAmount);
await findLog(repayTx, yearnProtectionMarket, 'RepayBorrow', provider);
logSuccess('Successfully repaid a portion of the borrow');
```

{% endcode %}

This example, repays a debt of 25 DAI for the account that called the `repayBorrow` method.

If you wanted to repay the full amount instead of just 25 DAI, the best way to do this is to set the `repayAmount` to `MaxUint256`. The Cozy contracts recognize this as a magic number that will repay all your token debt. If you try to repay all token debt without using `MaxUint256` as the amount, you'll be left with a very tiny borrow balance, known as dust. This happens because interest accrues at the beginning of the repay transaction, and it's extremely difficult to predict how much will accrue and send the exact amount of tokens required. Using `MaxUint256` tells the contracts to repay the full debt after interest accrues.

#### repayBorrowBehalf

Alternatively, you could have executed the same logic in the code snippet above using the `repayBorrowBehalf` method. For example, you could have used `repayBorrowBehalf(borrower,repayAmount)` to repay `repayAmount` on behalf of `borrower`.

The `repayBorrowBehalf()` method is particularly useful for repaying ETH debt. Because ETH is required for gas, calculating how much ETH you need to repay ETH debt can be difficult. For example, if you wanted to repay a full ETH balance, you would need to calculate the gas required for the transaction as well as the interest accrued. Instead of trying to predict the exact gas usage plus interest accrual, you can repay full ETH debts by using a special contract called the `Maximillion` contract. The `Maximillion` contract lets you send extra ETH along with your transaction. The contract repays your debt using `repayBorrowBehalf()`, then refunds you the excess after paying back all debt.

The following code snippet illustrates using the `Maximillion` contract to repay ETH debt.

{% code title="manage-protection.ts" %}

```typescript
// Repay all ETH debt with the Maximillion contract (we actually have
// zero ETH debt in the script, but that's ok). First we get an
// instance of the Maximillion contract
const maximillionAddress = getContractAddress('Maximillion', chainId);
const maximillion = new Contract(maximillionAddress, maximillionAbi, signer);

// Get the address of the Cozy ETH Money Market
const ethMarketAddress = getContractAddress('CozyETH', chainId);

// Now we do the repay. In this case our debt is zero, so any ETH sent
// is excess ETH that will be refunded after repaying the debt. Notice
// how we specify that we are repaying debt for ourselves,
// `signer.address`, and we specify the address of the market to repay
// debt in, `ethMarketAddress`. (We don't look for the success logs
// since this is a dummy transaction and we have no debt, but in
// practice you should).
const value = parseUnits('0.1', 18); // ETH has 18 decimals
const repayEthTx = await maximillion.repayBehalfExplicit(signer.address, ethMarketAddress, { value });
```

{% endcode %}


# Provide protection programmatically

Learn how to provide protection by supplying assets to a protection market programmatically.

Cozy provides a protected borrowing marketplace for investing in decentralized finance protocols that offer protection against a loss of funds. You can participate in this marketplace by supplying assets to an existing protection market. After you deposit assets, you earn interest on the deposit from investors who borrow from the protection market. You continue earning interest as long If the protection market operates without having a trigger event occur. If there is a hack, exploit, or other problem that triggers protection in the market where you have supplied assets, all outstanding debts in that market are forgiven. The interest you earn is your reward for taking on the risk associated with trigger event. In evaluating the risk involved, you should consider how likely it will be for a particular market's trigger condition to be satisfied.

This guide illustrates how you can write a script using TypeScript that you can then use to supply assets to a protection market programmatically.

All code snippets are from the `provide-protection.ts` script in the [Cozy Developer Guides](https://github.com/Cozy-Finance/cozy-developer-guides) repository. See that repository for more context, definitions of helper methods used, etc.

{% hint style="info" %}
Everything in this guide assumes that you have experience with JavaScript, [ethers.js](https://github.com/ethers-io/ethers.js/), and [Solidity](https://docs.soliditylang.org/en/latest/).
{% endhint %}

## Supply assets to a protection market

Before you can provide protection, you need to identify the asset you want to deposit and select the protection market where you want the assets you supply to be used.

All markets in Cozy—money markets and protection markets—have a `trigger` state variable. If the value of the `trigger` property is the [zero address](https://etherscan.io/address/0x0000000000000000000000000000000000000000), the money market does not have a trigger contract associated with it. A money market that does not have a trigger contract associated with it cannot be used for protected borrowing, but can be used for ordinary borrowing. If the value of the `trigger` property is anything except the zero address, the value of the `trigger` property represents the address of the trigger contract associated with that market. Only Cozy markets that have a trigger contract can be used for protected borrowing.

If you want to provide assets to a market for protected borrowing and to earn interest from the borrowers participating in that market, you need to verify that the market is a supported protection market. To see how to do that, let's assume the following:

* You have 1000 USDC that you want to deposit.
* You want to use that asset to provide protection to a Yearn Protection Market for yUSDC.

The following code snippet illustrates how you can verify that the Yearn market is part of the Cozy protocol.

{% code title="provide-protection.ts" %}

```javascript
// STEP 0: ENVIRONMENT SETUP
const supplyAmount = '1000'; // Amount of USDC we want to supply, in dollars (e.g. 1000 = $1000 = 1000 USDC)

// Since we are testing on a forked mainnet and our account has no
// funds, we need to initialize the account with the required tokens.
// This step is not needed when the private key in your .env file has
// funds on mainnet
const usdcAddress = getContractAddress('USDC', chainId);
await fundAccount(usdcAddress, supplyAmount, signer.address, hre);

// If the account also needed ETH, you could fund it as shown here
const ethAddress = getContractAddress('ETH', chainId);
await fundAccount(ethAddress, '10', signer.address, hre);

// STEP 1: VERIFY MARKET
// We know we'll need the Comptroller, so create an instance the Comptroller contract
const comptrollerAddress = getContractAddress('Comptroller', chainId);
const comptroller = new Contract(comptrollerAddress, comptrollerAbi, signer); // connect signer for sending transactions

// The first check is to make sure our protection market is a valid
// protection market that we can supply to
const yearnProtectionMarketAddress = getContractAddress('YearnProtectionMarket', chainId);
const allMarkets = await comptroller.getAllMarkets();
if (!allMarkets.includes(yearnProtectionMarketAddress)) {
  logFailure("Provided Protection Market address not found in the Comptroller's list of all markets");
  return;
}
logSuccess('Provided Protection Market address is valid');
```

{% endcode %}

After verifying the market to which you plan to supply assets is a valid protection market according to the Cozy protocol's Comptroller, you are ready to supply assets to the market. In this example, you are supplying 1000 USDC and USDC has 6 decimal places, so your script needs to account for that.

The following code and comments describe how to adjust the units to 6 decimal places, approve the protection market to spend your USDC, then supply funds to the protection market.

{% code title="provide-protection.ts" %}

```javascript
// STEP 2: PROVIDE PROTECTION
// We're now ready to supply collateral (i.e. provide protection) to
// the market, but there's some preparation we need to do beforehand.
// First, recall that USDC has 6 decimal places, so we need to take
// that into account. We'll do this programmatically by querying the
// USDC contract for the number of decimals it has
const usdc = new Contract(usdcAddress, erc20Abi, signer);
const decimals = await usdc.decimals();
const parsedSupplyAmount = parseUnits(supplyAmount, decimals); // scale amount based on number of decimals

// Next we need to approve the protection market contract to spend
// our USDC. We trust the contract, so approve it to spend the
// maximum possible amount to avoid future approvals and save gas
const approveTx = await usdc.approve(yearnProtectionMarketAddress, MaxUint256);
await approveTx.wait();

// Let's verify this approve transaction was successful
const allowance = await usdc.allowance(signer.address, yearnProtectionMarketAddress);
if (!allowance.eq(MaxUint256)) {
  logFailure('CozyUSDC does not have sufficient allowance to spend our USDC. Exiting script');
  return;
}
logSuccess('Approval transaction successful. Ready to mint CozyUSDC with our USDC');

// Now we can supply funds to the protection market to provide
// protection. Just like with ordinary Money Markets, this mints a
// receipt token that is sent to our wallet
const yearnProtectionMarket = new Contract(yearnProtectionMarketAddress, cozyTokenAbi, signer);
const mintTx = await yearnProtectionMarket.mint(parsedSupplyAmount);
const { log: mintLog, receipt: mintReceipt } = await findLog(mintTx, yearnProtectionMarket, 'Mint', provider);
const yearnProtectionMarketSymbol = await yearnProtectionMarket.symbol();
const yearnProtectionMarketName = await yearnProtectionMarket.name();
logSuccess(
  `${yearnProtectionMarketName} (${yearnProtectionMarketSymbol}) successfully minted in transaction ${mintReceipt.transactionHash}`
);
```

{% endcode %}

### Verify transaction results

In some cases, a `mintTx` transaction can appear to be successful without the mint operation actually being successful.

Because of how Cozy does error handling, transactions can be successful—and be displayed as successful on Etherscan and other block explorers—but without doing what you expected. For example, if a transaction returns an error code and emits a `Failure` event instead of reverting, it might appear as if the transaction was successful when it has actually failed.

You can read more about error codes and failures in [Error codes](/for-developers/error-codes), and see information about error handling history [here](https://www.comp.xyz/t/brief-history-of-error-handling-in-the-protocol/1169).

You should manually ensure the mint transaction succeeded before continuing to the next step. You can use the `findLog()` helper method to simplify the verification process. For more details about using the `findLog()` method, see the [utils.ts](https://github.com/Cozy-Finance/cozy-developer-guides/blob/master/utils/utils.ts) file in the [Cozy developer Guides](https://github.com/Cozy-Finance/cozy-developer-guides) repository.

After you manually verify that your transaction was successful, your 1000 USDC are used to provide protection in the Yearn yUSDC protection market.


# Liquidate a vault

Learn how to liquidating a vault programmatically on the Cozy protocol.

Users who borrow funds are required to maintain a minimal level of account liquidity. If their account falls below the minimum liquidity threshold, they risk liquidation and losing their collateral.

Users can avoid liquidation by adding collateral or repaying debts. If a user with an account at risk of liquidation fails to respond—by adding collateral or repaying outstanding debt—the account will eventually have negative account liquidity, also known as a shortfall. Any user account with negative account liquidity can be liquidated and taken over programmatically by someone else. By liquidating an account with a shortfall, you can seize its assets at a discount.

This guide illustrates how you can liquidate vaults programmatically using a script written in TypeScript.

All code snippets in this guide are from the [`liquidate.ts` script](https://github.com/Cozy-Finance/cozy-developer-guides/blob/master/guides/liquidate.ts) in the [Cozy developer guides](https://github.com/Cozy-Finance/cozy-developer-guides) repository. See that repository for more context, definitions of helper methods used, and related information.

{% hint style="info" %}
Everything in this guide assumes that you have experience with JavaScript, [ethers.js](https://github.com/ethers-io/ethers.js/), and [Solidity](https://docs.soliditylang.org/en/latest/), as well familiarity with the Cozy protocol.
{% endhint %}

## Check account liquidity

The collateral value of an account is computed by multiplying the supplied USD balance in a market by that market's collateral factor, and summing the result across all markets. The total USD borrow balances for a user are subtracted from that result to arrive at the account liquidity value.

Only accounts with negative liquidity, also known as a shortfall, can be liquidated. Therefore, before liquidating an account, you need to check whether the account has a shortfall. The following code snippet illustrates how to check if an account has a shortfall using an arbitrary address.

% hint style="info" %} The sample script uses an arbitrary address because there's no way to guarantee there is a mainnet account with negative liquidity that could actually be liquidated. The comments describe what to expect if the arbitrary account could be liquidated.

{% code title="liquidate.ts" %}

```typescript
// STEP 1: CHECK ACCOUNT LIQUIDITY

// Get instance of Comptroller contract and connect signer for sending transactions
const comptrollerAddress = getContractAddress('Comptroller', chainId);
const comptroller = new Contract(comptrollerAddress, comptrollerAbi, signer);

// Define the address to liquidate and check their liquidity
const borrowerToLiquidate = '0x0000000000000000000000000000000000000001';
const [errorCode, liquidity, shortfall] = await comptroller.getAccountLiquidity(borrowerToLiquidate);

// Make sure there were no errors reading the data
if (errorCode.toString() !== '0') {
  logFailure(`Could not read liquidity. Received error code ${errorCode}. Exiting script`);
  return;
}

// There were no errors, so now we check if we have an excess or a shortfall. 
// One and only one of `shortfall` and `liquidity` will be above zero. (Since
// our chosen account above has no shortfall, you'll need to comment out the
// return statements to move past this section)
if (shortfall.gt(Zero)) {
  logSuccess(`Account is undercollateralized and can be liquidated! Shortfall amount: ${shortfall}`);
} else if (liquidity.gt(Zero)) {
  logFailure(`Account has excess liquidity and is safe. Amount of liquidity: ${liquidity}. Exiting script`);
  return;
} else {
  logFailure('Account has no liquidity and no shortfall. Exiting script.');
  return;
}
```

{% endcode %}

## Liquidate an account

If the script had found that the arbitrary account had a shortfall, it would proceed with liquidating the account. In liquidating the account, you can configure the script to repay some or all of the outstanding debt on behalf of the borrower. As a result of the liquidation, you receive some of the borrower's collateral at a discount. Receiving a portion of a borrower's collateral at a discount is referred to as the liquidation incentive.

As an account liquidator, you first need to determine the maximum percentage of the outstanding debt for an account that can be closed by repayment.

The following code snippet illustrates how to check the maximum percentage—called the close factor—that can be closed by liquidation:

{% code title="liquidate.ts" %}

```typescript
// STEP 2: PERFORM LIQUIDATION

// Check the max close factor that can be liquidated for Cozy
const closeFactor = await comptroller.closeFactorMantissa();
logSuccess(`Close factor: ${formatUnits(closeFactor, 18)}`);
```

{% endcode %}

As part of the liquidation process, you can choose one of the assets that were supplied as collateral by the borrower as the asset you'll seize and receive at a discount. If needed, you could get a list of available collateral using the `getAssetsIn()` method described in [Viewing Positions](/for-developers/guides/how-do-i-manage-protection-programmatically#view-positions) guide. For simplicity, the following code snippet assumes the collateral is ETH and the borrow is a protected Yearn yUSDC vault, then checks how much this user has borrowed and computes the maximum repay amount.

{% code title="liquidate.ts" %}

```typescript
// Get contract instances
const cozyEthAddress = getContractAddress('CozyETH', chainId);
const yearnProtectionMarketAddress = getContractAddress('YearnProtectionMarket', chainId);
const yearnProtectionMarket = new Contract(yearnProtectionMarketAddress, cozyTokenAbi, signer);

// Next we choose an amount of their debt to repay. The max amount we
// can repay is equal to the closeFactor multiplied by their borrow
// balance, so let's check their borrow balance
const usdcBorrowed = await yearnProtectionMarket.borrowBalanceStored(borrowerToLiquidate);

// If we wanted to liquidate the max amount, we can compute this
// below. Here we divide the amount by 1e18 because we multiply the
// USDC amount (6 decimals) by the closeFactor (18 decimals), giving
// us a 24 decimal number. The liquidation amount should be in units
// of the borrowed asset, which is USDC, so we divide by 1e18 to get
// there
const scale = '1000000000000000000'; // 1e18
const repayAmount = usdcBorrowed.mul(closeFactor).div(scale);
logSuccess(`Ready to repay ${repayAmount.toString()} USDC`);
```

{% endcode %}

After the collateral is seized, the seized amount is transferred as Cozy tokens. Those tokens can be redeemed as if you had supplied the collateral asset yourself. Remember to approve the Cozy token contract to spend your tokens before calling `liquidateBorrow()`.

The following code snippet illustrates executing the liquidation. However, in this case, the account to liquidate does not have a shortfall. Therefore, the `findLog()` method reports that the `LiquidateBorrow` event was not found and prints an error code (3) this corresponds to the `COMPTROLLER_REJECTION` failure message. Looking at the Comptroller's `liquidateBorrowAllowed` hook, you can find that the Comptroller rejected the liquidation because there is no shortfall.

{% code title="liquidate.ts" %}

```typescript
// Execute the liquidation
const tx = await yearnProtectionMarket.liquidateBorrow(borrowerToLiquidate, repayAmount, cozyEthAddress);
await findLog(tx, yearnProtectionMarket, 'LiquidateBorrow', provider);
```

{% endcode %}


# Create a protected investing opportunity

Learn how to create a protected investment opportunity for another DeFi protocol.

After obtaining protection via a Cozy protection market, many users will want to deploy the newly borrowed funds to earn yield. That’s where Cozy Protected Investing comes in.

Cozy Protected Investing enables users to borrow, invest and track returns in one step, in one place. This guide details how you can create a Protected Investment opportunity for users on [cozy.finance](https://app.cozy.finance) or on your DeFi app.

## Deploy a protection market

Each Cozy Protected Investment opportunity requires a corresponding Protection Market. Please refer to the [Create a protection market](/for-developers/guides/how-do-i-create-a-protection-market#step-3-protection-market-deployment) guide for details on developing and deploying trigger and protection market contracts.

## Adding protected investment opportunities to the Cozy app

### Deploy an invest/divest contract

Protection markets cover the borrow-side of an investment opportunity; however, you’ll also need to provide instructions for how the borrowed funds should be invested.  For this, you’ll deploy an additional contract that is responsible for investing, divesting and managing any other assets related to the investment position (e.g. reward tokens or airdrops).

Please refer to [Create an invest/divest contract guide](/for-developers/guides/how-do-i-create-an-invest-divest-contract) for details on developing and deploying an invest/divest contract.

### Data fetching

The Cozy app requires a few pieces of data to support an investment opportunity. The Cozy subgraph (covered in detail below) supplies much of this data, but the subgraph is limited to Cozy protocol-specific data (i.e. protection markets and positions in those markets). Data related to an investment opportunity on a separate DeFi protocol requires a separate data source.

That’s why it’s necessary to create an endpoint — on a per opportunity basis — which is responsible for investment performance data as well as data that facilitates invest/divest contract interaction. This endpoint — referred to as the opportunity's `dataURI` — uniquely identifies that opportunity.

Assuming a `dataURI` ending in `/new-opty`, this data endpoint must handle the following query parameters:

#### No query params

`/new-opty` - returns base data about the investment opportunity, like the rate of return, the remaining capacity to be deposited into the opportunity and whether the opportunity is disabled. Sample response:

```json
// Typical
{
  "isDisabled": false,
  "investCapacity": "991422.323294438226440458",
  "investRate": 0.07662908620704814
}

// Two Step Invest Flow
{
  /* All fields from typical return plus... */
  "investFlow": "twoStepInvest",
  "twoStepDeployTime": "Friday at 10am PST"
}
```

| **Typical Fields** | **Description**                                                                                                                                                                                                                                |
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| isDisabled         | Boolean. Whether the investment opportunity is still accepting funds. All invest transactions will fail if this is true.                                                                                                                       |
| investingCapacity  | String. The amount of funds in human-readable units which the investment opportunity can accept. The invest transaction will fail in an attempt to deposit funds beyond this amount. Null if there is no maximum capacity for the opportunity. |
| investRate         | Number. The percentage return in decimal form associated with funds invested into this opportunity. The investRate minus the borrowRate equals the netReturnRate — or the overall APY — associated with this opportunity.                      |

| **Two Step Invest Fields** | **Description**                                                                                                                                                                                                                                                                                                                                               |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| investFlow                 | String. Sometimes, an investment opportunity will have a non-standard flow. The Cozy app currently supports only one non-standard flow: the `twoStepInvest` flow. This flow is used by protocols like Ribbon, in which funds are not immediately deployed to an investment strategy when deposited, but instead batched into a single deployment each period. |
| twoStepDeployTime          | String. The time when funds in a `twoStepinvest` opportunity are deployed, for display in the UI, of the format “ at ”                                                                                                                                                                                                                                        |

#### Ethereum account

`/new-opty?account=<ethereumAccount>` - returns all the data of the base `new-opty` endpoint, but adds balance information for the passed in Ethereum account. Sample response:

```json
// Typical Response
{
  /* All fields from base response plus... */
  "balances": {
    "balanceUnderlying": "0.00089522599655054241457996374997540428",
    "balanceUsd": 2.526979298059575,
    "lastUpdatedBlockNumber": 7368120,
    "receiptTokenBalances": [
      {
        "balance": "0.001678155500972884",
        "balanceUnderlying": "0.00089309310068732528257996374997540428",
        "balanceUsd": 2.520958713635045,
        "token": {
          "chainId": 42161,
          "address": "0x8e0b8c8bb9db49a46697f3a5bb8a308e744821d2",
          "decimals": 18,
          "name": "Curve.fi USD-BTC-ETH",
          "symbol": "crv3crypto"
        }
      }
    ],
    "rewardTokenBalances": [
      {
        "balance": "0.002417905391377535",
        "balanceUnderlying": "0.000002132895863217132",
        "balanceUsd": 0.006020584424530063,
        "token": {
          "chainId": 42161,
          "address": "0x11cdb42b0eb46d95f990bedd4695a6e3fa034978",
          "decimals": 18,
          "name": "Curve DAO Token",
          "symbol": "CRV"
        }
      }
    ],
    "totalWithdrawableAmount": "1678155500972884"
  }
}

// Two Step Invest Flow
{
  /* All fields from the typical response plus...  */
  "pendingDepositsUnderlying": "100000000000000000000",
  "scheduledWithdrawalReady": true,
  "scheduledWithdrawalUnderlying": "100000000000000000000",
}
```

| **Typical Response Fields** | **Description**                                                                                                                                                                                                                       |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| balanceUnderlying           | String. The total value of the position in human-readable units of underlying from the borrow market for the investment opportunity                                                                                                   |
| balanceUsd                  | Number. The total value of the position in USD                                                                                                                                                                                        |
| lastUpdatedBlockNumber      | Number. The block number corresponding to the data in this response. Used for communicating the sync-status of the data currently being presented. (i.e. does the state of the invest position data match the data from the subgraph) |
| receiptTokenBalances        | Array. An array of the receipt tokens associated with this position                                                                                                                                                                   |
| rewardTokenBalances         | Array. An array of the reward tokens associated with this position                                                                                                                                                                    |
| totalWithdrawableAmount     | String. The number of receipt tokens as a raw, contract-friendly string that can be redeemed when divesting from the investment opportunity                                                                                           |

| **Two Step Invest Fields**    | **Description**                                                                                                                                                                    |
| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| pendingDepositsUnderlying     | String. The amount of funds in human-readable units of underlying that have been deposited into the protocol but not yet deployed to earn yield                                    |
| scheduledWithdrawalReady      | Boolean. Whether funds that were previously scheduled to be withdrawn are now ready to be withdrawn                                                                                |
| scheduledWithdrawalUnderlying | String. The amount of funds in human-readable units of underlying that were previously scheduled to be withdrawn but require additional time before they are ready to be withdrawn |

| **Token Info Fields** | **Description**                                                                                                                      |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| balance               | String. Balance in human-readable units of this token for the investment account                                                     |
| balanceUnderlying     | String. The value of this token balance, in human-readable units of underlying from the borrow market for the investment opportunity |
| balanceUsd            | Number. The value of this token balance, in USD                                                                                      |
| decimals              | Number. The number of decimals to divide a raw balance by to produce its human-readable form                                         |
| token                 | Object. The standard details of an erc20 token                                                                                       |

{% hint style="info" %}
When describing balance fields in this guide, we will always refer to their units as either raw or human-readable. Raw fields are the format used by smart contracts that have no decimal places. If you divide a raw value by Math.pow(10, decimals), you get the human-readable form.
{% endhint %}

#### Invest params

`/new-opty?invest=[<marketContractAddress>, <investAmountInUnderlying>]` - returns the parameters which will be passed into the `invest` method of the invest/divest contract deployed for this investment opportunity. Sample response:

```json
// For invest function signature:
// function invest(address _ethMarket, uint256 _borrowAmount, uint256 _curveMinAmountOut) external payable
[
  '0x7d4377114fd3c61c59d72de48102bf6acd3882b1', // Cozy market address
  '697746377352637', // borrow armount in underlying
  '442383085561', // min amount out for call to Curve pool
];
```

#### Divest params

`/new-opty?invest=[<marketContractAddress>, <divestAmountInUnderlying>, <eoaAddress>]` - returns the parameters which will be passed into the `divest` method of the invest/divest contract deployed for this investment opportunity. Sample response

```json
// For divest function signature:
// function divest(address _ethMarket, address _recipient, uint256 _redeemAmount, uint256 _curveMinAmountOut) external payable
[
  '0x7d4377114fd3c61c59d72de48102bf6acd3882b1', // market address
  '0x123abc123abc123abc123abc123abc123abc123a', // EOA address
  '1678155500972884', // redeem amount in LP tokens
  '855549635374828', // min amount out for call to Curve pool
];
```

### Surfacing

Cozy displays investment opportunities based on a set of `market-lists` maintained in the `cozy-invest-lists` repo. Inspired by [Uniswap’s `token-lists`](https://github.com/Uniswap/token-lists) standard, all [Cozy `market-lists`](https://github.com/Cozy-Finance/market-lists) conform to a simple, JSON schema.

Once all the smart contracts related to your investment opportunity have been deployed, you can create a new protection market entry in the `community` `protection-market-list` in Cozy’s `cozy-invest-lists` repo and submit a PR. Make sure to validate your entry to the schema using the validation framework found in the `protection-market-list` schema.

Amongst other things, your list entry will include:

* Invest/divest contract details: the contract addresses and signatures of the invest/divest contracts you deployed
* Investment opportunity strategy: a description of the steps taken when borrowed funds are deployed

Sample `protection-market-list` entry:

```json
{
  "chainId": 42161,
  "address": "0x7d4377114fd3c61c59d72de48102bf6acd3882b1",
  "symbol": "Cozy-ETH-1",
  "name": "Cozy-ETH-1-Curve 3Crypto Trigger",
  "decimals": 8,
  "tags": [],
  "trigger": "0x73ea553cd95211956420329c2c7d23851c577725",
  "underlying": {
    "chainId": 1,
    "decimals": 18,
    "address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
    "name": "Ether",
    "symbol": "ETH"
  },
  "investmentOpportunities": [
    {
      "invest": {
        "address": "0x551F34Ba6cd876CAe2265DA1f3e030e82f703A13",
        "signature": "function invest(address _ethMarket, uint256 _borrowAmount, uint256 _curveMinAmountOut) external payable"
      },
      "divest": {
        "address": "0x551F34Ba6cd876CAe2265DA1f3e030e82f703A13",
        "signature": "function divest(address _ethMarket, address _recipient, uint256 _redeemAmount, uint256 _curveMinAmountOut) external payable"
      },
      "dataURI": "https://cozy-api-k1ojdh8ct-cozy-finance.vercel.app/api/opportunities/arb-eth-tricrypto",
      "logoURI": "https://app.cozy.finance/images/tokens/crvtricrypto.png",
      "name": "crvTricrypto",
      "tokens": {
        "input": [
          {
            "chainId": 1,
            "decimals": 18,
            "address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
            "name": "Ether",
            "symbol": "ETH"
          }
        ],
        "receipt": [
          {
            "chainId": 42161,
            "address": "0x8e0b8c8bb9db49a46697f3a5bb8a308e744821d2",
            "decimals": 18,
            "name": "Curve.fi USD-BTC-ETH",
            "symbol": "crv3crypto"
          }
        ],
        "rewards": [
          {
            "chainId": 1,
            "address": "0xd533a949740bb3306d119cc777fa900ba034cd52",
            "decimals": 18,
            "name": "Curve DAO Token",
            "symbol": "CRV"
          }
        ]
      },
      "strategy": [
        {
          "action": "Borrow",
          "object": "ETH",
          "logoURI": "https://app.cozy.finance/images/tokens/eth.png",
          "platformId": 0,
          "token": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
        },
        {
          "action": "Deposit to",
          "object": "crvTricrypto",
          "logoURI": "https://app.cozy.finance/images/tokens/crvtricrypto.png",
          "platformId": 3,
          "token": "0x8e0b8c8bb9db49a46697f3a5bb8a308e744821d2"
        }
      ]
    }
  ]
}
```

| **Selected Fields**     | **Description**                                                                                                                                                                                                                                              |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| platformId              | Number. Cozy’s ID for the platform to which funds will be deposited; please consult the [Cozy-Finance/platform-ids repo](https://github.com/Cozy-Finance/platform-ids) for the correct `platformId` and submit a PR to add your protocol if it’s not listed. |
| tokens#input            | Object. Details on tokens that are deposited to enter into the opportunity                                                                                                                                                                                   |
| tokens#receipt          | Object. Details on tokens that are returned in receipt when an opportunity is entered; these tokens are exchanged again to exit the position.                                                                                                                |
| tokens#rewards          | Object. Details on all the tokens which may be accrued as rewards while a position is active                                                                                                                                                                 |
| divest#address          | String. Address of the invest/divest contract you deployed                                                                                                                                                                                                   |
| divest#signature        | String. Signature of the divest function on the invest/divest contract you deployed                                                                                                                                                                          |
| invest#address          | String. Address of the invest/divest contract you deployed                                                                                                                                                                                                   |
| invest#signature        | String. Signature of the invest function on the invest/divest contract you deployed                                                                                                                                                                          |
| strategy                | Array. Array of `strategyLegs` which capture the steps an investment opportunity takes when deploying funds; used only for display in the UI.                                                                                                                |
| strategy#action         | String. The action taking place in this leg of the investing strategy                                                                                                                                                                                        |
| strategy#actionReceiver | String. The receiver of the action taking place (grammatically, the direct or indirect object)                                                                                                                                                               |

### PR review

After submitting your new protection market list entry to the `cozy-invest-lists` repo for PR, we’ll review your invest/divest contracts and test your `dataURI` endpoint to ensure everything is working properly. Please ensure your invest/divest contracts are verified on [Etherscan](https://etherscan.com/), so we can review the code.

## Adding protected investment opportunities to your DeFi app

Hosting a protected investment opportunity on your site is easy and allows new users to engage with your project while staying protected.

### Depositing collateral

To enter into a protected investing position, a user must first have supplied collateral to borrow against. This collateral must be supplied to a Cozy money market, a process is [detailed in this guide](/for-developers/guides/how-do-i-buy-protection-programmatically#supply-collateral).

Each market has a `collateralFactor` which is applied to funds deposited into a money market that determines how much funds can be borrowed by that account (i.e. If $100 was supplied to a money market with a 0.75 collateral factor, that account can borrow $75).

If a user’s borrows exceed the total value of their collateral, they will be subject to liquidation.

### Entering a protected investing position

In order to create a protected investing position, the flow is as simple as:

1. Borrow from the Cozy protection market you just deployed. See this guide on how to [Buy protection programmatically](/for-developers/guides/how-do-i-buy-protection-programmatically#borrow-funds). Note: a user must have already deposited collateral for the borrow to succeed!
2. Follow the same logic your app usually does for entering into a new position, for the amount that was borrowed.

### Tracking an investing position

To track the performance of the investing position, you’ll need data on both the borrow-side and invest-side of the position (from the Cozy market side and other DeFi protocol side, respectively).

The [Cozy Subgraph](https://thegraph.com/hosted-service/subgraph/cozy-finance/cozy) supplies all the data for borrow-side. For example, the user’s collateral balance, how much borrowing power they have and their protected borrow balance can all be found in the Cozy Subgraph.

The subgraph automatically indexes all Cozy protection markets and indexes all positions which are opened on those markets. In the subgraph, these are represented by `Market` & `AccountCToken` entities.

Please see discussion of these two entities below, but for additional information consult the comments in the Schema panel of the [subgraph’s page](https://thegraph.com/hosted-service/subgraph/cozy-finance/cozy).

#### Markets

The `Market` entity holds a lot of critical information for presenting a Cozy protection market including:

* Basic descriptive data: the name, symbol, underlying of the market and associated trigger contract address
* Key numbers used by the protocol: borrow cap, exchange rate, borrow rate

| **Selected Market Fields** | **Description**                                                                                                                                                                                                                        |
| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| borrowCap                  | String. Total cumulative amount in human-readable units of underlying that can be borrowed from a market at one time                                                                                                                   |
| borrowRate                 | String. The annualized interest rate in decimal form users must pay to borrow from a market                                                                                                                                            |
| exchangeRate               | String. The exchange rate of underlying / receipt token in decimal form                                                                                                                                                                |
| cash                       | String. The amount in human-readable underlying available to be borrowed on a market. Any borrow transactions greater than the available cash in the market will fail.                                                                 |
| collateralFactor           | String. Factor applied to the supplied funds of a money market that determines how much funds can be borrowed by that account (i.e. If $100 was supplied to a money market with a 0.75 collateral factor, that account can borrow $75) |

#### AccountCTokens

The `AccountCToken` entity represents a position opened by a user on a protection market. It includes data on:

* Current balances of the position: the cToken balance and the stored borrow balance
* Historical tabulations for this user in the market: total underlying borrowed, repaid, supplied or redeemed

| **Selected AccountCTokens Fields** | **Description**                                                                                                                                                                              |
| ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| cTokenBalance                      | String. The receipt token balance of this position in human-readable units                                                                                                                   |
| enteredMarket                      | Boolean. Whether the user’s supplied funds should be used as collateral for other borrows (see guide on supplying collateral)                                                                |
| storedBorrowBalance                | String. Current borrow balance stored in the protocol contracts in human-readable units (excludes interest since last accrual block; see calculations below to get up-to-date borrowBalance) |

#### Key calculations

To calculate the borrow balance of a position in underlying:

```javascript
const borrowBalanceUnderlying =
  position.storedBorrowBalance * market.borrowIndex /
  position.accountBorrowIndex;
```

To calculate the supply balance of a position in underlying:

```javascript
const supplyBalanceUnderlying = position.cTokenBalance * market.exchangeRate;
```

### Exiting a position

To close out a position, follow the opposite steps to opening it:

1. Follow the normal steps for closing a position in your protocol.
2. Repay the Cozy protection market using the funds just received from closing the position on your protocol. For details on repaying debt on Cozy, please consult the [Repay Debt](/for-developers/guides/how-do-i-manage-protection-programmatically#repay-debt) section of the [Manage protection programmatically](/for-developers/guides/how-do-i-manage-protection-programmatically) guide.


# Create an invest/divest contract

Learn how to create an invest/divest contract for an investment opportunity.

## Create an invest/divest contract

Invest/divest smart contracts are used to programmatically borrow from Cozy protection markets and/or Cozy unprotected money markets and invest into DeFi products for investors in on-chain protocols, such as [Yearn Finance](https://yearn.finance/#/home).

At a high-level, the contract needs the following `external` functions to be implemented:

1. `invest`: Automates borrowing from Cozy markets and investing the borrowed funds in a DeFi product.
2. `divest`: Automates closing positions in a DeFi product that were opened with the contract's `invest` function and repays debt in the Cozy market.
3. `claimRewards`: If the investment opportunity accrues reward tokens, this function is required to claim them and transfer them to the investor's wallet.

Additionally, invest/divest contracts are intended to be used by delegatecalling to them from a proxy wallet to borrow, invest, and divest on behalf of the user. This means these contracts **cannot** be used directly with EOAs, as EOAs cannot execute code and therefore the investments will occur on behalf of the invest contract, and not on behalf of the user.

At Cozy, we use [DSProxy wallets](https://github.com/dapphub/ds-proxy) alongside a `DSProxyMulticall` helper contract which allows batched execution of a sequence of contract calls, without the need for deploying a new "script" contract for each sequence (additional context can be found in `DSProxyMulticall.sol` in the [Cozy Developer Guides](https://github.com/Cozy-Finance/cozy-developer-guides)). The address of the `DSProxyMultiCall` contract can be found in the [Cozy Subgraph](https://thegraph.com/hosted-service/subgraph/cozy-finance/cozy?query=Market%20List).

{% hint style="info" %}
The contract examples shown throughout this document can be referenced from the `CozyInvestCurve3CryptoEth.sol` and `CozyInvestConvex.sol` contracts in the [Cozy Developer Guides](https://github.com/Cozy-Finance/cozy-developer-guides) repository. `CozyInvestCurve3CryptoEth.sol` is an example of investing with ETH, and `CozyInvestConvex.sol` is an example of investing with ERC20 tokens.
{% endhint %}

{% hint style="info" %}
Everything in this guide assumes that you have experience with JavaScript, [ethers.js](https://github.com/ethers-io/ethers.js/), and [Solidity](https://docs.soliditylang.org/en/latest/).
{% endhint %}

### Contracts used by an invest/divest contract <a href="#step-1-trigger-contract-setup" id="step-1-trigger-contract-setup"></a>

An invest/divest contract needs to know the addresses of a few contracts found on the [Cozy Subgraph](https://thegraph.com/hosted-service/subgraph/cozy-finance/cozy?query=Market%20List):

* The address of the protection market contract to borrow from.
* If the underlying asset of the protection market is Ether (ETH), the address of the Maxmillion contract is required. The Maximillion contract is used to repay ETH debt to the protection market.
  * *Note*: Cozy uses `0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE` as the address the represent ETH.
* *Optional*: If you'd like to support unprotected investing, the address of the unprotected money market to borrow from.

In addition to the above, any contracts specific to investing and divesting from the target DeFi product are required (ie: a Curve liquidity pool, a Yearn Vault, etc.).

### Interfaces required for Cozy contracts

The following snippet includes interfaces for interacting with Cozy contracts required for borrowing.

{% code title="ICozy.sol" %}

```typescript
pragma solidity ^0.8.9;

interface ICozyShared {
  function underlying() external view returns (address);

  function borrow(uint256 borrowAmount) external returns (uint256);

  function borrowBalanceCurrent(address account) external returns (uint256);
}

// @dev Interface for a Cozy market with an ERC20 token underlying
interface ICozyToken is ICozyShared {
  function repayBorrowBehalf(address borrower, uint256 repayAmount) external returns (uint256);

  function repayBorrow(uint256 repayAmount) external returns (uint256);
}

// @dev Interface for a Cozy market with ETH underlying
interface ICozyEther is ICozyShared {
  function repayBorrowBehalf(address borrower) external payable;
}

// @dev Interface for the Maximillion contract used to repay ETH borrows
interface IMaximillion {
  function repayBehalfExplicit(address borrower, ICozyEther market) external payable;
}
```

{% endcode %}

### Develop the invest/divest contract constructor

The constructor for the invest/divest contract should be used to initialize any declared state variables required by the contract logic that were not initialized at the time they were declared. The state variables required may vary between different investment opportunities, but there are a few that should always be initialized:

* The protection market contract address to borrow from.
* If the underlying asset is ETH, the Maximillion contract address to repay borrows with.

The following snippet is an example of a constructor for an invest/divest contract for borrowing ETH from a market and investing into the [Curve](https://curve.fi) tricrypto pool.

{% code title="CozyInvestCurve3CryptoEth.sol" %}

```typescript
/**
 * @notice On-chain scripts for borrowing from a Cozy Curve 3Crypto Trigger protection market or 
 * ETH money market and using that ETH to add liquidity to the Curve tricrypto USDT/WBTC/WETH pool
 * @dev This contract is intended to be used by delegatecalling to it from a DSProxy
 */
contract CozyInvestCurve3CryptoEth {
  /// @dev OpenZeppelin's Address and SafeERC20 implementations are used for addresses and ERC20 tokens
  using Address for address payable;
  using SafeERC20 for IERC20;

  /// @notice Cozy protection market with ETH underlying to borrow from: Curve 3Crypto Trigger
  address public immutable protectionMarket;

  /// @notice Cozy unprotected money market with ETH underlying
  address public immutable moneyMarket;

  /// @notice Curve 3Crypto Deposit Zap -- helper contract for wrapping ETH before depositing
  ICrvDepositZap public immutable depositZap;

  /// @notice Curve 3Crypto Liquidity Gauge -- contract for measuring liquidity provided over time
  /// and distributing reward tokens
  ICrvGauge public immutable gauge;

  /// @notice Curve 3Crypto receipt token
  IERC20 public immutable curveLpToken;

  /// @notice Maximillion contract for repaying ETH debt
  IMaximillion public immutable maximillion;

  /// @dev Index of WETH in the curve `coins` mapping
  uint256 internal constant ethIndex = 2;

  constructor(
    address _moneyMarket,
    address _protectionMarket,
    address _maximillion,
    address _depositZap,
    address _gauge
  ) {
    moneyMarket = _moneyMarket;
    protectionMarket = _protectionMarket;
    maximillion = IMaximillion(_maximillion);
    gauge = ICrvGauge(_gauge);

    depositZap = ICrvDepositZap(_depositZap);
    curveLpToken = IERC20(depositZap.token());
  }

  ...
```

{% endcode %}

*Note*: The contract above uses the constructor to initalize state variables for required contract addresses to allow re-use among different chains; this is not required.

### Develop the invest logic

The `invest` function logic should automate borrowing from a valid protection market and investing the borrowed funds into a DeFi product.

The following snippet is an example of an `invest` function on an invest/divest contract for borrowing ETH and investing the borrowed ETH into the [Curve](https://curve.fi) tricrypto pool.

{% code title="CozyInvestCurve3CryptoEth.sol" %}

```typescript
/**
 * @notice Protected invest method for borrowing from given cozy ETH market,
 * and using that ETH to add liquidity to the Curve 3Crypto pool
 * @param _ethMarket Address of the market to borrow ETH from
 * @param _borrowAmount Amount of ETH to borrow and deposit into Curve
 * @param _curveMinAmountOut The minAmountOut we expect to receive when adding liquidity to Curve
 */
function invest(
  address _ethMarket,
  uint256 _borrowAmount,
  uint256 _curveMinAmountOut
) external payable {
  require(_ethMarket == moneyMarket || _ethMarket == protectionMarket, "Invalid borrow market");
  ICozyEther _market = ICozyEther(_ethMarket);

  // Borrow ETH from Cozy market. The return value from this method is an error code,
  // where a value of zero indicates no error (i.e. the borrow was successful)
  require(_market.borrow(_borrowAmount) == 0, "Borrow failed");

  // Add liquidity to Curve, which gives the caller a receipt token and returns the amount of receipt tokens received
  uint256 _balance = depositZap.add_liquidity{value: _borrowAmount}(
    [0, 0, _borrowAmount],
    _curveMinAmountOut,
    address(this)
  );

  // Approve the Curve tricrypto liquidity gauge to spend our receipt tokens using the safeApprove method. 
  // As mentioned in ERC-20, allowance is set to 0 first to prevent attack vectors 
  // on the approve method (https://eips.ethereum.org/EIPS/eip-20#approve). This is explicitly required by
  // some ERC-20 tokens, such as USDT.
  curveLpToken.safeApprove(address(gauge), 0);
  curveLpToken.safeApprove(address(gauge), type(uint256).max);

  // Deposit lp tokens in to liquidity gauge to earn reward tokens
  gauge.deposit(_balance);
}
```

{% endcode %}

Let's decompose the `CozyInvestCurve3CryptoEth.sol` snippet above:

1. An error check to ensure that a valid market is requested to be borrowed from. In this case, unprotected borrowing is also supported (optional).
2. Borrow from the market, wrapped within an error check to ensure the borrow was successful. *Note*: The borrow will fail if there is insufficient collateral supplied to the market by the sender for the desired borrow amount.
3. Logic specific to Curve for adding ETH liquidity to a pool and staking Curve LP tokens.

### Develop the divest logic

The `divest` function logic should automate closing positions in a DeFi product that were entered with the contract's `invest` function, repaying borrowed funds to Cozy markets, and transfering any earnings to the investor's wallet.

#### Logic for divesting ETH

The following snippet is an example of a `divest` function on an invest/divest contract for borrowing ETH and investing the borrowed ETH into the [Curve](https://curve.fi) tricrypto pool.

{% code title="CozyInvestCurve3CryptoEth.sol" %}

```typescript
/**
 * @notice Protected divest method for closing a position opened using this contract's `invest` method
 * @param _ethMarket Address of the market to repay ETH to
 * @param _recipient Address where any leftover ETH should be transferred
 * @param _redeemAmount Amount of Curve receipt tokens to redeem
 * @param _curveMinAmountOut The minAmountOut we expect to receive when removing liquidity from Curve
 */
function divest(
  address _ethMarket,
  address _recipient,
  uint256 _redeemAmount,
  uint256 _curveMinAmountOut
) external payable {
  require(_ethMarket == moneyMarket || _ethMarket == protectionMarket, "Invalid borrow market");

  ICozyEther _market = ICozyEther(_ethMarket);

  // Withdraw lp tokens from liquidity gauge
  gauge.withdraw(_redeemAmount);

  // Approve Curve's depositZap to spend our receipt tokens using the safeApprove method.
  // As mentioned in ERC-20, allowance is set to 0 first to prevent attack vectors 
  // on the approve method (https://eips.ethereum.org/EIPS/eip-20#approve). This is explicitly required by
  // some ERC-20 tokens, such as USDT.
  curveLpToken.safeApprove(address(depositZap), 0);
  curveLpToken.safeApprove(address(depositZap), type(uint256).max);

  // Withdraw from Curve
  depositZap.remove_liquidity_one_coin(_redeemAmount, ethIndex, _curveMinAmountOut, address(this));

  // Pay back as much of the borrow as possible, excess ETH is refunded to `recipient`. Maximillion handles
  // error codes when repayment is unsuccessful.
  maximillion.repayBehalfExplicit{value: address(this).balance}(address(this), _market);

  // Transfer any remaining funds to the user
  payable(_recipient).sendValue(address(this).balance);

  // Claim reward tokens from liquidity gauge and transfer to the user
  claimRewards(_recipient);
}
```

{% endcode %}

Let's decompose the `CozyInvestCurve3CryptoEth.sol` snippet above:

1. An error check to ensure that a valid market is requested to repay debt to. In this case, unprotected borrowing is also supported (optional).
2. Logic specific to Curve for closing the investment position; unstaking Curve LP tokens and withdrawing liquidity from Curve (in this case, ETH).
3. Cozy market debt repayment. Any remaining funds after repayment are transferred to the user. In this case, the underlying asset is ETH, so the Maximillion contract is used which includes error code handling.
4. Curve reward tokens are claimed and transferred to the user. This is only required for investment opportunities that accrue rewards.

#### Logic for divesting ERC20 tokens

There are a few notable differences for divesting ERC20 tokens, as shown in the following example of a `divest` function on an invest/divest contract for borrowing WBTC and depositing the borrowed WBTC into the [Curve](https://curve.fi) TBTC pool for receipt tokens, then staking the receipt tokens in the [Convex](https://www.convexfinance.com) TBTC pool.

{% code title="CozyInvestConvex.sol" %}

```typescript
/**
  * @notice Protected divest method for exiting a position entered using this contract's `invest` method
  * @param _market Address of the market to repay debt to
  * @param _recipient Address where any leftover funds should be transferred
  * @param _withdrawAmount Amount of Curve receipt tokens to redeem
  * @param _excessTokens Quantity to transfer from the caller into this address to ensure
  * the borrow can be repaid in full.
  * @param _curveMinAmountOut The minAmountOut we expect to receive when removing liquidity from Curve
  */
function divest(
  address _market,
  address _recipient,
  uint256 _withdrawAmount,
  uint256 _excessTokens,
  uint256 _curveMinAmountOut
) external {
  require(_market == moneyMarket || _market == protectionMarket, "Invalid borrow market");

  // 1. Withdraw Curve receipt tokens from from Convex
  IConvexRewardManager _convexRewardManager = IConvexRewardManager(convexRewardManager);
  _convexRewardManager.withdrawAndUnwrap(_withdrawAmount, false);

  // 2. Withdraw from Curve
  // There are two kinds of curve zaps -- one requires curve pool to be specified in first argument.
  // Approve Curve's depositZap to spend our receipt tokens.
  // As mentioned in ERC-20, allowance is set to 0 first to prevent attack vectors on the approve 
  // method (https://eips.ethereum.org/EIPS/eip-20#approve). This is explicitly required by some 
  // ERC-20 tokens, such as USDT.
  IERC20(curveLpToken).safeApprove(curveDepositZap, 0);
  IERC20(curveLpToken).safeApprove(curveDepositZap, type(uint256).max);
  if (longSigFormat) {
    ICrvDepositZap(curveDepositZap).remove_liquidity_one_coin(
      curveLpToken,
      _withdrawAmount,
      curveIndex,
      _curveMinAmountOut
    );
  } else {
    ICrvDepositZap(curveDepositZap).remove_liquidity_one_coin(_withdrawAmount, curveIndex, _curveMinAmountOut);
  }

  // Pay back as much of the borrow as possible, excess is refunded to `recipient`
  executeMaxRepay(_market, address(underlying), _excessTokens);

  // Transfer any remaining tokens to the user after paying back borrow
  IERC20(underlying).transfer(_recipient, IERC20(underlying).balanceOf(address(this)));
  claimRewards(_recipient);
}
```

{% endcode %}

Let's decompose the `CozyInvestConvex.sol` snippet above:

1. An `_excessTokens` function parameter is supported, which allows the caller to transfer additional quantities of the underlying asset to repay borrows if the investment withdrawal does not fully cover the debt owed to the Cozy market.
2. An error check to ensure that a valid market is requested to repay debt to. In this case, unprotected borrowing is also supported (optional).
3. Logic specific to Convex and Curve for closing the investment position; unstaking Curve LP tokens in Convex and withdrawing liquidity from Curve (in this case, WBTC).
4. Cozy market debt repayment. Any remaining funds after repayment are transferred to the user. For ERC20 tokens, make sure to include error code checks for repaying borrows. In this case, we use a custom defined `executeMaxRepay` function which includes the error check and supports debt repayment with `_excessTokens`.

   ```
    /**
    * @notice Repays as much token debt as possible
    * @param _market Market to repay
    * @param _underlying That market's underlying token (can be obtained by a call, but passing it in saves gas)
    * @param _excessTokens Quantity to transfer from the caller into this address to ensure
    * the borrow can be repaid in full. Only required if you want to repay the full borrow amount and the
    * amount obtained from withdrawing from the invest opportunity will not cover the full debt. A value of zero
    * will not attempt to transfer tokens from the caller, and the transfer will not be attempted if it's not required
    */
    function executeMaxRepay(
      address _market,
      address _underlying,
      uint256 _excessTokens
    ) internal {
      // Pay back as much of the borrow as possible, excess is refunded to `recipient`
      uint256 _borrowBalance = ICozyToken(_market).borrowBalanceCurrent(address(this));
      uint256 _initialBalance = IERC20(_underlying).balanceOf(address(this));
      if (_initialBalance < _borrowBalance && _excessTokens > 0) {
        TransferHelper.safeTransferFrom(_underlying, msg.sender, address(this), _excessTokens);
      }
      uint256 _balance = _initialBalance + _excessTokens; // this contract's current balance
      uint256 _repayAmount = _balance >= _borrowBalance ? type(uint256).max : _balance;

      // Approve the market to spend the repay amount in the given underlying token
      TransferHelper.safeApprove(_underlying, address(_market), _repayAmount);

      // Repay borrow to the Cozy market. The return value from this method is an error code,
      // where a value of zero indicates no error (i.e. the repay was successful)
      require(ICozyToken(_market).repayBorrow(_repayAmount) == 0, "Repay failed");
    }
   ```
5. Any remaining underlying tokens (in this case, WBTC) are transferred to the user after debt repayment.
6. Convex reward tokens are claimed and transferred to the user. This is only required for investment opportunities that accrue rewards.

### Develop the reward claim logic

If the investment opportunity accrues rewards, this function is required to claim them and transfer them to the investor's wallet. This function should also be used in the `divest` function.

The following snippet is an example of a `claimRewards` function on an invest/divest contract for claiming staking rewards from [Curve](https://curve.fi).

{% code title="CozyInvestCurve3CryptoEth.sol" %}

```typescript
/**
 * @notice Method to claim reward tokens from Curve and transfer to recipient
 * @param _recipient Address of the owner's wallet
 */
function claimRewards(address _recipient) public {
  gauge.claim_rewards(address(this), _recipient);
}
```

{% endcode %}

### Testing

When writing tests for invest/divest contracts, some setup is required in your test suite to replicate production behaviour. The following steps should be implemented in your test suite setup fixture:

1. Deploy the new invest/divest contract.
2. Deploy a proxy wallet. Cozy uses a proxy wallet for all borrows and investment opportunities.
3. Supply funds to the protection market used in the test suite.
4. Give the user's proxy wallet collateral so they can successfully borrow from Cozy markets.

Examples on how to implement the above in a development environment using JavaScript and [Hardhat](https://hardhat.org) can be found in the `CozyInvestCurve3CryptoEth.test.ts` and `CozyInvestConvex.test.ts` files in the [Cozy Developer Guides](https://github.com/Cozy-Finance/cozy-developer-guides) repository. The test suites in these examples also include examples of test cases.

Once there is sufficient test coverage, you are ready to deploy your new invest/divest contract.


# Error codes

Explanation of what error codes are and how to handle them in your code

## Introduction

Like Compound, just because a transaction was successful does not mean it actually did what we expected. Cozy inherited some of Compound's error handling approaches, which means a transaction may be successful—and show as successful on Etherscan and other block explorers—but in reality it didn't succeed. This is because some failed transactions will return an error code and emit a `Failure` event instead of reverting. You can find Compound's error codes [here](https://compound.finance/docs/ctokens#error-codes), and a brief history of why it's handled this way [here](https://www.comp.xyz/t/brief-history-of-error-handling-in-the-protocol/1169).

This approach can be a bit tedious for users and developers, as we now we have to manually ensure our transaction succeeded before continuing to the next step. In the [Cozy Developer Guides](https://github.com/Cozy-Finance/cozy-developer-guides/) repo you'll find a method called `findLog()` in the `utils/utils.ts` folder to help you with this.

This method searches for the expected success log in a transaction and returns it if found. If it's not found, an error is thrown and the `Failure` error codes are reported. You can compare those error codes to those in the table below to learn why your transaction failed.

Error codes are defined in `ErrorReporter.sol` and provided here for convenience.

## Comptroller

If an error code was emitted from a transaction to the Comptroller, refer to these error codes.

### Error Codes

Error codes 0–17 are identical to Compound's. Error codes 18 and 19 are unique to Cozy.

| Code | Name                              | Description                                                                                                  |
| ---- | --------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| 0    | `NO_ERROR`                        | Not a failure                                                                                                |
| 1    | `UNAUTHORIZED`                    | The sender is not authorized to perform this action.                                                         |
| 2    | `COMPTROLLER_MISMATCH`            | Liquidation cannot be performed in markets with different comptrollers.                                      |
| 3    | `INSUFFICIENT_SHORTFALL`          | The account does not have sufficient shortfall to perform this action.                                       |
| 4    | `INSUFFICIENT_LIQUIDITY`          | The account does not have sufficient liquidity to perform this action.                                       |
| 5    | `INVALID_CLOSE_FACTOR`            | The close factor is not valid.                                                                               |
| 6    | `INVALID_COLLATERAL_FACTOR`       | The collateral factor is not valid.                                                                          |
| 7    | `INVALID_LIQUIDATION_INCENTIVE`   | The liquidation incentive is invalid.                                                                        |
| 8    | `MARKET_NOT_ENTERED`              | The market has not been entered by the account.                                                              |
| 9    | `MARKET_NOT_LISTED`               | The market is not currently listed by the comptroller.                                                       |
| 10   | `MARKET_ALREADY_LISTED`           | An admin tried to list the same market more than once.                                                       |
| 11   | `MATH_ERROR`                      | A math calculation error occurred.                                                                           |
| 12   | `NONZERO_BORROW_BALANCE`          | The action cannot be performed since the account carries a borrow balance.                                   |
| 13   | `PRICE_ERROR`                     | The comptroller could not obtain a required price of an asset.                                               |
| 14   | `REJECTION`                       | The comptroller rejects the action requested by the market.                                                  |
| 15   | `SNAPSHOT_ERROR`                  | The comptroller could not get the account borrows and exchange rate from the market.                         |
| 16   | `TOO_MANY_ASSETS`                 | Attempted to enter more markets than are currently supported.                                                |
| 17   | `TOO_MUCH_REPAY`                  | Attempted to repay more than is allowed by the protocol.                                                     |
| 18   | `INVALID_TRIGGER`                 | The Protection Market cannot be created because the trigger is not a valid trigger, or was already triggered |
| 19   | `PROTECTION_MARKET_FACTORY_ERROR` | The admin tried to set the Protection Market Factory to an invalid contract                                  |

### Failure Info

TODO

## Cozy Token

If an error code was emitted from a transaction to a Cozy Token, refer to these error codes.

### Error Codes

| Code | Description                      |   |
| ---- | -------------------------------- | - |
| 0    | `NO_ERROR`                       |   |
| 1    | `UNAUTHORIZED`                   |   |
| 2    | `BAD_INPUT`                      |   |
| 3    | `COMPTROLLER_REJECTION`          |   |
| 4    | `COMPTROLLER_CALCULATION_ERROR`  |   |
| 5    | `INTEREST_RATE_MODEL_ERROR`      |   |
| 6    | `INVALID_ACCOUNT_PAIR`           |   |
| 7    | `INVALID_CLOSE_AMOUNT_REQUESTED` |   |
| 8    | `INVALID_COLLATERAL_FACTOR`      |   |
| 9    | `MATH_ERROR`                     |   |
| 10   | `MARKET_NOT_FRESH`               |   |
| 11   | `MARKET_NOT_LISTED`              |   |
| 12   | `TOKEN_INSUFFICIENT_ALLOWANCE`   |   |
| 13   | `TOKEN_INSUFFICIENT_BALANCE`     |   |
| 14   | `TOKEN_INSUFFICIENT_CASH`        |   |
| 15   | `TOKEN_TRANSFER_IN_FAILED`       |   |
| 16   | `TOKEN_TRANSFER_OUT_FAILED`      |   |
| 17   | `INVALID_GUARDIAN`               |   |

### Failure Info

TODO

## Protection Market Factory

If an error code was emitted from a transaction to the Protection Market Factory, refer to these error codes.

### Error Codes

| Code | Name                        | Description |
| ---- | --------------------------- | ----------- |
| 0    | `NO_ERROR`                  |             |
| 1    | `UNAUTHORIZED`              |             |
| 2    | `INTEREST_RATE_MODEL_ERROR` |             |

### Failure Info

TODO

## Oracle

If an error code was emitted from a transaction to the Oracle, refer to these error codes.

### Error Codes

| Code | Name           | Description |
| ---- | -------------- | ----------- |
| 0    | `NO_ERROR`     |             |
| 1    | `UNAUTHORIZED` |             |

### Failure Info

TODO


# API reference

Reference information for the methods available in the Cozy protocol.

The main two contracts you use to interact with the Cozy protocol are:

* Cozy token contracts
* Cozy Comptroller contract

There are dedicated API reference sections for these core contracts that explain the key concepts and how to use the methods they provide. In addition to the API reference sections for Cozy tokens and the Comptroller, there is a separate full API reference for all contracts that are part of the Cozy protocol. For details about using the Cozy API, see the following sections:

* [Cozy tokens API reference](/for-developers/api-reference/cozy-tokens)
* [Comptroller API Rrference](/for-developers/api-reference/comptroller)
* [Full API reference](/for-developers/api-reference/full-api-reference)

{% hint style="info" %}
When reading the API references, note that any variable described as a *mantissa* is an 18 decimal number. For example, if a contract is storing the number 3.14 as a mantissa, the value in storage will be 3.14e18 = 3,140,000,000,000,000,000.
{% endhint %}


# Cozy tokens

API reference for Cozy tokens. Cozy tokens are a core contract in the Cozy protocol and each market is a unique instance of a Cozy token.

## Core methods

This section contains the primary methods for interacting with the Cozy protocol. Most methods in this section return a `uint256` value of zero (0) for a successful call, or return an [error code](/for-developers/error-codes) on a unsuccessful call. The main exceptions to this general rule are the methods that are part of the standard [ERC-20 specification](https://eips.ethereum.org/EIPS/eip-20), such as the `transfer` and `balanceOf` methods.

### Mint

You use the `mint` function to transfer assets from your wallet to any Cozy market. You can use the `mint` function when you want to do the following:

* supply funds to use as collateral for protected borrowing.
* deposit funds to provide protection and earn interest.

Depending on whether you are minting tokens or ETH, use one of the following function signatures:

```javascript
// For markets with tokens as underlying
function mint(uint256 amount) external returns (uint256);

// For markets with ETH as underlying
function mint() external payable;
```

For tokens, the `amount` is the number of tokens to supply, denominated in units of the underlying token. For ETH, instead of specifying an amount, you send ETH along with the transaction and `msg.value` is used in place of `amount`.

Before supplying a token, remember to `approve` the Cozy market. A successful `mint` call returns a value of zero and transfers Cozy tokens to the caller's wallet. The number of Cozy tokens the user receives is equal to the supplied amount divided by the [exchange rate](#exchange-rate).

### Redeem

You use the `redeem` method to redeem Cozy tokens for the underlying supplying funds. The amount of underlying received is equal to the number of Cozy tokens redeemed multiplied by the [exchange rate](#exchange-rate). There are two methods you can use to redeem tokens:

```javascript
// Specify amount to redeem denominated in amount of Cozy tokens
function redeem(uint256 redeemTokens) external returns (uint256);

// Specify amount to redeem denominated in amount of underlying
function redeemUnderlying(uint256 redeemAmount) external returns (uint256);
```

A successful redeem burns the caller's Cozy tokens, transfers a proportional amount of the underlying asset, and returns a value of zero.

### Borrow

After supplying collateral with the `mint` method, you can use the `borrow` method to borrow funds from the Cozy protocol. Borrowed funds accrue interest at the current [borrow rate](#borrow-rate). If a borrower has insufficient account liquidity, however, the borrowed funds can be liquidated.

The method for borrowing funds from a market is:

```javascript
function borrow(uint256 borrowAmount) external returns (uint256);
```

where `borrowAmount` is specified in units of the token to borrow.

### Repay debt

You can use either the `repayBorrow` or `repayBorrowBehalf` function to repay borrowed funds as follows:

```javascript
// --- For markets with tokens as underlying ---
// Repays `repayAmount` of the underlying for `msg.sender`
function repayBorrow(uint256 repayAmount) external returns (uint256);

// Repays `repayAmount` of the underlying for `borrower`
function repayBorrowBehalf(address borrower, uint256 repayAmount) external returns (uint256);

// --- For markets with ETH as underlying ---
// Repays `msg.value` ETH for `msg.sender`
function repayBorrow() external payable;

// Repays `msg.value` ETH for `borrower`
function repayBorrowBehalf(address borrower) external payable;
```

To repay all token debt without leaving any dust, you can specify a `repayAmount` of`MAX_UINT256 = 2^256 - 1`.

To repay all ETH debt without leaving any dust, it is recommended to use a special helper contract called `Maximillion` and call the following method:

```javascript
function repayBehalfExplicit(address borrower, CEther cEther_) external payable;
```

where `borrower` is the address of the user to pay back debt for, and `cEther_` is the address of the market to pay back debt in (for example, the Cozy Ether money market, or a protection market with ETH as the underlying). When calling this method, send along more ETH than the debt amount, and after paying off the full debt, the excess ETH will be refunded.

The `Maximillion` contract is deployed on mainnet at [0xf859A1AD94BcF445A406B892eF0d3082f4174088](https://etherscan.io/address/0xf859A1AD94BcF445A406B892eF0d3082f4174088).

### Liquidate

You use the `liquidateBorrow` function to liquidate a user's assets when their account liquidity is negative. This action brings the user back to a solvent state. During a liquidation, the liquidator repays some or all of the user's borrow and, in return, receives a portion of their collateral, as Cozy tokens, at a discount.

The maximum portion of the borrow that can be liquidated is specified by the close factor in the Comptroller. As with mints and repays, liquidating pulls tokens from the caller, so the liquidator must `approve` the Cozy token contract before liquidating.

Liquidations can be executed with the following methods:

```javascript
// For markets with tokens as underlying
function liquidateBorrow(
    address borrower,
    uint256 repayAmount,
    CTokenInterface cTokenCollateral
) external returns (uint256);

// For markets with ETH as underlying
function liquidateBorrow(
    address borrower,
    CToken cTokenCollateral
) external payable;
```

where `borrower` is the account with a shortfall to liquidate and `cTokenCollateral` is the token being used by the borrower as collateral that the liquidator will receive. For token-based markets, `repayAmount` specifies how much of the borrowed asset to repay, and for ETH-based markets that amount is specified by `msg.value`.

### Transfer

All Cozy tokens are [ERC-20](https://eips.ethereum.org/EIPS/eip-20) compliant and can be transferred with both the `transfer` and `transferFrom` functions. They also implement [ERC-2612](https://eips.ethereum.org/EIPS/eip-2612) `permit` function to improve the approval flow.

{% hint style="info" %}
Token transfers fail if the transfer would put the account into an under-collateralized position.
{% endhint %}

## View methods

This section contains the primary methods for viewing information about Cozy markets.

### Exchange rate

Every Cozy token has it's own exchange rate, which is a function of the market's cash, borrows, reserves, and supply. This value is initialized to 0.02 when a market is created, and increases as the accrues interest. The exchange rate for a given market is calculated as:

```javascript
exchangeRate = ( getCash() + totalBorrows() - totalReserves() ) / totalSupply();
```

The exchange rate is represented as a mantissa (an 18 decimal number) with a precision of `18 + underlyingDecimals - cozyTokenDecimals`. For example, all Cozy tokens have 8 decimals. If the underlying token has 6 decimals, the initial exchange rate for that market would have 18 + 6 - 8 = 16 decimals. Querying the exchange rate of this market immediately after deployment would return `0.02e16 = 200000000000000`.

### Cash

Cash is the amount of the underlying token held by the Cozy token. You can read the cash held by the contract using the following function:

```javascript
function getCash() external view returns (uint256);
```

For markets with tokens as the underlying, this function returns the value of `underlyingToken.balanceOf(address(this));`. For markets with ETH as the underlying, the function returns `address(this).balance - msg.value`.

### Borrows

A market's total borrows is the amount of the underlying token actively borrowed. This amount is used when computing the accrued interest. It can be queried for a given market with the function below. When a market is triggered, this value is set to zero, so the below methods always returns zero after a trigger event.

```javascript
// View method which returns the last known borrow amount, `totalBorrows`
function totalBorrows() external view returns (uint256);

// Non-view method which accrues interest before returning `totalBorrows`.
// Because this version accrues interest first, it will be more up to date
function totalBorrowsCurrent() external returns (uint256);
```

The amount being borrowed by an individual user can be read with the method below. Both methods always returns a borrow balance of zero after a market is triggered.

```javascript
// View method which returns the last known borrow balance for `account`
function borrowBalanceStored(address account) external view returns (uint256);

// Non-view method which accrues interest before returning `borrowBalanceStored`.
// Because this version accrues interest first, it will be more up to date
function borrowBalanceCurrent(address account) external returns (uint256);
```

### Supply

A market's total supply is the number of Cozy tokens that have been minted and are currently in circulation. You can use the standard ERC-20 `totalSupply` method to return the number of Cozy tokens in a market as follows:

```javascript
function totalSupply() external view returns (uint256);
```

### Balances

To read a user's Cozy token balance, you can use the standard ERC-20 `balanceOf` method as follows:

```javascript
function balanceOf(address account) external view returns (uint256);
```

You can also read a user's balance with the `balanceOfUnderlying` function, which returns the user's Cozy token balance multiplied by the exchange rate.

```javascript
// Note that `balanceOfUnderlying` is not a view method
function balanceOfUnderlying(address account) external returns (uint256);
```

For example, if a user supplies 1000 USDC with an exchange rate of 0.02, she receives `1000 / 0.02 = 50,000` Cozy tokens. Calling `balanceOf` will return 50,000e8, and calling `balanceOfUnderlying` will return 1000e6, since Cozy tokens have 8 decimals and USDC has 6 decimals).

### Interest rates

You can use the `borrowRatePerBlock` function to read the current interest rate accrued by borrowers every block.

```javascript
function borrowRatePerBlock() external view returns (uint256);
```

The supply-rate-per-block is a function of the borrow-rate-per-block, as well the market's reserve factor and the its utilization rate. The utilization rate is the ratio of borrowed funds to supplied funds, calculated as `borrows / (cash + borrows - reserves)`. The supply rate is then calculated as `utilizationRate * (borrowRatePerBlock * (1 - reserveFactor))`. You can query this value as follows:

```javascript
function supplyRatePerBlock() external view returns (uint256);
```

Both the borrow rate and supply rate returned from these methods will always be zero after a market is triggered.

### Reserves

A portion of interest accrued from borrowers is set aside as cash, and cash from this source is known as reserves. The amount of reserves set aside is determined by the reserve factor. You can use the `reserveFactorMantissa` method to return the reserve factor. See the [Interest Rates](#interest-rates) section for more information on how the reserve factor is used.

```javascript
// Returns a mantissa, so it's scaled by 1e18
function reserveFactorMantissa() external view returns (uint256)
```

The total reserves in a given market can be read with:

```javascript
function totalReserves() external view returns (uint256)
```

Reserves can be withdrawn or transferred by the protocol administrator.

## Events

This sections contains the core events emitted by Cozy token contracts, and is not a comprehensive list.

```javascript
// Emitted when interest is accrued
event AccrueInterest(uint256 cashPrior, uint256 interestAccumulated, uint256 borrowIndex, uint256 totalBorrows);

// Emitted when tokens are minted
event Mint(address minter, uint256 mintAmount, uint256 mintTokens);

// Emitted when tokens are redeemed
event Redeem(address redeemer, uint256 redeemAmount, uint256 redeemTokens);

// Emitted when underlying is borrowed
event Borrow(address borrower, uint256 borrowAmount, uint256 accountBorrows, uint256 totalBorrows);

// Emitted when a borrow is repaid
event RepayBorrow(address payer, address borrower, uint256 repayAmount, uint256 accountBorrows, uint256 totalBorrows);

// Emitted when a borrow is liquidated
event LiquidateBorrow(
  address liquidator,
  address borrower,
  uint256 repayAmount,
  address cTokenCollateral,
  uint256 seizeTokens
);

// Emitted when trigger status is set. This is emitted once at
// construction and one more time when the trigger is toggled
event TriggerSet(bool isTriggered);
```

## Error handling

This section contains information about error codes and failure messages that may be returned when calling methods on a Cozy token contract.

### Error codes

The table below contains a list of error codes that may be returned when calling methods on a Cozy token contract.

| Code | Name                             | Description                                                          |
| ---- | -------------------------------- | -------------------------------------------------------------------- |
| 0    | `NO_ERROR`                       | Call succeeded                                                       |
| 1    | `UNAUTHORIZED`                   | Caller is not authorized                                             |
| 2    | `BAD_INPUT`                      | Caller provided bad arguments                                        |
| 3    | `COMPTROLLER_REJECTION`          | The Comptroller blocked this action                                  |
| 4    | `COMPTROLLER_CALCULATION_ERROR`  | A calculation failed in the Comptroller                              |
| 5    | `INTEREST_RATE_MODEL_ERROR`      | An invalid value was returned from the interest rate model           |
| 6    | `INVALID_ACCOUNT_PAIR`           | The borrower and liquidator are the same account                     |
| 7    | `INVALID_CLOSE_AMOUNT_REQUESTED` | The `MAX_UINT256` is passed as the `repayAmount` during liquidation  |
| 8    | `INVALID_COLLATERAL_FACTOR`      | Provided collateral factor is not allowed                            |
| 9    | `MATH_ERROR`                     | An error occurred in a math operation                                |
| 10   | `MARKET_NOT_FRESH`               | The market has not properly accrued interest                         |
| 11   | `MARKET_NOT_LISTED`              | The market is not supported by the Comptroller                       |
| 12   | `TOKEN_INSUFFICIENT_ALLOWANCE`   | Caller has not approved the contract to spend enough tokens          |
| 13   | `TOKEN_INSUFFICIENT_BALANCE`     | Caller has an insufficient token balance to complete the transaction |
| 14   | `TOKEN_INSUFFICIENT_CASH`        | The market does not have enough cash at this time                    |
| 15   | `TOKEN_TRANSFER_IN_FAILED`       | ERC-20 token transfer to the market failed                           |
| 16   | `TOKEN_TRANSFER_OUT_FAILED`      | ERC-20 token transfer from the market failed                         |
| 17   | `INVALID_GUARDIAN`               | Reserve guardian cannot be the zero address                          |

### Failure codes and logged messages

The table below contains a list of error codes that may be emitted in `Failure` logs when calling methods on a Cozy token contract. These codes are descriptive so no additional description is provided.

| Code | Name                                                         |
| ---- | ------------------------------------------------------------ |
| 0    | `ACCEPT_ADMIN_PENDING_ADMIN_CHECK`                           |
| 1    | `ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED`    |
| 2    | `ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED`             |
| 3    | `ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED`        |
| 4    | `ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED`       |
| 5    | `ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED`      |
| 6    | `ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED`  |
| 7    | `BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED`              |
| 8    | `BORROW_ACCRUE_INTEREST_FAILED`                              |
| 9    | `BORROW_CASH_NOT_AVAILABLE`                                  |
| 10   | `BORROW_FRESHNESS_CHECK`                                     |
| 11   | `BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED`                |
| 12   | `BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED`       |
| 13   | `BORROW_MARKET_NOT_LISTED`                                   |
| 14   | `BORROW_COMPTROLLER_REJECTION`                               |
| 15   | `LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED`                    |
| 16   | `LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED`                |
| 17   | `LIQUIDATE_COLLATERAL_FRESHNESS_CHECK`                       |
| 18   | `LIQUIDATE_COMPTROLLER_REJECTION`                            |
| 19   | `LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED`        |
| 20   | `LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX`                         |
| 21   | `LIQUIDATE_CLOSE_AMOUNT_IS_ZERO`                             |
| 22   | `LIQUIDATE_FRESHNESS_CHECK`                                  |
| 23   | `LIQUIDATE_LIQUIDATOR_IS_BORROWER`                           |
| 24   | `LIQUIDATE_REPAY_BORROW_FRESH_FAILED`                        |
| 25   | `LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED`                   |
| 26   | `LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED`                   |
| 27   | `LIQUIDATE_SEIZE_COMPTROLLER_REJECTION`                      |
| 28   | `LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER`                     |
| 29   | `LIQUIDATE_SEIZE_TOO_MUCH`                                   |
| 30   | `MINT_ACCRUE_INTEREST_FAILED`                                |
| 31   | `MINT_COMPTROLLER_REJECTION`                                 |
| 32   | `MINT_EXCHANGE_CALCULATION_FAILED`                           |
| 33   | `MINT_EXCHANGE_RATE_READ_FAILED`                             |
| 34   | `MINT_FRESHNESS_CHECK`                                       |
| 35   | `MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED`                |
| 36   | `MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED`                   |
| 37   | `MINT_TRANSFER_IN_FAILED`                                    |
| 38   | `MINT_TRANSFER_IN_NOT_POSSIBLE`                              |
| 39   | `REDEEM_ACCRUE_INTEREST_FAILED`                              |
| 40   | `REDEEM_COMPTROLLER_REJECTION`                               |
| 41   | `REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED`                  |
| 42   | `REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED`                  |
| 43   | `REDEEM_EXCHANGE_RATE_READ_FAILED`                           |
| 44   | `REDEEM_FRESHNESS_CHECK`                                     |
| 45   | `REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED`              |
| 46   | `REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED`                 |
| 47   | `REDEEM_TRANSFER_OUT_NOT_POSSIBLE`                           |
| 48   | `REDUCE_RESERVES_ACCRUE_INTEREST_FAILED`                     |
| 49   | `REDUCE_RESERVES_ADMIN_CHECK`                                |
| 50   | `REDUCE_RESERVES_CASH_NOT_AVAILABLE`                         |
| 51   | `REDUCE_RESERVES_FRESH_CHECK`                                |
| 52   | `REDUCE_RESERVES_VALIDATION`                                 |
| 53   | `REPAY_BEHALF_ACCRUE_INTEREST_FAILED`                        |
| 54   | `REPAY_BORROW_ACCRUE_INTEREST_FAILED`                        |
| 55   | `REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED`        |
| 56   | `REPAY_BORROW_COMPTROLLER_REJECTION`                         |
| 57   | `REPAY_BORROW_FRESHNESS_CHECK`                               |
| 58   | `REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED` |
| 59   | `REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED`          |
| 60   | `REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE`                      |
| 61   | `SET_COLLATERAL_FACTOR_OWNER_CHECK`                          |
| 62   | `SET_COLLATERAL_FACTOR_VALIDATION`                           |
| 63   | `SET_COMPTROLLER_OWNER_CHECK`                                |
| 64   | `SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED`             |
| 65   | `SET_INTEREST_RATE_MODEL_FRESH_CHECK`                        |
| 66   | `SET_INTEREST_RATE_MODEL_OWNER_CHECK`                        |
| 67   | `SET_MAX_ASSETS_OWNER_CHECK`                                 |
| 68   | `SET_ORACLE_MARKET_NOT_LISTED`                               |
| 69   | `SET_PENDING_ADMIN_OWNER_CHECK`                              |
| 70   | `SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED`                  |
| 71   | `SET_RESERVE_FACTOR_ADMIN_CHECK`                             |
| 72   | `SET_RESERVE_FACTOR_FRESH_CHECK`                             |
| 73   | `SET_RESERVE_FACTOR_BOUNDS_CHECK`                            |
| 74   | `TRANSFER_COMPTROLLER_REJECTION`                             |
| 75   | `TRANSFER_NOT_ALLOWED`                                       |
| 76   | `TRANSFER_NOT_ENOUGH`                                        |
| 77   | `TRANSFER_TOO_MUCH`                                          |
| 78   | `ADD_RESERVES_ACCRUE_INTEREST_FAILED`                        |
| 79   | `ADD_RESERVES_FRESH_CHECK`                                   |
| 80   | `ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE`                      |
| 81   | `REDUCE_RESERVES_GUARDIAN_NOT_SET`                           |
| 82   | `TRIGGER_ACTIVATED_BEFORE_REDEEM_OR_BORROW`                  |


# Comptroller

API reference for the Comptroller, which is responsible for ensuring the safety of the protocol.

## Core methods

This section contains the primary methods for interacting with the Comptroller for the Cozy protocol.

### Create protection markets

Anyone can create new protection markets with the Comptroller's `deployProtectionMarket` methods. For more information on creating protection markets, see the [Create a protection Mmrket](/for-developers/guides/how-do-i-create-a-protection-market) guide.

### Entering and exiting markets

When supplying assets to a money market, those funds are not automatically available as collateral for borrowing. Instead, you must specify when you want supplied assets to be used as collateral. Telling the protocol you want to use a certain asset as collateral is known as "entering the market".

{% hint style="info" %}
All protection markets have collateral factors of zero, meaning funds supplied to protection markets cannot be used as collateral. Therefore, you should only explicitly enter markets for funds supplied to a money market.
{% endhint %}

To enter a market, call the `enterMarkets` method on the Comptroller, where `cTokens` is an array of Cozy money market addresses.

```javascript
function enterMarkets(address[] calldata cTokens) external returns (uint256[] memory);
```

When you no longer want to use supplied funds in a market as collateral, you can exit the market with the `exitMarket` method described below. Notice that you can enter multiple markets in a single transaction, but you can only exit one market per call. When exiting a market, your transaction will fail with an error code if you have an outstanding borrow balance in that market, or if exiting the market would result in insufficient [account liquidity](#account-liquidity).

```javascript
function exitMarket(address cTokenAddress) external returns (uint256);
```

Note that borrowing from a market automatically enters you into that market, since liquidity calculations loop through all entered markets to determine if you have sufficient account liquidity.

Both the `enterMarkets` method and the `exitMarket` methods return a `uint256` value of 0 for a successful call, and return an [error code](/for-developers/error-codes) for an unsuccessful call.

## View methods

This section contains the primary methods for viewing information managed by the Comptroller.

### Account assets

You can use the `getAssetsIn` method to return a list of markets that a user has [entered](#entering-and-exiting-markets). The method takes the user's address as an input and returns the full set of markets for the specified user in an array. The array of markets returned by this method is the full set of markets used for liquidity calculations.

```javascript
function getAssetsIn(address account) external view returns (CToken[] memory);
```

### Collateral factors

Every market has a collateral factor that represents how much borrow power is increased by when that market's assets are used as collateral. This collateral factor can range from 0% to 90% and can be interpreted as:

* A value of 0% means using that an asset cannot be used as collateral, as it gives you no borrowing power.
* A value of 90% means supplying $100 of that asset allows you to borrow up to $90 of another asset.

All protection markets have collateral factors of 0%, and money markets can have collateral factors anywhere in the 0–90% range.

You can retrieve the collateral factor for a given market with the following `markets` function by providing a Cozy token market address as input:

```javascript
function markets(address cTokenAddress) view returns (bool, uint256, bool)
```

The function returns the first `bool` value for the `isListed` property as `true` if the market is recognized by the Comptroller or `false` if it is not.

The `uint256` returned by the function is an 18 decimal number for the `collateralFactorMantissa` property described above. A value of 0.9 means that you can supply this market's assets as collateral to borrow up to 90% of the supplied value.

The second `bool` value is for the `isComped` property that is not currently used and can be safely ignored.

### Listed markets

You can use the `getAllMarkets` method to return an array of all Cozy token markets supported by the Comptroller as follows:

```javascript
function getAllMarkets() external view returns (CToken[] memory);
```

The addresses returned from this array can be directly passed as inputs to the `markets` function described in the [CollateralFactors](#collateral-factors) section to retrieve various metadata for the specified market.

### Account liquidity

Account liquidity specifies a user's borrowing power in USD. If you borrow too much (for example, if the value of your collateral falls), your account liquidity can fall below zero and can result in your account being liquidated.

Account liquidity is based on [all markets entered](#account-assets) by a user. For each of those assets, the collateral quantity is converted to USD and multiplied by that asset's collateral factor. Summing these values and subtracting current borrow balances results in the current account liquidity for a user.

You can query the account liquidity for a user as follows:

```javascript
function getAccountLiquidity(address account) external view returns (uint256, uint256, uint256);
```

The first `uint256` returned is zero on success or an [error code](/for-developers/error-codes) on failure.

If the account queried has positive account liquidity, that is, the user can borrow more assets, the second `uint256` will equal the user's account liquidity and the third `uint256` will equal zero. If the account queried has negative account liquidity, that is, the user has a shortfall and can be liquidated, the second `uint256` will be zero and the third `uint256` will equal the shortfall amount.

### Liquidation incentive

To incentivize liquidations of accounts that have a shortfall, the `liquidationIncentiveMantissa` method specifies additional collateral that liquidators receive. For example, if the liquidation incentive is 1.08e18, then liquidators receive 8% more collateral than the borrow amount they closed.

To illustrate how the incentive works, assume a liquidator repays $1000 worth of a user's borrows. If the liquidation incentive is 1.08e18, then the liquidator will receive $1000 \* 1.08 = $1080 of the user's collateral. The liquidation incentive is the same for all markets, and can be changed. You can read the current value as follows:

```javascript
function liquidationIncentiveMantissa() external view returns (uint256);
```

### Close factor

When liquidating an account, you cannot necessarily repay the full borrow amount and entirely liquidate the borrower. Instead, the close factor specifies what portion of their account can be repaid in a single liquidation. This value applies to individual borrowed assets, not the overall position. The close factor is the same for all markets, and can be changed. You can read the current value as follows:

```javascript
function closeFactorMantissa() external view returns (uint256);
```

## Events

This sections contains the core events emitted by the Comptroller, and is not a comprehensive list.

```javascript
// Emitted when a third party adds a protection market
event ProtectionMarketListed(CToken cToken, address trigger);

// Emitted when an account enters a market
event MarketEntered(CToken cToken, address account);

// Emitted when an account exits a market
event MarketExited(CToken cToken, address account);
```

## Error handling

This section contains information about error codes and failure messages that you might see when calling methods on the Comptroller.

### Error codes

The following table below contains a list of error codes that you might see when calling methods on the Comptroller.

| Code | Name                              | Description                                                                         |
| ---- | --------------------------------- | ----------------------------------------------------------------------------------- |
| 0    | `NO_ERROR`                        | Call succeeded                                                                      |
| 1    | `UNAUTHORIZED`                    | Caller is not authorized                                                            |
| 2    | `COMPTROLLER_MISMATCH`            | Cannot liquidate across markets with different comptrollers                         |
| 3    | `INSUFFICIENT_SHORTFALL`          | The account cannot be liquidated since it has no shortfall                          |
| 4    | `INSUFFICIENT_LIQUIDITY`          | Redeem or borrow not allowed because the account has insufficient liquidity         |
| 5    | `INVALID_CLOSE_FACTOR`            | Outdated, not used                                                                  |
| 6    | `INVALID_COLLATERAL_FACTOR`       | Cannot set new collateral factor, as specified value is invalid                     |
| 7    | `INVALID_LIQUIDATION_INCENTIVE`   | Outdated, not used                                                                  |
| 8    | `MARKET_NOT_ENTERED`              | Outdated, not used                                                                  |
| 9    | `MARKET_NOT_LISTED`               | The specified market is not listed by the Comptroller                               |
| 10   | `MARKET_ALREADY_LISTED`           | Specified market already exists                                                     |
| 11   | `MATH_ERROR`                      | An error occurred in a math operation                                               |
| 12   | `NONZERO_BORROW_BALANCE`          | Cannot exit market if borrow balance is above zero                                  |
| 13   | `PRICE_ERROR`                     | The Comptroller could not get a valid price for an asset                            |
| 14   | `REJECTION`                       | The Comptroller rejected the action specified by a Cozy token                       |
| 15   | `SNAPSHOT_ERROR`                  | Unable to read a user's account borrows and market exchange rate                    |
| 16   | `TOO_MANY_ASSETS`                 | Cannot enter a number of markets greater than \`maxAssets'                          |
| 17   | `TOO_MUCH_REPAY`                  | Cannot repay more than the protocol will allow                                      |
| 18   | `INVALID_TRIGGER`                 | The specified trigger is not valid so a protection market cannot be created with it |
| 19   | `PROTECTION_MARKET_FACTORY_ERROR` | The specified ProtectionMarketFactory address is not valid                          |

### Failure codes and logged messages

The following table below contains a list of error codes that may be emitted in `Failure` logs when calling methods on the Comptroller. These codes are descriptive so no additional description is provided.

| Code | Name                                           |
| ---- | ---------------------------------------------- |
| 0    | `ACCEPT_ADMIN_PENDING_ADMIN_CHECK`             |
| 1    | `ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK`  |
| 2    | `EXIT_MARKET_BALANCE_OWED`                     |
| 3    | `EXIT_MARKET_REJECTION`                        |
| 4    | `SET_CLOSE_FACTOR_OWNER_CHECK`                 |
| 5    | `SET_CLOSE_FACTOR_VALIDATION`                  |
| 6    | `SET_COLLATERAL_FACTOR_OWNER_CHECK`            |
| 7    | `SET_COLLATERAL_FACTOR_NO_EXISTS`              |
| 8    | `SET_COLLATERAL_FACTOR_VALIDATION`             |
| 9    | `SET_COLLATERAL_FACTOR_WITHOUT_PRICE`          |
| 10   | `SET_IMPLEMENTATION_OWNER_CHECK`               |
| 11   | `SET_LIQUIDATION_INCENTIVE_OWNER_CHECK`        |
| 12   | `SET_LIQUIDATION_INCENTIVE_VALIDATION`         |
| 13   | `SET_MAX_ASSETS_OWNER_CHECK`                   |
| 14   | `SET_PENDING_ADMIN_OWNER_CHECK`                |
| 15   | `SET_PENDING_IMPLEMENTATION_OWNER_CHECK`       |
| 16   | `SET_PRICE_ORACLE_OWNER_CHECK`                 |
| 17   | `SUPPORT_MARKET_EXISTS`                        |
| 18   | `SUPPORT_MARKET_OWNER_CHECK`                   |
| 19   | `SET_PAUSE_GUARDIAN_OWNER_CHECK`               |
| 20   | `SET_TRIGGER_CHECK`                            |
| 21   | `SET_PROTECTION_WITH_INVALID_UNDERLYING`       |
| 22   | `SET_PROTECTION_UNDERLYING_WITHOUT_PRICE`      |
| 23   | `SET_PROTECTION_MARKET_FACTORY_OWNER_CHECK`    |
| 24   | `SET_PROTECTION_MARKET_FACTORY_VALIDITY_CHECK` |
| 25   | `SET_RESERVE_GUARDIAN_OWNER_CHECK`             |


# Full API reference

API reference for all Cozy contracts

## Cozy Tokens

### CEther

### CErc20

### Shared

## Comptroller

The protocol's Comptroller is an instance of the `ComptrollerStatic` contract, which has the following interface.

## Chainlink Reporter

The `ChainlinkReporter` contract is the protocol's price oracle.

### Error Handling

#### Error Codes

| Code | Name           | Description              |
| ---- | -------------- | ------------------------ |
| 0    | `NO_ERROR`     | Call succeeded           |
| 1    | `UNAUTHORIZED` | Caller is not authorized |

#### Failure Info

| Code | Name                                |
| ---- | ----------------------------------- |
| 0    | `ACCEPT_ADMIN_PENDING_ADMIN_CHECK`  |
| 1    | `ADD_OR_UPDATE_ORACLES_OWNER_CHECK` |
| 2    | `SET_PENDING_ADMIN_OWNER_CHECK`     |

## Protection Market Factory

### Error Handling

#### Error Codes

| Code | Name                        | Description                           |
| ---- | --------------------------- | ------------------------------------- |
| 0    | `NO_ERROR`                  | Call succeeded                        |
| 1    | `UNAUTHORIZED`              | Caller is not authorized              |
| 2    | `INTEREST_RATE_MODEL_ERROR` | Invalid interest rate model specified |

#### Failure Info

| Code | Name                                             |
| ---- | ------------------------------------------------ |
| 0    | `SET_DEFAULT_INTEREST_RATE_MODEL_OWNER_CHECK`    |
| 1    | `SET_DEFAULT_INTEREST_RATE_MODEL_VALIDITY_CHECK` |


# Contract deployments

Cozy Protocol contract deployment addresses

{% tabs %}
{% tab title="Production" %}
The latest Cozy Protocol is deployed on mainnet at the addresses below.

| Contract                                      | Address                                                                                                                 |
| --------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| Cozy ETH Money Market                         | ​[0xF8ec0F87036565d6B2B19780A54996c3B03e91Ea](https://etherscan.io/address/0xF8ec0F87036565d6B2B19780A54996c3B03e91Ea)​ |
| Cozy DAI Money Market                         | ​[0xe6EF65EC40D943c3f675165B0b17e06862Fe3d82](https://etherscan.io/address/0xe6EF65EC40D943c3f675165B0b17e06862Fe3d82)​ |
| Cozy USDC Money Market                        | ​[0xdBDF2fC3Af896e18f2A9DC58883d12484202b57E](https://etherscan.io/address/0xdBDF2fC3Af896e18f2A9DC58883d12484202b57E)​ |
| Cozy WBTC Money Market                        | ​[0xf146c26136C1F80c9f0967d27BCb7E500D45681f](https://etherscan.io/address/0xf146c26136C1F80c9f0967d27BCb7E500D45681f)​ |
| Comptroller                                   | ​[0x895879B2c1Fbb6CCFcD101f2D3F3c76363664f92](https://etherscan.io/address/0x895879B2c1Fbb6CCFcD101f2D3F3c76363664f92)​ |
| Oracle                                        | ​[0x6f668117CaA90Ea73c27adC562f5A2A06CCA9092](https://etherscan.io/address/0x6f668117CaA90Ea73c27adC562f5A2A06CCA9092)​ |
| Cozy ETH Interest Rate Model                  | ​[0x3eC8e03BF8b67b7d793f2de6EB59045277D02831](https://etherscan.io/address/0x3eC8e03BF8b67b7d793f2de6EB59045277D02831)​ |
| Cozy DAI Interest Rate Model                  | ​[0xb7DB062cAAcdd0b74EFEb15026f46b792Ca5c75A](https://etherscan.io/address/0xb7DB062cAAcdd0b74EFEb15026f46b792Ca5c75A)​ |
| Cozy USDC Interest Rate Model                 | ​[0xb7DB062cAAcdd0b74EFEb15026f46b792Ca5c75A](https://etherscan.io/address/0xb7DB062cAAcdd0b74EFEb15026f46b792Ca5c75A)​ |
| Cozy WBTC Interest Rate Model                 | ​[0x47cef4AB8f68Da8156D705e0046A970b6b9cf3e8](https://etherscan.io/address/0x47cef4AB8f68Da8156D705e0046A970b6b9cf3e8)​ |
| Default Protection Market Interest Rate Model | ​[0x795cEf98568515D7Ed28Aec8dEaaa76b58b40a6C](https://etherscan.io/address/0x795cEf98568515D7Ed28Aec8dEaaa76b58b40a6C)​ |
| {% endtab %}                                  |                                                                                                                         |

{% tab title="Deprecated" %}
The prior, now deprecated Cozy Protocol is deployed on mainnet at the addresses below.

| Contract                                      | Address                                     |
| --------------------------------------------- | ------------------------------------------- |
| Cozy ETH Money Market                         | 0x38B050b6f78c66a7dD9b336cD1Ff10fF2B9e9922  |
| Cozy DAI Money Market                         | 0xdcB99DFbe5368d7c2d671A9AE5C4164FF69D86D3  |
| Cozy USDC Money Market                        | 0xeEEE96017550c817643bB0e85EBEbc512e7A27BA  |
| Cozy WBTC Money Market                        | 0xA60ffbB5caAcA4d26Cb4326D82494163B1071Fc6  |
| Comptroller                                   | 0x349f0A62CE40055b70557e1173287469d601A1e0  |
| Oracle                                        | 0x6f668117CaA90Ea73c27adC562f5A2A06CCA9092  |
| Cozy ETH Interest Rate Model                  | 0x3eC8e03BF8b67b7d793f2de6EB59045277D02831  |
| Cozy DAI Interest Rate Model                  | 0xb7DB062cAAcdd0b74EFEb15026f46b792Ca5c75A  |
| Cozy USDC Interest Rate Model                 | 0xb7DB062cAAcdd0b74EFEb15026f46b792Ca5c75A  |
| Cozy WBTC Interest Rate Model                 | 0x47cef4AB8f68Da8156D705e0046A970b6b9cf3e8  |
| Default Protection Market Interest Rate Model | ​0x795cEf98568515D7Ed28Aec8dEaaa76b58b40a6C |
| {% endtab %}                                  |                                             |
| {% endtabs %}                                 |                                             |


# Get started

Depending on your interests and experience, you’ll want to explore different parts of the Cozy application and corresponding documentation.

## What is Cozy?

Cozy is an open-source protocol for automated and trust-minimized [Protection Markets](/staging/what-is-cozy/overview#what-are-protection-markets). Protection Markets allow you to provide and receive protection against predefined conditions like a loss of funds due to a smart contract hack. Anybody can create and use Protection Markets.

To learn more, visit the [Overview](/staging/what-is-cozy/overview).

## For Users

Learn about the protocol, how to get protection, and how to provide protection.

{% content-ref url="/pages/-MgMrf5EZlosiQYBLniA" %}
[Overview](/staging/what-is-cozy/overview)
{% endcontent-ref %}

{% content-ref url="/pages/-MgMrf5FxFsCXjqA7HtU" %}
[Case study](/staging/what-is-cozy/case-study)
{% endcontent-ref %}

{% content-ref url="/pages/-MgMrf5GA\_1bT59plbqx" %}
[FAQ](/staging/what-is-cozy/faq)
{% endcontent-ref %}

## For Developers

Learn how to programmatically create, provide, and purchase protections.

### Guides

{% content-ref url="/pages/-MgMrf5Q5E-OIzt3IN7r" %}
[Create a protection market](/staging/for-developers/guides/how-do-i-create-a-protection-market)
{% endcontent-ref %}

{% content-ref url="/pages/-MgMrf5RCxepCvdW359T" %}
[Buy protection programmatically](/staging/for-developers/guides/how-do-i-buy-protection-programmatically)
{% endcontent-ref %}

{% content-ref url="/pages/-MgMrf5S6n4JmNbxUGcc" %}
[Manage protection programmatically](/staging/for-developers/guides/how-do-i-manage-protection-programmatically)
{% endcontent-ref %}

{% content-ref url="/pages/-MgMrf5TM4Ei7VQkNmP3" %}
[Provide protection programmatically](/staging/for-developers/guides/providing-protection-programmatically)
{% endcontent-ref %}

{% content-ref url="/pages/-MgMrf5UA9g75YnSsiZ\_" %}
[Liquidate a vault](/staging/for-developers/guides/how-do-i-liquidate-a-vault)
{% endcontent-ref %}

{% content-ref url="/pages/IsaxGUgmFO1m37Zbo25b" %}
[Create a protected investing opportunity](/staging/for-developers/guides/create-a-protected-investing-opportunity)
{% endcontent-ref %}

{% content-ref url="/pages/AwO8UT7RWedBk0btC1Qs" %}
[Create an invest/divest contract](/staging/for-developers/guides/how-do-i-create-an-invest-divest-contract)
{% endcontent-ref %}

### Reference

{% content-ref url="/pages/-MgMrf5WuytiOJCcyHWy" %}
[API reference](/staging/for-developers/api-reference)
{% endcontent-ref %}

{% content-ref url="/pages/-MgMrf5\_21pPOkHE0--z" %}
[Contract deployments](/staging/for-developers/contract-deployments)
{% endcontent-ref %}


# Overview

Invest in decentralized financial markets with protection against risks like hacks and protocol vulnerabilities.

Cozy is an open-source protocol that enables investors to participate in automated and trust-minimized **protection markets**.

Protection markets mitigate the risks often associated with investing in decentralized financial (DeFi) markets and applications. Because DeFi application protocols might seem more vulnerable to hacks and exploitation than traditional financial instruments for some investors, Cozy provides a platform for protecting assets against losses programmatically. Investors with confidence in DeFi application security can use the Cozy platform to earn interest by supplying assets to a protection market.

The two key components of a protection market are:

* A money market with a **liquidity pool** of digital assets.
* A **trigger contract** that specifies a condition to protect the assets in the pool against.

There are three main ways to participate in a protection market:

* As a **protection market developer**, you create the trigger contract that protects assets if a specific **trigger condition**—such as a sudden, sharp decline in value—is met in one or more protocol markets.
* As a **protection market supplier**, you deposit assets to be used in a protection market pool and earn interest from borrowers who pay for the having their deposited asset protected against losses. If you think that a market is not likely to lose funds—that the trigger condition is unlikely to occur—you can use Cozy to earn interest by providing protection.
* As a **protection market borrower**, you deposit collateral and borrow against it with a reduced rate of return in exchange for protecting your deposit against the condition defined in the trigger contract. If you borrow from a protection market and the trigger condition is met, the collateral you deposited remains safe and any outstanding debt is cancelled.

![](https://3311836203-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MQOlThYns4gV0tad8h_-2777116370%2Fuploads%2Fgit-blob-2a6568ada93705239e1036fd27060be20dbbb7a4%2FGroup%209.png?alt=media)

For a closer look at how Cozy protection markets work, see [Case Study](/staging/what-is-cozy/case-study).

## Borrowing and investing

With protected borrowing and investing, you borrow assets in a protection market to protect your position against losses if the condition contained in the trigger contract occurs. You pay interest to receive this protection. If the trigger condition occurs, the collateral you deposited is safe. If you have any outstanding debt for borrowed assets, you no longer have to pay it back.

Participants in a protection market pay a small fee on their potential earnings to reduce the risk of holding a particular asset. For borrowers, debt cancellation is essentially the insured event that they have paid their premiums to guard against.

To get started with protected borrowing:

1. Open the [Cozy website](https://cozy.finance) in a browser.
2. Connect to your wallet.
3. Deposit collateral on the Your Funds page.
4. Click **Protected Borrowing** and select a protection market.
5. Borrow assets from that protection market.

   Borrowed assets are transferred to the your wallet.

   Borrowers pay an interest rate until they repay their borrowed assets. If the trigger condition is met, the debts are cancelled and borrowers can withdraw their collateral.

## Supplying assets

If you are confident that a condition contained in a trigger contract is unlikely to occur, you can supply assets to a protection market and earn interest from investors who borrow from the protection market.

You continue earning interest as long as the protection market operates without having its trigger condition occur. If there is a hack, exploit, or other problem that triggers protection in the market where you have supplied assets, all outstanding debts in that market are forgiven. The interest you earn is your reward for taking on the risk associated with the trigger condition. In evaluating the risk involved, you should consider how likely it will be for a particular market's trigger condition to be satisfied.

To get started with providing protection:

1. Open the [Cozy website](https://cozy.finance) in a browser.
2. Click **Provive Protection**.
3. Select a protection market.
4. Select an Asset to supply to the protection market.

   You earn interest until you withdraw your supplied assets.

   If the trigger condition is met, debts are cancelled and you can withdraw your share of the remaining funds in the protection market.

## Creating protection markets

You must be able to write a trigger contract to develop and deploy a protection market. You can learn how to write trigger contracts using the scripts in the [Cozy Developer Guides](https://github.com/Cozy-Finance/cozy-developer-guides) repository and the [Create a protectionmarket](/staging/for-developers/guides/how-do-i-create-a-protection-market) guide.


# Case study

How a Cozy protection market might have protected investors in the Pickle Finance DAI pool.

In November of 2020, [an exploit](https://decrypt.co/49149/pickle-finance-hack) drained nearly $20M in funds from the Pickle Finance DAI pool. Investors who had deposited funds in the Pickle DAI pool had no protection from the exploit and lost all of the funds they had deposited. If a Cozy protection market had been available, investors who chose to participate in the protection market would have been protected against the exploit. Instead of losing all of their funds, participants in the protection market would have limited their exposure and retained their original investment.

![](https://3311836203-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MQOlThYns4gV0tad8h_-2777116370%2Fuploads%2Fgit-blob-90da163be14f17ea0223a411b49351dd7bab40f9%2FCozy%20Case%20Study.jpg?alt=media)

Let's use the Pickle Finance DAI pool as a concrete example to illustrate how a Cozy protection market would have protected investors.

## Create a protection market

Before investors can participate in the protection market, someone needs to design, develop, and deploy a contract that protects an asset from an exploit. For this example, someone familiar with Pickle Finance decides to create a protection market for the Pickle Finance DAI pool.

The developer of the protection market must identity the condition that would trigger protection for deposited funds. In this example, the developer has decided that a 25%+ loss of funds in the pool would indicate a serious problem and should trigger protection. She expresses this condition by writing a `getPricePerFullShare()` function. If this function in the Pickle DAI pool contract returns a value less than `0.75`, the result would indicate a 25%+ loss of funds and trigger protection for the DAI pool.

In this example, there is only one trigger condition, but a protection market developer could add multiple trigger events to a trigger contract to make the protection it provides more robust or sophisticated. If any event occurs, protection is enabled. It is up to the protection market developer to identify the condition or set of conditions for which to offer protection in the trigger contract.

To learn more about creating trigger contracts and protection markets, visit [this guide](/staging/for-developers/guides/how-do-i-create-a-protection-market).

## Provide protection by supplying assets

People who want to bet against the condition—in this case, the Pickle DAI pool losing 25% of its value—supply capital to the protection market to earn an interest rate from users seeking protection. In this example, participants supply DAI. The protection market developer wants to earn interest by making the protection market available to borrowers and protection-seekers, so she supplies DAI assets to the pool.

## Get protection by paying interest

People who want protection for the Pickle DAI pool borrow DAI from the protection market and invest those assets into the Pickle DAI that offers protection. As protection-seekers, borrowers pay an interest rate for borrowing DAI from the pool. If the condition is met—in this example, the Pickle DAI pool losing 25% of its value—their debts are forgiven and their principal deposit remains safe.

## Receive protection if an exploit occurs

If an exploit like the one in November 2020 were to occur with the protection market in place, the `getPricePerFullShare()` function would return \~0 because all of the funds in the pool were drained in an attack. However, this change satisfies the condition that the protection market is in place to guard against and triggers the cancellation of all debts in the protected Pickle DAI pool.

If you had borrowed DAI from that protection market and invested that DAI into Pickle, you would have lost all of your DAI on Pickle, but would owe zero DAI back to Cozy. Your principal would be preserved.

## Summary

Cozy allows anybody to create and use protection markets. By using protection markets, you can provide and receive protection against any condition that can be defined on chain. This case study illustrates how a protection market could have protected investors against the insolvency of the Pickle DAI pool. Instead of losing all of their deposits in the exploit, Cozy users would have kept all of their principal.


# FAQ

If you can't find an answer to your question here, contact us on discord {{TODO:LINK}}.

If you can't find an answer to your question here, contact us on [discord](https://discord.com/invite/kK84saQYyg).

{% hint style="warning" %}
Under construction
{% endhint %}

## What is Cozy?

Cozy is an open-source protocol for automated and trust-minimized [protection markets](/staging/what-is-cozy/overview#what-are-protection-markets). Protection markets allow users to provide and receive protection against predefined conditions like loss of funds due to a smart contract hack.

## What is a protection market?

Conceptually, a **protection market** is what enables Cozy users and developers to get and provide protection against losses stemming from a specific **trigger condition**.

The main components that define a protection market are:

* A money market with a **liquidity pool** of digital assets with an **underlying token** for the market.
* A **trigger contract** that specifies an on-chain condition to protect the assets in the pool against.
* An **interest rate model** that determines the interest rate that borrowers pay.

The trigger contract for a protection market defines a **trigger condition** to check for. As long as the trigger condition has not occurred, the protection market borrowers and suppliers accrue interest. If the trigger condition occurs, the trigger contract is executed and any outstanding debts in the protection market are cancelled for protection borrowers.

To learn how to create a protection market, see [Create a protection market](/for-developers/guides/how-do-i-create-a-protection-market).

## How does protection work?

Users provide and get protection by participating in protection markets. Each protection market has a trigger contract that defines the condition users can provide and purchase protection against.

The **trigger condition** is an expression that, when evaluated, returns true if the trigger condition has occurred. If the trigger condition remains unchanged (that is, when evaluated, the trigger condition returns false), the protection market earns interest and collects payments from protection borrowers. If the trigger condition occurs, the trigger contract is executed and any outstanding debts in the protection market are cancelled for protection borrowers.

## What types of protection are available?

You can get and provide protection for any DeFi protocol that has a protection market. The specific conditions you are protected again depend on the trigger contract for the protection market in which you are interested.

If a protection market doesn't yet exist for the protocol or the type of protection you're interested in, you can create a new protection market.

## How much does protection cost?

Protection markets price protection based on utilization. Typically, the more demand there is for protection relative to supply, the higher the interest rate. However, creators of protection markets can set their own interest rate curves, so make sure to check how pricing works for the protection market you're interested in using.

## Who can create protection markets?

Anybody can create protection markets.

## What assets are supported?

You can use ETH, USDC, DAI, and WBTC.

## What fees does Cozy charge?

Each protection market takes a percentage of each interest payment. This fee is determined by the `Reserve Factor` just like in Compound. The `Reserve Factor` for each market is adjustable by governance and is held to backstop shortfall events in the protocol.

## Do you have a The Graph subgraph?

Yes. You can find our Mainnet deployment [here](https://thegraph.com/legacy-explorer/subgraph/cozy-finance/cozy?query=Market%20List) and our Rinkeby deployment [here](https://thegraph.com/explorer/subgraph/cozy-finance/cozy-rinkeby-subgraph?selected=playground).

## How is borrowing power calculated?

Borrowing power is calculated by dividing your active borrow amount by your total collateral.

* Active borrows is the USD value of all the assets you've borrowed.
* Total collateral is the USD value of all the assets you've deposited as collateral multiplied by their collateral factor.

## What oracles does Cozy use?

Cozy uses [Chainlink](https://chain.link/solutions/defi) oracles to get asset prices for ETH, DAI, and WBTC. The one exception to this is USDC, which has a hardcoded price of $1.

## What is a temporary borrow limit?

In the first phase of the protocol (alpha), each market will have a maximum amount of assets that can be borrowed. This is to limit the overall exposure users can get on the protocol as things are still relatively untested. Over time, these borrow limits will be removed.

## Why am I being asked to migrate my positions?

The Cozy protocol is implemented through a mostly immutable set of smart contracts. Protocol improvements sometimes require a complete redeployment of the smart contracts. If you are reading this, it is likely that a new version of the protocol has been deployed, which means you'll have to migrate your funds to keep using the app.

Migrating your funds is as simple as closing out your positions, withdrawing your funds, and redepositing them in the latest version of the Cozy app available on the cozy.finance website.

## Why do I need to set up a proxy wallet?

Cozy uses DSProxy, a smart wallet, to execute multiple contract calls in one transaction. Normal addresses (or [EOAs](https://ethereum.stackexchange.com/questions/5828/what-is-an-eoa-account)) are limited to interacting with only one contract per transaction, which means complex interactions would require multiple transactions. But by using DSProxy, Cozy lets users execute complex interactions with only one transaction. This allows Cozy to provide a better user experience and saves users gas in the long run.

To learn more about DSProxy, visit the [DSProxy repo](https://github.com/dapphub/ds-proxy).

## What are Estimated Balances?

If you have both an unprotected and a protected investment in the same opportunity, Cozy will estimate your balance in each type of investment based on the ratio of unprotected vs protected assets borrowed. To estimate balances on protected investments, Cozy takes your total balance and multiplies it by your protected borrow divided by total borrow. And vice versa for estimating balances on unprotected investments.

When you want to close a position, you'll have access to your total balance (across both protected and unprotected investments) to repay your debts.


# Security

Security is a top priority for the Cozy Protocol. Learn more about prior and ongoing efforts to ensure the dependability of the Cozy Protocol here.

## Audits

The Cozy Protocol has been reviewed and audited by Quantstamp and Peckshield.


# Guides

Interact with Cozy markets programmatically using samle scripts and  developer guides.

The following developer guides provide instructions and code examples to help you create programs to perform common protection market tasks programmatically.

* [Set up your development environment](/staging/for-developers/guides/development-environment-setup)
* [Create a protection market](/staging/for-developers/guides/how-do-i-create-a-protection-market)
* [Buy protection programmatically](/staging/for-developers/guides/how-do-i-buy-protection-programmatically)
* [Manage protection programmatically](/staging/for-developers/guides/how-do-i-manage-protection-programmatically)
* [Provide protection programmatically](/staging/for-developers/guides/providing-protection-programmatically)
* [Liquidate a vault](/staging/for-developers/guides/how-do-i-liquidate-a-vault)
* [Create a protected investing opportunity](/staging/for-developers/guides/create-a-protected-investing-opportunity)
* [Create an invest/divest contract](/staging/for-developers/guides/how-do-i-create-an-invest-divest-contract)


# Set up your development environment

Get everything you need to start developing using the developer guides.

All of the [developer guides](/staging/for-developers/guides) assume that you are using a TypeScript development environment with a project structure similar to the one described here. You can follow the instructions in this section to prepare a development environment for working with the sample scripts in the [Cozy developer guide](https://github.com/Cozy-Finance/cozy-developer-guides) repository.

## Before you begin

Before you set up the development environment for creating protection markets, verify the following:

* You have an internet connection and access to a shell terminal.
* You have `node.js` and `yarn` installed.
* You can connect to a node running locally or through a service such as [Infura](https://infura.io/).
* You have access to a wallet—including its private key—and can send transactions.

## Prepare the development environment

To set up the development environment:

1. Clone the [Cozy Developer Guides](https://github.com/Cozy-Finance/cozy-developer-guides) repository by running the following command:

   ```
    git clone git@github.com:Cozy-Finance/cozy-developer-guides.git
   ```
2. Install package dependencies by running the following command:

   ```
    yarn
   ```
3. Create an environment file called `.env` to store information for connecting to the node provider and wallet.

   For example, if you are using the infura API and connecting to the Rinkeby test network, your `.env` file should look similar to the following example:

   ```bash
    RPC_URL=https://rinkeby.infura.io/v3/yourInfuraId
    PRIVATE_KEY=0xYourPrivateKey
   ```

   Be careful to never commit these secrets to a repository!
4. Test your local environment by running the following command:

   ```
    yarn test
   ```

   If your development environment is ready to use, you should see output similar to the following to indicate that tests have passed:

   ```
        Creating Typechain artifacts in directory typechain for target ethers-v5
        Successfully generated Typechain artifacts!

        MockTrigger
          Deployment
            ✓ initializes properly (52ms)
            ✓ should not deploy if market is already triggered (424ms)
          checkAndToggleTrigger
            ✓ does nothing when it should do nothing
            ✓ toggles trigger when expected to toggle trigger (58ms)
            ✓ returns a boolean with the value of isTriggered (446ms)
            5 passing (7s)
   ```

## What's next?

The settings in the `.env` file are used to initialize the wallet and send transactions when the TypeScript files such as `create-protection-market.ts` are executed.

For example:

```javascript
// Hardhat and ethers imports
import hre from 'hardhat';
import '@nomiclabs/hardhat-ethers';
import { Contract, ContractFactory } from 'ethers';

// Import some helper methods we have
import { getChainId, getContractAddress, logSuccess, logFailure, findLog, fundAccount } from '../utils/utils';

// Import any required ABIs
import comptrollerAbi from '../abi/Comptroller.json';

// STEP 0: ENVIRONMENT SETUP
// Use the default Hardhat provider
const provider = hre.ethers.provider;

// Initialize our signer using the private key from the environment variable
const signer = new hre.ethers.Wallet(process.env.PRIVATE_KEY as string, hre.ethers.provider);

// Chain ID is used to determine which contract addresses to use, and we use a 
// special helper method for getting chain ID. Normally you would get this from
// (await ethers.provider.getNetwork()).chainId, but since we are testing against
// a forked network we need to ensure we used the forked network's ID (e.g. 1 for
// mainnet) instead of the Hardhat default Chain ID of 1337
const chainId = getChainId(hre);
```

To finish setting up the development environment, you need to obtain the contract addresses and ABIs. You can find all of the contract addresses on the [Contract deployments](/staging/for-developers/contract-deployments) page. If you cloned the [Cozy Developer Guides](https://github.com/Cozy-Finance/cozy-developer-guides) repository, you'll already have the ABIs. If you did not clone the repository, the contracts are verified on Etherscan, so you can get the ABIs from there \[NOTE: currently not true].


# Create a protection market

Learn how to create a trigger contract for a protection market.

![](https://3311836203-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MQOlThYns4gV0tad8h_-2777116370%2Fuploads%2Fgit-blob-4136d7a8683c525acfbd574da2643f8194f0fc5e%2FCreate%20Protection%20Market.png?alt=media)

Protection markets are intended to protect users of on-chain protocols against the kinds of smart contract or protocol failures that make investing in decentralized financial products seem riskier than investing in traditional asset classes. Some of the common problems and risks that investors in on-chain protocols face include flaws in smart contract logic, security vulnerabilities that hackers can exploit, and unscrupulous insiders.

To address these issues, the key to creating a protection market is writing and deploying a trigger contract that limits an investor's exposure if a protocol is hacked or a fund suffers a rug pull maneuver.

At a high-level, you can create a protection market by taking the following steps:‌

1. ​[Prepare a trigger contract](#step-1-trigger-contract-setup) so that it's compatible with the Cozy protocol.
2. ​[Develop the trigger contract logic](#step-2-trigger-contract-development) to detect potential problems for one or more on-chain protocols.
3. ​[Deploy the trigger contract as a protection market](#step-3-protection-market-deployment) to make protected investing and protected borrowing available for users who want purchase protection or supply assets.

{% hint style="info" %}
Everything in this guide assumes that you have experience with JavaScript, [ethers.js](https://github.com/ethers-io/ethers.js/), and [Solidity](https://docs.soliditylang.org/en/latest/).
{% endhint %}

## Prepare a trigger contract <a href="#step-1-trigger-contract-setup" id="step-1-trigger-contract-setup"></a>

Before you start creating a trigger contract of your own, let’s take a closer look at what’s involved. There are three key parts that go into creating a trigger contract for a protection market:

* The *abstract* trigger contract.
* The trigger contract that inherits the abstract trigger contract and contains the code to check for a trigger condition.
* The deployment script that provides input parameters to the trigger contract when deployed.

Let’s review what’s in each of these files and what you do with them.

### Review the abstract trigger contract

if you cloned the [Cozy Developer Guides](https://github.com/Cozy-Finance/cozy-developer-guides) repository, you have an abstract trigger contract called `ITrigger` defined in the `ITrigger.sol` file in the `contracts/interface/` folder. This abstract trigger contract serves as the base or parent contract for the trigger contract you will write for a protection market.

You don't need to make any changes to the abstract trigger contract. It's provided to make developing your own trigger contract easier. Before you start writing your own trigger contract, however, you might want to take a closer look at what’s in the `ITrigger.sol` abstract trigger contract first.

As you review the `ITrigger.sol` file, there are just a few lines to take note of:

* The `ITrigger.sol` file specifies the data types and identifiers for the basic properties of the contract and define the constructor arguments that will be passed in from a deployment script after the contract is deployed on the network.
* The `ITrigger.sol` file declares the `isTriggered` state variable and declares a `TriggerActivated()` event to emit if a condition has resulted in the `isTriggered` function returning `true`.
* The `getPlatformIds()` function is used to get an array of platform identifiers, which represent the protocols protected by this trigger contract.
* The `checkTriggerCondition()` function defines the logic that determines if the trigger condition for any of the protected protocols has occurred. This function is not implemented in the `ITrigger.sol` file. You’ll implement the `checkTriggerCondition()` function when you write the trigger contract that inherits from the abstract contract.
* The `checkAndToggleTrigger()` function sets the `isTriggered` flag to `true` if the condition defined for the `checkTriggerCondition()` function is met. This function is implemented in the abstract contract and must not be modified.

Once you are familiar with the code in the `ITrigger.sol` file, you are ready to start coding your own trigger contract.

### Prepare a trigger contract skeleton

Now that you are familiar with what's in the base trigger contract that your contract will inherit, you are ready to start writing the contract that contains the trigger logic for your protection market. Let’s start by creating a trigger contract skeleton. You can create the basic framework for the trigger contract in an empty file or you can use the `MockTrigger.sol` file in the developer-guides repository as a starting point. To illustrate what’s involved, we’ll create an empty file and copy and paste portions of the `MockTrigger` into the custom contract.

To create the basic framework for your custom trigger contract:

1. Create a new empty file. For example, create a new file called `TestTrigger.sol` by running the following command:

   ```
    touch contracts/TestTrigger.sol
   ```
2. Open the file in a text editor and insert a line with the version `pragma` to specify the compiler version this trigger contract requires. For example:

   ```
    pragma solidity ^0.8.5;
   ```
3. Import the abstract trigger contract and set the current trigger contract to inherit it. For example:

   ```
    import "./interfaces/ITrigger.sol";

    contract TestTrigger is ITrigger {
   ```

   The `shouldToggle` function in the `MockTrigger` contract is only used for example purposes in that contract, so we don’t need to include it in our contract skeleton.
4. Prepare some expected properties for the contract:

   Because the `constructor` arguments of the base contract depend on values that will be passed to the derived contract, they are defined like this in our `TestTrigger` contract:

   ```
    constructor(
      string memory _name,
      string memory _symbol,
      string memory _description,
      uint256[] memory _platformIds,
      address _recipient,
      bool _shouldToggle
   ) ITrigger(_name, _symbol, _description, _platformIds, _recipient) {

    }
   ```

   These basic properties are inherited from the base trigger contract. The values for the properties are supplied when the contract is deployed.

   We’ll get to that step in a minute, but first, let’s complete our skeleton trigger contract by adding a placeholder for the required `checkTriggerCondition()` function.
5. Add a placeholder for `checkTriggerCondition()` function. For example:

   ```
    function checkTriggerCondition() internal override returns (bool) {

    }
   ```

### Configure parameters in a deployment script

So far, we’ve reviewed the abstract contract and built a skeleton for the trigger contract. The next step in preparing the trigger contract is to configure required trigger parameters that will be supplied to the trigger contract when it is deployed:‌ These parameters provide the data to the constructor properties you saw in the abstract contract and consist of the following:

* The trigger `name` is similar to the ERC-20 name property.
* The trigger `symbol` is similar to the ERC-20 symbol property.
* The `description` of the trigger that describes what the trigger does.
* The numeric identifier for each protocol that your trigger monitors for failure conditions. For example, if this trigger covers the failure of a Yearn vault, and Yearn has an ID of 1, the `platformId` would be `[1]`. For a list of platform names and their ID numbers, see [Platform identifiers for protocols](#platform-ids).
* The trigger `recipient` to define an address to which to distribute rewards. (Use a [sybil.org](https://sybil.org/) verified address if you want users to know you created the protection.)

For example:

{% code title="create-protection-market.ts" %}

```typescript
// Define required constructor parameters
const name = 'Mock Trigger'; // trigger name
const symbol = 'MOCK'; // trigger symbol
const description = 'A mock trigger that anyone can toggle'; // trigger description
const platformIds = [3]; // array of platform IDs that this trigger protects
const recipient = '0x1234567890AbcdEF1234567890aBcdef12345678'; // address of subsidy recipient
const shouldToggle = false; // specific to our MockTrigger, which we set to not be triggered at deployment
```

{% endcode %}

## Develop the trigger contract logic <a href="#step-2-trigger-contract-development" id="step-2-trigger-contract-development"></a>

You are now ready to implement the actual trigger logic for your contract using the `checkTriggerCondition()` function that you inherited from the abstract contract. The `checkTriggerCondition()` function is where you write the core logic of your trigger contract, specifying the condition that should trigger protection for the protocol(s) defined by `getPlatformIds()` parameter.

Note that the `checkAndToggleTrigger()` and `checkTriggerCondition()` functions are crucial to ensuring your trigger behaves properly, so read the following section carefully:

* You **must** implement `checkTriggerCondition()` to execute some logic and return `true` if the trigger event has occurred, and return `false` otherwise.
* You **must** ensure that the only way to update the value of the `isTriggered` variable is through the `checkTriggerCondition()` function.
* You **must not** modify the `checkAndToggleTrigger()` function inherited from the abstract contract. This function is implemented to conform to the interface and behavior expected by Cozy protection markets. The `checkAndToggleTrigger()` function is called by a protection market to determine the trigger's state.‌

You should also note that protection market triggers are "one-way" toggles. Each protection market stores its own `isTriggered` variable—separate from the trigger contract's `isTriggered` variable—which is initialized to `false` and toggled only once, when the trigger's`checkAndToggleTrigger()` method returns `true`. Because it can only be toggled once, to avoid confusion, it's recommended that triggers themselves should also follow the same convention of only allowing "one-way" toggles.‌

The following is an example [Mock Trigger](https://github.com/Cozy-Finance/cozy-developer-guides/blob/master/contracts/MockTrigger.sol) contract that is also available in the [Cozy Developer Guides](https://github.com/Cozy-Finance/cozy-developer-guides) repository.

{% code title="MockTrigger.sol" %}

```typescript
pragma solidity ^0.8.5;

import "./interfaces/ITrigger.sol";

contract MockTrigger is ITrigger {
  /// @notice If true, checkAndToggleTrigger will toggle the trigger on its next call
  bool public shouldToggle;

  constructor(
    string memory _name,
    string memory _symbol,
    string memory _description,
    uint256[] memory _platformIds,
    address _recipient,
    bool _shouldToggle
  ) ITrigger(_name, _symbol, _description, _platformIds, _recipient) {
    shouldToggle = _shouldToggle;

    // Verify market is not already triggered.
    require(!checkTriggerCondition(), "Already triggered");
  }

  /**
   * @notice Special function for this mock trigger to set whether or not the trigger should toggle
   */
  function setShouldToggle(bool _shouldToggle) external {
    require(!isTriggered, "Cannot set after trigger event");
    shouldToggle = _shouldToggle;
  }

  /**
   * @notice Returns true if the market has been triggered, false otherwise
   */
  function checkTriggerCondition() internal view override returns (bool) {
    return shouldToggle;
  }
}
```

{% endcode %}

When testing a trigger contract, it is helpful to initialize your test suite using the test template in `test/MockTrigger.test.ts`. This file contains sample implementations of common test cases that you'll want to use when testing your trigger's functionality.

## Deploy a protection market <a href="#step-3-protection-market-deployment" id="step-3-protection-market-deployment"></a>

Once your trigger contract is complete, you are ready to deploy a new protection market that uses that trigger.‌ You deploy a protection market by defining the following properties:

* Trigger contract address.
* Interest rate model contract address.
* Underlying token that is supplied to and borrowed from that market.

### Select an interest rate model

An interest rate model is a contract that takes current market parameters as inputs and returns what the market's borrowing interest rate should be. Before you deploy your protection market, you need to decide on the interest rate model to use for it.

The simplest option is to use the "Default Protection Market Interest Rate Model". You can find the contract address for this interest rate model on the [Contract deployments](/staging/for-developers/contract-deployments) page. This interest rate model is defined as follows:

* 0% base rate (if nothing is borrowed, the borrow rate is zero).
* At an 80% utilization ratio, the borrow rate is 20%, and the rate increases linearly between 0% and 80% utilization.
* At a 100% utilization ratio, the borrow rate is 125%, and the rate increases linearly between 80% and 100% utilization.

If you want to use a different interest rate model, the [Contract deployments](/staging/for-developers/contract-deployments) page lists other available options. If none of the pre-deployed interest rate models suit your use case, you can deploy your own. In the [cozy-developer-guides](https://github.com/Cozy-Finance/cozy-developer-guides) repository includes an abstract contract called [`IInterestRateModel`](https://github.com/Cozy-Finance/cozy-developer-guides/blob/master/contracts/interfaces/IInterestRateModel.sol). By inheriting this contract, you'll have the correct interface and layout for building and deploying any interest rate model you would like to use.

After you have selected an interest rate model, deploy the contract for it (if necessary), and save the contract address for use in later steps.

### Set the underlying token

The next step in deploying a protection market is to choose the underlying ERC-20 token (or ETH) to use for your protection market. For example, if you are writing a trigger to protect a Yearn yUSDC vault, selecting USDC as the underlying token would enable users to borrow protected USDC from the protection market and immediately use it to mint protected yUSDC shares on Yearn. If you were to chose DAI as the underlying token, users would have to borrow protected DAI and swap it for USDC before they can get protected yUSDC shares.

{% hint style="info" %}
To use ETH as the underlying token, use an address of `0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE`‌
{% endhint %}

To deploy a protection market with a given underlying token, a money market for that underlying token must exist. After you select an underlying token, you should verify that a money market for that token exists by calling the `Comptroller.getCToken(underlying, AddressZero)` function. The Comptroller stores a mapping—called `getCToken`—that maps an underlying token address to a trigger address to a market address. Money markets use the zero address as their `trigger` address. If the `Comptroller.getCToken(underlying, AddressZero)` check returns the zero address, a money market for the underlying token token does not exist, and you'll have to wait for one to be deployed by governance before continuing. (If you try to deploy without a supported underlying token money market, protection market deployment will revert).‌

The `create-protection-market.ts` script shows how to run this check when USDC is the underlying token. If a money market does exist, you can continue to the next step to deploy the final version of your trigger contract.

### Deploy the protection market

You can now deploy your protection market in one of two ways:

* By using the default interest rate model.

  ```typescript
  // Option 1: Use the default interest rate model
  Comptroller.deployProtectionMarket(underlying, trigger);
  ```
* By specifying an interest rate model.

  ```typescript
  // Option 2: Specify an interest rate model
  Comptroller.deployProtectionMarket(underlying, trigger, interestRateModel)
  ```

where

* `underlying` is the underlying token's address for this CozyToken market.
* `trigger` is the address of your trigger contract.
* `interestRateModel` is the address of your chosen interest rate model contract.

Because `deployProtectionMarket` is an overloaded function, when using ethers.js and the sample scripts to deploy a market, we must specify which syntax we're using.

The full process for deploying a trigger and using it to create a protection market is shown in the `create-protection-market.ts` script:

{% code title="create-protection-market.ts" %}

```typescript
// Get instance of the Trigger ContractFactory with our signer attached
const MockTriggerFactory: ContractFactory = await hre.ethers.getContractFactory('MockTrigger', signer);

// Deploy the trigger contract (last constructor parameter is
// specific to the mock trigger contract)
const triggerParams = [name, symbol, description, platformIds, recipient, shouldToggle];
const trigger: Contract = await MockTriggerFactory.deploy(...triggerParams);
await trigger.deployed();
logSuccess(`MockTrigger deployed to ${trigger.address}`);

// Let's choose USDC as the underlying, so first we need to check if
// there's a USDC Money Market. We know that Money Markets have a
// trigger address of the zero address, so we use that to query the
// Comptroller for the Money Market address
const usdcAddress = getContractAddress('USDC', chainId);
const comptrollerAddress = getContractAddress('Comptroller', chainId);
const comptroller = new Contract(comptrollerAddress, comptrollerAbi, signer); // connect signer for sending transactions
const cozyUsdcAddress = await comptroller.getCToken(usdcAddress, AddressZero);

// If the returned address is the zero address, a money market does
// not exist and we cannot deploy a protection market with USDC as
// the underlying
if (cozyUsdcAddress === AddressZero) {
  logFailure('No USDC Money Market exists. Exiting script');
  return;
}
logSuccess(`Safe to continue: Found USDC Money Market at ${cozyUsdcAddress}`);

// If we're here, a USDC Money Market exists, so it's safe to create
// our new Protection Market. If we tried to create a new Protection
// Market before a USDC Money Market existed, our transaction would
// revert. Also, notice how we do not provide an `interestRateModel`
// address--this means we'll use the default interest rate model
// specified by the `ProtectionMarketFactory` contract. If you want
// to use a custom interest rate model, develop, test, and deploy your
// interest rate model, then use the commented out version below
const tx = await comptroller['deployProtectionMarket(address,address)'](usdcAddress, trigger.address);
// const tx = await comptroller['deployProtectionMarket(address,address,address)'](usdcAddress, trigger.address, interestRateModelAddress);

// This should emit a ProtectionMarketListed event on success, so
// let's check for that event. If not found, this method will throw
// and print the Failure error codes which can be looked up in
// ErrorReporter.sol
const { log, receipt } = await findLog(tx, comptroller, 'ProtectionMarketListed', provider);
logSuccess(`Success! Protection Market deployed to ${log?.args.cToken} in transaction ${receipt.transactionHash}`);
```

{% endcode %}

## Verify your protection market

After you deploy your trigger contract and interest rate model contract to create a protection market, you can verify that your protection market exists by looking at the [Cozy subgraph](https://thegraph.com/legacy-explorer/subgraph/cozy-finance/cozy).

Your protection market will be initialized with a collateral factor of zero and use the specified `trigger`, `underlying` , and `interestRateModel` addresses. Note that you can change the interest rate model by submitting a governance proposal.

## Tips for trigger contract developers

Trigger contract logic can sometimes have unintended consequences or undesirable effects. This section provides some tips and suggestions to help you avoid the pitfalls.

### Consider the gas required for computation

In a protection market, the trigger contract always calls the `checkAndToggleTrigger()` method immediately before every borrow and redeem action. This call is required to mitigate front-running. However, each call incurs a cost in gas for execution and this increases the cost of borrowing and redeeming funds.

In writing trigger contract logic, you should try to keep the gas costs for checking the trigger condition as low as possible, as users will pay the cost on every borrow and redeem action. For example, you can reduce the gas required tor checking the trigger condition by:

* Keeping trigger logic as simple as possible.
* Minimizing operations that read from or write to storage.
* Minimizing calls to external contracts or reading data from other contracts.

You can also find general guidelines for limiting gas usage in [Solidity gas optimization tips](https://mudit.blog/solidity-gas-optimization-tips/) and [Solidity tips and tricks to save gas and reduce bytecode size](https://blog.polymath.network/solidity-tips-and-tricks-to-save-gas-and-reduce-bytecode-size-c44580b218e6).

### Avoid code that encourages front-running

If it's known that a trigger condition will occur before reflected on-chain, that trigger may be susceptible to front-running. This would incentive suppliers to race to withdraw their funds immediately before a trigger is toggled, while borrowers try to max out their borrows immediately before their debt is forgiven. This is not an ideal property for triggers and consequently these types of triggers should be avoided.

Let's consider a Yearn V2 vault's `pricePerShare` as a trigger condition. Under normal operation, this value should only ever increase, though there are expected decreases immediately after each harvest. Therefore we may want to encode a trigger condition that says "if the value of `pricePerShare` drops and remains at some decreased value for X hours, toggle the trigger". This seems logical—if `pricePerShare` decreases, it may have been expected as part of a harvest, so let's wait to see if it recovers before toggling the trigger.

But this type of trigger is a prime example of a trigger that's susceptible to frontrunning. Let's say the trigger condition used a 12 hour duration. After 11 hours have elapsed, everyone knows that the trigger is likely to toggle very soon. As a result, suppliers will race to pull out their funds to remove the risk of losing funds, and borrowers will race to borrow as much as possible knowing they won't have to pay back debt. This "race" is not a desirable property for average users, so consider avoiding triggers that result in this type of scenario.

### Data availability

Every borrow and redeem calls your trigger's `checkAndToggleTrigger()` method. This method does not take any inputs, and therefore your trigger's condition cannot be dependent on function inputs or call data. This also means your trigger will not be able to use a Merkle proof to access and validate historical state. If you need access to historical state, you'll need to save data to storage on each call to `checkAndToggleTrigger()`.

### Governance

While you can initialize the parameters for your protection market, governance can change the following properties and activities:

* Interest rate model used.
* Borrowing cap.
* Mints, borrow, transfer, and liquidation operations.

## Platform identifiers for protocols

Platform identifiers are used to label DeFi protocols in Cozy applications. The protocol does not require you to use them in your trigger contracts, but they will help your protection market get proper surfacing.

The list of platform identifiers is maintained in the [Cozy-Finance/platform-ids](https://github.com/Cozy-Finance/platform-ids) repo. Please consult the list to get the proper ID for the trigger you're developing.

{% hint style="info" %}
Cozy is actively adding support for new protocols and corresponding platform identifiers. If the platform you're writing a trigger for doesn't have a platform ID assigned in the repo above, please submit a PR to add it!
{% endhint %}


# Buy protection programmatically

Learn how to buy protection programmatically on the Cozy protocol.

![](https://3311836203-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MQOlThYns4gV0tad8h_-2777116370%2Fuploads%2Fgit-blob-be83971e6f3a4243768f612ebb00a48bd64e2931%2FAutomatic%20purchase.png?alt=media)

Cozy provides a protected borrowing marketplace for investing in decentralized finance protocols that offer protection against a loss of funds. You pay a small premium to purchase protection for funds you deposit and can leverage your investment by borrowing against it. This guide illustrates how you can write a script using TypeScript that you can then use to buy protection from a [protection market](/staging/what-is-cozy/faq#protection-market) programmatically,

All code snippets are from the `buy-protection.ts` script in the [Cozy Developer Guides](https://github.com/Cozy-Finance/cozy-developer-guides) repository. See that repository for more context, definitions of helper methods used, etc.

{% hint style="info" %}
Everything in this guide assumes that you have experience with JavaScript, [ethers.js](https://github.com/ethers-io/ethers.js/), and [Solidity](https://docs.soliditylang.org/en/latest/).
{% endhint %}

## Supply collateral

Before you can buy protection by borrowing protected funds from a Cozy market, you must supply collateral to borrow against.

All markets in Cozy—money markets and protection markets—have a `trigger` state variable. If the value of the `trigger` property is the [zero address](https://etherscan.io/address/0x0000000000000000000000000000000000000000), the money market does not have a trigger contract associated with it. A money market that does not have a trigger contract associated with it cannot be used for protected borrowing, but can be used for ordinary borrowing. If the value of the `trigger` property is anything except the zero address, the value of the `trigger` property represents the address of the trigger contract associated with that market. Only assets supplied to Cozy markets that have the zero address for the `trigger` property, known as money markets, can be used as collateral. Similarly, only Cozy markets with a defined trigger contract, known as protection markets, can be used for protected borrowing.

Therefore, the first step toward protected borrowing is to determine the address of the Cozy money market you intend to use as collateral. To see how to do that, let's assume that you want to buy protection for an ETH investment and you have 2 ETH to use as collateral.

### Determine address of the money market

The following code snippet illustrates how to check the `trigger` property to see if it returns the zero address and how to find the address for the Cozy ETH Money Market where you will deposit your collateral:

{% code title="buy-protection.ts" %}

```javascript
// STEP 0: ENVIRONMENT SETUP
const supplyAmount = '2'; // Supply 2 ETH as collateral
const borrowAmount = '500'; // Borrow 500 USDC

// STEP 1: SUPPLY COLLATERAL
// We need the Comptroller, so create an instance of the Comptroller contract
const comptrollerAddress = getContractAddress('Comptroller', chainId);
const comptroller = new Contract(comptrollerAddress, comptrollerAbi, signer); // connect signer for sending transactions

// Let's say we have ETH to use as collateral
// The first check is to make sure an ETH Money Market exists that we
// can supply to. We know that Money Markets have a trigger address
// of the zero address, so we use that to query the Comptroller for
// the Money Market address
const cozyEthAddress = await comptroller.getCToken(ethAddress, AddressZero);

// If the returned address is the zero address, a money market does
// not exist and we cannot supply ETH
if (cozyEthAddress === AddressZero) {
  logFailure('No ETH Money Market exists. Exiting script');
  return;
}
logSuccess(`Safe to continue: Found ETH Money Market at ${cozyEthAddress}`);
```

{% endcode %}

In this example, the `ethAddress` used as input to the `getCToken` method is the address `0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE` that Cozy uses to represent ETH.

### Supply the collateral

After verifying that there's a valid Cozy money market available for depositing your collateral, you are ready to supply the collateral to that money market. In this example, you are supplying 2 ETH, and ETH has 18 decimal places, so your script need to account for that. The process is slightly different for ETH than for ERC-20 tokens. The following code and comments describe how supplying collateral using ETH differs from supplying collateral when using ERC-20 tokens.

{% code title="buy-protection.ts" %}

```javascript
// Create a contract instance of the Cozy ETH money market
const cozyEth = new Contract(cozyEthAddress, cozyEthAbi, signer); 
// To supply ERC-20 tokens as collateral:
// const cozyToken = new Contract(cozyTokenAddress, cozyTokenAbi, signer); // for tokens

// We're now ready to supply the collateral to the market, but there's
// some preparation we need to do beforehand. For example, ETH
// has 18 decimal places, so we need to take that into account.
// `parseUnits` is a method from ethers.js
const parsedSupplyAmount = parseUnits(supplyAmount, 18); // scale amount based on number of decimals

// If using a token, here is where you'd approve the Cozy Money Market
// contract to spend your tokens. If you trust the Cozy contract,
// approve it to spend the maximum possible amount to avoid future
// approvals and save gas. Below we show a sample snippet of an
// approval transaction and verifying it was successful:
//   const approveTx = await token.approve(cozyToken.address, MaxUint256);
//   await approveTx.wait();
//   const allowance = await token.allowance(signer.address, cozyToken.address);
//   if (!allowance.eq(MaxUint256)) {
//     logFailure('CozyToken does not have sufficient allowance to spend our token. Exiting script');
//     return;
//   }
//   logSuccess('Approval transaction successful. Ready to mint CozyToken with our token');

// Ready to mint our CozyETH from ETH
const mintTx = await cozyEth.mint({ value: parsedSupplyAmount, gasLimit: '5000000' }); 
// const mintTx =await cozyToken.mint(parsedSupplyAmount); // for tokens
const { log: mintLog, receipt: mintReceipt } = await findLog(mintTx, cozyEth, 'Mint', provider);
logSuccess(`CozyETH successfully minted in transaction ${mintReceipt.transactionHash}`);
```

{% endcode %}

### Verify transaction results

In some cases, the mint transaction can appear to be successful without the mint operation actually being successful.

Because of how Cozy does error handling, transactions can be successful—and be displayed as successful on Etherscan and other block explorers—but without doing what you expected. For example, if a transaction returns an error code and emits a `Failure` event instead of reverting, it might appear as if the transaction was successful when it has actually failed. You can read more about error codes and failures in [Error codes](/staging/for-developers/error-codes), and see information about error handling history [here](https://www.comp.xyz/t/brief-history-of-error-handling-in-the-protocol/1169).

You should manually ensure the mint transaction succeeded before continuing to the next step. You can use the `findLog()` helper method to simplify the verification process. For more details about using the `findLog()` method, see the [utils.ts](https://github.com/Cozy-Finance/cozy-developer-guides/blob/master/utils/utils.ts) file in the [Cozy developer Guides](https://github.com/Cozy-Finance/cozy-developer-guides) repository.

## Enter markets

Supplying assets does not automatically mean you can use them as collateral. To use the supplied assets as collateral, you must explicitly call the `enterMarkets` function on the Comptroller. The following code snippet illustrates how to add your collateral to the market:

{% code title="buy-protection.ts" %}

```javascript
// STEP 2: ENTER MARKETS
// Supplying assets does not automatically mean we can use them as
// collateral. To do that, we need to explicitly call enterMarkets
// on the Comptroller for each asset we want to use as collateral. For
// now, that's just ETH. (We use `em` as shorthand for `enterMarkets`
// in our variable names)
const markets = [cozyEth.address]; // array of markets to enter
const emTx = await comptroller.enterMarkets(markets);
const { log: emLog, receipt: emReceipt } = await findLog(emTx, comptroller, 'MarketEntered', provider);
logSuccess(`Markets entered successfully: ETH can now be used as collateral`);
```

{% endcode %}

## Borrow funds

Your account is now ready to borrow protected funds. Let's say there's a Yearn protection market for yUSDC, and you want to borrow protected USDC to invest in that protection market. The steps are very similar to the steps for supplying collateral, so let's jump straight to the code:

{% code title="buy-protection.ts" %}

```javascript
// STEP 3: BORROW FUNDS
// Your account is now ready to borrow funds

// We want to borrow protected USDC so we can deposit it straight into
// Yearn's yUSDC vault, so first let's verify the underlying token
// we'd borrow is in fact USDC
const usdc = new Contract(getContractAddress('USDC', chainId), erc20Abi, signer);
const yearnProtectionMarketAddress = getContractAddress('YearnProtectionMarket', chainId);
const yearnProtectionMarket = new Contract(yearnProtectionMarketAddress, cozyTokenAbi, signer);
const underlying = await yearnProtectionMarket.underlying();
if (usdc.address !== getAddress(underlying)) {
  // We use ethers' getAddress() method to ensure both addresses are
  // checksummed before comparing them. If this block executes, the
  // underlying of the protection market is not the underlying we
  // want (USDC), so we exit the script
  logFailure('USDC addresses do not match. Exiting script');
  return;
}

// Now we execute the borrow
const parsedBorrowAmount = parseUnits(borrowAmount, await usdc.decimals()); // scale amount based on number of decimals
const borrowTx = await yearnProtectionMarket.borrow(parsedBorrowAmount);
const { log: borrowLog, receipt: borrowReceipt } = await findLog(borrowTx, yearnProtectionMarket, 'Borrow', provider);
logSuccess(`Protected USDC borrowed in transaction ${borrowReceipt.transactionHash}`);

// Done! You are now supplying ETH as collateral to borrow protected
// USDC. The USDC debt will not need to be paid back if the Yearn
// trigger event occurs, so the borrowed USDC can now be safely
// supplied to Yearn
```

{% endcode %}

At this point, your account is now supplying 2 ETH as collateral to borrow 500 USDC. That USDC debt will not need to be paid back if the trigger event occurs, so you can safely deposit the 500 USDC into a Yearn vault.


# Manage protection programmatically

Learn how to view and manage positions and accounts programmatically on the Cozy protocol.

![](https://3311836203-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MQOlThYns4gV0tad8h_-2777116370%2Fuploads%2Fgit-blob-cf0831fe3528adc037d7db3d87ede0312279c1c7%2FProvide.png?alt=media)

This guide illustrates how you can view and manage your protection positions programmatically using a script written in TypeScript. The tasks in this section assume that you are a participant in a protection market and have supplied collateral to purchase protection as described in [Buy protection programmatically](/staging/for-developers/guides/how-do-i-buy-protection-programmatically). If you haven't already done so, you should read the [Buy protection programmatically](/staging/for-developers/guides/how-do-i-buy-protection-programmatically) guide or review the `buy-protection.ts` script before continuing with this guide.

All of the code snippets in this guide are from the `manage-protection.ts` script in the [Cozy developer guides](https://github.com/Cozy-Finance/cozy-developer-guides) repository. See that repository for more context, definitions of helper methods used, and related information.

{% hint style="info" %}
Everything in this guide assumes that you have experience with JavaScript, [ethers.js](https://github.com/ethers-io/ethers.js/), and [Solidity](https://docs.soliditylang.org/en/latest/).
{% endhint %}

## Prepare to manage positions

The `manage-protection.ts` script includes code to set up a your environment and buy protection so that you have an account with positions to manage. Because those steps are covered in other guides, they aren't included in this guide. For managing positions, however, you need to specify how many decimals Cozy tokens have. You can add this information to the Environment Setup section of the code with a line like this:

{% code title="manage-protection.ts" %}

```typescript
// All Cozy Tokens have 8 decimals, so we define this for convenience
const cTokenDecimals = 8;
```

{% endcode %}

After the Environment Setup instructions, the `manage-protection.ts` script includes a condensed version of the code for buying protection, which is covered in more detail in the `buy-protection.ts` script. You can view the condensed version of the code [here](https://github.com/Cozy-Finance/cozy-developer-guides/blob/9c6deb7cdad49322e82871381b146bd9c9867689/guides/manage-protection.ts#L32-L73).

## View positions

As the last step of buying protection, you borrowed funds from a protection market. In this case, you have borrowed protected USDC from a Yearn protection market. Now, let's get an array of Cozy token (cToken) addresses for each market you've entered.

{% code title="manage-protection.ts" %}

```typescript
// STEP 1: VIEWING POSITIONS
// To start, let's get an array of CToken addresses for each market
// we've entered. When you borrow from a market, you are automatically
// entered into that market
const ourAddress = signer.address; // shorthand, for convenience

 // Get an array of CozyToken addresses of markets entered
const assets = await comptroller.getAssetsIn(ourAddress);
```

{% endcode %}

{% hint style="info" %}
When you borrow from a market, you are automatically entered into that market. When you supply to a market, however, you must explicitly enter the market.
{% endhint %}

In practice, this distinction means that the `getAssetsIn` method only returns:

* Assets that you have **borrowed**.
* Assets that you have **supplied** and have used to **enter markets**.

If you have supplied assets but have not explicitly entered a market with them, those assets are not included in the results because there's no position to manage and the Comptroller does not need to be aware of those assets.

To determine whether you have borrowed from a market or supplied to the markets, you can loop through each asset and learn its current status. The comments in this code snippet explain what's happening at each step.

{% code title="manage-protection.ts" %}

```typescript
console.log('Checking status of each asset...\n');
for (const asset of assets) {
  // First we'll check balances in this loop and see if any of our
  // balances come from borrows. For brevity, we prefix all properties
  // about the underlying token with `u`
  const cToken = new Contract(asset, cozyTokenAbi, signer);
  const [name, symbol] = await Promise.all([cToken.name(), cToken.symbol()]);
  console.log(`Current asset has name "${name}" and symbol "${symbol}"`);

  // Let's also learn about the underlying token. First we determine
  // if the underlying is ETH then get a contract instance for the
  // underlying token if the underlying is not ETH
  const uAddr = await cToken.underlying();
  const isEth = uAddr === ethAddress; // true if underlying is ETH, false otherwise
  const underlying = isEth ? null : new Contract(uAddr, erc20Abi, signer);

  // Lastly we either read set the values if ETH is underlying, or
  // read the values if it's a token
  const uName = underlying ? await underlying.name() : 'Ether';
  const uSymbol = underlying ? await cToken.symbol() : 'ETH';
  const uDecimals = underlying ? await underlying.decimals() : 18;
  console.log(`  Underlying ${uName} (${uSymbol}) has ${uDecimals} decimals`);

  // Get our balance of the Cozy token
  const balance = await cToken.balanceOf(ourAddress);
  const balanceScaled = formatUnits(balance, cTokenDecimals);
  if (balance.eq(Zero)) {
    // Balance is zero, so we have not supplied the underlying token
    console.log('  No Cozy Token balance, so nothing supplied');
  } else {
    // Balance is > 0, so we have supplied some amount of underlying
    // tokens. We get exchange rate to figure out how much underlying
    // we have. The exchange rate is a mantissa (18 decimal value), so
    // the value returned is scaled by
    // 10 ** (18 + underlyingDecimals - cTokenDecimals)
    const exchangeRate = await cToken.exchangeRateStored();
    const scale = 18 + uDecimals - cTokenDecimals;
    const uBalance = balance.mul(exchangeRate);
    const uBalanceScaled = formatUnits(uBalance, scale + cTokenDecimals);
    console.log(`  Balance of ${balanceScaled} Cozy Tokens (equal to ${uBalanceScaled} underlying)`);
  }

  // Now get our balance of the underlying token
  const uBalance = underlying ? await underlying.balanceOf(ourAddress) : await signer.provider.getBalance(ourAddress);
  if (uBalance.eq(Zero)) {
    // Underlying balance is zero, so we have not borrowed the
    // underlying token
    console.log(`  No underlying ${uSymbol} balance`);
  } else {
    // Underlying balance is above zero, BUT we still may not have
    // borrowed this token -- we may have already had some
    const uBalanceScaled = formatUnits(uBalance, uDecimals);
    console.log(`  Balance of ${uBalanceScaled} underlying ${uSymbol} tokens`);

    // Read the amount borrowed
    const borrowBalance = await cToken.borrowBalanceStored(ourAddress);
    const borrowBalanceScaled = formatUnits(borrowBalance, uDecimals); // scale to human readable units

    // Now we determine if the funds were borrowed
    if (borrowBalance.eq(Zero)) console.log(`  None of the underlying ${uSymbol} tokens we have were borrowed`);
    else if (borrowBalance.eq(uBalance)) console.log(`  All the underlying ${uSymbol} tokens we have were borrowed`);
    else console.log(`  ${borrowBalanceScaled} of the ${uBalanceScaled} underlying ${uSymbol} tokens were borrowed`);
  }
  console.log('\n');
} // end for each asset
```

{% endcode %}

## Check account liquidity

The amount of collateral you have is computed by multiplying the supplied USD balance in a market by that market's collateral factor, and summing that across all markets. Total borrow balances are subtracted from that, resulting in an **account liquidity** value. Users who have negative account liquidity, i.e. a shortfall, are subject to liquidation, and are prevented from withdrawing or borrowing assets.

To avoid liquidation, you must ensure that account liquidity is always greater than zero. You can check this for an account as follows:

{% code title="manage-protection.ts" %}

```javascript
// STEP 2: CHECKING ACCOUNT LIQUIDITY

// getAccountLiquidity() returns three values. The first is an error
// code, the second is the excess liquidity, and the third is the
// shortfall. Only one of the last two will ever be positive
const [errorCode, liquidity, shortfall] = await comptroller.getAccountLiquidity(signer.address);

// Make sure there were no errors reading the data
if (errorCode.toString() !== '0') {
  logFailure(`Could not read liquidity. Received error code ${errorCode}. Exiting script`);
  return;
}

// There were no errors, so now we check if we have an excess or a
// shortfall
if (shortfall.gt(Zero)) {
  logFailure(`WARNING: Account is under-collateralized and may get liquidated! Shortfall amount: ${shortfall}`);
} else if (liquidity.gt(Zero)) {
  logSuccess(`Account has excess liquidity and is safe. Amount of liquidity: ${liquidity}`);
} else {
  logFailure('WARNING: Account has no liquidity and no shortfall');
}
```

{% endcode %}

## Manage liquidity

After checking your account liquidity, you might find that you are at risk of having your account liquidated. If you find your account liquidity is too close to the minimum required—for example, you have a shortfall or only a small amount of excess liquidity—you can adjust your position by doing the following:

* Supply additional collateral.
* Repay debt.

### Supply additional collateral

If you want to adjust your account liquidity (another way of measuring what's commonly known as your collateralization ratio) to reduce the risk of liquidation, you can supply more collateral.

To supply more collateral programmatically, follow the detailed steps in `buy-protection.ts` script (or reference the abbreviated version of the code for supplying collateral in the `manage`-`protection.ts` script).

### Repay debt

An alternate way to reduce your chance of liquidation is to pay back some, or all, of your borrowed debt.

There are two options for repaying debts:

* Repay debt you, as the transaction caller, borrowed.
* Repay debt on behalf of another borrower.

#### repayBorrow

You can repay your own borrows using the `repayBorrow()` method. As the following code snippet illustrates, you first approve the contract to spend DAI, then execute the repay.

{% code title="manage-protection.ts" %}

```typescript
// If we want to repay our own borrows, we can use the repayBorrow
// method. First we approve the contract to spend our USDC, then we
// execute the repay

// Send approval transaction and wait it to be mined
const usdcApproveTx = await usdc.approve(yearnProtectionMarket.address, MaxUint256);
await usdcApproveTx.wait();

// Define the amount to repay, taking USDC's decimals into account
const usdcDecimals = await usdc.decimals();
const repayAmount = parseUnits('25', usdcDecimals); // repay 25 USDC
const repayTx = await yearnProtectionMarket.repayBorrow(repayAmount);
await findLog(repayTx, yearnProtectionMarket, 'RepayBorrow', provider);
logSuccess('Successfully repaid a portion of the borrow');
```

{% endcode %}

This example, repays a debt of 25 DAI for the account that called the `repayBorrow` method.

If you wanted to repay the full amount instead of just 25 DAI, the best way to do this is to set the `repayAmount` to `MaxUint256`. The Cozy contracts recognize this as a magic number that will repay all your token debt. If you try to repay all token debt without using `MaxUint256` as the amount, you'll be left with a very tiny borrow balance, known as dust. This happens because interest accrues at the beginning of the repay transaction, and it's extremely difficult to predict how much will accrue and send the exact amount of tokens required. Using `MaxUint256` tells the contracts to repay the full debt after interest accrues.

#### repayBorrowBehalf

Alternatively, you could have executed the same logic in the code snippet above using the `repayBorrowBehalf` method. For example, you could have used `repayBorrowBehalf(borrower,repayAmount)` to repay `repayAmount` on behalf of `borrower`.

The `repayBorrowBehalf()` method is particularly useful for repaying ETH debt. Because ETH is required for gas, calculating how much ETH you need to repay ETH debt can be difficult. For example, if you wanted to repay a full ETH balance, you would need to calculate the gas required for the transaction as well as the interest accrued. Instead of trying to predict the exact gas usage plus interest accrual, you can repay full ETH debts by using a special contract called the `Maximillion` contract. The `Maximillion` contract lets you send extra ETH along with your transaction. The contract repays your debt using `repayBorrowBehalf()`, then refunds you the excess after paying back all debt.

The following code snippet illustrates using the `Maximillion` contract to repay ETH debt.

{% code title="manage-protection.ts" %}

```typescript
// Repay all ETH debt with the Maximillion contract (we actually have
// zero ETH debt in the script, but that's ok). First we get an
// instance of the Maximillion contract
const maximillionAddress = getContractAddress('Maximillion', chainId);
const maximillion = new Contract(maximillionAddress, maximillionAbi, signer);

// Get the address of the Cozy ETH Money Market
const ethMarketAddress = getContractAddress('CozyETH', chainId);

// Now we do the repay. In this case our debt is zero, so any ETH sent
// is excess ETH that will be refunded after repaying the debt. Notice
// how we specify that we are repaying debt for ourselves,
// `signer.address`, and we specify the address of the market to repay
// debt in, `ethMarketAddress`. (We don't look for the success logs
// since this is a dummy transaction and we have no debt, but in
// practice you should).
const value = parseUnits('0.1', 18); // ETH has 18 decimals
const repayEthTx = await maximillion.repayBehalfExplicit(signer.address, ethMarketAddress, { value });
```

{% endcode %}


# Provide protection programmatically

Learn how to provide protection by supplying assets to a protection market programmatically.

Cozy provides a protected borrowing marketplace for investing in decentralized finance protocols that offer protection against a loss of funds. You can participate in this marketplace by supplying assets to an existing protection market. After you deposit assets, you earn interest on the deposit from investors who borrow from the protection market. You continue earning interest as long If the protection market operates without having a trigger event occur. If there is a hack, exploit, or other problem that triggers protection in the market where you have supplied assets, all outstanding debts in that market are forgiven. The interest you earn is your reward for taking on the risk associated with trigger event. In evaluating the risk involved, you should consider how likely it will be for a particular market's trigger condition to be satisfied.

This guide illustrates how you can write a script using TypeScript that you can then use to supply assets to a protection market programmatically.

All code snippets are from the `provide-protection.ts` script in the [Cozy Developer Guides](https://github.com/Cozy-Finance/cozy-developer-guides) repository. See that repository for more context, definitions of helper methods used, etc.

{% hint style="info" %}
Everything in this guide assumes that you have experience with JavaScript, [ethers.js](https://github.com/ethers-io/ethers.js/), and [Solidity](https://docs.soliditylang.org/en/latest/).
{% endhint %}

## Supply assets to a protection market

Before you can provide protection, you need to identify the asset you want to deposit and select the protection market where you want the assets you supply to be used.

All markets in Cozy—money markets and protection markets—have a `trigger` state variable. If the value of the `trigger` property is the [zero address](https://etherscan.io/address/0x0000000000000000000000000000000000000000), the money market does not have a trigger contract associated with it. A money market that does not have a trigger contract associated with it cannot be used for protected borrowing, but can be used for ordinary borrowing. If the value of the `trigger` property is anything except the zero address, the value of the `trigger` property represents the address of the trigger contract associated with that market. Only Cozy markets that have a trigger contract can be used for protected borrowing.

If you want to provide assets to a market for protected borrowing and to earn interest from the borrowers participating in that market, you need to verify that the market is a supported protection market. To see how to do that, let's assume the following:

* You have 1000 USDC that you want to deposit.
* You want to use that asset to provide protection to a Yearn Protection Market for yUSDC.

The following code snippet illustrates how you can verify that the Yearn market is part of the Cozy protocol.

{% code title="provide-protection.ts" %}

```javascript
// STEP 0: ENVIRONMENT SETUP
const supplyAmount = '1000'; // Amount of USDC we want to supply, in dollars (e.g. 1000 = $1000 = 1000 USDC)

// Since we are testing on a forked mainnet and our account has no
// funds, we need to initialize the account with the required tokens.
// This step is not needed when the private key in your .env file has
// funds on mainnet
const usdcAddress = getContractAddress('USDC', chainId);
await fundAccount(usdcAddress, supplyAmount, signer.address, hre);

// If the account also needed ETH, you could fund it as shown here
const ethAddress = getContractAddress('ETH', chainId);
await fundAccount(ethAddress, '10', signer.address, hre);

// STEP 1: VERIFY MARKET
// We know we'll need the Comptroller, so create an instance the Comptroller contract
const comptrollerAddress = getContractAddress('Comptroller', chainId);
const comptroller = new Contract(comptrollerAddress, comptrollerAbi, signer); // connect signer for sending transactions

// The first check is to make sure our protection market is a valid
// protection market that we can supply to
const yearnProtectionMarketAddress = getContractAddress('YearnProtectionMarket', chainId);
const allMarkets = await comptroller.getAllMarkets();
if (!allMarkets.includes(yearnProtectionMarketAddress)) {
  logFailure("Provided Protection Market address not found in the Comptroller's list of all markets");
  return;
}
logSuccess('Provided Protection Market address is valid');
```

{% endcode %}

After verifying the market to which you plan to supply assets is a valid protection market according to the Cozy protocol's Comptroller, you are ready to supply assets to the market. In this example, you are supplying 1000 USDC and USDC has 6 decimal places, so your script needs to account for that.

The following code and comments describe how to adjust the units to 6 decimal places, approve the protection market to spend your USDC, then supply funds to the protection market.

{% code title="provide-protection.ts" %}

```javascript
// STEP 2: PROVIDE PROTECTION
// We're now ready to supply collateral (i.e. provide protection) to
// the market, but there's some preparation we need to do beforehand.
// First, recall that USDC has 6 decimal places, so we need to take
// that into account. We'll do this programmatically by querying the
// USDC contract for the number of decimals it has
const usdc = new Contract(usdcAddress, erc20Abi, signer);
const decimals = await usdc.decimals();
const parsedSupplyAmount = parseUnits(supplyAmount, decimals); // scale amount based on number of decimals

// Next we need to approve the protection market contract to spend
// our USDC. We trust the contract, so approve it to spend the
// maximum possible amount to avoid future approvals and save gas
const approveTx = await usdc.approve(yearnProtectionMarketAddress, MaxUint256);
await approveTx.wait();

// Let's verify this approve transaction was successful
const allowance = await usdc.allowance(signer.address, yearnProtectionMarketAddress);
if (!allowance.eq(MaxUint256)) {
  logFailure('CozyUSDC does not have sufficient allowance to spend our USDC. Exiting script');
  return;
}
logSuccess('Approval transaction successful. Ready to mint CozyUSDC with our USDC');

// Now we can supply funds to the protection market to provide
// protection. Just like with ordinary Money Markets, this mints a
// receipt token that is sent to our wallet
const yearnProtectionMarket = new Contract(yearnProtectionMarketAddress, cozyTokenAbi, signer);
const mintTx = await yearnProtectionMarket.mint(parsedSupplyAmount);
const { log: mintLog, receipt: mintReceipt } = await findLog(mintTx, yearnProtectionMarket, 'Mint', provider);
const yearnProtectionMarketSymbol = await yearnProtectionMarket.symbol();
const yearnProtectionMarketName = await yearnProtectionMarket.name();
logSuccess(
  `${yearnProtectionMarketName} (${yearnProtectionMarketSymbol}) successfully minted in transaction ${mintReceipt.transactionHash}`
);
```

{% endcode %}

### Verify transaction results

In some cases, a `mintTx` transaction can appear to be successful without the mint operation actually being successful.

Because of how Cozy does error handling, transactions can be successful—and be displayed as successful on Etherscan and other block explorers—but without doing what you expected. For example, if a transaction returns an error code and emits a `Failure` event instead of reverting, it might appear as if the transaction was successful when it has actually failed.

You can read more about error codes and failures in [Error codes](/staging/for-developers/error-codes), and see information about error handling history [here](https://www.comp.xyz/t/brief-history-of-error-handling-in-the-protocol/1169).

You should manually ensure the mint transaction succeeded before continuing to the next step. You can use the `findLog()` helper method to simplify the verification process. For more details about using the `findLog()` method, see the [utils.ts](https://github.com/Cozy-Finance/cozy-developer-guides/blob/master/utils/utils.ts) file in the [Cozy developer Guides](https://github.com/Cozy-Finance/cozy-developer-guides) repository.

After you manually verify that your transaction was successful, your 1000 USDC are used to provide protection in the Yearn yUSDC protection market.


# Liquidate a vault

Learn how to liquidating a vault programmatically on the Cozy protocol.

Users who borrow funds are required to maintain a minimal level of account liquidity. If their account falls below the minimum liquidity threshold, they risk liquidation and losing their collateral.

Users can avoid liquidation by adding collateral or repaying debts. If a user with an account at risk of liquidation fails to respond—by adding collateral or repaying outstanding debt—the account will eventually have negative account liquidity, also known as a shortfall. Any user account with negative account liquidity can be liquidated and taken over programmatically by someone else. By liquidating an account with a shortfall, you can seize its assets at a discount.

This guide illustrates how you can liquidate vaults programmatically using a script written in TypeScript.

All code snippets in this guide are from the [`liquidate.ts` script](https://github.com/Cozy-Finance/cozy-developer-guides/blob/master/guides/liquidate.ts) in the [Cozy developer guides](https://github.com/Cozy-Finance/cozy-developer-guides) repository. See that repository for more context, definitions of helper methods used, and related information.

{% hint style="info" %}
Everything in this guide assumes that you have experience with JavaScript, [ethers.js](https://github.com/ethers-io/ethers.js/), and [Solidity](https://docs.soliditylang.org/en/latest/), as well familiarity with the Cozy protocol.
{% endhint %}

## Check account liquidity

The collateral value of an account is computed by multiplying the supplied USD balance in a market by that market's collateral factor, and summing the result across all markets. The total USD borrow balances for a user are subtracted from that result to arrive at the account liquidity value.

Only accounts with negative liquidity, also known as a shortfall, can be liquidated. Therefore, before liquidating an account, you need to check whether the account has a shortfall. The following code snippet illustrates how to check if an account has a shortfall using an arbitrary address.

% hint style="info" %} The sample script uses an arbitrary address because there's no way to guarantee there is a mainnet account with negative liquidity that could actually be liquidated. The comments describe what to expect if the arbitrary account could be liquidated.

{% code title="liquidate.ts" %}

```typescript
// STEP 1: CHECK ACCOUNT LIQUIDITY

// Get instance of Comptroller contract and connect signer for sending transactions
const comptrollerAddress = getContractAddress('Comptroller', chainId);
const comptroller = new Contract(comptrollerAddress, comptrollerAbi, signer);

// Define the address to liquidate and check their liquidity
const borrowerToLiquidate = '0x0000000000000000000000000000000000000001';
const [errorCode, liquidity, shortfall] = await comptroller.getAccountLiquidity(borrowerToLiquidate);

// Make sure there were no errors reading the data
if (errorCode.toString() !== '0') {
  logFailure(`Could not read liquidity. Received error code ${errorCode}. Exiting script`);
  return;
}

// There were no errors, so now we check if we have an excess or a shortfall. 
// One and only one of `shortfall` and `liquidity` will be above zero. (Since
// our chosen account above has no shortfall, you'll need to comment out the
// return statements to move past this section)
if (shortfall.gt(Zero)) {
  logSuccess(`Account is undercollateralized and can be liquidated! Shortfall amount: ${shortfall}`);
} else if (liquidity.gt(Zero)) {
  logFailure(`Account has excess liquidity and is safe. Amount of liquidity: ${liquidity}. Exiting script`);
  return;
} else {
  logFailure('Account has no liquidity and no shortfall. Exiting script.');
  return;
}
```

{% endcode %}

## Liquidate an account

If the script had found that the arbitrary account had a shortfall, it would proceed with liquidating the account. In liquidating the account, you can configure the script to repay some or all of the outstanding debt on behalf of the borrower. As a result of the liquidation, you receive some of the borrower's collateral at a discount. Receiving a portion of a borrower's collateral at a discount is referred to as the liquidation incentive.

As an account liquidator, you first need to determine the maximum percentage of the outstanding debt for an account that can be closed by repayment.

The following code snippet illustrates how to check the maximum percentage—called the close factor—that can be closed by liquidation:

{% code title="liquidate.ts" %}

```typescript
// STEP 2: PERFORM LIQUIDATION

// Check the max close factor that can be liquidated for Cozy
const closeFactor = await comptroller.closeFactorMantissa();
logSuccess(`Close factor: ${formatUnits(closeFactor, 18)}`);
```

{% endcode %}

As part of the liquidation process, you can choose one of the assets that were supplied as collateral by the borrower as the asset you'll seize and receive at a discount. If needed, you could get a list of available collateral using the `getAssetsIn()` method described in [Viewing Positions](/staging/for-developers/guides/how-do-i-manage-protection-programmatically#view-positions) guide. For simplicity, the following code snippet assumes the collateral is ETH and the borrow is a protected Yearn yUSDC vault, then checks how much this user has borrowed and computes the maximum repay amount.

{% code title="liquidate.ts" %}

```typescript
// Get contract instances
const cozyEthAddress = getContractAddress('CozyETH', chainId);
const yearnProtectionMarketAddress = getContractAddress('YearnProtectionMarket', chainId);
const yearnProtectionMarket = new Contract(yearnProtectionMarketAddress, cozyTokenAbi, signer);

// Next we choose an amount of their debt to repay. The max amount we
// can repay is equal to the closeFactor multiplied by their borrow
// balance, so let's check their borrow balance
const usdcBorrowed = await yearnProtectionMarket.borrowBalanceStored(borrowerToLiquidate);

// If we wanted to liquidate the max amount, we can compute this
// below. Here we divide the amount by 1e18 because we multiply the
// USDC amount (6 decimals) by the closeFactor (18 decimals), giving
// us a 24 decimal number. The liquidation amount should be in units
// of the borrowed asset, which is USDC, so we divide by 1e18 to get
// there
const scale = '1000000000000000000'; // 1e18
const repayAmount = usdcBorrowed.mul(closeFactor).div(scale);
logSuccess(`Ready to repay ${repayAmount.toString()} USDC`);
```

{% endcode %}

After the collateral is seized, the seized amount is transferred as Cozy tokens. Those tokens can be redeemed as if you had supplied the collateral asset yourself. Remember to approve the Cozy token contract to spend your tokens before calling `liquidateBorrow()`.

The following code snippet illustrates executing the liquidation. However, in this case, the account to liquidate does not have a shortfall. Therefore, the `findLog()` method reports that the `LiquidateBorrow` event was not found and prints an error code (3) this corresponds to the `COMPTROLLER_REJECTION` failure message. Looking at the Comptroller's `liquidateBorrowAllowed` hook, you can find that the Comptroller rejected the liquidation because there is no shortfall.

{% code title="liquidate.ts" %}

```typescript
// Execute the liquidation
const tx = await yearnProtectionMarket.liquidateBorrow(borrowerToLiquidate, repayAmount, cozyEthAddress);
await findLog(tx, yearnProtectionMarket, 'LiquidateBorrow', provider);
```

{% endcode %}


# Create a protected investing opportunity

Learn how to create a protected investment opportunity for another DeFi protocol.

After obtaining protection via a Cozy protection market, many users will want to deploy the newly borrowed funds to earn yield. That’s where Cozy Protected Investing comes in.

Cozy Protected Investing enables users to borrow, invest and track returns in one step, in one place. This guide details how you can create a Protected Investment opportunity for users on [cozy.finance](https://app.cozy.finance) or on your DeFi app.

## Deploy a protection market

Each Cozy Protected Investment opportunity requires a corresponding Protection Market. Please refer to the [Create a protection market](/staging/for-developers/guides/how-do-i-create-a-protection-market#step-3-protection-market-deployment) guide for details on developing and deploying trigger and protection market contracts.

## Adding protected investment opportunities to the Cozy app

### Deploy an invest/divest contract

Protection markets cover the borrow-side of an investment opportunity; however, you’ll also need to provide instructions for how the borrowed funds should be invested.  For this, you’ll deploy an additional contract that is responsible for investing, divesting and managing any other assets related to the investment position (e.g. reward tokens or airdrops).

Please refer to [Create an invest/divest contract guide](/staging/for-developers/guides/how-do-i-create-an-invest-divest-contract) for details on developing and deploying an invest/divest contract.

### Data fetching

The Cozy app requires a few pieces of data to support an investment opportunity. The Cozy subgraph (covered in detail below) supplies much of this data, but the subgraph is limited to Cozy protocol-specific data (i.e. protection markets and positions in those markets). Data related to an investment opportunity on a separate DeFi protocol requires a separate data source.

That’s why it’s necessary to create an endpoint — on a per opportunity basis — which is responsible for investment performance data as well as data that facilitates invest/divest contract interaction. This endpoint — referred to as the opportunity's `dataURI` — uniquely identifies that opportunity.

Assuming a `dataURI` ending in `/new-opty`, this data endpoint must handle the following query parameters:

#### No query params

`/new-opty` - returns base data about the investment opportunity, like the rate of return, the remaining capacity to be deposited into the opportunity and whether the opportunity is disabled. Sample response:

```json
// Typical
{
  "isDisabled": false,
  "investCapacity": "991422.323294438226440458",
  "investRate": 0.07662908620704814
}

// Two Step Invest Flow
{
  /* All fields from typical return plus... */
  "investFlow": "twoStepInvest",
  "twoStepDeployTime": "Friday at 10am PST"
}
```

| **Typical Fields** | **Description**                                                                                                                                                                                                                                |
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| isDisabled         | Boolean. Whether the investment opportunity is still accepting funds. All invest transactions will fail if this is true.                                                                                                                       |
| investingCapacity  | String. The amount of funds in human-readable units which the investment opportunity can accept. The invest transaction will fail in an attempt to deposit funds beyond this amount. Null if there is no maximum capacity for the opportunity. |
| investRate         | Number. The percentage return in decimal form associated with funds invested into this opportunity. The investRate minus the borrowRate equals the netReturnRate — or the overall APY — associated with this opportunity.                      |

| **Two Step Invest Fields** | **Description**                                                                                                                                                                                                                                                                                                                                               |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| investFlow                 | String. Sometimes, an investment opportunity will have a non-standard flow. The Cozy app currently supports only one non-standard flow: the `twoStepInvest` flow. This flow is used by protocols like Ribbon, in which funds are not immediately deployed to an investment strategy when deposited, but instead batched into a single deployment each period. |
| twoStepDeployTime          | String. The time when funds in a `twoStepinvest` opportunity are deployed, for display in the UI, of the format “ at ”                                                                                                                                                                                                                                        |

#### Ethereum account

`/new-opty?account=<ethereumAccount>` - returns all the data of the base `new-opty` endpoint, but adds balance information for the passed in Ethereum account. Sample response:

```json
// Typical Response
{
  /* All fields from base response plus... */
  "balances": {
    "balanceUnderlying": "0.00089522599655054241457996374997540428",
    "balanceUsd": 2.526979298059575,
    "lastUpdatedBlockNumber": 7368120,
    "receiptTokenBalances": [
      {
        "balance": "0.001678155500972884",
        "balanceUnderlying": "0.00089309310068732528257996374997540428",
        "balanceUsd": 2.520958713635045,
        "token": {
          "chainId": 42161,
          "address": "0x8e0b8c8bb9db49a46697f3a5bb8a308e744821d2",
          "decimals": 18,
          "name": "Curve.fi USD-BTC-ETH",
          "symbol": "crv3crypto"
        }
      }
    ],
    "rewardTokenBalances": [
      {
        "balance": "0.002417905391377535",
        "balanceUnderlying": "0.000002132895863217132",
        "balanceUsd": 0.006020584424530063,
        "token": {
          "chainId": 42161,
          "address": "0x11cdb42b0eb46d95f990bedd4695a6e3fa034978",
          "decimals": 18,
          "name": "Curve DAO Token",
          "symbol": "CRV"
        }
      }
    ],
    "totalWithdrawableAmount": "1678155500972884"
  }
}

// Two Step Invest Flow
{
  /* All fields from the typical response plus...  */
  "pendingDepositsUnderlying": "100000000000000000000",
  "scheduledWithdrawalReady": true,
  "scheduledWithdrawalUnderlying": "100000000000000000000",
}
```

| **Typical Response Fields** | **Description**                                                                                                                                                                                                                       |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| balanceUnderlying           | String. The total value of the position in human-readable units of underlying from the borrow market for the investment opportunity                                                                                                   |
| balanceUsd                  | Number. The total value of the position in USD                                                                                                                                                                                        |
| lastUpdatedBlockNumber      | Number. The block number corresponding to the data in this response. Used for communicating the sync-status of the data currently being presented. (i.e. does the state of the invest position data match the data from the subgraph) |
| receiptTokenBalances        | Array. An array of the receipt tokens associated with this position                                                                                                                                                                   |
| rewardTokenBalances         | Array. An array of the reward tokens associated with this position                                                                                                                                                                    |
| totalWithdrawableAmount     | String. The number of receipt tokens as a raw, contract-friendly string that can be redeemed when divesting from the investment opportunity                                                                                           |

| **Two Step Invest Fields**    | **Description**                                                                                                                                                                    |
| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| pendingDepositsUnderlying     | String. The amount of funds in human-readable units of underlying that have been deposited into the protocol but not yet deployed to earn yield                                    |
| scheduledWithdrawalReady      | Boolean. Whether funds that were previously scheduled to be withdrawn are now ready to be withdrawn                                                                                |
| scheduledWithdrawalUnderlying | String. The amount of funds in human-readable units of underlying that were previously scheduled to be withdrawn but require additional time before they are ready to be withdrawn |

| **Token Info Fields** | **Description**                                                                                                                      |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| balance               | String. Balance in human-readable units of this token for the investment account                                                     |
| balanceUnderlying     | String. The value of this token balance, in human-readable units of underlying from the borrow market for the investment opportunity |
| balanceUsd            | Number. The value of this token balance, in USD                                                                                      |
| decimals              | Number. The number of decimals to divide a raw balance by to produce its human-readable form                                         |
| token                 | Object. The standard details of an erc20 token                                                                                       |

{% hint style="info" %}
When describing balance fields in this guide, we will always refer to their units as either raw or human-readable. Raw fields are the format used by smart contracts that have no decimal places. If you divide a raw value by Math.pow(10, decimals), you get the human-readable form.
{% endhint %}

#### Invest params

`/new-opty?invest=[<marketContractAddress>, <investAmountInUnderlying>]` - returns the parameters which will be passed into the `invest` method of the invest/divest contract deployed for this investment opportunity. Sample response:

```json
// For invest function signature:
// function invest(address _ethMarket, uint256 _borrowAmount, uint256 _curveMinAmountOut) external payable
[
  '0x7d4377114fd3c61c59d72de48102bf6acd3882b1', // Cozy market address
  '697746377352637', // borrow armount in underlying
  '442383085561', // min amount out for call to Curve pool
];
```

#### Divest params

`/new-opty?invest=[<marketContractAddress>, <divestAmountInUnderlying>, <eoaAddress>]` - returns the parameters which will be passed into the `divest` method of the invest/divest contract deployed for this investment opportunity. Sample response

```json
// For divest function signature:
// function divest(address _ethMarket, address _recipient, uint256 _redeemAmount, uint256 _curveMinAmountOut) external payable
[
  '0x7d4377114fd3c61c59d72de48102bf6acd3882b1', // market address
  '0x123abc123abc123abc123abc123abc123abc123a', // EOA address
  '1678155500972884', // redeem amount in LP tokens
  '855549635374828', // min amount out for call to Curve pool
];
```

### Surfacing

Cozy displays investment opportunities based on a set of `market-lists` maintained in the `cozy-invest-lists` repo. Inspired by [Uniswap’s `token-lists`](https://github.com/Uniswap/token-lists) standard, all [Cozy `market-lists`](https://github.com/Cozy-Finance/market-lists) conform to a simple, JSON schema.

Once all the smart contracts related to your investment opportunity have been deployed, you can create a new protection market entry in the `community` `protection-market-list` in Cozy’s `cozy-invest-lists` repo and submit a PR. Make sure to validate your entry to the schema using the validation framework found in the `protection-market-list` schema.

Amongst other things, your list entry will include:

* Invest/divest contract details: the contract addresses and signatures of the invest/divest contracts you deployed
* Investment opportunity strategy: a description of the steps taken when borrowed funds are deployed

Sample `protection-market-list` entry:

```json
{
  "chainId": 42161,
  "address": "0x7d4377114fd3c61c59d72de48102bf6acd3882b1",
  "symbol": "Cozy-ETH-1",
  "name": "Cozy-ETH-1-Curve 3Crypto Trigger",
  "decimals": 8,
  "tags": [],
  "trigger": "0x73ea553cd95211956420329c2c7d23851c577725",
  "underlying": {
    "chainId": 1,
    "decimals": 18,
    "address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
    "name": "Ether",
    "symbol": "ETH"
  },
  "investmentOpportunities": [
    {
      "invest": {
        "address": "0x551F34Ba6cd876CAe2265DA1f3e030e82f703A13",
        "signature": "function invest(address _ethMarket, uint256 _borrowAmount, uint256 _curveMinAmountOut) external payable"
      },
      "divest": {
        "address": "0x551F34Ba6cd876CAe2265DA1f3e030e82f703A13",
        "signature": "function divest(address _ethMarket, address _recipient, uint256 _redeemAmount, uint256 _curveMinAmountOut) external payable"
      },
      "dataURI": "https://cozy-api-k1ojdh8ct-cozy-finance.vercel.app/api/opportunities/arb-eth-tricrypto",
      "logoURI": "https://app.cozy.finance/images/tokens/crvtricrypto.png",
      "name": "crvTricrypto",
      "tokens": {
        "input": [
          {
            "chainId": 1,
            "decimals": 18,
            "address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
            "name": "Ether",
            "symbol": "ETH"
          }
        ],
        "receipt": [
          {
            "chainId": 42161,
            "address": "0x8e0b8c8bb9db49a46697f3a5bb8a308e744821d2",
            "decimals": 18,
            "name": "Curve.fi USD-BTC-ETH",
            "symbol": "crv3crypto"
          }
        ],
        "rewards": [
          {
            "chainId": 1,
            "address": "0xd533a949740bb3306d119cc777fa900ba034cd52",
            "decimals": 18,
            "name": "Curve DAO Token",
            "symbol": "CRV"
          }
        ]
      },
      "strategy": [
        {
          "action": "Borrow",
          "object": "ETH",
          "logoURI": "https://app.cozy.finance/images/tokens/eth.png",
          "platformId": 0,
          "token": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
        },
        {
          "action": "Deposit to",
          "object": "crvTricrypto",
          "logoURI": "https://app.cozy.finance/images/tokens/crvtricrypto.png",
          "platformId": 3,
          "token": "0x8e0b8c8bb9db49a46697f3a5bb8a308e744821d2"
        }
      ]
    }
  ]
}
```

| **Selected Fields**     | **Description**                                                                                                                                                                                                                                              |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| platformId              | Number. Cozy’s ID for the platform to which funds will be deposited; please consult the [Cozy-Finance/platform-ids repo](https://github.com/Cozy-Finance/platform-ids) for the correct `platformId` and submit a PR to add your protocol if it’s not listed. |
| tokens#input            | Object. Details on tokens that are deposited to enter into the opportunity                                                                                                                                                                                   |
| tokens#receipt          | Object. Details on tokens that are returned in receipt when an opportunity is entered; these tokens are exchanged again to exit the position.                                                                                                                |
| tokens#rewards          | Object. Details on all the tokens which may be accrued as rewards while a position is active                                                                                                                                                                 |
| divest#address          | String. Address of the invest/divest contract you deployed                                                                                                                                                                                                   |
| divest#signature        | String. Signature of the divest function on the invest/divest contract you deployed                                                                                                                                                                          |
| invest#address          | String. Address of the invest/divest contract you deployed                                                                                                                                                                                                   |
| invest#signature        | String. Signature of the invest function on the invest/divest contract you deployed                                                                                                                                                                          |
| strategy                | Array. Array of `strategyLegs` which capture the steps an investment opportunity takes when deploying funds; used only for display in the UI.                                                                                                                |
| strategy#action         | String. The action taking place in this leg of the investing strategy                                                                                                                                                                                        |
| strategy#actionReceiver | String. The receiver of the action taking place (grammatically, the direct or indirect object)                                                                                                                                                               |

### PR review

After submitting your new protection market list entry to the `cozy-invest-lists` repo for PR, we’ll review your invest/divest contracts and test your `dataURI` endpoint to ensure everything is working properly. Please ensure your invest/divest contracts are verified on [Etherscan](https://etherscan.com/), so we can review the code.

## Adding protected investment opportunities to your DeFi app

Hosting a protected investment opportunity on your site is easy and allows new users to engage with your project while staying protected.

### Depositing collateral

To enter into a protected investing position, a user must first have supplied collateral to borrow against. This collateral must be supplied to a Cozy money market, a process is [detailed in this guide](/staging/for-developers/guides/how-do-i-buy-protection-programmatically#supply-collateral).

Each market has a `collateralFactor` which is applied to funds deposited into a money market that determines how much funds can be borrowed by that account (i.e. If $100 was supplied to a money market with a 0.75 collateral factor, that account can borrow $75).

If a user’s borrows exceed the total value of their collateral, they will be subject to liquidation.

### Entering a protected investing position

In order to create a protected investing position, the flow is as simple as:

1. Borrow from the Cozy protection market you just deployed. See this guide on how to [Buy protection programmatically](/staging/for-developers/guides/how-do-i-buy-protection-programmatically#borrow-funds). Note: a user must have already deposited collateral for the borrow to succeed!
2. Follow the same logic your app usually does for entering into a new position, for the amount that was borrowed.

### Tracking an investing position

To track the performance of the investing position, you’ll need data on both the borrow-side and invest-side of the position (from the Cozy market side and other DeFi protocol side, respectively).

The [Cozy Subgraph](https://thegraph.com/hosted-service/subgraph/cozy-finance/cozy) supplies all the data for borrow-side. For example, the user’s collateral balance, how much borrowing power they have and their protected borrow balance can all be found in the Cozy Subgraph.

The subgraph automatically indexes all Cozy protection markets and indexes all positions which are opened on those markets. In the subgraph, these are represented by `Market` & `AccountCToken` entities.

Please see discussion of these two entities below, but for additional information consult the comments in the Schema panel of the [subgraph’s page](https://thegraph.com/hosted-service/subgraph/cozy-finance/cozy).

#### Markets

The `Market` entity holds a lot of critical information for presenting a Cozy protection market including:

* Basic descriptive data: the name, symbol, underlying of the market and associated trigger contract address
* Key numbers used by the protocol: borrow cap, exchange rate, borrow rate

| **Selected Market Fields** | **Description**                                                                                                                                                                                                                        |
| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| borrowCap                  | String. Total cumulative amount in human-readable units of underlying that can be borrowed from a market at one time                                                                                                                   |
| borrowRate                 | String. The annualized interest rate in decimal form users must pay to borrow from a market                                                                                                                                            |
| exchangeRate               | String. The exchange rate of underlying / receipt token in decimal form                                                                                                                                                                |
| cash                       | String. The amount in human-readable underlying available to be borrowed on a market. Any borrow transactions greater than the available cash in the market will fail.                                                                 |
| collateralFactor           | String. Factor applied to the supplied funds of a money market that determines how much funds can be borrowed by that account (i.e. If $100 was supplied to a money market with a 0.75 collateral factor, that account can borrow $75) |

#### AccountCTokens

The `AccountCToken` entity represents a position opened by a user on a protection market. It includes data on:

* Current balances of the position: the cToken balance and the stored borrow balance
* Historical tabulations for this user in the market: total underlying borrowed, repaid, supplied or redeemed

| **Selected AccountCTokens Fields** | **Description**                                                                                                                                                                              |
| ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| cTokenBalance                      | String. The receipt token balance of this position in human-readable units                                                                                                                   |
| enteredMarket                      | Boolean. Whether the user’s supplied funds should be used as collateral for other borrows (see guide on supplying collateral)                                                                |
| storedBorrowBalance                | String. Current borrow balance stored in the protocol contracts in human-readable units (excludes interest since last accrual block; see calculations below to get up-to-date borrowBalance) |

#### Key calculations

To calculate the borrow balance of a position in underlying:

```javascript
const borrowBalanceUnderlying =
  position.storedBorrowBalance * market.borrowIndex /
  position.accountBorrowIndex;
```

To calculate the supply balance of a position in underlying:

```javascript
const supplyBalanceUnderlying = position.cTokenBalance * market.exchangeRate;
```

### Exiting a position

To close out a position, follow the opposite steps to opening it:

1. Follow the normal steps for closing a position in your protocol.
2. Repay the Cozy protection market using the funds just received from closing the position on your protocol. For details on repaying debt on Cozy, please consult the [Repay Debt](/staging/for-developers/guides/how-do-i-manage-protection-programmatically#repay-debt) section of the [Manage protection programmatically](/staging/for-developers/guides/how-do-i-manage-protection-programmatically) guide.


# Create an invest/divest contract

Learn how to create an invest/divest contract for an investment opportunity.

## Create an invest/divest contract

Invest/divest smart contracts are used to programmatically borrow from Cozy protection markets and/or Cozy unprotected money markets and invest into DeFi products for investors in on-chain protocols, such as [Yearn Finance](https://yearn.finance/#/home).

At a high-level, the contract needs the following `external` functions to be implemented:

1. `invest`: Automates borrowing from Cozy markets and investing the borrowed funds in a DeFi product.
2. `divest`: Automates closing positions in a DeFi product that were opened with the contract's `invest` function and repays debt in the Cozy market.
3. `claimRewards`: If the investment opportunity accrues reward tokens, this function is required to claim them and transfer them to the investor's wallet.

Additionally, invest/divest contracts are intended to be used by delegatecalling to them from a proxy wallet to borrow, invest, and divest on behalf of the user. This means these contracts **cannot** be used directly with EOAs, as EOAs cannot execute code and therefore the investments will occur on behalf of the invest contract, and not on behalf of the user.

At Cozy, we use [DSProxy wallets](https://github.com/dapphub/ds-proxy) alongside a `DSProxyMulticall` helper contract which allows batched execution of a sequence of contract calls, without the need for deploying a new "script" contract for each sequence (additional context can be found in `DSProxyMulticall.sol` in the [Cozy Developer Guides](https://github.com/Cozy-Finance/cozy-developer-guides)). The address of the `DSProxyMultiCall` contract can be found in the [Cozy Subgraph](https://thegraph.com/hosted-service/subgraph/cozy-finance/cozy?query=Market%20List).

{% hint style="info" %}
The contract examples shown throughout this document can be referenced from the `CozyInvestCurve3CryptoEth.sol` and `CozyInvestConvex.sol` contracts in the [Cozy Developer Guides](https://github.com/Cozy-Finance/cozy-developer-guides) repository. `CozyInvestCurve3CryptoEth.sol` is an example of investing with ETH, and `CozyInvestConvex.sol` is an example of investing with ERC20 tokens.
{% endhint %}

{% hint style="info" %}
Everything in this guide assumes that you have experience with JavaScript, [ethers.js](https://github.com/ethers-io/ethers.js/), and [Solidity](https://docs.soliditylang.org/en/latest/).
{% endhint %}

### Contracts used by an invest/divest contract <a href="#step-1-trigger-contract-setup" id="step-1-trigger-contract-setup"></a>

An invest/divest contract needs to know the addresses of a few contracts found on the [Cozy Subgraph](https://thegraph.com/hosted-service/subgraph/cozy-finance/cozy?query=Market%20List):

* The address of the protection market contract to borrow from.
* If the underlying asset of the protection market is Ether (ETH), the address of the Maxmillion contract is required. The Maximillion contract is used to repay ETH debt to the protection market.
  * *Note*: Cozy uses `0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE` as the address the represent ETH.
* *Optional*: If you'd like to support unprotected investing, the address of the unprotected money market to borrow from.

In addition to the above, any contracts specific to investing and divesting from the target DeFi product are required (ie: a Curve liquidity pool, a Yearn Vault, etc.).

### Interfaces required for Cozy contracts

The following snippet includes interfaces for interacting with Cozy contracts required for borrowing.

{% code title="ICozy.sol" %}

```typescript
pragma solidity ^0.8.9;

interface ICozyShared {
  function underlying() external view returns (address);

  function borrow(uint256 borrowAmount) external returns (uint256);

  function borrowBalanceCurrent(address account) external returns (uint256);
}

// @dev Interface for a Cozy market with an ERC20 token underlying
interface ICozyToken is ICozyShared {
  function repayBorrowBehalf(address borrower, uint256 repayAmount) external returns (uint256);

  function repayBorrow(uint256 repayAmount) external returns (uint256);
}

// @dev Interface for a Cozy market with ETH underlying
interface ICozyEther is ICozyShared {
  function repayBorrowBehalf(address borrower) external payable;
}

// @dev Interface for the Maximillion contract used to repay ETH borrows
interface IMaximillion {
  function repayBehalfExplicit(address borrower, ICozyEther market) external payable;
}
```

{% endcode %}

### Develop the invest/divest contract constructor

The constructor for the invest/divest contract should be used to initialize any declared state variables required by the contract logic that were not initialized at the time they were declared. The state variables required may vary between different investment opportunities, but there are a few that should always be initialized:

* The protection market contract address to borrow from.
* If the underlying asset is ETH, the Maximillion contract address to repay borrows with.

The following snippet is an example of a constructor for an invest/divest contract for borrowing ETH from a market and investing into the [Curve](https://curve.fi) tricrypto pool.

{% code title="CozyInvestCurve3CryptoEth.sol" %}

```typescript
/**
 * @notice On-chain scripts for borrowing from a Cozy Curve 3Crypto Trigger protection market or 
 * ETH money market and using that ETH to add liquidity to the Curve tricrypto USDT/WBTC/WETH pool
 * @dev This contract is intended to be used by delegatecalling to it from a DSProxy
 */
contract CozyInvestCurve3CryptoEth {
  /// @dev OpenZeppelin's Address and SafeERC20 implementations are used for addresses and ERC20 tokens
  using Address for address payable;
  using SafeERC20 for IERC20;

  /// @notice Cozy protection market with ETH underlying to borrow from: Curve 3Crypto Trigger
  address public immutable protectionMarket;

  /// @notice Cozy unprotected money market with ETH underlying
  address public immutable moneyMarket;

  /// @notice Curve 3Crypto Deposit Zap -- helper contract for wrapping ETH before depositing
  ICrvDepositZap public immutable depositZap;

  /// @notice Curve 3Crypto Liquidity Gauge -- contract for measuring liquidity provided over time
  /// and distributing reward tokens
  ICrvGauge public immutable gauge;

  /// @notice Curve 3Crypto receipt token
  IERC20 public immutable curveLpToken;

  /// @notice Maximillion contract for repaying ETH debt
  IMaximillion public immutable maximillion;

  /// @dev Index of WETH in the curve `coins` mapping
  uint256 internal constant ethIndex = 2;

  constructor(
    address _moneyMarket,
    address _protectionMarket,
    address _maximillion,
    address _depositZap,
    address _gauge
  ) {
    moneyMarket = _moneyMarket;
    protectionMarket = _protectionMarket;
    maximillion = IMaximillion(_maximillion);
    gauge = ICrvGauge(_gauge);

    depositZap = ICrvDepositZap(_depositZap);
    curveLpToken = IERC20(depositZap.token());
  }

  ...
```

{% endcode %}

*Note*: The contract above uses the constructor to initalize state variables for required contract addresses to allow re-use among different chains; this is not required.

### Develop the invest logic

The `invest` function logic should automate borrowing from a valid protection market and investing the borrowed funds into a DeFi product.

The following snippet is an example of an `invest` function on an invest/divest contract for borrowing ETH and investing the borrowed ETH into the [Curve](https://curve.fi) tricrypto pool.

{% code title="CozyInvestCurve3CryptoEth.sol" %}

```typescript
/**
 * @notice Protected invest method for borrowing from given cozy ETH market,
 * and using that ETH to add liquidity to the Curve 3Crypto pool
 * @param _ethMarket Address of the market to borrow ETH from
 * @param _borrowAmount Amount of ETH to borrow and deposit into Curve
 * @param _curveMinAmountOut The minAmountOut we expect to receive when adding liquidity to Curve
 */
function invest(
  address _ethMarket,
  uint256 _borrowAmount,
  uint256 _curveMinAmountOut
) external payable {
  require(_ethMarket == moneyMarket || _ethMarket == protectionMarket, "Invalid borrow market");
  ICozyEther _market = ICozyEther(_ethMarket);

  // Borrow ETH from Cozy market. The return value from this method is an error code,
  // where a value of zero indicates no error (i.e. the borrow was successful)
  require(_market.borrow(_borrowAmount) == 0, "Borrow failed");

  // Add liquidity to Curve, which gives the caller a receipt token and returns the amount of receipt tokens received
  uint256 _balance = depositZap.add_liquidity{value: _borrowAmount}(
    [0, 0, _borrowAmount],
    _curveMinAmountOut,
    address(this)
  );

  // Approve the Curve tricrypto liquidity gauge to spend our receipt tokens using the safeApprove method. 
  // As mentioned in ERC-20, allowance is set to 0 first to prevent attack vectors 
  // on the approve method (https://eips.ethereum.org/EIPS/eip-20#approve). This is explicitly required by
  // some ERC-20 tokens, such as USDT.
  curveLpToken.safeApprove(address(gauge), 0);
  curveLpToken.safeApprove(address(gauge), type(uint256).max);

  // Deposit lp tokens in to liquidity gauge to earn reward tokens
  gauge.deposit(_balance);
}
```

{% endcode %}

Let's decompose the `CozyInvestCurve3CryptoEth.sol` snippet above:

1. An error check to ensure that a valid market is requested to be borrowed from. In this case, unprotected borrowing is also supported (optional).
2. Borrow from the market, wrapped within an error check to ensure the borrow was successful. *Note*: The borrow will fail if there is insufficient collateral supplied to the market by the sender for the desired borrow amount.
3. Logic specific to Curve for adding ETH liquidity to a pool and staking Curve LP tokens.

### Develop the divest logic

The `divest` function logic should automate closing positions in a DeFi product that were entered with the contract's `invest` function, repaying borrowed funds to Cozy markets, and transfering any earnings to the investor's wallet.

#### Logic for divesting ETH

The following snippet is an example of a `divest` function on an invest/divest contract for borrowing ETH and investing the borrowed ETH into the [Curve](https://curve.fi) tricrypto pool.

{% code title="CozyInvestCurve3CryptoEth.sol" %}

```typescript
/**
 * @notice Protected divest method for closing a position opened using this contract's `invest` method
 * @param _ethMarket Address of the market to repay ETH to
 * @param _recipient Address where any leftover ETH should be transferred
 * @param _redeemAmount Amount of Curve receipt tokens to redeem
 * @param _curveMinAmountOut The minAmountOut we expect to receive when removing liquidity from Curve
 */
function divest(
  address _ethMarket,
  address _recipient,
  uint256 _redeemAmount,
  uint256 _curveMinAmountOut
) external payable {
  require(_ethMarket == moneyMarket || _ethMarket == protectionMarket, "Invalid borrow market");

  ICozyEther _market = ICozyEther(_ethMarket);

  // Withdraw lp tokens from liquidity gauge
  gauge.withdraw(_redeemAmount);

  // Approve Curve's depositZap to spend our receipt tokens using the safeApprove method.
  // As mentioned in ERC-20, allowance is set to 0 first to prevent attack vectors 
  // on the approve method (https://eips.ethereum.org/EIPS/eip-20#approve). This is explicitly required by
  // some ERC-20 tokens, such as USDT.
  curveLpToken.safeApprove(address(depositZap), 0);
  curveLpToken.safeApprove(address(depositZap), type(uint256).max);

  // Withdraw from Curve
  depositZap.remove_liquidity_one_coin(_redeemAmount, ethIndex, _curveMinAmountOut, address(this));

  // Pay back as much of the borrow as possible, excess ETH is refunded to `recipient`. Maximillion handles
  // error codes when repayment is unsuccessful.
  maximillion.repayBehalfExplicit{value: address(this).balance}(address(this), _market);

  // Transfer any remaining funds to the user
  payable(_recipient).sendValue(address(this).balance);

  // Claim reward tokens from liquidity gauge and transfer to the user
  claimRewards(_recipient);
}
```

{% endcode %}

Let's decompose the `CozyInvestCurve3CryptoEth.sol` snippet above:

1. An error check to ensure that a valid market is requested to repay debt to. In this case, unprotected borrowing is also supported (optional).
2. Logic specific to Curve for closing the investment position; unstaking Curve LP tokens and withdrawing liquidity from Curve (in this case, ETH).
3. Cozy market debt repayment. Any remaining funds after repayment are transferred to the user. In this case, the underlying asset is ETH, so the Maximillion contract is used which includes error code handling.
4. Curve reward tokens are claimed and transferred to the user. This is only required for investment opportunities that accrue rewards.

#### Logic for divesting ERC20 tokens

There are a few notable differences for divesting ERC20 tokens, as shown in the following example of a `divest` function on an invest/divest contract for borrowing WBTC and depositing the borrowed WBTC into the [Curve](https://curve.fi) TBTC pool for receipt tokens, then staking the receipt tokens in the [Convex](https://www.convexfinance.com) TBTC pool.

{% code title="CozyInvestConvex.sol" %}

```typescript
/**
  * @notice Protected divest method for exiting a position entered using this contract's `invest` method
  * @param _market Address of the market to repay debt to
  * @param _recipient Address where any leftover funds should be transferred
  * @param _withdrawAmount Amount of Curve receipt tokens to redeem
  * @param _excessTokens Quantity to transfer from the caller into this address to ensure
  * the borrow can be repaid in full.
  * @param _curveMinAmountOut The minAmountOut we expect to receive when removing liquidity from Curve
  */
function divest(
  address _market,
  address _recipient,
  uint256 _withdrawAmount,
  uint256 _excessTokens,
  uint256 _curveMinAmountOut
) external {
  require(_market == moneyMarket || _market == protectionMarket, "Invalid borrow market");

  // 1. Withdraw Curve receipt tokens from from Convex
  IConvexRewardManager _convexRewardManager = IConvexRewardManager(convexRewardManager);
  _convexRewardManager.withdrawAndUnwrap(_withdrawAmount, false);

  // 2. Withdraw from Curve
  // There are two kinds of curve zaps -- one requires curve pool to be specified in first argument.
  // Approve Curve's depositZap to spend our receipt tokens.
  // As mentioned in ERC-20, allowance is set to 0 first to prevent attack vectors on the approve 
  // method (https://eips.ethereum.org/EIPS/eip-20#approve). This is explicitly required by some 
  // ERC-20 tokens, such as USDT.
  IERC20(curveLpToken).safeApprove(curveDepositZap, 0);
  IERC20(curveLpToken).safeApprove(curveDepositZap, type(uint256).max);
  if (longSigFormat) {
    ICrvDepositZap(curveDepositZap).remove_liquidity_one_coin(
      curveLpToken,
      _withdrawAmount,
      curveIndex,
      _curveMinAmountOut
    );
  } else {
    ICrvDepositZap(curveDepositZap).remove_liquidity_one_coin(_withdrawAmount, curveIndex, _curveMinAmountOut);
  }

  // Pay back as much of the borrow as possible, excess is refunded to `recipient`
  executeMaxRepay(_market, address(underlying), _excessTokens);

  // Transfer any remaining tokens to the user after paying back borrow
  IERC20(underlying).transfer(_recipient, IERC20(underlying).balanceOf(address(this)));
  claimRewards(_recipient);
}
```

{% endcode %}

Let's decompose the `CozyInvestConvex.sol` snippet above:

1. An `_excessTokens` function parameter is supported, which allows the caller to transfer additional quantities of the underlying asset to repay borrows if the investment withdrawal does not fully cover the debt owed to the Cozy market.
2. An error check to ensure that a valid market is requested to repay debt to. In this case, unprotected borrowing is also supported (optional).
3. Logic specific to Convex and Curve for closing the investment position; unstaking Curve LP tokens in Convex and withdrawing liquidity from Curve (in this case, WBTC).
4. Cozy market debt repayment. Any remaining funds after repayment are transferred to the user. For ERC20 tokens, make sure to include error code checks for repaying borrows. In this case, we use a custom defined `executeMaxRepay` function which includes the error check and supports debt repayment with `_excessTokens`.

   ```
    /**
    * @notice Repays as much token debt as possible
    * @param _market Market to repay
    * @param _underlying That market's underlying token (can be obtained by a call, but passing it in saves gas)
    * @param _excessTokens Quantity to transfer from the caller into this address to ensure
    * the borrow can be repaid in full. Only required if you want to repay the full borrow amount and the
    * amount obtained from withdrawing from the invest opportunity will not cover the full debt. A value of zero
    * will not attempt to transfer tokens from the caller, and the transfer will not be attempted if it's not required
    */
    function executeMaxRepay(
      address _market,
      address _underlying,
      uint256 _excessTokens
    ) internal {
      // Pay back as much of the borrow as possible, excess is refunded to `recipient`
      uint256 _borrowBalance = ICozyToken(_market).borrowBalanceCurrent(address(this));
      uint256 _initialBalance = IERC20(_underlying).balanceOf(address(this));
      if (_initialBalance < _borrowBalance && _excessTokens > 0) {
        TransferHelper.safeTransferFrom(_underlying, msg.sender, address(this), _excessTokens);
      }
      uint256 _balance = _initialBalance + _excessTokens; // this contract's current balance
      uint256 _repayAmount = _balance >= _borrowBalance ? type(uint256).max : _balance;

      // Approve the market to spend the repay amount in the given underlying token
      TransferHelper.safeApprove(_underlying, address(_market), _repayAmount);

      // Repay borrow to the Cozy market. The return value from this method is an error code,
      // where a value of zero indicates no error (i.e. the repay was successful)
      require(ICozyToken(_market).repayBorrow(_repayAmount) == 0, "Repay failed");
    }
   ```
5. Any remaining underlying tokens (in this case, WBTC) are transferred to the user after debt repayment.
6. Convex reward tokens are claimed and transferred to the user. This is only required for investment opportunities that accrue rewards.

### Develop the reward claim logic

If the investment opportunity accrues rewards, this function is required to claim them and transfer them to the investor's wallet. This function should also be used in the `divest` function.

The following snippet is an example of a `claimRewards` function on an invest/divest contract for claiming staking rewards from [Curve](https://curve.fi).

{% code title="CozyInvestCurve3CryptoEth.sol" %}

```typescript
/**
 * @notice Method to claim reward tokens from Curve and transfer to recipient
 * @param _recipient Address of the owner's wallet
 */
function claimRewards(address _recipient) public {
  gauge.claim_rewards(address(this), _recipient);
}
```

{% endcode %}

### Testing

When writing tests for invest/divest contracts, some setup is required in your test suite to replicate production behaviour. The following steps should be implemented in your test suite setup fixture:

1. Deploy the new invest/divest contract.
2. Deploy a proxy wallet. Cozy uses a proxy wallet for all borrows and investment opportunities.
3. Supply funds to the protection market used in the test suite.
4. Give the user's proxy wallet collateral so they can successfully borrow from Cozy markets.

Examples on how to implement the above in a development environment using JavaScript and [Hardhat](https://hardhat.org) can be found in the `CozyInvestCurve3CryptoEth.test.ts` and `CozyInvestConvex.test.ts` files in the [Cozy Developer Guides](https://github.com/Cozy-Finance/cozy-developer-guides) repository. The test suites in these examples also include examples of test cases.

Once there is sufficient test coverage, you are ready to deploy your new invest/divest contract.


# Error codes

Explanation of what error codes are and how to handle them in your code

## Introduction

Like Compound, just because a transaction was successful does not mean it actually did what we expected. Cozy inherited some of Compound's error handling approaches, which means a transaction may be successful—and show as successful on Etherscan and other block explorers—but in reality it didn't succeed. This is because some failed transactions will return an error code and emit a `Failure` event instead of reverting. You can find Compound's error codes [here](https://compound.finance/docs/ctokens#error-codes), and a brief history of why it's handled this way [here](https://www.comp.xyz/t/brief-history-of-error-handling-in-the-protocol/1169).

This approach can be a bit tedious for users and developers, as we now we have to manually ensure our transaction succeeded before continuing to the next step. In the [Cozy Developer Guides](https://github.com/Cozy-Finance/cozy-developer-guides/) repo you'll find a method called `findLog()` in the `utils/utils.ts` folder to help you with this.

This method searches for the expected success log in a transaction and returns it if found. If it's not found, an error is thrown and the `Failure` error codes are reported. You can compare those error codes to those in the table below to learn why your transaction failed.

Error codes are defined in `ErrorReporter.sol` and provided here for convenience.

## Comptroller

If an error code was emitted from a transaction to the Comptroller, refer to these error codes.

### Error Codes

Error codes 0–17 are identical to Compound's. Error codes 18 and 19 are unique to Cozy.

| Code | Name                              | Description                                                                                                  |
| ---- | --------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| 0    | `NO_ERROR`                        | Not a failure                                                                                                |
| 1    | `UNAUTHORIZED`                    | The sender is not authorized to perform this action.                                                         |
| 2    | `COMPTROLLER_MISMATCH`            | Liquidation cannot be performed in markets with different comptrollers.                                      |
| 3    | `INSUFFICIENT_SHORTFALL`          | The account does not have sufficient shortfall to perform this action.                                       |
| 4    | `INSUFFICIENT_LIQUIDITY`          | The account does not have sufficient liquidity to perform this action.                                       |
| 5    | `INVALID_CLOSE_FACTOR`            | The close factor is not valid.                                                                               |
| 6    | `INVALID_COLLATERAL_FACTOR`       | The collateral factor is not valid.                                                                          |
| 7    | `INVALID_LIQUIDATION_INCENTIVE`   | The liquidation incentive is invalid.                                                                        |
| 8    | `MARKET_NOT_ENTERED`              | The market has not been entered by the account.                                                              |
| 9    | `MARKET_NOT_LISTED`               | The market is not currently listed by the comptroller.                                                       |
| 10   | `MARKET_ALREADY_LISTED`           | An admin tried to list the same market more than once.                                                       |
| 11   | `MATH_ERROR`                      | A math calculation error occurred.                                                                           |
| 12   | `NONZERO_BORROW_BALANCE`          | The action cannot be performed since the account carries a borrow balance.                                   |
| 13   | `PRICE_ERROR`                     | The comptroller could not obtain a required price of an asset.                                               |
| 14   | `REJECTION`                       | The comptroller rejects the action requested by the market.                                                  |
| 15   | `SNAPSHOT_ERROR`                  | The comptroller could not get the account borrows and exchange rate from the market.                         |
| 16   | `TOO_MANY_ASSETS`                 | Attempted to enter more markets than are currently supported.                                                |
| 17   | `TOO_MUCH_REPAY`                  | Attempted to repay more than is allowed by the protocol.                                                     |
| 18   | `INVALID_TRIGGER`                 | The Protection Market cannot be created because the trigger is not a valid trigger, or was already triggered |
| 19   | `PROTECTION_MARKET_FACTORY_ERROR` | The admin tried to set the Protection Market Factory to an invalid contract                                  |

### Failure Info

TODO

## Cozy Token

If an error code was emitted from a transaction to a Cozy Token, refer to these error codes.

### Error Codes

| Code | Description                      |   |
| ---- | -------------------------------- | - |
| 0    | `NO_ERROR`                       |   |
| 1    | `UNAUTHORIZED`                   |   |
| 2    | `BAD_INPUT`                      |   |
| 3    | `COMPTROLLER_REJECTION`          |   |
| 4    | `COMPTROLLER_CALCULATION_ERROR`  |   |
| 5    | `INTEREST_RATE_MODEL_ERROR`      |   |
| 6    | `INVALID_ACCOUNT_PAIR`           |   |
| 7    | `INVALID_CLOSE_AMOUNT_REQUESTED` |   |
| 8    | `INVALID_COLLATERAL_FACTOR`      |   |
| 9    | `MATH_ERROR`                     |   |
| 10   | `MARKET_NOT_FRESH`               |   |
| 11   | `MARKET_NOT_LISTED`              |   |
| 12   | `TOKEN_INSUFFICIENT_ALLOWANCE`   |   |
| 13   | `TOKEN_INSUFFICIENT_BALANCE`     |   |
| 14   | `TOKEN_INSUFFICIENT_CASH`        |   |
| 15   | `TOKEN_TRANSFER_IN_FAILED`       |   |
| 16   | `TOKEN_TRANSFER_OUT_FAILED`      |   |
| 17   | `INVALID_GUARDIAN`               |   |

### Failure Info

TODO

## Protection Market Factory

If an error code was emitted from a transaction to the Protection Market Factory, refer to these error codes.

### Error Codes

| Code | Name                        | Description |
| ---- | --------------------------- | ----------- |
| 0    | `NO_ERROR`                  |             |
| 1    | `UNAUTHORIZED`              |             |
| 2    | `INTEREST_RATE_MODEL_ERROR` |             |

### Failure Info

TODO

## Oracle

If an error code was emitted from a transaction to the Oracle, refer to these error codes.

### Error Codes

| Code | Name           | Description |
| ---- | -------------- | ----------- |
| 0    | `NO_ERROR`     |             |
| 1    | `UNAUTHORIZED` |             |

### Failure Info

TODO


# API reference

Reference information for the methods available in the Cozy protocol.

The main two contracts you use to interact with the Cozy protocol are:

* Cozy token contracts
* Cozy Comptroller contract

There are dedicated API reference sections for these core contracts that explain the key concepts and how to use the methods they provide. In addition to the API reference sections for Cozy tokens and the Comptroller, there is a separate full API reference for all contracts that are part of the Cozy protocol. For details about using the Cozy API, see the following sections:

* [Cozy tokens API reference](/staging/for-developers/api-reference/cozy-tokens)
* [Comptroller API Rrference](/staging/for-developers/api-reference/comptroller)
* [Full API reference](/staging/for-developers/api-reference/full-api-reference)

{% hint style="info" %}
When reading the API references, note that any variable described as a *mantissa* is an 18 decimal number. For example, if a contract is storing the number 3.14 as a mantissa, the value in storage will be 3.14e18 = 3,140,000,000,000,000,000.
{% endhint %}


# Cozy tokens

API reference for Cozy tokens. Cozy tokens are a core contract in the Cozy protocol and each market is a unique instance of a Cozy token.

## Core methods

This section contains the primary methods for interacting with the Cozy protocol. Most methods in this section return a `uint256` value of zero (0) for a successful call, or return an [error code](/staging/for-developers/error-codes) on a unsuccessful call. The main exceptions to this general rule are the methods that are part of the standard [ERC-20 specification](https://eips.ethereum.org/EIPS/eip-20), such as the `transfer` and `balanceOf` methods.

### Mint

You use the `mint` function to transfer assets from your wallet to any Cozy market. You can use the `mint` function when you want to do the following:

* supply funds to use as collateral for protected borrowing.
* deposit funds to provide protection and earn interest.

Depending on whether you are minting tokens or ETH, use one of the following function signatures:

```javascript
// For markets with tokens as underlying
function mint(uint256 amount) external returns (uint256);

// For markets with ETH as underlying
function mint() external payable;
```

For tokens, the `amount` is the number of tokens to supply, denominated in units of the underlying token. For ETH, instead of specifying an amount, you send ETH along with the transaction and `msg.value` is used in place of `amount`.

Before supplying a token, remember to `approve` the Cozy market. A successful `mint` call returns a value of zero and transfers Cozy tokens to the caller's wallet. The number of Cozy tokens the user receives is equal to the supplied amount divided by the [exchange rate](#exchange-rate).

### Redeem

You use the `redeem` method to redeem Cozy tokens for the underlying supplying funds. The amount of underlying received is equal to the number of Cozy tokens redeemed multiplied by the [exchange rate](#exchange-rate). There are two methods you can use to redeem tokens:

```javascript
// Specify amount to redeem denominated in amount of Cozy tokens
function redeem(uint256 redeemTokens) external returns (uint256);

// Specify amount to redeem denominated in amount of underlying
function redeemUnderlying(uint256 redeemAmount) external returns (uint256);
```

A successful redeem burns the caller's Cozy tokens, transfers a proportional amount of the underlying asset, and returns a value of zero.

### Borrow

After supplying collateral with the `mint` method, you can use the `borrow` method to borrow funds from the Cozy protocol. Borrowed funds accrue interest at the current [borrow rate](#borrow-rate). If a borrower has insufficient account liquidity, however, the borrowed funds can be liquidated.

The method for borrowing funds from a market is:

```javascript
function borrow(uint256 borrowAmount) external returns (uint256);
```

where `borrowAmount` is specified in units of the token to borrow.

### Repay debt

You can use either the `repayBorrow` or `repayBorrowBehalf` function to repay borrowed funds as follows:

```javascript
// --- For markets with tokens as underlying ---
// Repays `repayAmount` of the underlying for `msg.sender`
function repayBorrow(uint256 repayAmount) external returns (uint256);

// Repays `repayAmount` of the underlying for `borrower`
function repayBorrowBehalf(address borrower, uint256 repayAmount) external returns (uint256);

// --- For markets with ETH as underlying ---
// Repays `msg.value` ETH for `msg.sender`
function repayBorrow() external payable;

// Repays `msg.value` ETH for `borrower`
function repayBorrowBehalf(address borrower) external payable;
```

To repay all token debt without leaving any dust, you can specify a `repayAmount` of`MAX_UINT256 = 2^256 - 1`.

To repay all ETH debt without leaving any dust, it is recommended to use a special helper contract called `Maximillion` and call the following method:

```javascript
function repayBehalfExplicit(address borrower, CEther cEther_) external payable;
```

where `borrower` is the address of the user to pay back debt for, and `cEther_` is the address of the market to pay back debt in (for example, the Cozy Ether money market, or a protection market with ETH as the underlying). When calling this method, send along more ETH than the debt amount, and after paying off the full debt, the excess ETH will be refunded.

The `Maximillion` contract is deployed on mainnet at [0xf859A1AD94BcF445A406B892eF0d3082f4174088](https://etherscan.io/address/0xf859A1AD94BcF445A406B892eF0d3082f4174088).

### Liquidate

You use the `liquidateBorrow` function to liquidate a user's assets when their account liquidity is negative. This action brings the user back to a solvent state. During a liquidation, the liquidator repays some or all of the user's borrow and, in return, receives a portion of their collateral, as Cozy tokens, at a discount.

The maximum portion of the borrow that can be liquidated is specified by the close factor in the Comptroller. As with mints and repays, liquidating pulls tokens from the caller, so the liquidator must `approve` the Cozy token contract before liquidating.

Liquidations can be executed with the following methods:

```javascript
// For markets with tokens as underlying
function liquidateBorrow(
    address borrower,
    uint256 repayAmount,
    CTokenInterface cTokenCollateral
) external returns (uint256);

// For markets with ETH as underlying
function liquidateBorrow(
    address borrower,
    CToken cTokenCollateral
) external payable;
```

where `borrower` is the account with a shortfall to liquidate and `cTokenCollateral` is the token being used by the borrower as collateral that the liquidator will receive. For token-based markets, `repayAmount` specifies how much of the borrowed asset to repay, and for ETH-based markets that amount is specified by `msg.value`.

### Transfer

All Cozy tokens are [ERC-20](https://eips.ethereum.org/EIPS/eip-20) compliant and can be transferred with both the `transfer` and `transferFrom` functions. They also implement [ERC-2612](https://eips.ethereum.org/EIPS/eip-2612) `permit` function to improve the approval flow.

{% hint style="info" %}
Token transfers fail if the transfer would put the account into an under-collateralized position.
{% endhint %}

## View methods

This section contains the primary methods for viewing information about Cozy markets.

### Exchange rate

Every Cozy token has it's own exchange rate, which is a function of the market's cash, borrows, reserves, and supply. This value is initialized to 0.02 when a market is created, and increases as the accrues interest. The exchange rate for a given market is calculated as:

```javascript
exchangeRate = ( getCash() + totalBorrows() - totalReserves() ) / totalSupply();
```

The exchange rate is represented as a mantissa (an 18 decimal number) with a precision of `18 + underlyingDecimals - cozyTokenDecimals`. For example, all Cozy tokens have 8 decimals. If the underlying token has 6 decimals, the initial exchange rate for that market would have 18 + 6 - 8 = 16 decimals. Querying the exchange rate of this market immediately after deployment would return `0.02e16 = 200000000000000`.

### Cash

Cash is the amount of the underlying token held by the Cozy token. You can read the cash held by the contract using the following function:

```javascript
function getCash() external view returns (uint256);
```

For markets with tokens as the underlying, this function returns the value of `underlyingToken.balanceOf(address(this));`. For markets with ETH as the underlying, the function returns `address(this).balance - msg.value`.

### Borrows

A market's total borrows is the amount of the underlying token actively borrowed. This amount is used when computing the accrued interest. It can be queried for a given market with the function below. When a market is triggered, this value is set to zero, so the below methods always returns zero after a trigger event.

```javascript
// View method which returns the last known borrow amount, `totalBorrows`
function totalBorrows() external view returns (uint256);

// Non-view method which accrues interest before returning `totalBorrows`.
// Because this version accrues interest first, it will be more up to date
function totalBorrowsCurrent() external returns (uint256);
```

The amount being borrowed by an individual user can be read with the method below. Both methods always returns a borrow balance of zero after a market is triggered.

```javascript
// View method which returns the last known borrow balance for `account`
function borrowBalanceStored(address account) external view returns (uint256);

// Non-view method which accrues interest before returning `borrowBalanceStored`.
// Because this version accrues interest first, it will be more up to date
function borrowBalanceCurrent(address account) external returns (uint256);
```

### Supply

A market's total supply is the number of Cozy tokens that have been minted and are currently in circulation. You can use the standard ERC-20 `totalSupply` method to return the number of Cozy tokens in a market as follows:

```javascript
function totalSupply() external view returns (uint256);
```

### Balances

To read a user's Cozy token balance, you can use the standard ERC-20 `balanceOf` method as follows:

```javascript
function balanceOf(address account) external view returns (uint256);
```

You can also read a user's balance with the `balanceOfUnderlying` function, which returns the user's Cozy token balance multiplied by the exchange rate.

```javascript
// Note that `balanceOfUnderlying` is not a view method
function balanceOfUnderlying(address account) external returns (uint256);
```

For example, if a user supplies 1000 USDC with an exchange rate of 0.02, she receives `1000 / 0.02 = 50,000` Cozy tokens. Calling `balanceOf` will return 50,000e8, and calling `balanceOfUnderlying` will return 1000e6, since Cozy tokens have 8 decimals and USDC has 6 decimals).

### Interest rates

You can use the `borrowRatePerBlock` function to read the current interest rate accrued by borrowers every block.

```javascript
function borrowRatePerBlock() external view returns (uint256);
```

The supply-rate-per-block is a function of the borrow-rate-per-block, as well the market's reserve factor and the its utilization rate. The utilization rate is the ratio of borrowed funds to supplied funds, calculated as `borrows / (cash + borrows - reserves)`. The supply rate is then calculated as `utilizationRate * (borrowRatePerBlock * (1 - reserveFactor))`. You can query this value as follows:

```javascript
function supplyRatePerBlock() external view returns (uint256);
```

Both the borrow rate and supply rate returned from these methods will always be zero after a market is triggered.

### Reserves

A portion of interest accrued from borrowers is set aside as cash, and cash from this source is known as reserves. The amount of reserves set aside is determined by the reserve factor. You can use the `reserveFactorMantissa` method to return the reserve factor. See the [Interest Rates](#interest-rates) section for more information on how the reserve factor is used.

```javascript
// Returns a mantissa, so it's scaled by 1e18
function reserveFactorMantissa() external view returns (uint256)
```

The total reserves in a given market can be read with:

```javascript
function totalReserves() external view returns (uint256)
```

Reserves can be withdrawn or transferred by the protocol administrator.

## Events

This sections contains the core events emitted by Cozy token contracts, and is not a comprehensive list.

```javascript
// Emitted when interest is accrued
event AccrueInterest(uint256 cashPrior, uint256 interestAccumulated, uint256 borrowIndex, uint256 totalBorrows);

// Emitted when tokens are minted
event Mint(address minter, uint256 mintAmount, uint256 mintTokens);

// Emitted when tokens are redeemed
event Redeem(address redeemer, uint256 redeemAmount, uint256 redeemTokens);

// Emitted when underlying is borrowed
event Borrow(address borrower, uint256 borrowAmount, uint256 accountBorrows, uint256 totalBorrows);

// Emitted when a borrow is repaid
event RepayBorrow(address payer, address borrower, uint256 repayAmount, uint256 accountBorrows, uint256 totalBorrows);

// Emitted when a borrow is liquidated
event LiquidateBorrow(
  address liquidator,
  address borrower,
  uint256 repayAmount,
  address cTokenCollateral,
  uint256 seizeTokens
);

// Emitted when trigger status is set. This is emitted once at
// construction and one more time when the trigger is toggled
event TriggerSet(bool isTriggered);
```

## Error handling

This section contains information about error codes and failure messages that may be returned when calling methods on a Cozy token contract.

### Error codes

The table below contains a list of error codes that may be returned when calling methods on a Cozy token contract.

| Code | Name                             | Description                                                          |
| ---- | -------------------------------- | -------------------------------------------------------------------- |
| 0    | `NO_ERROR`                       | Call succeeded                                                       |
| 1    | `UNAUTHORIZED`                   | Caller is not authorized                                             |
| 2    | `BAD_INPUT`                      | Caller provided bad arguments                                        |
| 3    | `COMPTROLLER_REJECTION`          | The Comptroller blocked this action                                  |
| 4    | `COMPTROLLER_CALCULATION_ERROR`  | A calculation failed in the Comptroller                              |
| 5    | `INTEREST_RATE_MODEL_ERROR`      | An invalid value was returned from the interest rate model           |
| 6    | `INVALID_ACCOUNT_PAIR`           | The borrower and liquidator are the same account                     |
| 7    | `INVALID_CLOSE_AMOUNT_REQUESTED` | The `MAX_UINT256` is passed as the `repayAmount` during liquidation  |
| 8    | `INVALID_COLLATERAL_FACTOR`      | Provided collateral factor is not allowed                            |
| 9    | `MATH_ERROR`                     | An error occurred in a math operation                                |
| 10   | `MARKET_NOT_FRESH`               | The market has not properly accrued interest                         |
| 11   | `MARKET_NOT_LISTED`              | The market is not supported by the Comptroller                       |
| 12   | `TOKEN_INSUFFICIENT_ALLOWANCE`   | Caller has not approved the contract to spend enough tokens          |
| 13   | `TOKEN_INSUFFICIENT_BALANCE`     | Caller has an insufficient token balance to complete the transaction |
| 14   | `TOKEN_INSUFFICIENT_CASH`        | The market does not have enough cash at this time                    |
| 15   | `TOKEN_TRANSFER_IN_FAILED`       | ERC-20 token transfer to the market failed                           |
| 16   | `TOKEN_TRANSFER_OUT_FAILED`      | ERC-20 token transfer from the market failed                         |
| 17   | `INVALID_GUARDIAN`               | Reserve guardian cannot be the zero address                          |

### Failure codes and logged messages

The table below contains a list of error codes that may be emitted in `Failure` logs when calling methods on a Cozy token contract. These codes are descriptive so no additional description is provided.

| Code | Name                                                         |
| ---- | ------------------------------------------------------------ |
| 0    | `ACCEPT_ADMIN_PENDING_ADMIN_CHECK`                           |
| 1    | `ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED`    |
| 2    | `ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED`             |
| 3    | `ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED`        |
| 4    | `ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED`       |
| 5    | `ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED`      |
| 6    | `ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED`  |
| 7    | `BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED`              |
| 8    | `BORROW_ACCRUE_INTEREST_FAILED`                              |
| 9    | `BORROW_CASH_NOT_AVAILABLE`                                  |
| 10   | `BORROW_FRESHNESS_CHECK`                                     |
| 11   | `BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED`                |
| 12   | `BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED`       |
| 13   | `BORROW_MARKET_NOT_LISTED`                                   |
| 14   | `BORROW_COMPTROLLER_REJECTION`                               |
| 15   | `LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED`                    |
| 16   | `LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED`                |
| 17   | `LIQUIDATE_COLLATERAL_FRESHNESS_CHECK`                       |
| 18   | `LIQUIDATE_COMPTROLLER_REJECTION`                            |
| 19   | `LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED`        |
| 20   | `LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX`                         |
| 21   | `LIQUIDATE_CLOSE_AMOUNT_IS_ZERO`                             |
| 22   | `LIQUIDATE_FRESHNESS_CHECK`                                  |
| 23   | `LIQUIDATE_LIQUIDATOR_IS_BORROWER`                           |
| 24   | `LIQUIDATE_REPAY_BORROW_FRESH_FAILED`                        |
| 25   | `LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED`                   |
| 26   | `LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED`                   |
| 27   | `LIQUIDATE_SEIZE_COMPTROLLER_REJECTION`                      |
| 28   | `LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER`                     |
| 29   | `LIQUIDATE_SEIZE_TOO_MUCH`                                   |
| 30   | `MINT_ACCRUE_INTEREST_FAILED`                                |
| 31   | `MINT_COMPTROLLER_REJECTION`                                 |
| 32   | `MINT_EXCHANGE_CALCULATION_FAILED`                           |
| 33   | `MINT_EXCHANGE_RATE_READ_FAILED`                             |
| 34   | `MINT_FRESHNESS_CHECK`                                       |
| 35   | `MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED`                |
| 36   | `MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED`                   |
| 37   | `MINT_TRANSFER_IN_FAILED`                                    |
| 38   | `MINT_TRANSFER_IN_NOT_POSSIBLE`                              |
| 39   | `REDEEM_ACCRUE_INTEREST_FAILED`                              |
| 40   | `REDEEM_COMPTROLLER_REJECTION`                               |
| 41   | `REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED`                  |
| 42   | `REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED`                  |
| 43   | `REDEEM_EXCHANGE_RATE_READ_FAILED`                           |
| 44   | `REDEEM_FRESHNESS_CHECK`                                     |
| 45   | `REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED`              |
| 46   | `REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED`                 |
| 47   | `REDEEM_TRANSFER_OUT_NOT_POSSIBLE`                           |
| 48   | `REDUCE_RESERVES_ACCRUE_INTEREST_FAILED`                     |
| 49   | `REDUCE_RESERVES_ADMIN_CHECK`                                |
| 50   | `REDUCE_RESERVES_CASH_NOT_AVAILABLE`                         |
| 51   | `REDUCE_RESERVES_FRESH_CHECK`                                |
| 52   | `REDUCE_RESERVES_VALIDATION`                                 |
| 53   | `REPAY_BEHALF_ACCRUE_INTEREST_FAILED`                        |
| 54   | `REPAY_BORROW_ACCRUE_INTEREST_FAILED`                        |
| 55   | `REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED`        |
| 56   | `REPAY_BORROW_COMPTROLLER_REJECTION`                         |
| 57   | `REPAY_BORROW_FRESHNESS_CHECK`                               |
| 58   | `REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED` |
| 59   | `REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED`          |
| 60   | `REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE`                      |
| 61   | `SET_COLLATERAL_FACTOR_OWNER_CHECK`                          |
| 62   | `SET_COLLATERAL_FACTOR_VALIDATION`                           |
| 63   | `SET_COMPTROLLER_OWNER_CHECK`                                |
| 64   | `SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED`             |
| 65   | `SET_INTEREST_RATE_MODEL_FRESH_CHECK`                        |
| 66   | `SET_INTEREST_RATE_MODEL_OWNER_CHECK`                        |
| 67   | `SET_MAX_ASSETS_OWNER_CHECK`                                 |
| 68   | `SET_ORACLE_MARKET_NOT_LISTED`                               |
| 69   | `SET_PENDING_ADMIN_OWNER_CHECK`                              |
| 70   | `SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED`                  |
| 71   | `SET_RESERVE_FACTOR_ADMIN_CHECK`                             |
| 72   | `SET_RESERVE_FACTOR_FRESH_CHECK`                             |
| 73   | `SET_RESERVE_FACTOR_BOUNDS_CHECK`                            |
| 74   | `TRANSFER_COMPTROLLER_REJECTION`                             |
| 75   | `TRANSFER_NOT_ALLOWED`                                       |
| 76   | `TRANSFER_NOT_ENOUGH`                                        |
| 77   | `TRANSFER_TOO_MUCH`                                          |
| 78   | `ADD_RESERVES_ACCRUE_INTEREST_FAILED`                        |
| 79   | `ADD_RESERVES_FRESH_CHECK`                                   |
| 80   | `ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE`                      |
| 81   | `REDUCE_RESERVES_GUARDIAN_NOT_SET`                           |
| 82   | `TRIGGER_ACTIVATED_BEFORE_REDEEM_OR_BORROW`                  |


# Comptroller

API reference for the Comptroller, which is responsible for ensuring the safety of the protocol.

## Core methods

This section contains the primary methods for interacting with the Comptroller for the Cozy protocol.

### Create protection markets

Anyone can create new protection markets with the Comptroller's `deployProtectionMarket` methods. For more information on creating protection markets, see the [Create a protection Mmrket](/staging/for-developers/guides/how-do-i-create-a-protection-market) guide.

### Entering and exiting markets

When supplying assets to a money market, those funds are not automatically available as collateral for borrowing. Instead, you must specify when you want supplied assets to be used as collateral. Telling the protocol you want to use a certain asset as collateral is known as "entering the market".

{% hint style="info" %}
All protection markets have collateral factors of zero, meaning funds supplied to protection markets cannot be used as collateral. Therefore, you should only explicitly enter markets for funds supplied to a money market.
{% endhint %}

To enter a market, call the `enterMarkets` method on the Comptroller, where `cTokens` is an array of Cozy money market addresses.

```javascript
function enterMarkets(address[] calldata cTokens) external returns (uint256[] memory);
```

When you no longer want to use supplied funds in a market as collateral, you can exit the market with the `exitMarket` method described below. Notice that you can enter multiple markets in a single transaction, but you can only exit one market per call. When exiting a market, your transaction will fail with an error code if you have an outstanding borrow balance in that market, or if exiting the market would result in insufficient [account liquidity](#account-liquidity).

```javascript
function exitMarket(address cTokenAddress) external returns (uint256);
```

Note that borrowing from a market automatically enters you into that market, since liquidity calculations loop through all entered markets to determine if you have sufficient account liquidity.

Both the `enterMarkets` method and the `exitMarket` methods return a `uint256` value of 0 for a successful call, and return an [error code](/staging/for-developers/error-codes) for an unsuccessful call.

## View methods

This section contains the primary methods for viewing information managed by the Comptroller.

### Account assets

You can use the `getAssetsIn` method to return a list of markets that a user has [entered](#entering-and-exiting-markets). The method takes the user's address as an input and returns the full set of markets for the specified user in an array. The array of markets returned by this method is the full set of markets used for liquidity calculations.

```javascript
function getAssetsIn(address account) external view returns (CToken[] memory);
```

### Collateral factors

Every market has a collateral factor that represents how much borrow power is increased by when that market's assets are used as collateral. This collateral factor can range from 0% to 90% and can be interpreted as:

* A value of 0% means using that an asset cannot be used as collateral, as it gives you no borrowing power.
* A value of 90% means supplying $100 of that asset allows you to borrow up to $90 of another asset.

All protection markets have collateral factors of 0%, and money markets can have collateral factors anywhere in the 0–90% range.

You can retrieve the collateral factor for a given market with the following `markets` function by providing a Cozy token market address as input:

```javascript
function markets(address cTokenAddress) view returns (bool, uint256, bool)
```

The function returns the first `bool` value for the `isListed` property as `true` if the market is recognized by the Comptroller or `false` if it is not.

The `uint256` returned by the function is an 18 decimal number for the `collateralFactorMantissa` property described above. A value of 0.9 means that you can supply this market's assets as collateral to borrow up to 90% of the supplied value.

The second `bool` value is for the `isComped` property that is not currently used and can be safely ignored.

### Listed markets

You can use the `getAllMarkets` method to return an array of all Cozy token markets supported by the Comptroller as follows:

```javascript
function getAllMarkets() external view returns (CToken[] memory);
```

The addresses returned from this array can be directly passed as inputs to the `markets` function described in the [CollateralFactors](#collateral-factors) section to retrieve various metadata for the specified market.

### Account liquidity

Account liquidity specifies a user's borrowing power in USD. If you borrow too much (for example, if the value of your collateral falls), your account liquidity can fall below zero and can result in your account being liquidated.

Account liquidity is based on [all markets entered](#account-assets) by a user. For each of those assets, the collateral quantity is converted to USD and multiplied by that asset's collateral factor. Summing these values and subtracting current borrow balances results in the current account liquidity for a user.

You can query the account liquidity for a user as follows:

```javascript
function getAccountLiquidity(address account) external view returns (uint256, uint256, uint256);
```

The first `uint256` returned is zero on success or an [error code](/staging/for-developers/error-codes) on failure.

If the account queried has positive account liquidity, that is, the user can borrow more assets, the second `uint256` will equal the user's account liquidity and the third `uint256` will equal zero. If the account queried has negative account liquidity, that is, the user has a shortfall and can be liquidated, the second `uint256` will be zero and the third `uint256` will equal the shortfall amount.

### Liquidation incentive

To incentivize liquidations of accounts that have a shortfall, the `liquidationIncentiveMantissa` method specifies additional collateral that liquidators receive. For example, if the liquidation incentive is 1.08e18, then liquidators receive 8% more collateral than the borrow amount they closed.

To illustrate how the incentive works, assume a liquidator repays $1000 worth of a user's borrows. If the liquidation incentive is 1.08e18, then the liquidator will receive $1000 \* 1.08 = $1080 of the user's collateral. The liquidation incentive is the same for all markets, and can be changed. You can read the current value as follows:

```javascript
function liquidationIncentiveMantissa() external view returns (uint256);
```

### Close factor

When liquidating an account, you cannot necessarily repay the full borrow amount and entirely liquidate the borrower. Instead, the close factor specifies what portion of their account can be repaid in a single liquidation. This value applies to individual borrowed assets, not the overall position. The close factor is the same for all markets, and can be changed. You can read the current value as follows:

```javascript
function closeFactorMantissa() external view returns (uint256);
```

## Events

This sections contains the core events emitted by the Comptroller, and is not a comprehensive list.

```javascript
// Emitted when a third party adds a protection market
event ProtectionMarketListed(CToken cToken, address trigger);

// Emitted when an account enters a market
event MarketEntered(CToken cToken, address account);

// Emitted when an account exits a market
event MarketExited(CToken cToken, address account);
```

## Error handling

This section contains information about error codes and failure messages that you might see when calling methods on the Comptroller.

### Error codes

The following table below contains a list of error codes that you might see when calling methods on the Comptroller.

| Code | Name                              | Description                                                                         |
| ---- | --------------------------------- | ----------------------------------------------------------------------------------- |
| 0    | `NO_ERROR`                        | Call succeeded                                                                      |
| 1    | `UNAUTHORIZED`                    | Caller is not authorized                                                            |
| 2    | `COMPTROLLER_MISMATCH`            | Cannot liquidate across markets with different comptrollers                         |
| 3    | `INSUFFICIENT_SHORTFALL`          | The account cannot be liquidated since it has no shortfall                          |
| 4    | `INSUFFICIENT_LIQUIDITY`          | Redeem or borrow not allowed because the account has insufficient liquidity         |
| 5    | `INVALID_CLOSE_FACTOR`            | Outdated, not used                                                                  |
| 6    | `INVALID_COLLATERAL_FACTOR`       | Cannot set new collateral factor, as specified value is invalid                     |
| 7    | `INVALID_LIQUIDATION_INCENTIVE`   | Outdated, not used                                                                  |
| 8    | `MARKET_NOT_ENTERED`              | Outdated, not used                                                                  |
| 9    | `MARKET_NOT_LISTED`               | The specified market is not listed by the Comptroller                               |
| 10   | `MARKET_ALREADY_LISTED`           | Specified market already exists                                                     |
| 11   | `MATH_ERROR`                      | An error occurred in a math operation                                               |
| 12   | `NONZERO_BORROW_BALANCE`          | Cannot exit market if borrow balance is above zero                                  |
| 13   | `PRICE_ERROR`                     | The Comptroller could not get a valid price for an asset                            |
| 14   | `REJECTION`                       | The Comptroller rejected the action specified by a Cozy token                       |
| 15   | `SNAPSHOT_ERROR`                  | Unable to read a user's account borrows and market exchange rate                    |
| 16   | `TOO_MANY_ASSETS`                 | Cannot enter a number of markets greater than \`maxAssets'                          |
| 17   | `TOO_MUCH_REPAY`                  | Cannot repay more than the protocol will allow                                      |
| 18   | `INVALID_TRIGGER`                 | The specified trigger is not valid so a protection market cannot be created with it |
| 19   | `PROTECTION_MARKET_FACTORY_ERROR` | The specified ProtectionMarketFactory address is not valid                          |

### Failure codes and logged messages

The following table below contains a list of error codes that may be emitted in `Failure` logs when calling methods on the Comptroller. These codes are descriptive so no additional description is provided.

| Code | Name                                           |
| ---- | ---------------------------------------------- |
| 0    | `ACCEPT_ADMIN_PENDING_ADMIN_CHECK`             |
| 1    | `ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK`  |
| 2    | `EXIT_MARKET_BALANCE_OWED`                     |
| 3    | `EXIT_MARKET_REJECTION`                        |
| 4    | `SET_CLOSE_FACTOR_OWNER_CHECK`                 |
| 5    | `SET_CLOSE_FACTOR_VALIDATION`                  |
| 6    | `SET_COLLATERAL_FACTOR_OWNER_CHECK`            |
| 7    | `SET_COLLATERAL_FACTOR_NO_EXISTS`              |
| 8    | `SET_COLLATERAL_FACTOR_VALIDATION`             |
| 9    | `SET_COLLATERAL_FACTOR_WITHOUT_PRICE`          |
| 10   | `SET_IMPLEMENTATION_OWNER_CHECK`               |
| 11   | `SET_LIQUIDATION_INCENTIVE_OWNER_CHECK`        |
| 12   | `SET_LIQUIDATION_INCENTIVE_VALIDATION`         |
| 13   | `SET_MAX_ASSETS_OWNER_CHECK`                   |
| 14   | `SET_PENDING_ADMIN_OWNER_CHECK`                |
| 15   | `SET_PENDING_IMPLEMENTATION_OWNER_CHECK`       |
| 16   | `SET_PRICE_ORACLE_OWNER_CHECK`                 |
| 17   | `SUPPORT_MARKET_EXISTS`                        |
| 18   | `SUPPORT_MARKET_OWNER_CHECK`                   |
| 19   | `SET_PAUSE_GUARDIAN_OWNER_CHECK`               |
| 20   | `SET_TRIGGER_CHECK`                            |
| 21   | `SET_PROTECTION_WITH_INVALID_UNDERLYING`       |
| 22   | `SET_PROTECTION_UNDERLYING_WITHOUT_PRICE`      |
| 23   | `SET_PROTECTION_MARKET_FACTORY_OWNER_CHECK`    |
| 24   | `SET_PROTECTION_MARKET_FACTORY_VALIDITY_CHECK` |
| 25   | `SET_RESERVE_GUARDIAN_OWNER_CHECK`             |


# Full API reference

API reference for all Cozy contracts

## Cozy Tokens

### CEther

### CErc20

### Shared

## Comptroller

The protocol's Comptroller is an instance of the `ComptrollerStatic` contract, which has the following interface.

## Chainlink Reporter

The `ChainlinkReporter` contract is the protocol's price oracle.

### Error Handling

#### Error Codes

| Code | Name           | Description              |
| ---- | -------------- | ------------------------ |
| 0    | `NO_ERROR`     | Call succeeded           |
| 1    | `UNAUTHORIZED` | Caller is not authorized |

#### Failure Info

| Code | Name                                |
| ---- | ----------------------------------- |
| 0    | `ACCEPT_ADMIN_PENDING_ADMIN_CHECK`  |
| 1    | `ADD_OR_UPDATE_ORACLES_OWNER_CHECK` |
| 2    | `SET_PENDING_ADMIN_OWNER_CHECK`     |

## Protection Market Factory

### Error Handling

#### Error Codes

| Code | Name                        | Description                           |
| ---- | --------------------------- | ------------------------------------- |
| 0    | `NO_ERROR`                  | Call succeeded                        |
| 1    | `UNAUTHORIZED`              | Caller is not authorized              |
| 2    | `INTEREST_RATE_MODEL_ERROR` | Invalid interest rate model specified |

#### Failure Info

| Code | Name                                             |
| ---- | ------------------------------------------------ |
| 0    | `SET_DEFAULT_INTEREST_RATE_MODEL_OWNER_CHECK`    |
| 1    | `SET_DEFAULT_INTEREST_RATE_MODEL_VALIDITY_CHECK` |


# Contract deployments

Cozy Protocol contract deployment addresses

{% tabs %}
{% tab title="Production" %}
The latest Cozy Protocol is deployed on mainnet at the addresses below.

| Contract                                      | Address                                                                                                                 |
| --------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| Cozy ETH Money Market                         | ​[0xF8ec0F87036565d6B2B19780A54996c3B03e91Ea](https://etherscan.io/address/0xF8ec0F87036565d6B2B19780A54996c3B03e91Ea)​ |
| Cozy DAI Money Market                         | ​[0xe6EF65EC40D943c3f675165B0b17e06862Fe3d82](https://etherscan.io/address/0xe6EF65EC40D943c3f675165B0b17e06862Fe3d82)​ |
| Cozy USDC Money Market                        | ​[0xdBDF2fC3Af896e18f2A9DC58883d12484202b57E](https://etherscan.io/address/0xdBDF2fC3Af896e18f2A9DC58883d12484202b57E)​ |
| Cozy WBTC Money Market                        | ​[0xf146c26136C1F80c9f0967d27BCb7E500D45681f](https://etherscan.io/address/0xf146c26136C1F80c9f0967d27BCb7E500D45681f)​ |
| Comptroller                                   | ​[0x895879B2c1Fbb6CCFcD101f2D3F3c76363664f92](https://etherscan.io/address/0x895879B2c1Fbb6CCFcD101f2D3F3c76363664f92)​ |
| Oracle                                        | ​[0x6f668117CaA90Ea73c27adC562f5A2A06CCA9092](https://etherscan.io/address/0x6f668117CaA90Ea73c27adC562f5A2A06CCA9092)​ |
| Cozy ETH Interest Rate Model                  | ​[0x3eC8e03BF8b67b7d793f2de6EB59045277D02831](https://etherscan.io/address/0x3eC8e03BF8b67b7d793f2de6EB59045277D02831)​ |
| Cozy DAI Interest Rate Model                  | ​[0xb7DB062cAAcdd0b74EFEb15026f46b792Ca5c75A](https://etherscan.io/address/0xb7DB062cAAcdd0b74EFEb15026f46b792Ca5c75A)​ |
| Cozy USDC Interest Rate Model                 | ​[0xb7DB062cAAcdd0b74EFEb15026f46b792Ca5c75A](https://etherscan.io/address/0xb7DB062cAAcdd0b74EFEb15026f46b792Ca5c75A)​ |
| Cozy WBTC Interest Rate Model                 | ​[0x47cef4AB8f68Da8156D705e0046A970b6b9cf3e8](https://etherscan.io/address/0x47cef4AB8f68Da8156D705e0046A970b6b9cf3e8)​ |
| Default Protection Market Interest Rate Model | ​[0x795cEf98568515D7Ed28Aec8dEaaa76b58b40a6C](https://etherscan.io/address/0x795cEf98568515D7Ed28Aec8dEaaa76b58b40a6C)​ |
| {% endtab %}                                  |                                                                                                                         |

{% tab title="Deprecated" %}
The prior, now deprecated Cozy Protocol is deployed on mainnet at the addresses below.

| Contract                                      | Address                                     |
| --------------------------------------------- | ------------------------------------------- |
| Cozy ETH Money Market                         | 0x38B050b6f78c66a7dD9b336cD1Ff10fF2B9e9922  |
| Cozy DAI Money Market                         | 0xdcB99DFbe5368d7c2d671A9AE5C4164FF69D86D3  |
| Cozy USDC Money Market                        | 0xeEEE96017550c817643bB0e85EBEbc512e7A27BA  |
| Cozy WBTC Money Market                        | 0xA60ffbB5caAcA4d26Cb4326D82494163B1071Fc6  |
| Comptroller                                   | 0x349f0A62CE40055b70557e1173287469d601A1e0  |
| Oracle                                        | 0x6f668117CaA90Ea73c27adC562f5A2A06CCA9092  |
| Cozy ETH Interest Rate Model                  | 0x3eC8e03BF8b67b7d793f2de6EB59045277D02831  |
| Cozy DAI Interest Rate Model                  | 0xb7DB062cAAcdd0b74EFEb15026f46b792Ca5c75A  |
| Cozy USDC Interest Rate Model                 | 0xb7DB062cAAcdd0b74EFEb15026f46b792Ca5c75A  |
| Cozy WBTC Interest Rate Model                 | 0x47cef4AB8f68Da8156D705e0046A970b6b9cf3e8  |
| Default Protection Market Interest Rate Model | ​0x795cEf98568515D7Ed28Aec8dEaaa76b58b40a6C |
| {% endtab %}                                  |                                             |
| {% endtabs %}                                 |                                             |


