This repository contains various guides to show you how to interact with the Cozy Protocol. These guides assume knowledge of TypeScript, ethers.js, and Solidity, as well as familiarity with the Cozy Protocol. Hardhat is used as well, but you shouldn't need to be too familiar with Hardhat to use this repo.
All scripts in this repository are run against a local fork of the Ethereum mainnet using Hardhat, so you can have confidence that if your scripts work in this environment they should also work in production. For more information on running scripts against a forked network, see the Mainnet Forking section of the Hardhat documentation.
First, run yarn
at the project root to install all dependencies.
Next, copy the .env.example
file, rename it to .env
, and set the variables accordingly:
RPC_URL
shows an Infura endpoint as the default, but you are free to use any node provider of your choice. Use the full RPC URL as the value for this environment variable- The
PRIVATE_KEY
will be used to generate the primary account used in scripts, so you can either:- Use a private key corresponding to an account that has ETH on mainnet, or
- Use any arbitrary private key and use the
fundAccount()
method ofutils.ts
to supply the account with funds at the beginning of a script (this is what the scripts do by default)
Let's also discuss one important aspect of Cozy: handling failed transactions. As with Compound, just because a transaction was successful does not mean it succeeded in doing what you 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 do what you expected. 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, and a brief history of why it's handled this way here.
This approach can be a bit tedious for user's and developers, as we now we have to manually ensure our transaction succeeded before continuing to the next step. To simplify that process, you'll notice this repository has a helper method that can be run in place of ethers' tx.wait()
after sending a transaction. It will look for the expected success logs, and if not found, throw an error and print the failure codes for additional debugging. This helper method is called findLog()
and lives in utils/utils.ts
.
All guides are located in the guides
folder and contain up to two files:
- An executable TypeScript file
- A markdown file with additional information and details
A script may be run with the command yarn hardhat run guides/<script-name.ts>
. Additional notes on the guides:
- All TypeScript files are heavily commented to aid understanding and readability, and TypeScript is used throughout so there's no ambiguity around what a variable or parameter is.
- Some guides require contracts. Any required contracts live in the
contracts
folder, and you can compile the contracts in that folder withyarn build
. - Contract addresses used to test against live deployments on a forked network can be found in the
deployments
folder - Money Markets are named
CozyToken
with a symbol ofcozyTokenSymbol
, for exampleCozy Dai
andcozyDAI
. Scripts use this naming convention to identify money markets
And finally, a few notes on Hardhat:
- The scripts explicitly require the Hardhat Runtime Environment with
import hre from 'hardhat'
. This is optional, but is required if you wanted to run the script in a standalone fashion withyarn ts-node <script.ts>
. When running the script withyarn hardhat run <script>
this explicit import is unnecessary. We default to the explicit,ts-node
approach so there's less hardhat magic and improved readability and portability. Similarly, this is why some scripts callawait hre.run('compile')
—this compiles our contracts, and would otherwise be done automatically when running withyarn hardhat run <script>
- Some scripts deploy contracts by using
hre.ethers.getContractFactory()
to get the Contract Factory instance. If you want to do this without Hardhat, use the regular ethers Contract Factory approach. Deploying contracts is not the focus of these guides, so it uses the Hardhat approach for convenience and brevity. - For convenience, these scripts often access ethers methods using
hre.ethers
. If you want to remove Hardhat, you should be able to replacehre.ethers
withethers
seamlessly. - Normally, if you want to know which chain ID your provider is connected to, you could simply use
(await ethers.provider.getNetwork()).chainId
. Because these scripts runs against a local, forked network, the chain ID is Hardhat's default value of 1337. ThegetContractAddress()
helper method inutils/utils.ts
relies on the chain ID to properly fetch contract addresses, so we define a customgetChainId()
method to override the chain ID based on which network we've forked locally against
For an explanation of Error Codes that may be returned, see [TODO GitBook link]. For a brief description of each script in the guides
folder, see the table below.
Script Name | Description |
---|---|
buy-protection.ts |
Supply collateral and use that collateral to borrow protected funds |
create-protection-market.ts |
Write a Trigger contract and use that as the foundation for a new Protection Market |
liquidate.ts |
Check if an account can be liquidated, how much can be liquidated, and liquidate the account |
manage-protection.ts |
View your existing positions and account liquidity, supply more collateral, and repay debt |
provide-protection.ts |
Supply funds to provide protection to a Protection Market |