Skip to content

Commit

Permalink
feat: market factories implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
lekhovitsky committed Nov 16, 2024
1 parent ba8bf86 commit d1d06dd
Show file tree
Hide file tree
Showing 28 changed files with 1,100 additions and 773 deletions.
64 changes: 48 additions & 16 deletions contracts/factories/AbstractFactory.sol
Original file line number Diff line number Diff line change
@@ -1,44 +1,76 @@
// SPDX-License-Identifier: BUSL-1.1
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2024.
pragma solidity ^0.8.17;
pragma solidity ^0.8.23;

import {IVersion} from "@gearbox-protocol/core-v3/contracts/interfaces/base/IVersion.sol";
import {IVotingContract} from "@gearbox-protocol/core-v3/contracts/interfaces/base/IVotingContract.sol";

import {IAddressProvider} from "../interfaces/IAddressProvider.sol";
import {IMarketConfigurator} from "../interfaces/IMarketConfigurator.sol";
import {IBytecodeRepository} from "../interfaces/IBytecodeRepository.sol";
import {IMarketConfiguratorFactory} from "../interfaces/IMarketConfiguratorFactory.sol";

import {
AP_BYTECODE_REPOSITORY,
AP_MARKET_CONFIGURATOR_FACTORY,
NO_VERSION_CONTROL
} from "../libraries/ContractLiterals.sol";
import {Call} from "../interfaces/Types.sol";

import {IMarketConfiguratorFactory} from "../interfaces/IMarketConfiguratorFactory.sol";

abstract contract AbstractFactory is IVersion {
address public immutable addressProvider;
address public immutable bytecodeRepository;

address public immutable marketConfiguratorFactory;

address public immutable addressProvider;

error CallerIsNotMarketConfiguratorException();

modifier marketConfiguratorOnly() {
modifier marketConfiguratorsOnly() {
_ensureCallerIsMarketConfigurator();
_;
}

constructor(address addressProvider_) {
addressProvider = addressProvider_;
bytecodeRepository = _getContract(AP_BYTECODE_REPOSITORY, NO_VERSION_CONTROL);
marketConfiguratorFactory = _getContract(AP_MARKET_CONFIGURATOR_FACTORY, NO_VERSION_CONTROL);
}

function _ensureCallerIsMarketConfigurator() internal view {
if (IMarketConfiguratorFactory(marketConfiguratorFactory).isMarketConfigurator(msg.sender)) {
revert CallerIsNotMarketConfiguratorException();
}
_;
}

constructor(address _addressProvider) {
marketConfiguratorFactory =
IAddressProvider(_addressProvider).getAddressOrRevert(AP_MARKET_CONFIGURATOR_FACTORY, NO_VERSION_CONTROL);
function _getLatestContract(bytes32 key) internal view returns (address) {
return IAddressProvider(addressProvider).getLatestAddressOrRevert(key);
}

function _getContract(bytes32 key, uint256 version_) internal view returns (address) {
return IAddressProvider(addressProvider).getAddressOrRevert(key, version_);
}

bytecodeRepository =
IAddressProvider(_addressProvider).getAddressOrRevert(AP_BYTECODE_REPOSITORY, NO_VERSION_CONTROL);
function _deploy(bytes32 type_, uint256 version_, bytes memory constructorParams, bytes32 salt)
internal
returns (address)
{
return IBytecodeRepository(bytecodeRepository).deploy(type_, version_, constructorParams, salt);
}

addressProvider = _addressProvider;
function _deployByDomain(
bytes32 domain,
bytes32 postfix,
uint256 version_,
bytes memory constructorParams,
bytes32 salt
) internal returns (address) {
return
IBytecodeRepository(bytecodeRepository).deployByDomain(domain, postfix, version_, constructorParams, salt);
}

function _isVotingContract(address contract_) internal view returns (bool) {
try IVotingContract(contract_).voter() returns (address) {
return true;
} catch {
return false;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import {
} from "../libraries/ContractLiterals.sol";
import {IBytecodeRepository} from "../interfaces/IBytecodeRepository.sol";
import {IContractsRegister} from "../interfaces/extensions/IContractsRegister.sol";
import {Call, DeployResult} from "../interfaces/Types.sol";
import {Call, DeployParams, DeployResult} from "../interfaces/Types.sol";
import {CallBuilder} from "../libraries/CallBuilder.sol";

interface ICreditConfig {
Expand All @@ -47,7 +47,6 @@ struct CreditSuiteDeployParams {
string name;
address degenNFT;
bool expirable;
//
uint256 debtLimit;
uint128 minDebt;
uint128 maxDebt;
Expand All @@ -58,7 +57,7 @@ struct CreditSuiteDeployParams {
}

// CreditFactoryV3 is responsible for deploying the entire credit suite and managing specific management functions.
contract CreditFactoryV3 is AbstractFactory, ICreditFactory {
contract CreditFactory is AbstractFactory, ICreditFactory {
using CallBuilder for Call;
/// @notice Contract version

Expand All @@ -75,6 +74,8 @@ contract CreditFactoryV3 is AbstractFactory, ICreditFactory {
address public immutable weth;

constructor(address _addressProvider) AbstractFactory(_addressProvider) {
// shouldn't factory be the owner?
// FIXME: all credit factories of version 3_1x should be able to access these two contracts
accountFactory = address(new AccountFactoryV3(msg.sender));
botList = address(new BotListV3(msg.sender));
weth = IAddressProvider(_addressProvider).getAddressOrRevert(AP_WETH_TOKEN, NO_VERSION_CONTROL);
Expand All @@ -87,7 +88,7 @@ contract CreditFactoryV3 is AbstractFactory, ICreditFactory {
function deployCreditSuite(address pool, bytes calldata encodedParams)
external
override
marketConfiguratorOnly
marketConfiguratorsOnly
returns (DeployResult memory)
{
// Control pool version
Expand Down Expand Up @@ -143,7 +144,7 @@ contract CreditFactoryV3 is AbstractFactory, ICreditFactory {
function configure(address creditManager, bytes calldata callData)
external
override
marketConfiguratorOnly
marketConfiguratorsOnly
returns (Call[] memory calls)
{
bytes4 selector = bytes4(callData);
Expand Down Expand Up @@ -184,12 +185,12 @@ contract CreditFactoryV3 is AbstractFactory, ICreditFactory {
//
// CREDIT HOOKS
//
function onUpdatePriceOracle(address creditManager, address priceOracle, address prevOracle)
function onUpdatePriceOracle(address creditManager, address newPriceOracle, address)
external
view
returns (Call[] memory calls)
{
calls = CallBuilder.build(_updatePriceOracle(creditManager, priceOracle));
calls = CallBuilder.build(_updatePriceOracle(creditManager, newPriceOracle));
}

function onAddEmergencyLiquidator(address creditManager, address liquidator)
Expand All @@ -208,12 +209,12 @@ contract CreditFactoryV3 is AbstractFactory, ICreditFactory {
calls = CallBuilder.build(_removeEmergencyLiquidator(creditManager, liquidator));
}

function onUpdateLossLiquidator(address creditManager, address lossLiquidator)
function onUpdateLossLiquidator(address creditManager, address newLossLiquidator, address)
external
view
returns (Call[] memory calls)
{
calls = CallBuilder.build(_updateLossLiquidator(creditManager, lossLiquidator));
calls = CallBuilder.build(_updateLossLiquidator(creditManager, newLossLiquidator));
}

//
Expand Down
44 changes: 31 additions & 13 deletions contracts/factories/InterestRateModelFactory.sol
Original file line number Diff line number Diff line change
@@ -1,43 +1,60 @@
// SPDX-License-Identifier: BUSL-1.1
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2024.
pragma solidity ^0.8.17;
pragma solidity ^0.8.23;

import {AbstractFactory} from "./AbstractFactory.sol";
import {MarketHookFactory} from "./MarketHookFactory.sol";
import {IInterestRateModelFactory} from "../interfaces/IInterestRateModelFactory.sol";
import {AP_INTEREST_MODEL_FACTORY, DOMAIN_IRM} from "../libraries/ContractLiterals.sol";
import {DeployResult, Call} from "../interfaces/Types.sol";
import {Call, DeployParams, DeployResult} from "../interfaces/Types.sol";
import {IBytecodeRepository} from "../interfaces/IBytecodeRepository.sol";
import {IMarketConfigurator} from "../interfaces/IMarketConfigurator.sol";

contract InterestRateModelFactory is AbstractFactory, IInterestRateModelFactory {
// Contract meta data
contract InterestRateModelFactory is AbstractFactory, MarketHookFactory, IInterestRateModelFactory {
/// @notice Contract version
uint256 public constant override version = 3_10;

/// @notice Contract type
bytes32 public constant override contractType = AP_INTEREST_MODEL_FACTORY;

error InvalidConstructorParamsException();

constructor(address _addressProvider) AbstractFactory(_addressProvider) {}

// @dev Deploy new interest rate model
// @param acl - ACL address
// @param postfix - postfix for the interest rate model
// @param encodedParams - encoded parameters for the interest rate model
// @return result - deploy result
function deployInterestRateModel(bytes32 postfix, bytes calldata constructorParams)
function deployInterestRateModel(address pool, DeployParams calldata params)
external
override
returns (DeployResult memory)
{
// Get required addresses from MarketConfigurator
address acl = IMarketConfigurator(msg.sender).acl();
// QUESTION: how to add ACL here?
address model = IBytecodeRepository(bytecodeRepository).deployByDomain(
DOMAIN_IRM, postfix, version, constructorParams, bytes32(bytes20(msg.sender))
);
if (params.postfix != "IRM_LINEAR") {
(address decodedAddressProvider, address decodedPool) =
abi.decode(params.constructorParams[:64], (address, address));
if (decodedAddressProvider != addressProvider || decodedPool != pool) {
revert InvalidConstructorParamsException();
}
}

address irm = _deployByDomain({
domain: DOMAIN_IRM,
postfix: params.postfix,
version_: version,
constructorParams: params.constructorParams,
salt: bytes32(bytes20(msg.sender))
});

address[] memory accessList = new address[](1);
accessList[0] = model;
accessList[0] = irm;

// TODO:
// if (_isVotingContract()) add onInstallOps

return DeployResult({newContract: model, accessList: accessList, onInstallOps: new Call[](0)});
return DeployResult({newContract: irm, accessList: accessList, onInstallOps: new Call[](0)});
}

// @dev Hook which is called when interest rate model is configured
Expand All @@ -46,5 +63,6 @@ contract InterestRateModelFactory is AbstractFactory, IInterestRateModelFactory
// @return calls - array of calls to be executed
function configure(address irm, bytes calldata callData) external view returns (Call[] memory calls) {
// TODO: implement
// just forbid setController?
}
}
37 changes: 16 additions & 21 deletions contracts/factories/MarketConfiguratorFactory.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: BUSL-1.1
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2024.
pragma solidity ^0.8.17;
pragma solidity ^0.8.23;

import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import {AbstractFactory} from "./AbstractFactory.sol";
Expand All @@ -11,6 +11,8 @@ import {ContractsRegister} from "../market/ContractsRegister.sol";
import {IAddressProvider} from "../interfaces/IAddressProvider.sol";

import {IBytecodeRepository} from "../interfaces/IBytecodeRepository.sol";
import {IMarketConfiguratorFactory} from "../interfaces/IMarketConfiguratorFactory.sol";

import {AP_MARKET_CONFIGURATOR, AP_MARKET_CONFIGURATOR_FACTORY} from "../libraries/ContractLiterals.sol";

contract MarketConfiguratorFactory is AbstractFactory {
Expand All @@ -22,34 +24,27 @@ contract MarketConfiguratorFactory is AbstractFactory {

uint256 public latestMCversion;

/// @notice Contract version
error CantRemoveMarketConfiguratorWithExistingPoolsException();

mapping(address => uint8) public targetTypes;
mapping(uint8 => mapping(uint256 => address)) public adapterDeployers;

constructor(address _addressProvider) AbstractFactory(_addressProvider) {}
constructor(address addressProvider_) AbstractFactory(addressProvider_) {
// deploy legacy?
}

function createMarketConfigurator(address _treasury, string calldata name, address _vetoAdmin) external {
function createMarketConfigurator(string calldata name) external {
ACL acl = new ACL();
ContractsRegister contractsRegister = new ContractsRegister(address(acl));
// TODO: deploy treasury splitter
address treasury;

// TODO: add selecting / deploying of treasury splitter
bytes memory constructorParams =
abi.encode(msg.sender, addressProvider, acl, contractsRegister, _treasury, name, _vetoAdmin);
address marketConfigurator = _deploy({
type_: AP_MARKET_CONFIGURATOR,
version_: latestMCversion,
constructorParams: abi.encode(msg.sender, addressProvider, acl, treasury),
salt: bytes32(bytes20(msg.sender))
});

address _marketConfigurator = IBytecodeRepository(bytecodeRepository).deploy(
AP_MARKET_CONFIGURATOR, latestMCversion, constructorParams, bytes32(bytes20(msg.sender))
);

/// Makes market configurator contract owner
acl.transferOwnership(_marketConfigurator);
acl.transferOwnership(marketConfigurator);
}

// function removeMarketConfigurator(address _marketConfigurator) external apOwnerOnly {
// if (MarketConfigurator(_marketConfigurator).pools().length != 0) {
// revert CantRemoveMarketConfiguratorWithExistingPoolsException();
// }
// IAddressProvider(addressProvider).removeMarketConfigurator(_marketConfigurator);
// }
}
Loading

0 comments on commit d1d06dd

Please sign in to comment.