Vault.sol

Setup

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import "lib/chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
import "lib/yield-utils-v2/contracts/token/IERC20.sol";
import "lib/openzeppelin-contracts/contracts/access/Ownable.sol";

contract Vault is Ownable {

    //vault records DEPOSITS & Debt
    mapping (address => uint) public deposits; //deposits in WETH
    mapping (address => uint) public debts;   //debt in DAI

    ///@notice ERC20 interface specifying token contract functions
    ///@dev For constant variables, the value has to be fixed at compile-time, while for immutable, it can still be assigned at construction time.
    IERC20 public immutable collateral;    
    IERC20 public immutable debt;  

    // DAi/WETH Pricefeed
    AggregatorV3Interface public immutable priceFeed;   
    
    event Deposit(address indexed collateralAsset, address indexed user, uint collateralAmount);  
    event Borrow(address indexed debtAsset, address indexed user, uint debtAmount); 
    event Repay(address indexed debtAsset, address indexed user, uint debtAmount);
    event Withdraw(address indexed collateralAsset, address indexed user, uint collateralAmount);  
    event Liquidation(address indexed collateralAsset, address indexed debtAsset, address indexed user, uint debtToCover, uint liquidatedCollateralAmount);
  
    uint bufferDenominator; 
    uint bufferNumerator;
    
    constructor(address dai_, address weth_, address priceFeedAddress, uint bufferNumerator_, uint bufferDenominator_) {
        collateral = IERC20(weth_);
        debt = IERC20(dai_);
        priceFeed = AggregatorV3Interface(priceFeedAddress);
        // collateralization level
        bufferNumerator = bufferNumerator_;
        bufferDenominator = bufferDenominator_;
    }
  • mappings to track deposits & debt for each user address

  • IERC20 interfaces to interact with both the DAI and WETH contracts

  • AggregatorV3Interface for interacting with Chainlink Oracle

use of immutable vs constant

  • for constant variables, the value has to be fixed at compile-time, (initial and assign in one line)

  • for immutable, it can still be assigned at construction time (within constructor)

Margin level

buffer Num/Denominator for setting margin level: 8/10 -> 80%

  • 80% collateralization level.

  • maxDebt is calculated against 80% of deposits.

Functions

deposit()

borrow()

  • can borrow up till maxDebt as calculated below

getMaxDebt()

  • based on user's deposits, calculate the available collateral, as per specified Margin level

  • convert availableCollateral to the quantity of corresponding debtAsset as per mkt price

repay()

  • covers partial and full repayments

withdraw()

  • users can withdraw their deposited collateral

  • if user has debt, checks for spare capacity before initiating withdrawal

getCollateralRequired()

  • Calculates collateral required to support existing debt position at current market prices

  • it is important to do the multiplication before the division in the pricing calculation

    • because leading with a division may result in a decimal -> which solidity cannot handle

liquidation()

  • Triggers liquidation check on supplied user address

  • Can only be called by Vault owner;

  • if collateralRequired > deposits[user] -> liquidation

get_daiETH_price()

  • Get current market price of Collateral/Debt asset from Chainlink

  • Price is returned as integer extending over its decimal places

getDecimals()

  • Returns number of decimal places in price returned

Using get_daiETH_price & getDecimals() together

  • getPrice returns: 386372840000000

  • getDecimals returns: 18

Used to rebase chainlink price into market price, to account for decimal places

  • price = 386372840000000, decimals =18, actual_price = 0.00038637284

  • actual price should match the market price as quotes by websites and frontends.

Chainlink API documentation will inform us of the decimals in each price quote on:

Full code

Last updated