Skip to content

Latest commit

 

History

History
907 lines (740 loc) · 26.7 KB

VaultLibV1.md

File metadata and controls

907 lines (740 loc) · 26.7 KB

VaultLibV1.sol

View Source: contracts/libraries/VaultLibV1.sol

VaultLibV1

Contract Members

Constants & Variables

uint256 public constant WITHDRAWAL_HEIGHT_OFFSET;

Functions

calculatePodsInternal

Calculates the amount of PODS to mint for the given amount of liquidity to transfer

function calculatePodsInternal(IStore s, bytes32 coverKey, address pod, uint256 liquidityToAdd) public view
returns(uint256)

Arguments

Name Type Description
s IStore
coverKey bytes32
pod address
liquidityToAdd uint256
Source Code
function calculatePodsInternal(
    IStore s,
    bytes32 coverKey,
    address pod,
    uint256 liquidityToAdd
  ) public view returns (uint256) {
    require(s.getBoolByKeys(ProtoUtilV1.NS_COVER_HAS_FLASH_LOAN, coverKey) == false, "On flash loan, please try again");

    uint256 balance = s.getStablecoinOwnedByVaultInternal(coverKey);
    uint256 podSupply = IERC20(pod).totalSupply();
    uint256 stablecoinPrecision = s.getStablecoinPrecision();

    // This smart contract contains stablecoins without liquidity provider contribution.
    // This can happen if someone wants to create a nuisance by sending stablecoin
    // to this contract immediately after deployment.
    if (podSupply == 0 && balance > 0) {
      revert("Liquidity/POD mismatch");
    }

    if (balance > 0) {
      return (podSupply * liquidityToAdd) / balance;
    }

    return (liquidityToAdd * ProtoUtilV1.POD_PRECISION) / stablecoinPrecision;
  }

calculateLiquidityInternal

Calculates the amount of liquidity to transfer for the given amount of PODs to burn. The Vault contract lends out liquidity to external protocols to maximize reward regularly. But it also withdraws periodically to receive back the loaned amount with interest. In other words, the Vault contract continuously supplies available liquidity to lending protocols and withdraws during a fixed interval. For example, supply during 180-day lending period and allow withdrawals during 7-day withdrawal period.

function calculateLiquidityInternal(IStore s, bytes32 coverKey, address pod, uint256 podsToBurn) public view
returns(uint256)

Arguments

Name Type Description
s IStore
coverKey bytes32
pod address
podsToBurn uint256
Source Code
function calculateLiquidityInternal(
    IStore s,
    bytes32 coverKey,
    address pod,
    uint256 podsToBurn
  ) public view returns (uint256) {
    require(s.getBoolByKeys(ProtoUtilV1.NS_COVER_HAS_FLASH_LOAN, coverKey) == false, "On flash loan, please try again");

    uint256 balance = s.getStablecoinOwnedByVaultInternal(coverKey);
    uint256 podSupply = IERC20(pod).totalSupply();

    return (balance * podsToBurn) / podSupply;
  }

getInfoInternal

Gets information of a given vault by the cover key

function getInfoInternal(IStore s, bytes32 coverKey, address pod, address you) external view
returns(info struct IVault.VaultInfoType)

Arguments

Name Type Description
s IStore Provide a store instance
coverKey bytes32 Specify cover key to obtain the info of.
pod address Provide the address of the POD
you address The address for which the info will be customized
Source Code
function getInfoInternal(
    IStore s,
    bytes32 coverKey,
    address pod,
    address you
  ) external view returns (IVault.VaultInfoType memory info) {
    info.totalPods = IERC20(pod).totalSupply(); // Total PODs in existence
    info.balance = s.getStablecoinOwnedByVaultInternal(coverKey); // Stablecoins held in the vault
    info.extendedBalance = s.getAmountInStrategies(coverKey, s.getStablecoin()); //  Stablecoins lent outside of the protocol
    info.totalReassurance = s.getReassuranceAmountInternal(coverKey); // Total reassurance for this cover
    info.myPodBalance = IERC20(pod).balanceOf(you); // Your POD Balance
    info.myShare = calculateLiquidityInternal(s, coverKey, pod, info.myPodBalance); //  My share of the liquidity pool (in stablecoin)
    info.withdrawalOpen = s.getUintByKey(RoutineInvokerLibV1.getNextWithdrawalStartKey(coverKey)); // The timestamp when withdrawals are opened
    info.withdrawalClose = s.getUintByKey(RoutineInvokerLibV1.getNextWithdrawalEndKey(coverKey)); // The timestamp when withdrawals are closed again
  }

preAddLiquidityInternal

Called before adding liquidity to the specified cover contract

function preAddLiquidityInternal(IStore s, bytes32 coverKey, address pod, address account, uint256 amount, uint256 npmStakeToAdd) external nonpayable
returns(podsToMint uint256, myPreviousStake uint256)

Arguments

Name Type Description
s IStore
coverKey bytes32 Enter the cover key
pod address
account address Specify the account on behalf of which the liquidity is being added.
amount uint256 Enter the amount of liquidity token to supply.
npmStakeToAdd uint256 Enter the amount of NPM token to stake.
Source Code
function preAddLiquidityInternal(
    IStore s,
    bytes32 coverKey,
    address pod,
    address account,
    uint256 amount,
    uint256 npmStakeToAdd
  ) external returns (uint256 podsToMint, uint256 myPreviousStake) {
    require(account != address(0), "Invalid account");

    // Update values
    myPreviousStake = _updateNpmStake(s, coverKey, account, npmStakeToAdd);
    podsToMint = calculatePodsInternal(s, coverKey, pod, amount);

    _updateLastBlock(s, coverKey);
  }

_updateLastBlock

function _updateLastBlock(IStore s, bytes32 coverKey) private nonpayable

Arguments

Name Type Description
s IStore
coverKey bytes32
Source Code
function _updateLastBlock(IStore s, bytes32 coverKey) private {
    s.setUintByKey(CoverUtilV1.getLastDepositHeightKey(coverKey), block.number);
  }

_updateNpmStake

function _updateNpmStake(IStore s, bytes32 coverKey, address account, uint256 amount) private nonpayable
returns(myPreviousStake uint256)

Arguments

Name Type Description
s IStore
coverKey bytes32
account address
amount uint256
Source Code
function _updateNpmStake(
    IStore s,
    bytes32 coverKey,
    address account,
    uint256 amount
  ) private returns (uint256 myPreviousStake) {
    myPreviousStake = _getMyNpmStake(s, coverKey, account);
    require(amount + myPreviousStake >= s.getMinStakeToAddLiquidity(), "Insufficient stake");

    if (amount > 0) {
      s.addUintByKey(CoverUtilV1.getCoverLiquidityStakeKey(coverKey), amount); // Total stake
      s.addUintByKey(CoverUtilV1.getCoverLiquidityStakeIndividualKey(coverKey, account), amount); // Your stake
    }
  }

_getMyNpmStake

function _getMyNpmStake(IStore s, bytes32 coverKey, address account) private view
returns(myStake uint256)

Arguments

Name Type Description
s IStore
coverKey bytes32
account address
Source Code
function _getMyNpmStake(
    IStore s,
    bytes32 coverKey,
    address account
  ) private view returns (uint256 myStake) {
    (, myStake) = getCoverNpmStake(s, coverKey, account);
  }

getCoverNpmStake

function getCoverNpmStake(IStore s, bytes32 coverKey, address account) public view
returns(totalStake uint256, myStake uint256)

Arguments

Name Type Description
s IStore
coverKey bytes32
account address
Source Code
function getCoverNpmStake(
    IStore s,
    bytes32 coverKey,
    address account
  ) public view returns (uint256 totalStake, uint256 myStake) {
    totalStake = s.getUintByKey(CoverUtilV1.getCoverLiquidityStakeKey(coverKey));
    myStake = s.getUintByKey(CoverUtilV1.getCoverLiquidityStakeIndividualKey(coverKey, account));
  }

mustHaveNoBalanceInStrategies

function mustHaveNoBalanceInStrategies(IStore s, bytes32 coverKey, address stablecoin) external view

Arguments

Name Type Description
s IStore
coverKey bytes32
stablecoin address
Source Code
function mustHaveNoBalanceInStrategies(
    IStore s,
    bytes32 coverKey,
    address stablecoin
  ) external view {
    require(s.getAmountInStrategies(coverKey, stablecoin) == 0, "Strategy balance is not zero");
  }

mustMaintainBlockHeightOffset

function mustMaintainBlockHeightOffset(IStore s, bytes32 coverKey) external view

Arguments

Name Type Description
s IStore
coverKey bytes32
Source Code
function mustMaintainBlockHeightOffset(IStore s, bytes32 coverKey) external view {
    uint256 lastDeposit = s.getUintByKey(CoverUtilV1.getLastDepositHeightKey(coverKey));
    require(block.number > lastDeposit + WITHDRAWAL_HEIGHT_OFFSET, "Please wait a few blocks");
  }

preRemoveLiquidityInternal

Removes liquidity from the specified cover contract

function preRemoveLiquidityInternal(IStore s, bytes32 coverKey, address pod, address account, uint256 podsToRedeem, uint256 npmStakeToRemove, bool exit) external nonpayable
returns(stablecoin address, releaseAmount uint256)

Arguments

Name Type Description
s IStore
coverKey bytes32 Enter the cover key
pod address sToRedeem Enter the amount of liquidity token to remove.
account address
podsToRedeem uint256 Enter the amount of liquidity token to remove.
npmStakeToRemove uint256
exit bool
Source Code
function preRemoveLiquidityInternal(
    IStore s,
    bytes32 coverKey,
    address pod,
    address account,
    uint256 podsToRedeem,
    uint256 npmStakeToRemove,
    bool exit
  ) external returns (address stablecoin, uint256 releaseAmount) {
    stablecoin = s.getStablecoin();

    // Redeem the PODs and receive DAI
    releaseAmount = _redeemPodCalculation(s, coverKey, pod, podsToRedeem);

    ValidationLibV1.mustNotExceedStablecoinThreshold(s, releaseAmount);
    GovernanceUtilV1.mustNotExceedNpmThreshold(npmStakeToRemove);

    // Unstake NPM tokens
    if (npmStakeToRemove > 0) {
      _unStakeNpm(s, account, coverKey, npmStakeToRemove, exit);
    }
  }

_unStakeNpm

function _unStakeNpm(IStore s, address account, bytes32 coverKey, uint256 amount, bool exit) private nonpayable

Arguments

Name Type Description
s IStore
account address
coverKey bytes32
amount uint256
exit bool
Source Code
function _unStakeNpm(
    IStore s,
    address account,
    bytes32 coverKey,
    uint256 amount,
    bool exit
  ) private {
    uint256 remainingStake = _getMyNpmStake(s, coverKey, account);
    uint256 minStakeToMaintain = s.getMinStakeToAddLiquidity();

    if (exit) {
      require(remainingStake == amount, "Invalid NPM stake to exit");
    } else {
      require(remainingStake - amount >= minStakeToMaintain, "Can't go below min stake");
    }

    s.subtractUintByKey(CoverUtilV1.getCoverLiquidityStakeKey(coverKey), amount); // Total stake
    s.subtractUintByKey(CoverUtilV1.getCoverLiquidityStakeIndividualKey(coverKey, account), amount); // Your stake
  }

_redeemPodCalculation

function _redeemPodCalculation(IStore s, bytes32 coverKey, address pod, uint256 podsToRedeem) private view
returns(uint256)

Arguments

Name Type Description
s IStore
coverKey bytes32
pod address
podsToRedeem uint256
Source Code
function _redeemPodCalculation(
    IStore s,
    bytes32 coverKey,
    address pod,
    uint256 podsToRedeem
  ) private view returns (uint256) {
    if (podsToRedeem == 0) {
      return 0;
    }

    s.mustBeProtocolMember(pod);

    uint256 precision = s.getStablecoinPrecision();

    uint256 balance = s.getStablecoinOwnedByVaultInternal(coverKey);
    uint256 commitment = s.getTotalLiquidityUnderProtection(coverKey, precision);
    uint256 available = balance - commitment;

    uint256 releaseAmount = calculateLiquidityInternal(s, coverKey, pod, podsToRedeem);

    // You may need to wait till active policies expire
    require(available >= releaseAmount, "Insufficient balance. Lower the amount or wait till policy expiry."); // solhint-disable-line

    return releaseAmount;
  }

accrueInterestInternal

function accrueInterestInternal(IStore s, bytes32 coverKey) external nonpayable

Arguments

Name Type Description
s IStore
coverKey bytes32
Source Code
function accrueInterestInternal(IStore s, bytes32 coverKey) external {
    (bool isWithdrawalPeriod, , , , ) = s.getWithdrawalInfoInternal(coverKey);
    require(isWithdrawalPeriod == true, "Withdrawal hasn't yet begun");

    s.updateStateAndLiquidity(coverKey);

    s.setAccrualCompleteInternal(coverKey, true);
  }

mustBeAccrued

function mustBeAccrued(IStore s, bytes32 coverKey) external view

Arguments

Name Type Description
s IStore
coverKey bytes32
Source Code
function mustBeAccrued(IStore s, bytes32 coverKey) external view {
    require(s.isAccrualCompleteInternal(coverKey) == true, "Wait for accrual");
  }

getFlashFeesInternal

The fee to be charged for a given loan.

function getFlashFeesInternal(IStore s, bytes32 coverKey, address token, uint256 amount) public view
returns(fee uint256, protocolFee uint256)

Arguments

Name Type Description
s IStore Provide an instance of the store
coverKey bytes32
token address The loan currency.
amount uint256 The amount of tokens lent.
Source Code
function getFlashFeesInternal(
    IStore s,
    bytes32 coverKey,
    address token,
    uint256 amount
  ) public view returns (uint256 fee, uint256 protocolFee) {
    address stablecoin = s.getStablecoin();
    require(stablecoin != address(0), "Cover liquidity uninitialized");

    /*
    https://eips.ethereum.org/EIPS/eip-3156

    The flashFee function MUST return the fee charged for a loan of amount token.
    If the token is not supported flashFee MUST revert.
    */
    require(stablecoin == token, "Unsupported token");
    require(IERC20(stablecoin).balanceOf(s.getVaultAddress(coverKey)) >= amount, "Amount insufficient");

    uint256 rate = _getFlashLoanFeeRateInternal(s);
    uint256 protocolRate = _getProtocolFlashLoanFeeRateInternal(s);

    fee = (amount * rate) / ProtoUtilV1.MULTIPLIER;
    protocolFee = (fee * protocolRate) / ProtoUtilV1.MULTIPLIER;
  }

getFlashFeeInternal

function getFlashFeeInternal(IStore s, bytes32 coverKey, address token, uint256 amount) external view
returns(uint256)

Arguments

Name Type Description
s IStore
coverKey bytes32
token address
amount uint256
Source Code
function getFlashFeeInternal(
    IStore s,
    bytes32 coverKey,
    address token,
    uint256 amount
  ) external view returns (uint256) {
    (uint256 fee, ) = getFlashFeesInternal(s, coverKey, token, amount);
    return fee;
  }

_getFlashLoanFeeRateInternal

function _getFlashLoanFeeRateInternal(IStore s) private view
returns(uint256)

Arguments

Name Type Description
s IStore
Source Code
function _getFlashLoanFeeRateInternal(IStore s) private view returns (uint256) {
    return s.getUintByKey(ProtoUtilV1.NS_COVER_LIQUIDITY_FLASH_LOAN_FEE);
  }

_getProtocolFlashLoanFeeRateInternal

function _getProtocolFlashLoanFeeRateInternal(IStore s) private view
returns(uint256)

Arguments

Name Type Description
s IStore
Source Code
function _getProtocolFlashLoanFeeRateInternal(IStore s) private view returns (uint256) {
    return s.getUintByKey(ProtoUtilV1.NS_COVER_LIQUIDITY_FLASH_LOAN_FEE_PROTOCOL);
  }

getMaxFlashLoanInternal

The amount of currency available to be lent.

function getMaxFlashLoanInternal(IStore s, bytes32 coverKey, address token) external view
returns(uint256)

Arguments

Name Type Description
s IStore
coverKey bytes32
token address The loan currency.

Returns

The amount of token that can be borrowed.

Source Code
function getMaxFlashLoanInternal(
    IStore s,
    bytes32 coverKey,
    address token
  ) external view returns (uint256) {
    address stablecoin = s.getStablecoin();
    require(stablecoin != address(0), "Cover liquidity uninitialized");

    if (stablecoin == token) {
      return IERC20(stablecoin).balanceOf(s.getVaultAddress(coverKey));
    }

    /*
    https://eips.ethereum.org/EIPS/eip-3156

    The maxFlashLoan function MUST return the maximum loan possible for token.
    If a token is not currently supported maxFlashLoan MUST return 0, instead of reverting.    
    */
    return 0;
  }

Contracts