Skip to content

Commit

Permalink
VAL-114 First cut of adding an upgradeable contract (#127)
Browse files Browse the repository at this point in the history
  • Loading branch information
ams9198 authored Dec 6, 2022
1 parent bf92420 commit e6fe675
Show file tree
Hide file tree
Showing 33 changed files with 1,037 additions and 176 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,6 @@ typechain-types
cache
artifacts

# OpenZeppelin
.openzeppelin/unknown-*.json
.openzeppelin/.session
24 changes: 13 additions & 11 deletions contracts/Pool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,26 @@ import "./controllers/interfaces/IWithdrawController.sol";
import "./controllers/interfaces/IPoolController.sol";
import "./factories/interfaces/IWithdrawControllerFactory.sol";
import "./factories/interfaces/IPoolControllerFactory.sol";
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {ERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
import {IERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {SafeERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
import {SafeMath} from "@openzeppelin/contracts/utils/math/SafeMath.sol";
import {Math} from "@openzeppelin/contracts/utils/math/Math.sol";
import "./libraries/PoolLib.sol";
import "./FeeVault.sol";
import "./FirstLossVault.sol";
import "./upgrades/interfaces/IBeaconImplementation.sol";

/**
* @title Pool
*/
contract Pool is IPool, ERC20 {
using SafeERC20 for IERC20;
contract Pool is IPool, ERC20Upgradeable, IBeaconImplementation {
using SafeERC20Upgradeable for IERC20Upgradeable;
using SafeMath for uint256;
using EnumerableSet for EnumerableSet.AddressSet;

IERC20 private _liquidityAsset;
IERC20Upgradeable private _liquidityAsset;
FeeVault private _feeVault;
IPoolAccountings private _accountings;

Expand Down Expand Up @@ -105,7 +106,7 @@ contract Pool is IPool, ERC20 {
}

/**
* @dev Constructor for Pool
* @dev Initializer for Pool
* @param liquidityAsset asset held by the poo
* @param poolAdmin admin of the pool
* @param serviceConfiguration address of global service configuration
Expand All @@ -114,7 +115,7 @@ contract Pool is IPool, ERC20 {
* @param tokenName Name used for issued pool tokens
* @param tokenSymbol Symbol used for issued pool tokens
*/
constructor(
function initialize(
address liquidityAsset,
address poolAdmin,
address serviceConfiguration,
Expand All @@ -123,8 +124,9 @@ contract Pool is IPool, ERC20 {
IPoolConfigurableSettings memory poolSettings,
string memory tokenName,
string memory tokenSymbol
) ERC20(tokenName, tokenSymbol) {
_liquidityAsset = IERC20(liquidityAsset);
) public initializer {
__ERC20_init(tokenName, tokenSymbol);
_liquidityAsset = IERC20Upgradeable(liquidityAsset);
_feeVault = new FeeVault(address(this));

// Build the withdraw controller
Expand Down Expand Up @@ -366,7 +368,7 @@ contract Pool is IPool, ERC20 {
);

_accountings.fixedFeeDueDate += fixedFeeInterval * 1 days;
IERC20(_liquidityAsset).safeTransfer(recipient, fixedFee);
IERC20Upgradeable(_liquidityAsset).safeTransfer(recipient, fixedFee);
}

/*//////////////////////////////////////////////////////////////
Expand Down
61 changes: 50 additions & 11 deletions contracts/PoolFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ pragma solidity ^0.8.16;
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";

/**
* @title PoolFactory
*/
contract PoolFactory is IPoolFactory {
contract PoolFactory is IPoolFactory, IBeacon {
/**
* @dev Reference to the ServiceConfiguration contract
*/
Expand All @@ -24,6 +26,22 @@ contract PoolFactory is IPoolFactory {
*/
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,
Expand All @@ -34,6 +52,18 @@ contract PoolFactory is IPoolFactory {
_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 @@ -42,6 +72,10 @@ contract PoolFactory is IPoolFactory {
address liquidityAsset,
IPoolConfigurableSettings calldata settings
) public virtual returns (address poolAddress) {
require(
implementation != address(0),
"PoolFactory: no implementation set"
);
require(
IServiceConfiguration(_serviceConfiguration).paused() == false,
"PoolFactory: Protocol paused"
Expand Down Expand Up @@ -95,16 +129,21 @@ contract PoolFactory is IPoolFactory {
address liquidityAsset,
IPoolConfigurableSettings calldata settings
) internal virtual returns (address) {
Pool pool = new Pool(
liquidityAsset,
msg.sender,
_serviceConfiguration,
_withdrawControllerFactory,
_poolControllerFactory,
settings,
"PerimeterPoolToken",
"PPT"
// Create beacon proxy
BeaconProxy proxy = new BeaconProxy(
address(this),
abi.encodeWithSelector(
Pool.initialize.selector,
liquidityAsset,
msg.sender,
_serviceConfiguration,
_withdrawControllerFactory,
_poolControllerFactory,
settings,
"PerimeterPoolToken",
"PPT"
)
);
return address(pool);
return address(proxy);
}
}
57 changes: 43 additions & 14 deletions contracts/ServiceConfiguration.sol
Original file line number Diff line number Diff line change
@@ -1,33 +1,44 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.16;

import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";
import "./interfaces/IServiceConfiguration.sol";
import "./upgrades/DeployerUUPSUpgradeable.sol";
import "hardhat/console.sol";

/**
* @title The ServiceConfiguration contract
* @dev Implementation of the {IServiceConfiguration} interface.
*/
contract ServiceConfiguration is AccessControl, IServiceConfiguration {
contract ServiceConfiguration is
IServiceConfiguration,
AccessControlUpgradeable,
DeployerUUPSUpgradeable
{
/**
* @dev The Operator Role
*/
bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE");

/**
* @dev The Operator Role
*/
bytes32 public constant DEPLOYER_ROLE = keccak256("DEPLOYER_ROLE");

/**
* @dev Whether the protocol is paused.
*/
bool public paused = false;
bool public paused;

mapping(address => bool) public isLiquidityAsset;

mapping(address => uint256) public firstLossMinimum;

uint256 public firstLossFeeBps = 500;
uint256 public firstLossFeeBps;

address public tosAcceptanceRegistry;

uint256 public protocolFeeBps = 0;
uint256 public protocolFeeBps;

/**
* @dev Holds a reference to valid LoanFactories
Expand Down Expand Up @@ -69,15 +80,6 @@ contract ServiceConfiguration is AccessControl, IServiceConfiguration {
*/
event TermsOfServiceRegistrySet(address indexed registry);

/**
* @dev Constructor for the contract, which sets up the default roles and
* owners.
*/
constructor() {
// Grant the contract deployer the Operator role
_setupRole(OPERATOR_ROLE, msg.sender);
}

/**
* @dev Modifier that checks that the caller account has the Operator role.
*/
Expand All @@ -89,6 +91,19 @@ contract ServiceConfiguration is AccessControl, IServiceConfiguration {
_;
}

/**
* @dev Constructor for the contract, which sets up the default roles and
* owners.
*/
function initialize() public initializer {
// Initialize values
paused = false;
firstLossFeeBps = 500;
protocolFeeBps = 0;

_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
}

/**
* @dev Set a liquidity asset as valid or not.
*/
Expand Down Expand Up @@ -116,6 +131,13 @@ contract ServiceConfiguration is AccessControl, IServiceConfiguration {
return hasRole(OPERATOR_ROLE, addr);
}

/**
* @inheritdoc IServiceConfiguration
*/
function isDeployer(address addr) external view returns (bool) {
return hasRole(DEPLOYER_ROLE, addr);
}

/**
* @inheritdoc IServiceConfiguration
*/
Expand Down Expand Up @@ -159,4 +181,11 @@ contract ServiceConfiguration is AccessControl, IServiceConfiguration {
firstLossFeeBps = value;
emit ParameterSet("firstLossFeeBps", value);
}

/**
* @inheritdoc IServiceConfigurable
*/
function serviceConfiguration() external view override returns (address) {
return address(this);
}
}
4 changes: 2 additions & 2 deletions contracts/interfaces/IERC4626.sol
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.16;

import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {IERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";

/**
* @title The interface according to the ERC-4626 standard.
*/
interface IERC4626 is IERC20 {
interface IERC4626 is IERC20Upgradeable {
/**
* @dev Emitted when tokens are deposited into the vault via the mint and deposit methods.
*/
Expand Down
13 changes: 13 additions & 0 deletions contracts/interfaces/IServiceConfigurable.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.16;

/**
* @title IServiceConfigurable
* @dev Interface indicating that the contract is controlled by the protocol service configuration.
*/
interface IServiceConfigurable {
/**
* @dev Address of the protocol service configuration.
*/
function serviceConfiguration() external view returns (address);
}
9 changes: 6 additions & 3 deletions contracts/interfaces/IServiceConfiguration.sol
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.16;

import "@openzeppelin/contracts/access/IAccessControl.sol";

/**
* @title The protocol global Service Configuration
*/
interface IServiceConfiguration is IAccessControl {
interface IServiceConfiguration {
/**
* @dev checks if a given address has the Operator role
*/
function isOperator(address addr) external view returns (bool);

/**
* @dev checks if a given address has the Deployer role
*/
function isDeployer(address addr) external view returns (bool);

function paused() external view returns (bool);

function firstLossMinimum(address addr) external view returns (uint256);
Expand Down
8 changes: 8 additions & 0 deletions contracts/mocks/upgrades/MockUpgrade.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.16;

abstract contract MockUpgrade {
function foo() external pure returns (bool) {
return true;
}
}
12 changes: 12 additions & 0 deletions contracts/mocks/upgrades/PoolMockV2.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.16;

import "../../Pool.sol";
import "./MockUpgrade.sol";

/**
* @dev Simulated new Pool implementation
*/
contract PoolMockV2 is Pool, MockUpgrade {

}
12 changes: 12 additions & 0 deletions contracts/mocks/upgrades/ServiceConfigurationMockV2.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.16;

import "../../ServiceConfiguration.sol";
import "./MockUpgrade.sol";

/**
* @dev Simulated new ServiceConfiguration implementation
*/
contract ServiceConfigurationMockV2 is ServiceConfiguration, MockUpgrade {

}
Loading

0 comments on commit e6fe675

Please sign in to comment.