// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "./ConfiguratorStorage.sol"; import "./LendingFactory.sol"; contract Configurator is ConfiguratorStorage, UUPSUpgradeable, OwnableUpgradeable { event SetFactory(address indexed lendingProxy, address indexed oldFactory, address indexed newFactory); event SetConfiguration(address indexed lendingProxy, Configuration oldConfiguration, Configuration newConfiguration); event AddAsset(address indexed lendingProxy, AssetConfig assetConfig); event UpdateAsset(address indexed lendingProxy, AssetConfig oldAssetConfig, AssetConfig newAssetConfig); event LendingDeployed(address indexed lendingProxy, address indexed newLending); error AlreadyInitialized(); error AssetDoesNotExist(); error ConfigurationAlreadyExists(); error InvalidAddress(); /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } function initialize() external initializer { __UUPSUpgradeable_init(); __Ownable_init(msg.sender); } function _authorizeUpgrade(address newImplementation) internal override onlyOwner {} function setFactory(address lendingProxy, address newFactory) external onlyOwner { if (newFactory == address(0)) revert InvalidAddress(); address oldFactory = factory[lendingProxy]; factory[lendingProxy] = newFactory; emit SetFactory(lendingProxy, oldFactory, newFactory); } function setConfiguration(address lendingProxy, Configuration calldata newConfiguration) external onlyOwner { Configuration memory oldConfiguration = configuratorParams[lendingProxy]; if (oldConfiguration.baseToken != address(0) && (oldConfiguration.baseToken != newConfiguration.baseToken || oldConfiguration.trackingIndexScale != newConfiguration.trackingIndexScale)) revert ConfigurationAlreadyExists(); delete configuratorParams[lendingProxy]; configuratorParams[lendingProxy].baseToken = newConfiguration.baseToken; configuratorParams[lendingProxy].lendingPriceSource = newConfiguration.lendingPriceSource; configuratorParams[lendingProxy].supplyKink = newConfiguration.supplyKink; configuratorParams[lendingProxy].supplyPerYearInterestRateSlopeLow = newConfiguration.supplyPerYearInterestRateSlopeLow; configuratorParams[lendingProxy].supplyPerYearInterestRateSlopeHigh = newConfiguration.supplyPerYearInterestRateSlopeHigh; configuratorParams[lendingProxy].supplyPerYearInterestRateBase = newConfiguration.supplyPerYearInterestRateBase; configuratorParams[lendingProxy].borrowKink = newConfiguration.borrowKink; configuratorParams[lendingProxy].borrowPerYearInterestRateSlopeLow = newConfiguration.borrowPerYearInterestRateSlopeLow; configuratorParams[lendingProxy].borrowPerYearInterestRateSlopeHigh = newConfiguration.borrowPerYearInterestRateSlopeHigh; configuratorParams[lendingProxy].borrowPerYearInterestRateBase = newConfiguration.borrowPerYearInterestRateBase; configuratorParams[lendingProxy].storeFrontPriceFactor = newConfiguration.storeFrontPriceFactor; configuratorParams[lendingProxy].trackingIndexScale = newConfiguration.trackingIndexScale; configuratorParams[lendingProxy].baseBorrowMin = newConfiguration.baseBorrowMin; configuratorParams[lendingProxy].targetReserves = newConfiguration.targetReserves; for (uint i = 0; i < newConfiguration.assetConfigs.length; i++) { configuratorParams[lendingProxy].assetConfigs.push(newConfiguration.assetConfigs[i]); } emit SetConfiguration(lendingProxy, oldConfiguration, newConfiguration); } function addAsset(address lendingProxy, AssetConfig calldata assetConfig) external onlyOwner { configuratorParams[lendingProxy].assetConfigs.push(assetConfig); emit AddAsset(lendingProxy, assetConfig); } function updateAsset(address lendingProxy, AssetConfig calldata newAssetConfig) external onlyOwner { uint assetIndex = getAssetIndex(lendingProxy, newAssetConfig.asset); AssetConfig memory oldAssetConfig = configuratorParams[lendingProxy].assetConfigs[assetIndex]; configuratorParams[lendingProxy].assetConfigs[assetIndex] = newAssetConfig; emit UpdateAsset(lendingProxy, oldAssetConfig, newAssetConfig); } function updateAssetBorrowCollateralFactor( address lendingProxy, address asset, uint64 newBorrowCF ) external onlyOwner { uint assetIndex = getAssetIndex(lendingProxy, asset); configuratorParams[lendingProxy].assetConfigs[assetIndex].borrowCollateralFactor = newBorrowCF; } function updateAssetSupplyCap( address lendingProxy, address asset, uint128 newSupplyCap ) external onlyOwner { uint assetIndex = getAssetIndex(lendingProxy, asset); configuratorParams[lendingProxy].assetConfigs[assetIndex].supplyCap = newSupplyCap; } function deploy(address lendingProxy) external onlyOwner returns (address) { address newLending = LendingFactory(factory[lendingProxy]).deploy(); emit LendingDeployed(lendingProxy, newLending); return newLending; } function getAssetIndex(address lendingProxy, address asset) public view returns (uint) { AssetConfig[] memory assetConfigs = configuratorParams[lendingProxy].assetConfigs; uint numAssets = assetConfigs.length; for (uint i = 0; i < numAssets; ) { if (assetConfigs[i].asset == asset) { return i; } unchecked { i++; } } revert AssetDoesNotExist(); } function getConfiguration(address lendingProxy) external view returns (Configuration memory) { return configuratorParams[lendingProxy]; } uint256[50] private __gap; }