Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
bricestacey committed Dec 6, 2022
1 parent 9fd3773 commit e5855f1
Show file tree
Hide file tree
Showing 13 changed files with 293 additions and 208 deletions.
4 changes: 4 additions & 0 deletions contracts/FeeVault.sol
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ contract FeeVault {
* @dev Allows withdrawal of fees held by vault.
*/
function withdraw(address asset, uint256 amount) external onlyPoolAdmin {
require(
IPool(pool).serviceConfiguration().paused() == false,
"FeeVault: Protocol paused"
);
IERC20(asset).safeTransfer(msg.sender, amount);
}
}
18 changes: 13 additions & 5 deletions contracts/FirstLossVault.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.16;

import "./interfaces/IServiceConfiguration.sol";
import "./controllers/PoolController.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

Expand All @@ -12,6 +14,7 @@ import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol
contract FirstLossVault {
using SafeERC20 for IERC20;

address public serviceConfiguration;
address public poolController;
IERC20 private _asset;

Expand All @@ -31,7 +34,12 @@ contract FirstLossVault {
* @param _poolController address of pool controller
* @param firstLossAsset asset held by vault
*/
constructor(address _poolController, address firstLossAsset) {
constructor(
address _serviceConfiguration,
address _poolController,
address firstLossAsset
) {
serviceConfiguration = _serviceConfiguration;
poolController = _poolController;
_asset = IERC20(firstLossAsset);
}
Expand All @@ -46,10 +54,10 @@ contract FirstLossVault {
/**
* @dev Allows withdrawal of funds held by vault.
*/
function withdraw(uint256 amount, address receiver)
external
onlyPoolController
{
function withdraw(
uint256 amount,
address receiver
) external onlyPoolController {
require(receiver != address(0), "FirstLossVault: 0 address");
_asset.safeTransfer(receiver, amount);
}
Expand Down
5 changes: 5 additions & 0 deletions contracts/FundingVault.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.16;

import "./interfaces/ILoan.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

Expand Down Expand Up @@ -37,6 +38,10 @@ contract FundingVault {
* @dev Allows withdrawal of funds held by vault.
*/
function withdraw(uint256 amount, address receiver) external onlyLoan {
require(
ILoan(_loan).serviceConfiguration().paused() == false,
"FundingVault: Protocol paused"
);
require(receiver != address(0), "FundingVault: 0 address");
asset.safeTransfer(receiver, amount);
}
Expand Down
69 changes: 48 additions & 21 deletions contracts/Loan.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ import "./FundingVault.sol";
*/
contract Loan is ILoan {
using SafeMath for uint256;
uint256 constant RAY = 10**27;
uint256 constant RAY = 10 ** 27;

IServiceConfiguration private immutable _serviceConfiguration;
IServiceConfiguration private _serviceConfiguration;
address private immutable _factory;
ILoanLifeCycleState private _state = ILoanLifeCycleState.Requested;
address private immutable _borrower;
Expand Down Expand Up @@ -156,6 +156,7 @@ contract Loan is ILoan {
atState(ILoanLifeCycleState.Requested)
returns (ILoanLifeCycleState)
{
requireNotPaused();
_state = ILoanLifeCycleState.Canceled;
return _state;
}
Expand All @@ -170,6 +171,7 @@ contract Loan is ILoan {
atState(ILoanLifeCycleState.Collateralized)
returns (ILoanLifeCycleState)
{
requireNotPaused();
require(
settings.dropDeadTimestamp < block.timestamp,
"Loan: Drop dead date not met"
Expand All @@ -188,6 +190,7 @@ contract Loan is ILoan {
atState(ILoanLifeCycleState.Funded)
returns (ILoanLifeCycleState)
{
requireNotPaused();
require(
msg.sender == _borrower || msg.sender == IPool(_pool).admin(),
"Loan: invalid caller"
Expand All @@ -214,6 +217,7 @@ contract Loan is ILoan {
address[] memory assets,
ILoanNonFungibleCollateral[] memory nonFungibleAssets
) external override {
requireNotPaused();
require(
(_state == ILoanLifeCycleState.Canceled &&
msg.sender == _borrower) ||
Expand All @@ -234,14 +238,18 @@ contract Loan is ILoan {
/**
* @dev Post ERC20 tokens as collateral
*/
function postFungibleCollateral(address asset, uint256 amount)
function postFungibleCollateral(
address asset,
uint256 amount
)
external
virtual
onlyPermittedBorrower
onlyBorrower
onlyNonTerminalState
returns (ILoanLifeCycleState)
{
requireNotPaused();
require(amount > 0, "Loan: posting 0 collateral");
_state = LoanLib.postFungibleCollateral(
address(_collateralVault),
Expand All @@ -260,14 +268,18 @@ contract Loan is ILoan {
/**
* @dev Post ERC721 tokens as collateral
*/
function postNonFungibleCollateral(address asset, uint256 tokenId)
function postNonFungibleCollateral(
address asset,
uint256 tokenId
)
external
virtual
onlyPermittedBorrower
onlyBorrower
onlyNonTerminalState
returns (ILoanLifeCycleState)
{
requireNotPaused();
_state = LoanLib.postNonFungibleCollateral(
address(_collateralVault),
asset,
Expand All @@ -291,6 +303,7 @@ contract Loan is ILoan {
* @dev Can only be called by the pool
*/
function fund() external onlyPool returns (ILoanLifeCycleState) {
requireNotPaused();
require(
_state == ILoanLifeCycleState.Requested ||
_state == ILoanLifeCycleState.Collateralized,
Expand All @@ -308,6 +321,7 @@ contract Loan is ILoan {
* @dev Pool administrators can reclaim funds in open term loans.
*/
function reclaimFunds(uint256 amount) external onlyPoolAdmin {
requireNotPaused();
require(settings.loanType == ILoanType.Open);

fundingVault.withdraw(amount, _pool);
Expand All @@ -319,13 +333,10 @@ contract Loan is ILoan {
/**
* @dev Drawdown the Loan
*/
function drawdown(uint256 amount)
external
virtual
onlyPermittedBorrower
onlyBorrower
returns (uint256)
{
function drawdown(
uint256 amount
) external virtual onlyPermittedBorrower onlyBorrower returns (uint256) {
requireNotPaused();
(_state, paymentDueDate) = LoanLib.drawdown(
amount,
fundingVault,
Expand All @@ -343,11 +354,10 @@ contract Loan is ILoan {
* @dev Prepay principal.
* @dev Only callable by open term loans
*/
function paydownPrincipal(uint256 amount)
external
onlyPermittedBorrower
onlyBorrower
{
function paydownPrincipal(
uint256 amount
) external onlyPermittedBorrower onlyBorrower {
requireNotPaused();
require(outstandingPrincipal >= amount, "Loan: amount too high");
require(settings.loanType == ILoanType.Open, "Loan: invalid loan type");
LoanLib.paydownPrincipal(liquidityAsset, amount, fundingVault);
Expand All @@ -364,6 +374,7 @@ contract Loan is ILoan {
atState(ILoanLifeCycleState.Active)
returns (uint256)
{
requireNotPaused();
require(paymentsRemaining > 0, "Loan: No more payments remain");

ILoanFees memory _fees = LoanLib.previewFees(
Expand Down Expand Up @@ -397,11 +408,9 @@ contract Loan is ILoan {
* @dev Preview fees for a given interest payment amount.
* @param amount allows previewing the fee for a full or prorated payment.
*/
function previewFees(uint256 amount)
public
view
returns (ILoanFees memory)
{
function previewFees(
uint256 amount
) public view returns (ILoanFees memory) {
return
LoanLib.previewFees(
settings,
Expand All @@ -424,6 +433,7 @@ contract Loan is ILoan {
atState(ILoanLifeCycleState.Active)
returns (uint256)
{
requireNotPaused();
uint256 scalingValue = RAY;

if (settings.loanType == ILoanType.Open) {
Expand Down Expand Up @@ -486,6 +496,7 @@ contract Loan is ILoan {
atState(ILoanLifeCycleState.Active)
returns (ILoanLifeCycleState)
{
requireNotPaused();
_state = ILoanLifeCycleState.Defaulted;
IPool(_pool).onLoanStateTransitioned();
emit LifeCycleStateTransition(_state);
Expand All @@ -496,6 +507,7 @@ contract Loan is ILoan {
* @inheritdoc ILoan
*/
function markCallback() external override onlyPoolAdmin {
requireNotPaused();
callbackTimestamp = block.timestamp;
}

Expand Down Expand Up @@ -538,4 +550,19 @@ contract Loan is ILoan {
function loanType() external view returns (ILoanType) {
return settings.loanType;
}

function serviceConfiguration()
external
view
returns (IServiceConfiguration)
{
return _serviceConfiguration;
}

function requireNotPaused() internal view {
require(
IServiceConfiguration(_serviceConfiguration).paused() == false,
"Loan: Protocol paused"
);
}
}
Loading

0 comments on commit e5855f1

Please sign in to comment.