Skip to content

Commit

Permalink
feat: remove strategy
Browse files Browse the repository at this point in the history
  • Loading branch information
Schlagonia committed Feb 8, 2024
1 parent 7aa672e commit f1a9106
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 29 deletions.
58 changes: 51 additions & 7 deletions contracts/debtAllocators/DebtAllocator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ contract DebtAllocator {
uint256 newTotalDebtRatio
);

/// @notice An event emitted when a strategy is added or removed.
event StrategyChanged(address indexed strategy, Status status);

/// @notice An event emitted when the minimum time to wait is updated.
event UpdateMinimumWait(uint256 newMinimumWait);

Expand All @@ -49,20 +52,28 @@ contract DebtAllocator {
/// @notice An event emitted when the max debt update loss is updated.
event UpdateMaxDebtUpdateLoss(uint256 newMaxDebtUpdateLoss);

/// @notice Status when a strategy is added or removed from the allocator.
enum Status {
ADDED,
REMOVED
}

/// @notice Struct for each strategies info.
struct Config {
// Flag to set when a strategy is added.
bool added;
// The ideal percent in Basis Points the strategy should have.
uint16 targetRatio;
// The max percent of assets the strategy should hold.
uint16 maxRatio;
// Timestamp of the last time debt was updated.
// The debt updates must be done through this allocator
// for this to be used.
uint128 lastUpdate;
// We have an extra 96 bits in the slot.
uint96 lastUpdate;
// We have an extra 120 bits in the slot.
// So we declare the variable in the struct so it can be
// used if this contract is inherited.
uint96 open;
uint120 open;
}

/// @notice Make sure the caller is governance.
Expand Down Expand Up @@ -200,7 +211,7 @@ contract DebtAllocator {
}

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

/**
Expand All @@ -215,6 +226,12 @@ contract DebtAllocator {
function shouldUpdateDebt(
address _strategy
) public view virtual returns (bool, bytes memory) {
// Get the strategy specific debt config.
Config memory config = getConfig(_strategy);

// Make sure the strategy has been added to the allocator.
if (!config.added) return (false, bytes("!added"));

// Check the base fee isn't too high.
if (!DebtAllocatorFactory(factory).isCurrentBaseFeeAcceptable()) {
return (false, bytes("Base Fee"));
Expand All @@ -227,9 +244,6 @@ contract DebtAllocator {
// Make sure its an active strategy.
require(params.activation != 0, "!active");

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

if (block.timestamp - config.lastUpdate <= minimumWait) {
return (false, bytes("min wait"));
}
Expand Down Expand Up @@ -395,6 +409,12 @@ contract DebtAllocator {
// Get the current config.
Config memory config = getConfig(_strategy);

// Set added flag if not set yet.
if (!config.added) {
config.added = true;
emit StrategyChanged(_strategy, Status.ADDED);
}

// Get what will be the new total debt ratio.
uint256 newTotalDebtRatio = totalDebtRatio -
config.targetRatio +
Expand All @@ -419,6 +439,30 @@ contract DebtAllocator {
);
}

/**
* @notice Remove a strategy from this debt allocator.
* @dev Will delete the full config for the strategy
* @param _strategy Address of the address ro remove.
*/
function removeStrategy(address _strategy) external virtual onlyManagers {
Config memory config = getConfig(_strategy);
require(config.added, "!added");

uint256 target = config.targetRatio;

// Remove any debt ratio the strategy holds.
if (target != 0) {
totalDebtRatio -= target;
emit UpdateStrategyDebtRatio(_strategy, 0, 0, totalDebtRatio);
}

// Remove the full config including the `added` flag.
delete _configs[_strategy];

// Emit Event.
emit StrategyChanged(_strategy, Status.REMOVED);
}

/**
* @notice Set the minimum change variable for a strategy.
* @dev This is the minimum amount of debt to be
Expand Down
100 changes: 78 additions & 22 deletions tests/debtAllocators/test_debt_allocator.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@ def test_setup(debt_allocator_factory, brain, user, strategy, vault):
assert debt_allocator.managers(brain) == False
assert debt_allocator.factory() == debt_allocator_factory.address
assert debt_allocator.vault() == vault.address
assert debt_allocator.getConfig(strategy) == (0, 0, 0, 0)
assert debt_allocator.getConfig(strategy) == (False, 0, 0, 0, 0)
assert debt_allocator.totalDebtRatio() == 0
with ape.reverts("!active"):
debt_allocator.shouldUpdateDebt(strategy)
(bool, bytes) = debt_allocator.shouldUpdateDebt(strategy.address)
assert bool == False
assert bytes == ("!added").encode("utf-8")


def test_set_keepers(debt_allocator_factory, debt_allocator, brain, user):
Expand Down Expand Up @@ -75,7 +76,7 @@ def test_set_managers(debt_allocator, brain, user):


def test_set_minimum_change(debt_allocator, brain, strategy, user):
assert debt_allocator.getConfig(strategy) == (0, 0, 0, 0)
assert debt_allocator.getConfig(strategy) == (False, 0, 0, 0, 0)
assert debt_allocator.minimumChange() == 0

minimum = int(1e17)
Expand All @@ -95,7 +96,7 @@ def test_set_minimum_change(debt_allocator, brain, strategy, user):


def test_set_minimum_wait(debt_allocator, brain, strategy, user):
assert debt_allocator.getConfig(strategy) == (0, 0, 0, 0)
assert debt_allocator.getConfig(strategy) == (False, 0, 0, 0, 0)
assert debt_allocator.minimumWait() == 0

minimum = int(1e17)
Expand All @@ -112,7 +113,7 @@ def test_set_minimum_wait(debt_allocator, brain, strategy, user):


def test_set_max_debt_update_loss(debt_allocator, brain, strategy, user):
assert debt_allocator.getConfig(strategy) == (0, 0, 0, 0)
assert debt_allocator.getConfig(strategy) == (False, 0, 0, 0, 0)
assert debt_allocator.maxDebtUpdateLoss() == 1

max = int(69)
Expand All @@ -134,7 +135,7 @@ def test_set_max_debt_update_loss(debt_allocator, brain, strategy, user):
def test_set_ratios(
debt_allocator, brain, daddy, vault, strategy, create_strategy, user
):
assert debt_allocator.getConfig(strategy) == (0, 0, 0, 0)
assert debt_allocator.getConfig(strategy) == (False, 0, 0, 0, 0)

minimum = int(1e17)
max = int(6_000)
Expand All @@ -158,13 +159,18 @@ def test_set_ratios(

tx = debt_allocator.setStrategyDebtRatio(strategy, target, max, sender=brain)

event = list(tx.decode_logs(debt_allocator.StrategyChanged))[0]

assert event.strategy == strategy
assert event.status == 0

event = list(tx.decode_logs(debt_allocator.UpdateStrategyDebtRatio))[0]

assert event.newTargetRatio == target
assert event.newMaxRatio == max
assert event.newTotalDebtRatio == target
assert debt_allocator.totalDebtRatio() == target
assert debt_allocator.getConfig(strategy) == (target, max, 0, 0)
assert debt_allocator.getConfig(strategy) == (True, target, max, 0, 0)

new_strategy = create_strategy()
vault.add_strategy(new_strategy, sender=daddy)
Expand All @@ -182,13 +188,13 @@ def test_set_ratios(
assert event.newMaxRatio == target * 1.2
assert event.newTotalDebtRatio == target
assert debt_allocator.totalDebtRatio() == target
assert debt_allocator.getConfig(strategy) == (target, target * 1.2, 0, 0)
assert debt_allocator.getConfig(strategy) == (True, target, target * 1.2, 0, 0)


def test_increase_debt_ratio(
debt_allocator, brain, daddy, vault, strategy, create_strategy, user
):
assert debt_allocator.getConfig(strategy) == (0, 0, 0, 0)
assert debt_allocator.getConfig(strategy) == (False, 0, 0, 0, 0)

minimum = int(1e17)
target = int(5_000)
Expand All @@ -213,7 +219,7 @@ def test_increase_debt_ratio(
assert event.newMaxRatio == max
assert event.newTotalDebtRatio == target
assert debt_allocator.totalDebtRatio() == target
assert debt_allocator.getConfig(strategy) == (target, max, 0, 0)
assert debt_allocator.getConfig(strategy) == (True, target, max, 0, 0)

new_strategy = create_strategy()
vault.add_strategy(new_strategy, sender=daddy)
Expand All @@ -232,7 +238,7 @@ def test_increase_debt_ratio(
assert event.newMaxRatio == max
assert event.newTotalDebtRatio == target
assert debt_allocator.totalDebtRatio() == target
assert debt_allocator.getConfig(strategy) == (target, max, 0, 0)
assert debt_allocator.getConfig(strategy) == (True, target, max, 0, 0)

target = int(10_000)
max = int(10_000)
Expand All @@ -245,13 +251,13 @@ def test_increase_debt_ratio(
assert event.newMaxRatio == max
assert event.newTotalDebtRatio == target
assert debt_allocator.totalDebtRatio() == target
assert debt_allocator.getConfig(strategy) == (target, max, 0, 0)
assert debt_allocator.getConfig(strategy) == (True, target, max, 0, 0)


def test_decrease_debt_ratio(
debt_allocator, brain, vault, strategy, daddy, create_strategy, user
):
assert debt_allocator.getConfig(strategy) == (0, 0, 0, 0)
assert debt_allocator.getConfig(strategy) == (False, 0, 0, 0, 0)

minimum = int(1e17)
target = int(5_000)
Expand All @@ -273,7 +279,7 @@ def test_decrease_debt_ratio(
assert event.newMaxRatio == max
assert event.newTotalDebtRatio == target
assert debt_allocator.totalDebtRatio() == target
assert debt_allocator.getConfig(strategy) == (target, max, 0, 0)
assert debt_allocator.getConfig(strategy) == (True, target, max, 0, 0)

target = int(2_000)
max = target * 1.2
Expand All @@ -290,7 +296,7 @@ def test_decrease_debt_ratio(
assert event.newMaxRatio == max
assert event.newTotalDebtRatio == target
assert debt_allocator.totalDebtRatio() == target
assert debt_allocator.getConfig(strategy) == (target, max, 0, 0)
assert debt_allocator.getConfig(strategy) == (True, target, max, 0, 0)

target = int(0)
max = int(0)
Expand All @@ -303,17 +309,67 @@ def test_decrease_debt_ratio(
assert event.newMaxRatio == max
assert event.newTotalDebtRatio == target
assert debt_allocator.totalDebtRatio() == target
assert debt_allocator.getConfig(strategy) == (0, 0, 0, 0)
assert debt_allocator.getConfig(strategy) == (True, 0, 0, 0, 0)


def test_remove_strategy(
debt_allocator, brain, vault, strategy, daddy, user, deposit_into_vault, amount
):
assert debt_allocator.getConfig(strategy) == (False, 0, 0, 0, 0)

minimum = int(1)
max = int(6_000)
target = int(5_000)

vault.add_strategy(strategy.address, sender=daddy)

debt_allocator.setMinimumChange(minimum, sender=brain)

tx = debt_allocator.setStrategyDebtRatio(strategy, target, max, sender=brain)

event = list(tx.decode_logs(debt_allocator.StrategyChanged))[0]

assert event.strategy == strategy
assert event.status == 0

event = list(tx.decode_logs(debt_allocator.UpdateStrategyDebtRatio))[0]

assert event.newTargetRatio == target
assert event.newMaxRatio == max
assert event.newTotalDebtRatio == target
assert debt_allocator.totalDebtRatio() == target
assert debt_allocator.getConfig(strategy) == (True, target, max, 0, 0)

deposit_into_vault(vault, amount)
vault.update_max_debt_for_strategy(strategy, MAX_INT, sender=daddy)

print(debt_allocator.shouldUpdateDebt(strategy))
assert debt_allocator.shouldUpdateDebt(strategy)[0] == True

with ape.reverts("!manager"):
debt_allocator.removeStrategy(strategy, sender=user)

tx = debt_allocator.removeStrategy(strategy, sender=brain)

event = list(tx.decode_logs(debt_allocator.StrategyChanged))

assert len(event) == 1
assert event[0].strategy == strategy
assert event[0].status == 1
assert debt_allocator.totalDebtRatio() == 0
assert debt_allocator.getConfig(strategy) == (False, 0, 0, 0, 0)
assert debt_allocator.shouldUpdateDebt(strategy)[0] == False


def test_should_update_debt(
debt_allocator, vault, strategy, brain, daddy, deposit_into_vault, amount
):
assert debt_allocator.getConfig(strategy.address) == (0, 0, 0, 0)
assert debt_allocator.getConfig(strategy.address) == (False, 0, 0, 0, 0)
vault.add_role(debt_allocator, ROLES.DEBT_MANAGER, sender=daddy)

with ape.reverts("!active"):
debt_allocator.shouldUpdateDebt(strategy.address)
(bool, bytes) = debt_allocator.shouldUpdateDebt(strategy.address)
assert bool == False
assert bytes == ("!added").encode("utf-8")

vault.add_strategy(strategy.address, sender=daddy)

Expand Down Expand Up @@ -427,7 +483,7 @@ def test_update_debt(
deposit_into_vault,
amount,
):
assert debt_allocator.getConfig(strategy) == (0, 0, 0, 0)
assert debt_allocator.getConfig(strategy) == (False, 0, 0, 0, 0)
deposit_into_vault(vault, amount)

assert vault.totalIdle() == amount
Expand All @@ -452,7 +508,7 @@ def test_update_debt(

debt_allocator.update_debt(strategy, amount, sender=brain)

timestamp = debt_allocator.getConfig(strategy)[2]
timestamp = debt_allocator.getConfig(strategy)[3]
assert timestamp != 0
assert vault.totalIdle() == 0
assert vault.totalDebt() == amount
Expand Down

0 comments on commit f1a9106

Please sign in to comment.