LogoLogo
Return to CozyDiscord
Main
Main
  • Get started
  • What is Cozy
    • Overview
    • Case study
    • FAQ
    • Security
  • For Developers
    • Guides
      • Set up your development environment
      • Create a protection market
      • Buy protection programmatically
      • Manage protection programmatically
      • Provide protection programmatically
      • Liquidate a vault
      • Create a protected investing opportunity
      • Create an invest/divest contract
    • Error codes
    • API reference
      • Cozy tokens
      • Comptroller
      • Full API reference
    • Contract deployments
  • Get In Touch
    • Twitter
    • Discord
Powered by GitBook
On this page
  • Supply collateral
  • Determine address of the money market
  • Supply the collateral
  • Verify transaction results
  • Enter markets
  • Borrow funds

Was this helpful?

  1. For Developers
  2. Guides

Buy protection programmatically

Learn how to buy protection programmatically on the Cozy protocol.

PreviousCreate a protection marketNextManage protection programmatically

Last updated 3 years ago

Was this helpful?

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 programmatically,

All code snippets are from the buy-protection.ts script in the repository. See that repository for more context, definitions of helper methods used, etc.

Everything in this guide assumes that you have experience with JavaScript, , and .

Supply collateral

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

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:

buy-protection.ts
// 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}`);

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.

buy-protection.ts
// 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}`);

Verify transaction results

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

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:

buy-protection.ts
// 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`);

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:

buy-protection.ts
// 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

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.

All markets in Cozy—money markets and protection markets—have a trigger state variable. If the value of the trigger property is the , 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.

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 , and see information about error handling history .

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 file in the repository.

zero address
Error codes
here
utils.ts
Cozy developer Guides
Cozy Developer Guides
ethers.js
Solidity
protection market