From 7e6ae1abd9514f51b6ea2994062f212f6d4fadbf Mon Sep 17 00:00:00 2001 From: FP Date: Thu, 30 May 2024 08:04:14 -0700 Subject: [PATCH] feat: debt optimizer applicator --- .../DebtOptimizerApplicator.sol | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 contracts/debtAllocators/DebtOptimizerApplicator.sol diff --git a/contracts/debtAllocators/DebtOptimizerApplicator.sol b/contracts/debtAllocators/DebtOptimizerApplicator.sol new file mode 100644 index 0000000..9e70614 --- /dev/null +++ b/contracts/debtAllocators/DebtOptimizerApplicator.sol @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: GNU AGPLv3 +pragma solidity >=0.8.18; + +import {DebtAllocator, DebtAllocatorFactory} from "./DebtAllocator.sol"; + +contract DebtOptimizerApplicator { + /// @notice Make sure the caller is governance. + modifier onlyGovernance() { + _isGovernance(); + _; + } + + /// @notice Make sure the caller is governance or a manager. + modifier onlyManagers() { + _isManager(); + _; + } + + /// @notice Make sure the caller is a keeper + modifier onlyKeepers() { + _isKeeper(); + _; + } + + /// @notice Check the Factories governance address. + function _isGovernance() internal view virtual { + require( + msg.sender == + DebtAllocatorFactory(debtAllocatorFactory).governance(), + "!governance" + ); + } + + /// @notice Check is either factories governance or local manager. + function _isManager() internal view virtual { + require( + managers[msg.sender] || + msg.sender == + DebtAllocatorFactory(debtAllocatorFactory).governance(), + "!manager" + ); + } + + /// @notice Check is one of the allowed keepers. + function _isKeeper() internal view virtual { + require( + DebtAllocatorFactory(debtAllocatorFactory).keepers(msg.sender), + "!keeper" + ); + } + + struct StrategyDebtRatio { + address strategy; + uint256 targetRatio; + uint256 maxRatio; + } + + /// @notice The address of the debt allocator factory to use for some role checks. + address public immutable debtAllocatorFactory; + + /// @notice Mapping of addresses that are allowed to update debt ratios. + mapping(address => bool) public managers; + + constructor(address _debtAllocatorFactory) { + debtAllocatorFactory = _debtAllocatorFactory; + } + + /** + * @notice Set if a manager can update ratios. + * @param _address The address to set mapping for. + * @param _allowed If the address can call {update_debt}. + */ + function setManager( + address _address, + bool _allowed + ) external virtual onlyGovernance { + managers[_address] = _allowed; + + emit UpdateManager(_address, _allowed); + } + + function setStrategyDebtRatios( + DebtAllocator _debtAllocator, + StrategyDebtRatio[] memory _strategyDebtRatios // TODO: use calldata instead of memory? + ) public onlyManagers { + for (uint8 i; i < _strategyDebtRatios.length; ++i) { + if (_strategyDebtRatios[i].maxRatio == 0) { + _debtAllocator.setStrategyDebtRatio( + _strategyDebtRatios[i].strategy, + _strategyDebtRatios[i].targetRatio, + _strategyDebtRatios[i].maxRatio + ); + } else { + _debtAllocator.setStrategyDebtRatio( + _strategyDebtRatios[i].strategy, + _strategyDebtRatios[i].targetRatio + ); + } + } + } +}