Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VAL-117 Make Pool/WithdrawControllers upgradeable + Loan #131

Merged
merged 5 commits into from
Dec 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 16 additions & 15 deletions contracts/Loan.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,29 @@ import "./interfaces/IServiceConfiguration.sol";
import "./libraries/LoanLib.sol";
import "./CollateralVault.sol";
import "./FundingVault.sol";
import "./upgrades/interfaces/IBeaconImplementation.sol";

/**
* @title Loan
*
* Empty Loan contract.
*/
contract Loan is ILoan {
contract Loan is ILoan, IBeaconImplementation {
using SafeMath for uint256;
uint256 constant RAY = 10**27;

IServiceConfiguration private immutable _serviceConfiguration;
address private immutable _factory;
IServiceConfiguration private _serviceConfiguration;
address private _factory;
ILoanLifeCycleState private _state = ILoanLifeCycleState.Requested;
address private immutable _borrower;
address private immutable _pool;
CollateralVault public immutable _collateralVault;
FundingVault public immutable fundingVault;
address private _borrower;
address private _pool;
CollateralVault public _collateralVault;
FundingVault public fundingVault;
address[] private _fungibleCollateral;
ILoanNonFungibleCollateral[] private _nonFungibleCollateral;
uint256 public immutable createdAt;
address public immutable liquidityAsset;
uint256 public immutable payment;
uint256 public createdAt;
address public liquidityAsset;
uint256 public payment;
uint256 public outstandingPrincipal;
uint256 public paymentsRemaining;
uint256 public paymentDueDate;
Expand Down Expand Up @@ -111,15 +112,15 @@ contract Loan is ILoan {
_;
}

constructor(
IServiceConfiguration serviceConfiguration,
function initialize(
address serviceConfiguration,
address factory_,
address borrower_,
address pool_,
address liquidityAsset_,
ILoanSettings memory settings_
) {
_serviceConfiguration = serviceConfiguration;
) public virtual initializer {
_serviceConfiguration = IServiceConfiguration(serviceConfiguration);
_factory = factory_;
_borrower = borrower_;
_pool = pool_;
Expand All @@ -130,7 +131,7 @@ contract Loan is ILoan {
settings = settings_;

LoanLib.validateLoan(
serviceConfiguration,
_serviceConfiguration,
settings.duration,
settings.paymentPeriod,
settings.principal,
Expand Down
38 changes: 18 additions & 20 deletions contracts/LoanFactory.sol
Original file line number Diff line number Diff line change
@@ -1,28 +1,21 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.16;

import "./Loan.sol";
import "./interfaces/IServiceConfiguration.sol";
import "./interfaces/ILoanFactory.sol";
import "./Loan.sol";
import "./upgrades/BeaconProxyFactory.sol";
import {BeaconProxy} from "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol";

/**
* @title LoanFactory
*/
contract LoanFactory {
/**
* @dev Reference to the ServiceConfiguration contract
*/
IServiceConfiguration internal _serviceConfiguration;

contract LoanFactory is ILoanFactory, BeaconProxyFactory {
/**
* @dev Mapping of created loans
*/
mapping(address => bool) internal _isLoan;

/**
* @dev Emitted when a Loan is created.
*/
event LoanCreated(address indexed addr);

constructor(address serviceConfiguration) {
_serviceConfiguration = IServiceConfiguration(serviceConfiguration);
}
Expand All @@ -41,30 +34,35 @@ contract LoanFactory {
_serviceConfiguration.paused() == false,
"LoanFactory: Protocol paused"
);
require(implementation != address(0), "LoanFactory: no implementation");
address addr = initializeLoan(borrower, pool, liquidityAsset, settings);
emit LoanCreated(addr);
_isLoan[addr] = true;
return addr;
}

/**
* @dev Internal initialization of Loan contract
* @dev Internal initialization of Beacon proxy for Loans
*/
function initializeLoan(
address borrower,
address pool,
address liquidityAsset,
ILoanSettings memory settings
) internal virtual returns (address) {
Loan loan = new Loan(
_serviceConfiguration,
BeaconProxy proxy = new BeaconProxy(
address(this),
borrower,
pool,
liquidityAsset,
settings
abi.encodeWithSelector(
Loan.initialize.selector,
address(_serviceConfiguration),
address(this),
borrower,
pool,
liquidityAsset,
settings
)
);
return address(loan);
return address(proxy);
}

/**
Expand Down
49 changes: 6 additions & 43 deletions contracts/PoolFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,12 @@ import "./Pool.sol";
import "./interfaces/IServiceConfiguration.sol";
import "./interfaces/IPoolFactory.sol";
import {BeaconProxy} from "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol";
import "./upgrades/interfaces/IBeacon.sol";
import "./upgrades/BeaconProxyFactory.sol";

/**
* @title PoolFactory
*/
contract PoolFactory is IPoolFactory, IBeacon {
/**
* @dev Reference to the ServiceConfiguration contract
*/
address internal _serviceConfiguration;

contract PoolFactory is IPoolFactory, BeaconProxyFactory {
/**
* @dev Reference to the WithdrawControllerFactory contract
*/
Expand All @@ -26,44 +21,16 @@ contract PoolFactory is IPoolFactory, IBeacon {
*/
address internal _poolControllerFactory;

/**
* @inheritdoc IBeacon
*/
address public implementation;

/**
* @dev Modifier that requires that the sender is registered as a protocol deployer.
*/
modifier onlyDeployer() {
require(
IServiceConfiguration(_serviceConfiguration).isDeployer(msg.sender),
"Upgrade: unauthorized"
);
_;
}

constructor(
address serviceConfiguration,
address withdrawControllerFactory,
address poolControllerFactory
) {
_serviceConfiguration = serviceConfiguration;
_serviceConfiguration = IServiceConfiguration(serviceConfiguration);
_withdrawControllerFactory = withdrawControllerFactory;
_poolControllerFactory = poolControllerFactory;
}

/**
* @inheritdoc IBeacon
*/
function setImplementation(address newImplementation)
external
override
onlyDeployer
{
implementation = newImplementation;
emit ImplementationSet(newImplementation);
}

/**
* @dev Creates a pool
* @dev Emits `PoolCreated` event.
Expand All @@ -77,7 +44,7 @@ contract PoolFactory is IPoolFactory, IBeacon {
"PoolFactory: no implementation set"
);
require(
IServiceConfiguration(_serviceConfiguration).paused() == false,
_serviceConfiguration.paused() == false,
"PoolFactory: Protocol paused"
);
require(
Expand All @@ -92,9 +59,7 @@ contract PoolFactory is IPoolFactory, IBeacon {
}
require(
settings.firstLossInitialMinimum >=
IServiceConfiguration(_serviceConfiguration).firstLossMinimum(
liquidityAsset
),
_serviceConfiguration.firstLossMinimum(liquidityAsset),
"PoolFactory: Invalid first loss minimum"
);
require(
Expand All @@ -110,9 +75,7 @@ contract PoolFactory is IPoolFactory, IBeacon {
"PoolFactory: Invalid request cancellation fee"
);
require(
IServiceConfiguration(_serviceConfiguration).isLiquidityAsset(
liquidityAsset
),
_serviceConfiguration.isLiquidityAsset(liquidityAsset),
"PoolFactory: invalid asset"
);

Expand Down
8 changes: 1 addition & 7 deletions contracts/ServiceConfiguration.sol
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ contract ServiceConfiguration is
paused = false;
firstLossFeeBps = 500;
protocolFeeBps = 0;
_serviceConfiguration = IServiceConfiguration(address(this));

_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
}
Expand Down Expand Up @@ -181,11 +182,4 @@ contract ServiceConfiguration is
firstLossFeeBps = value;
emit ParameterSet("firstLossFeeBps", value);
}

/**
* @inheritdoc IServiceConfigurable
*/
function serviceConfiguration() external view override returns (address) {
return address(this);
}
}
7 changes: 4 additions & 3 deletions contracts/controllers/PoolController.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet
import {SafeMath} from "@openzeppelin/contracts/utils/math/SafeMath.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "../upgrades/interfaces/IBeaconImplementation.sol";

/**
* @title WithdrawState
*/
contract PoolController is IPoolController {
contract PoolController is IPoolController, IBeaconImplementation {
using SafeERC20 for IERC20;

IPool public pool;
Expand Down Expand Up @@ -91,13 +92,13 @@ contract PoolController is IPoolController {
_;
}

constructor(
function initialize(
address pool_,
address serviceConfiguration_,
address admin_,
address liquidityAsset_,
IPoolConfigurableSettings memory poolSettings_
) {
) public initializer {
_serviceConfiguration = serviceConfiguration_;
pool = IPool(pool_);

Expand Down
7 changes: 4 additions & 3 deletions contracts/controllers/WithdrawController.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ import "./interfaces/IPoolController.sol";
import "../libraries/PoolLib.sol";
import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import {SafeMath} from "@openzeppelin/contracts/utils/math/SafeMath.sol";
import "../upgrades/interfaces/IBeaconImplementation.sol";

/**
* @title WithdrawState
*/
contract WithdrawController is IWithdrawController {
contract WithdrawController is IWithdrawController, IBeaconImplementation {
using SafeMath for uint256;
using EnumerableSet for EnumerableSet.AddressSet;

Expand Down Expand Up @@ -44,9 +45,9 @@ contract WithdrawController is IWithdrawController {
}

/**
* @dev Constructor for a Pool's withdraw state
* @dev Initializer for a Pool's withdraw state
*/
constructor(address pool) {
function initialize(address pool) public initializer {
_pool = IPool(pool);
}

Expand Down
34 changes: 18 additions & 16 deletions contracts/factories/PoolControllerFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,16 @@ pragma solidity ^0.8.16;

import "../controllers/PoolController.sol";
import "../interfaces/IServiceConfiguration.sol";
import "./interfaces/IPoolControllerFactory.sol";
import "../factories/interfaces/IPoolControllerFactory.sol";
import "../upgrades/BeaconProxyFactory.sol";
import {BeaconProxy} from "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol";

/**
* @title PoolAdmin controller Factory
*/
contract PoolControllerFactory is IPoolControllerFactory {
/**
* @dev Reference to the ServiceConfiguration contract
*/
address private _serviceConfiguration;

contract PoolControllerFactory is IPoolControllerFactory, BeaconProxyFactory {
constructor(address serviceConfiguration) {
_serviceConfiguration = serviceConfiguration;
_serviceConfiguration = IServiceConfiguration(serviceConfiguration);
}

/**
Expand All @@ -29,18 +26,23 @@ contract PoolControllerFactory is IPoolControllerFactory {
IPoolConfigurableSettings memory poolSettings
) public virtual returns (address addr) {
require(
IServiceConfiguration(_serviceConfiguration).paused() == false,
_serviceConfiguration.paused() == false,
"PoolControllerFactory: Protocol paused"
);
require(implementation != address(0), "PoolControllerFactory: no impl");

PoolController controller = new PoolController(
pool,
serviceConfiguration,
admin,
liquidityAsset,
poolSettings
BeaconProxy proxy = new BeaconProxy(
address(this),
abi.encodeWithSelector(
PoolController.initialize.selector,
pool,
serviceConfiguration,
admin,
liquidityAsset,
poolSettings
)
);
addr = address(controller);
addr = address(proxy);
emit PoolControllerCreated(addr, admin);
}
}
Loading