Skip to content

Commit

Permalink
chore: Comment and NatSpec final pass (#392)
Browse files Browse the repository at this point in the history
* chore: Comment and NatSpec final pass

* PR fixes
  • Loading branch information
deluca-mike authored May 1, 2021
1 parent 308273d commit d921a7c
Show file tree
Hide file tree
Showing 72 changed files with 900 additions and 795 deletions.
13 changes: 7 additions & 6 deletions contracts/CollateralLocker.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ pragma solidity 0.6.11;

import "lib/openzeppelin-contracts/contracts/token/ERC20/SafeERC20.sol";

/// @title CollateralLocker holds custody of collateralAsset for Loans.
/// @title CollateralLocker holds custody of Collateral Asset for Loans.
contract CollateralLocker {

using SafeERC20 for IERC20;

IERC20 public immutable collateralAsset; // Address the loan is funded with
address public immutable loan; // Loan contract address this CollateralLocker is attached to
IERC20 public immutable collateralAsset; // Address the Collateral Asset the Loan is collateralized with.
address public immutable loan; // Loan contract address this CollateralLocker is attached to.

constructor(address _collateralAsset, address _loan) public {
collateralAsset = IERC20(_collateralAsset);
Expand All @@ -25,11 +25,12 @@ contract CollateralLocker {
}

/**
@dev Transfers amt of collateralAsset to dst. Only the Loan can call this function.
@param dst Destination to transfer collateralAsset to.
@param amt Amount of collateralAsset to transfer.
@dev Transfers amount of Collateral Asset to a destination account. Only the Loan can call this function.
@param dst Destination to transfer Collateral Asset to.
@param amt Amount of Collateral Asset to transfer.
*/
function pull(address dst, uint256 amt) isLoan external {
collateralAsset.safeTransfer(dst, amt);
}

}
15 changes: 8 additions & 7 deletions contracts/CollateralLockerFactory.sol
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.6.11;

import "./CollateralLocker.sol";

import "./interfaces/ILoanFactory.sol";

import "./CollateralLocker.sol";

/// @title CollateralLockerFactory instantiates CollateralLockers.
contract CollateralLockerFactory {

mapping(address => address) public owner; // Mapping of locker contract address to its owner i.e owner[locker] = Owner of the collateral locker
mapping(address => bool) public isLocker; // True if collateral locker was created by this factory, otherwise false
mapping(address => address) public owner; // Mapping of CollateralLocker addresses to their owner (i.e owner[locker] = Owner of the CollateralLocker).
mapping(address => bool) public isLocker; // True only if a CollateralLocker was created by this factory.

uint8 public constant factoryType = 0; // i.e FactoryType::COLLATERAL_LOCKER_FACTORY

event CollateralLockerCreated(address indexed owner, address collateralLocker, address collateralAsset);

/**
@dev Instantiate a CollateralLocker contract.
@dev Instantiates a CollateralLocker.
@dev It emits a `CollateralLockerCreated` event.
@param collateralAsset The asset this collateral locker will escrow.
@return collateralLocker Address of the instantiated collateral locker.
@param collateralAsset The Collateral Asset this CollateralLocker will escrow.
@return collateralLocker Address of the instantiated CollateralLocker.
*/
function newLocker(address collateralAsset) external returns (address collateralLocker) {
collateralLocker = address(new CollateralLocker(collateralAsset, msg.sender));
Expand All @@ -28,4 +28,5 @@ contract CollateralLockerFactory {

emit CollateralLockerCreated(msg.sender, collateralLocker, collateralAsset);
}

}
66 changes: 33 additions & 33 deletions contracts/DebtLocker.sol
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.6.11;

import "./interfaces/ILoan.sol";

import "lib/openzeppelin-contracts/contracts/math/SafeMath.sol";
import "lib/openzeppelin-contracts/contracts/token/ERC20/SafeERC20.sol";

import "./interfaces/ILoan.sol";

/// @title DebtLocker holds custody of LoanFDT tokens.
contract DebtLocker {

Expand All @@ -14,16 +14,16 @@ contract DebtLocker {

uint256 constant WAD = 10 ** 18;

ILoan public immutable loan; // The Loan contract this locker is holding tokens for
IERC20 public immutable liquidityAsset; // The liquidityAsset this locker can claim
address public immutable pool; // The owner of this Locker (the Pool)
ILoan public immutable loan; // The Loan contract this locker is holding tokens for.
IERC20 public immutable liquidityAsset; // The Liquidity Asset this locker can claim.
address public immutable pool; // The owner of this Locker (the Pool).

uint256 public lastPrincipalPaid; // Loan total principal paid at last time claim() was called
uint256 public lastInterestPaid; // Loan total interest paid at last time claim() was called
uint256 public lastFeePaid; // Loan total fees paid at last time claim() was called
uint256 public lastExcessReturned; // Loan total excess returned at last time claim() was called
uint256 public lastDefaultSuffered; // Loan total default suffered at last time claim() was called
uint256 public lastAmountRecovered; // Liquidity asset (a.k.a. loan asset) recovered from liquidation of Loan collateral
uint256 public lastPrincipalPaid; // Loan total principal paid at last time claim() was called.
uint256 public lastInterestPaid; // Loan total interest paid at last time claim() was called.
uint256 public lastFeePaid; // Loan total fees paid at last time claim() was called.
uint256 public lastExcessReturned; // Loan total excess returned at last time claim() was called.
uint256 public lastDefaultSuffered; // Loan total default suffered at last time claim() was called.
uint256 public lastAmountRecovered; // Liquidity Asset (a.k.a. loan asset) recovered from liquidation of Loan collateral.

/**
@dev Checks that `msg.sender` is the Pool.
Expand All @@ -45,7 +45,7 @@ contract DebtLocker {
}

/**
@dev Claim funds distribution for Loan via FDT. Only the Pool can call this function.
@dev Claims funds distribution for Loan via LoanFDT. Only the Pool can call this function.
@return [0] = Total Claimed
[1] = Interest Claimed
[2] = Principal Claimed
Expand All @@ -56,73 +56,73 @@ contract DebtLocker {
*/
function claim() external isPool returns (uint256[7] memory) {

// Initialize newDefaultSuffered as zero
uint256 newDefaultSuffered = uint256(0);
uint256 loan_defaultSuffered = loan.defaultSuffered();

// If a default has occurred, update storage variable and update memory variable from zero for return.
// `newDefaultSuffered` represents the proportional loss that the DebtLocker registers based on its balance
// of LoanFDTs in comparison to the totalSupply of LoanFDTs.
// Default will occur only once so below statement will only be `true` once.
// of LoanFDTs in comparison to the total supply of LoanFDTs.
// Default will occur only once, so below statement will only be `true` once.
if (lastDefaultSuffered == uint256(0) && loan_defaultSuffered > uint256(0)) {
newDefaultSuffered = lastDefaultSuffered = _calcAllotment(loan.balanceOf(address(this)), loan_defaultSuffered, loan.totalSupply());
}

// Account for any transfers into Loan that have occurred since last call
// Account for any transfers into Loan that have occurred since last call.
loan.updateFundsReceived();

// Handles case where no claimable funds are present but a default must be registered (zero-collateralized loans defaulting)
// Handles case where no claimable funds are present but a default must be registered (zero-collateralized loans defaulting).
if (loan.withdrawableFundsOf(address(this)) == uint256(0)) return([0, 0, 0, 0, 0, 0, newDefaultSuffered]);

// If there are claimable funds, calculate portions and claim using LoanFDT
// If there are claimable funds, calculate portions and claim using LoanFDT.

// Calculate payment deltas
// Calculate payment deltas.
uint256 newInterest = loan.interestPaid() - lastInterestPaid; // `loan.interestPaid` updated in `loan._makePayment()`
uint256 newPrincipal = loan.principalPaid() - lastPrincipalPaid; // `loan.principalPaid` updated in `loan._makePayment()`

// Update storage variables for next delta calculation
// Update storage variables for next delta calculation.
lastInterestPaid = loan.interestPaid();
lastPrincipalPaid = loan.principalPaid();

// Calculate one-time deltas if storage variables have not yet been updated
// Calculate one-time deltas if storage variables have not yet been updated.
uint256 newFee = lastFeePaid == uint256(0) ? loan.feePaid() : uint256(0); // `loan.feePaid` updated in `loan.drawdown()`
uint256 newExcess = lastExcessReturned == uint256(0) ? loan.excessReturned() : uint256(0); // `loan.excessReturned` updated in `loan.unwind()` OR `loan.drawdown()` if `amt < fundingLockerBal`
uint256 newAmountRecovered = lastAmountRecovered == uint256(0) ? loan.amountRecovered() : uint256(0); // `loan.amountRecovered` updated in `loan.triggerDefault()`

// Update DebtLocker storage variable if Loan storage variable has been updated since last claim
// Update DebtLocker storage variables if Loan storage variables has been updated since last claim.
if (newFee > 0) lastFeePaid = newFee;
if (newExcess > 0) lastExcessReturned = newExcess;
if (newAmountRecovered > 0) lastAmountRecovered = newAmountRecovered;

// Withdraw all claimable funds via LoanFDT
uint256 beforeBal = liquidityAsset.balanceOf(address(this)); // Current balance of DebtLocker (accounts for direct inflows)
loan.withdrawFunds(); // Transfer funds from Loan to DebtLocker
uint256 claimBal = liquidityAsset.balanceOf(address(this)).sub(beforeBal); // Amount claimed from Loan using LoanFDT
// Withdraw all claimable funds via LoanFDT.
uint256 beforeBal = liquidityAsset.balanceOf(address(this)); // Current balance of DebtLocker (accounts for direct inflows).
loan.withdrawFunds(); // Transfer funds from Loan to DebtLocker.
uint256 claimBal = liquidityAsset.balanceOf(address(this)).sub(beforeBal); // Amount claimed from Loan using LoanFDT.

// Calculate sum of all deltas, to be used to calculate portions for metadata
// Calculate sum of all deltas, to be used to calculate portions for metadata.
uint256 sum = newInterest.add(newPrincipal).add(newFee).add(newExcess).add(newAmountRecovered);

// Calculate payment portions based on LoanFDT claim
// Calculate payment portions based on LoanFDT claim.
newInterest = _calcAllotment(newInterest, claimBal, sum);
newPrincipal = _calcAllotment(newPrincipal, claimBal, sum);

// Calculate one-time portions based on LoanFDT claim
// Calculate one-time portions based on LoanFDT claim.
newFee = _calcAllotment(newFee, claimBal, sum);
newExcess = _calcAllotment(newExcess, claimBal, sum);
newAmountRecovered = _calcAllotment(newAmountRecovered, claimBal, sum);

liquidityAsset.safeTransfer(pool, claimBal); // Transfer entire amount claimed using LoanFDT
liquidityAsset.safeTransfer(pool, claimBal); // Transfer entire amount claimed using LoanFDT.

// Return claim amount plus all relevant metadata, to be used by Pool for further claim logic
// Return claim amount plus all relevant metadata, to be used by Pool for further claim logic.
// Note: newInterest + newPrincipal + newFee + newExcess + newAmountRecovered = claimBal - dust
// The dust on the right side of the equation gathers in the pool after transfers are made
// The dust on the right side of the equation gathers in the pool after transfers are made.
return([claimBal, newInterest, newPrincipal, newFee, newExcess, newAmountRecovered, newDefaultSuffered]);
}

/**
@dev Liquidate a loan that is held by this contract. Only the Pool can call this function.
@dev Liquidates a Loan that is held by this contract. Only the Pool can call this function.
*/
function triggerDefault() external isPool {
loan.triggerDefault();
}

}
11 changes: 6 additions & 5 deletions contracts/DebtLockerFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,18 @@ import "./DebtLocker.sol";
/// @title DebtLockerFactory instantiates DebtLockers.
contract DebtLockerFactory {

mapping(address => address) public owner; // Mapping of locker contract address to its owner i.e owner[locker] = Owner of the debt locker
mapping(address => bool) public isLocker; // True if debt locker was created in this factory, otherwise false
mapping(address => address) public owner; // Mapping of DebtLocker addresses to their owner (i.e owner[locker] = Owner of the DebtLocker).
mapping(address => bool) public isLocker; // True only if a DebtLocker was created by this factory.

uint8 public constant factoryType = 1; // i.e LockerFactoryTypes::DEBT_LOCKER_FACTORY

event DebtLockerCreated(address indexed owner, address debtLocker, address loan);

/**
@dev Instantiate a DebtLocker contract.
@dev Instantiates a DebtLocker.
@dev It emits a `DebtLockerCreated` event.
@param loan The loan this debt locker will escrow tokens for.
@return debtLocker Address of the instantiated debt locker.
@param loan The Loan this DebtLocker will escrow tokens for.
@return debtLocker Address of the instantiated DebtLocker.
*/
function newLocker(address loan) external returns (address debtLocker) {
debtLocker = address(new DebtLocker(loan, msg.sender));
Expand All @@ -26,4 +26,5 @@ contract DebtLockerFactory {

emit DebtLockerCreated(msg.sender, debtLocker, loan);
}

}
15 changes: 8 additions & 7 deletions contracts/FundingLocker.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ pragma solidity 0.6.11;

import "lib/openzeppelin-contracts/contracts/token/ERC20/SafeERC20.sol";

/// @title FundingLocker holds custody of liquidityAsset tokens during the funding period of a Loan.
/// @title FundingLocker holds custody of Liquidity Asset tokens during the funding period of a Loan.
contract FundingLocker {

using SafeERC20 for IERC20;

IERC20 public immutable liquidityAsset; // Asset the Loan was funded with
address public immutable loan; // Loan this FundingLocker has funded
IERC20 public immutable liquidityAsset; // Asset the Loan was funded with.
address public immutable loan; // Loan this FundingLocker has funded.

constructor(address _liquidityAsset, address _loan) public {
liquidityAsset = IERC20(_liquidityAsset);
Expand All @@ -25,19 +25,20 @@ contract FundingLocker {
}

/**
@dev Transfers amt of liquidityAsset to dst. Only the Loan can call this function.
@param dst Destination to transfer liquidityAsset to.
@param amt Amount of liquidityAsset to transfer.
@dev Transfers amount of Liquidity Asset to a destination account. Only the Loan can call this function.
@param dst Destination to transfer Liquidity Asset to.
@param amt Amount of Liquidity Asset to transfer.
*/
function pull(address dst, uint256 amt) isLoan external {
liquidityAsset.safeTransfer(dst, amt);
}

/**
@dev Transfers entire amount of liquidityAsset held in escrow to Loan. Only the Loan can call this function.
@dev Transfers entire amount of Liquidity Asset held in escrow to the Loan. Only the Loan can call this function.
*/
function drain() isLoan external {
uint256 amt = liquidityAsset.balanceOf(address(this));
liquidityAsset.safeTransfer(loan, amt);
}

}
11 changes: 6 additions & 5 deletions contracts/FundingLockerFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@ import "./interfaces/ILoanFactory.sol";
/// @title FundingLockerFactory instantiates FundingLockers.
contract FundingLockerFactory {

mapping(address => address) public owner; // Mapping of locker contract address to its owner i.e owner[locker] = Owner of the funding locker
mapping(address => bool) public isLocker; // True if funding locker was created by this factory, otherwise false
mapping(address => address) public owner; // Mapping of FundingLocker addresses to their owner (i.e owner[locker] = Owner of the FundingLocker).
mapping(address => bool) public isLocker; // True only if a FundingLocker was created by this factory.

uint8 public constant factoryType = 2; // i.e FactoryType::FUNDING_LOCKER_FACTORY

event FundingLockerCreated(address indexed owner, address fundingLocker, address liquidityAsset);

/**
@dev Instantiate a FundingLocker contract.
@dev Instantiates a FundingLocker.
@dev It emits a `FundingLockerCreated` event.
@param liquidityAsset The asset this funding locker will escrow.
@return fundingLocker Address of the instantiated funding locker.
@param liquidityAsset The Liquidity Asset this FundingLocker will escrow.
@return fundingLocker Address of the instantiated FundingLocker.
*/
function newLocker(address liquidityAsset) external returns (address fundingLocker) {
fundingLocker = address(new FundingLocker(liquidityAsset, msg.sender));
Expand All @@ -28,4 +28,5 @@ contract FundingLockerFactory {

emit FundingLockerCreated(msg.sender, fundingLocker, liquidityAsset);
}

}
9 changes: 5 additions & 4 deletions contracts/LateFeeCalc.sol
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.6.11;

import "lib/openzeppelin-contracts/contracts/math/SafeMath.sol";

import "./interfaces/ILoan.sol";
import "./interfaces/IRepaymentCalc.sol";

import "lib/openzeppelin-contracts/contracts/math/SafeMath.sol";

/// @title LateFeeCalc calculates late fees on Loans.
contract LateFeeCalc {

Expand All @@ -21,11 +21,12 @@ contract LateFeeCalc {
}

/**
@dev Calculates the late fee payment for a loan.
@dev Calculates the late fee payment for a Loan.
@param interest Amount of interest to be used to calculate late fee for.
@return Late fee that is charged to borrower.
@return Late fee that is charged to the Borrower.
*/
function getLateFee(uint256 interest) external view returns (uint256) {
return interest.mul(lateFee).div(10_000);
}

}
Loading

0 comments on commit d921a7c

Please sign in to comment.