Skip to content

Commit

Permalink
feat: increase and decrease
Browse files Browse the repository at this point in the history
  • Loading branch information
Schlagonia committed Jan 5, 2024
1 parent a29e6cf commit 5ff8880
Show file tree
Hide file tree
Showing 5 changed files with 295 additions and 105 deletions.
90 changes: 68 additions & 22 deletions contracts/debtAllocators/GenericDebtAllocator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import {IVault} from "@yearn-vaults/interfaces/IVault.sol";
*/
contract GenericDebtAllocator is Governance {
/// @notice An event emitted when a strategies debt ratios are Updated.
event UpdateStrategyDebtRatios(
event UpdateStrategyDebtRatio(
address indexed strategy,
uint256 newTargetRatio,
uint256 newMaxRatio,
Expand All @@ -55,13 +55,17 @@ contract GenericDebtAllocator is Governance {
/// @notice Struct for each strategies info.
struct Config {
// The ideal percent in Basis Points the strategy should have.
uint256 targetRatio;
uint16 targetRatio;
// The max percent of assets the strategy should hold.
uint256 maxRatio;
uint16 maxRatio;
// Timestamp of the last time debt was updated.
// The debt updates must be done through this allocator
// for this to be used.
uint256 lastUpdate;
uint128 lastUpdate;
// We have an extra 96 bits in the slot.
// So we declare the variable in the struct so it can be
// used if this contract is inherited.
uint96 open;
}

modifier onlyKeepers() {
Expand Down Expand Up @@ -100,7 +104,7 @@ contract GenericDebtAllocator is Governance {
mapping(address => bool) public keepers;

/// @notice Mapping of strategy => its config.
mapping(address => Config) public configs;
mapping(address => Config) internal _configs;

constructor(
address _vault,
Expand Down Expand Up @@ -154,7 +158,7 @@ contract GenericDebtAllocator is Governance {
function update_debt(
address _strategy,
uint256 _targetDebt
) external virtual onlyKeepers {
) public virtual onlyKeepers {
IVault _vault = IVault(vault);

// If going to 0 record full balance first.
Expand All @@ -179,7 +183,7 @@ contract GenericDebtAllocator is Governance {
}

// Update the last time the strategies debt was updated.
configs[_strategy].lastUpdate = block.timestamp;
_configs[_strategy].lastUpdate = uint128(block.timestamp);
}

/**
Expand All @@ -195,7 +199,7 @@ contract GenericDebtAllocator is Governance {
*/
function shouldUpdateDebt(
address _strategy
) external view virtual returns (bool, bytes memory) {
) public view virtual returns (bool, bytes memory) {
// Check the base fee isn't too high.
if (block.basefee > maxAcceptableBaseFee) {
return (false, bytes("Base Fee"));
Expand All @@ -209,7 +213,7 @@ contract GenericDebtAllocator is Governance {
require(params.activation != 0, "!active");

// Get the strategy specific debt config.
Config memory config = configs[_strategy];
Config memory config = getConfig(_strategy);

if (block.timestamp - config.lastUpdate <= minimumWait) {
return (false, bytes("min wait"));
Expand Down Expand Up @@ -301,19 +305,46 @@ contract GenericDebtAllocator is Governance {
return (false, bytes("Below Min"));
}

/**
* @notice Increase a strategies target debt ratio.
* @dev `setStrategyDebtRatio` functions will do all needed checks.
* @param _strategy The address of the strategy to increase the debt ratio for.
* @param _increase The amount in Basis Points to increase it.
*/
function increaseStrategyDebtRatio(
address _strategy,
uint256 _increase
) external virtual {
uint256 _currentRatio = getConfig(_strategy).targetRatio;
setStrategyDebtRatio(_strategy, _currentRatio + _increase);
}

/**
* @notice Decrease a strategies target debt ratio.
* @param _strategy The address of the strategy to decrease the debt ratio for.
* @param _decrease The amount in Basis Points to decrease it.
*/
function decreaseStrategyDebtRatio(
address _strategy,
uint256 _decrease
) external virtual {
uint256 _currentRatio = getConfig(_strategy).targetRatio;
setStrategyDebtRatio(_strategy, _currentRatio - _decrease);
}

/**
* @notice Sets a new target debt ratio for a strategy.
* @dev This will default to a 10% increase for max debt.
*
* @param _strategy Address of the strategy to set.
* @param _targetRatio Amount in Basis points to allocate.
*/
function setStrategyDebtRatios(
function setStrategyDebtRatio(
address _strategy,
uint256 _targetRatio
) external virtual {
) public virtual {
uint256 maxRatio = Math.min((_targetRatio * 11_000) / MAX_BPS, MAX_BPS);
setStrategyDebtRatios(_strategy, _targetRatio, maxRatio);
setStrategyDebtRatio(_strategy, _targetRatio, maxRatio);
}

/**
Expand All @@ -325,7 +356,7 @@ contract GenericDebtAllocator is Governance {
* @param _targetRatio Amount in Basis points to allocate.
* @param _maxRatio Max ratio to give on debt increases.
*/
function setStrategyDebtRatios(
function setStrategyDebtRatio(
address _strategy,
uint256 _targetRatio,
uint256 _maxRatio
Expand All @@ -337,21 +368,24 @@ contract GenericDebtAllocator is Governance {
// Max cannot be lower than the target.
require(_maxRatio >= _targetRatio, "max ratio");

// Get the current config.
Config memory config = getConfig(_strategy);

// Get what will be the new total debt ratio.
uint256 newDebtRatio = debtRatio -
configs[_strategy].targetRatio +
_targetRatio;
uint256 newDebtRatio = debtRatio - config.targetRatio + _targetRatio;

// Make sure it is under 100% allocated
require(newDebtRatio <= MAX_BPS, "ratio too high");

// Write to storage.
configs[_strategy].targetRatio = _targetRatio;
configs[_strategy].maxRatio = _maxRatio;
// Update local config.
config.targetRatio = uint16(_targetRatio);
config.maxRatio = uint16(_maxRatio);

// Write to storage.
_configs[_strategy] = config;
debtRatio = newDebtRatio;

emit UpdateStrategyDebtRatios(
emit UpdateStrategyDebtRatio(
_strategy,
_targetRatio,
_maxRatio,
Expand Down Expand Up @@ -435,6 +469,18 @@ contract GenericDebtAllocator is Governance {
emit UpdateMaxAcceptableBaseFee(_maxAcceptableBaseFee);
}

/**
* @notice Get a strategies full config.
* @dev Used for customizations by inheriting the contract.
* @param _strategy Address of the strategy.
* @return The strategies current Config.
*/
function getConfig(
address _strategy
) public view virtual returns (Config memory) {
return _configs[_strategy];
}

/**
* @notice Get a strategies target debt ratio.
* @param _strategy Address of the strategy.
Expand All @@ -443,7 +489,7 @@ contract GenericDebtAllocator is Governance {
function getStrategyTargetRatio(
address _strategy
) external view virtual returns (uint256) {
return configs[_strategy].targetRatio;
return getConfig(_strategy).targetRatio;
}

/**
Expand All @@ -454,6 +500,6 @@ contract GenericDebtAllocator is Governance {
function getStrategyMaxRatio(
address _strategy
) external view virtual returns (uint256) {
return configs[_strategy].maxRatio;
return getConfig(_strategy).maxRatio;
}
}
31 changes: 17 additions & 14 deletions contracts/debtAllocators/YieldManager/Keeper.sol
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ contract Keeper is Governance {
}

/// @notice Only the keepers can call.
modifier onlyKeepers(address _strategy) {
_checkKeepers(_strategy);
modifier onlyKeepers() {
_checkKeepers();
_;
}

Expand All @@ -33,12 +33,9 @@ contract Keeper is Governance {
require(strategyOwner[_strategy] == msg.sender, "!owner");
}

/// @notice Checks if the msg sender is a keeper and the strategy is added.
function _checkKeepers(address _strategy) internal view virtual {
require(
keepers[msg.sender] && strategyOwner[_strategy] != address(0),
"!keeper"
);
/// @notice Checks if the msg sender is a keeper.
function _checkKeepers() internal view virtual {
require(keepers[msg.sender], "!keeper");
}

/// @notice Address check for keepers allowed to call.
Expand Down Expand Up @@ -100,18 +97,24 @@ contract Keeper is Governance {
* @notice Reports full profit for a strategy.
* @param _strategy The address of the strategy.
*/
function report(address _strategy) external virtual onlyKeepers(_strategy) {
// Report profits.
IStrategy(_strategy).report();
function report(address _strategy) external virtual onlyKeepers {
// If the strategy has been added to the keeper.
if (strategyOwner[_strategy] != address(0)) {
// Report profits.
IStrategy(_strategy).report();
}
}

/**
* @notice Tends a strategy.
* @param _strategy The address of the strategy.
*/
function tend(address _strategy) external virtual onlyKeepers(_strategy) {
// Tend.
IStrategy(_strategy).tend();
function tend(address _strategy) external virtual onlyKeepers {
// If the strategy has been added to the keeper.
if (strategyOwner[_strategy] != address(0)) {
// Tend.
IStrategy(_strategy).tend();
}
}

/**
Expand Down
54 changes: 25 additions & 29 deletions contracts/debtAllocators/YieldManager/YieldManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -66,29 +66,6 @@ contract YieldManager is Governance {
keeper = _keeper;
}

/**
* @notice Update a `_vault`s allocation of debt.
* @dev This takes the address of a vault and an array of
* its strategies and their specific allocation.
*
* The `_newAllocations` array should:
* - Be ordered so that all debt decreases are at the beginning of the array
* and debt increases at the end.
*
* This will not do any APR checks and assumes the sender has completed
* any and all necessary checks before sending.
*
* @param _vault The address of the vault to propose an allocation for.
* @param _newAllocations Array of strategies and their new proposed allocation.
*/
function updateAllocationPermissioned(
address _vault,
Allocation[] memory _newAllocations
) public virtual onlyGovernance {
// Move funds
_allocate(_vault, _newAllocations);
}

/**
* @notice Update a `_vault`s target allocation of debt.
* @dev This takes the address of a vault and an array of
Expand Down Expand Up @@ -152,7 +129,7 @@ contract YieldManager is Governance {
if (_currentDebt > _newDebt) {
// If we are pulling all debt from a strategy.
if (_newDebt == 0) {
// We need to report profits to have them start to unlock.
// Try to report profits to have them start to unlock.
Keeper(keeper).report(_strategy);
}

Expand All @@ -179,6 +156,11 @@ contract YieldManager is Governance {
"max withdraw"
);
} else if (_currentDebt < _newDebt) {
// Make sure the strategy is allowed that much.
require(
IVault(_vault).strategies(_strategy).max_debt >= _newDebt,
"max debt"
);
// Make sure the vault can deposit the desired amount.
require(
IVault(_strategy).maxDeposit(_vault) >=
Expand All @@ -199,7 +181,7 @@ contract YieldManager is Governance {
) != _targetRatio
) {
// Update allocation.
GenericDebtAllocator(allocator).setStrategyDebtRatios(
GenericDebtAllocator(allocator).setStrategyDebtRatio(
_strategy,
_targetRatio
);
Expand Down Expand Up @@ -313,15 +295,24 @@ contract YieldManager is Governance {
}

/**
* @notice Allocate a vaults debt based on the new proposed Allocation.
* @notice Update a `_vault`s allocation of debt.
* @dev This takes the address of a vault and an array of
* its strategies and their specific allocation.
*
* The `_newAllocations` array should:
* - Be ordered so that all debt decreases are at the beginning of the array
* and debt increases at the end.
*
* This will not do any APR checks and assumes the sender has completed
* any and all necessary checks before sending.
*
* @param _vault The address of the vault to propose an allocation for.
* @param _newAllocations Array of strategies and their new proposed allocation.
*/
function _allocate(
function updateAllocationPermissioned(
address _vault,
Allocation[] memory _newAllocations
) internal virtual {
) external virtual onlyGovernance {
address allocator = vaultAllocator[_vault];
require(allocator != address(0), "vault not added");
address _strategy;
Expand Down Expand Up @@ -364,6 +355,11 @@ contract YieldManager is Governance {
"max withdraw"
);
} else if (_currentDebt < _newDebt) {
// Make sure the strategy is allowed that much.
require(
IVault(_vault).strategies(_strategy).max_debt >= _newDebt,
"max debt"
);
// Make sure the vault can deposit the desired amount.
require(
IVault(_strategy).maxDeposit(_vault) >=
Expand All @@ -383,7 +379,7 @@ contract YieldManager is Governance {
) != _targetRatio
) {
// Update allocation.
GenericDebtAllocator(allocator).setStrategyDebtRatios(
GenericDebtAllocator(allocator).setStrategyDebtRatio(
_strategy,
_targetRatio
);
Expand Down
Loading

0 comments on commit 5ff8880

Please sign in to comment.