Skip to content

Commit

Permalink
build: yield manager
Browse files Browse the repository at this point in the history
  • Loading branch information
Schlagonia committed Dec 1, 2023
1 parent 9c36607 commit bb48d12
Show file tree
Hide file tree
Showing 2 changed files with 469 additions and 0 deletions.
127 changes: 127 additions & 0 deletions contracts/debtAllocators/YieldManager/StrategyManager.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
// SPDX-License-Identifier: AGPL-3.0
pragma solidity 0.8.18;

import {IStrategy} from "@tokenized-strategy/interfaces/IStrategy.sol";

// Allow for an array of calls

contract StrategyManager {
struct StrategyInfo {
bool active;
address owner;
address debtManager;
}

modifier onlyStrategyOwner(address _strategy) {
_checkStrategyManager(_strategy);
_;
}

/// @notice Checks if the msg sender is the governance.
function _checkStrategyManager(address _strategy) internal view virtual {
require(strategyInfo[_strategy].owner == msg.sender, "!governance");
}

function _checkStrategyDebtManager(
address _strategy
) internal view virtual {
require(
strategyInfo[_strategy].debtManager == msg.sender ||
strategyInfo[_strategy].owner == msg.sender,
"!debt manager"
);
}

mapping(address => StrategyInfo) public strategyInfo;

mapping(bytes4 => bool) public allowedSelectors;

constructor(bytes4[] memory _allowedSelectors) {
for (uint256 i = 0; i < _allowedSelectors.length; ++i) {
allowedSelectors[_allowedSelectors[i]];
}
}

function manageNewStrategy(
address _strategy,
address _debtManager
) external {
require(!strategyInfo[_strategy].active, "already active");
// Cache the current strategy management.
address currentManager = IStrategy(_strategy).management();

// Accept management of the strategy.
IStrategy(_strategy).acceptManagement();

// Store the owner of the strategy.
strategyInfo[_strategy] = StrategyInfo({
active: true,
owner: currentManager,
debtManager: _debtManager
});
}

function updateStrategyOwner(
address _strategy,
address _newOwner
) external onlyStrategyOwner(_strategy) {
require(_newOwner != address(0), "ZERO ADDRESS");
strategyInfo[_strategy].owner = _newOwner;
}

// This gets rid of the benefits of two step transfers.
function removeManagement(
address _strategy,
address _newManager
) external onlyStrategyOwner(_strategy) {
require(strategyInfo[_strategy].active, "not active");

delete strategyInfo[_strategy];

IStrategy(_strategy).setPendingManagement(_newManager);
}

function forwardCalls(
address _strategy,
bytes[] memory _calldataArray
) external returns (bytes[] memory _returnData) {
uint256 _length = _calldataArray.length;
_returnData = new bytes[](_length);
for (uint256 i = 0; i < _length; ++i) {
_returnData[i] = forwardCall(_strategy, _calldataArray[i]);
}
}

function forwardCall(
address _strategy,
bytes memory _calldata
) public returns (bytes memory) {
bytes4 selector;

assembly {
// Copy the first 4 bytes of the memory array to the result variable
selector := mload(add(_calldata, 32))
}

if (allowedSelectors[selector]) {
_checkStrategyDebtManager(_strategy);
} else {
_checkStrategyManager(_strategy);
}

(bool success, bytes memory result) = _strategy.call(_calldata);

// If the call reverted. Return the error.
if (!success) {
assembly {
let ptr := mload(0x40)
let size := returndatasize()
returndatacopy(ptr, 0, size)
revert(ptr, size)
}
}

// Return the result.
return result;
}
}
Loading

0 comments on commit bb48d12

Please sign in to comment.