Skip to content

Commit

Permalink
build: refund accountant (#27)
Browse files Browse the repository at this point in the history
* build: refund rewards

* test: reward accountant

* feat: vault manager

* fix: report flow

* fix: rename to refund

* test: organize

* feat: remove max fee cap

* fix: wavey review

* fix: functions

* fix: scripts

* fix: dont check activation
  • Loading branch information
Schlagonia authored Nov 17, 2023
1 parent 52b1d06 commit 9c36607
Show file tree
Hide file tree
Showing 15 changed files with 1,859 additions and 70 deletions.
171 changes: 126 additions & 45 deletions contracts/accountants/HealthCheckAccountant.sol

Large diffs are not rendered by default.

122 changes: 122 additions & 0 deletions contracts/accountants/RefundAccountant.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
// SPDX-License-Identifier: GNU AGPLv3
pragma solidity 0.8.18;

import {HealthCheckAccountant, ERC20, SafeERC20, IVault} from "./HealthCheckAccountant.sol";

/// @title Refund Accountant
/// @dev Allows for configurable refunds to be given to specific strategies for a vault.
/// This can be used to auto compound reward into vault or provide retroactive refunds
/// from a previous loss.
contract RefundAccountant is HealthCheckAccountant {
using SafeERC20 for ERC20;

/// @notice An event emitted when a refund is added for a strategy.
event UpdateRefund(
address indexed vault,
address indexed strategy,
bool refund,
uint256 amount
);

/// @notice Struct to hold refund info for a strategy.
struct Refund {
// If the accountant should refund on the report.
bool refund;
// The amount if any to refund.
uint248 amount;
}

/// @notice Mapping of vault => strategy => struct if there is a reward refund to give.
mapping(address => mapping(address => Refund)) public refund;

constructor(
address _feeManager,
address _feeRecipient,
uint16 defaultManagement,
uint16 defaultPerformance,
uint16 defaultRefund,
uint16 defaultMaxFee,
uint16 defaultMaxGain,
uint16 defaultMaxLoss
)
HealthCheckAccountant(
_feeManager,
_feeRecipient,
defaultManagement,
defaultPerformance,
defaultRefund,
defaultMaxFee,
defaultMaxGain,
defaultMaxLoss
)
{}

/**
* @notice Called by a vault when a `strategy` is reporting.
* @dev The msg.sender must have been added to the `vaults` mapping.
* @param strategy Address of the strategy reporting.
* @param gain Amount of the gain if any.
* @param loss Amount of the loss if any.
* @return totalFees if any to charge.
* @return totalRefunds if any for the vault to pull.
*/
function report(
address strategy,
uint256 gain,
uint256 loss
)
public
virtual
override
returns (uint256 totalFees, uint256 totalRefunds)
{
(totalFees, totalRefunds) = super.report(strategy, gain, loss);

Refund memory refundConfig = refund[msg.sender][strategy];
// Check if the strategy is being given a refund.
if (refundConfig.refund) {
// Add it to the existing refunds.
totalRefunds += uint256(refundConfig.amount);

// Make sure the vault is approved correctly.
_checkAllowance(
msg.sender,
IVault(msg.sender).asset(),
totalRefunds
);

// Always reset the refund amount so it can't be reused.
delete refund[msg.sender][strategy];
}
}

/**
* @notice Set a strategy to use to refund a reward amount for
* aut compounding reward tokens.
*
* @param _vault Address of the vault to refund.
* @param _strategy Address of the strategy to refund during the report.
* @param _refund Bool to turn it on or off.
* @param _amount Amount to refund per report.
*/
function setRefund(
address _vault,
address _strategy,
bool _refund,
uint256 _amount
) external virtual onlyFeeManager {
require(vaults[_vault], "not added");
require(
IVault(_vault).strategies(_strategy).activation != 0,
"!active"
);
require(_refund || _amount == 0, "no refund and non zero amount");

refund[_vault][_strategy] = Refund({
refund: _refund,
amount: uint248(_amount)
});

emit UpdateRefund(_vault, _strategy, _refund, uint256(_amount));
}
}
2 changes: 0 additions & 2 deletions contracts/debtAllocators/GenericDebtAllocator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -300,8 +300,6 @@ contract GenericDebtAllocator is Governance {
uint256 _targetRatio,
uint256 _maxRatio
) external virtual onlyGovernance {
// Make sure the strategy is added to the vault.
require(IVault(vault).strategies(_strategy).activation != 0, "!active");
// Make sure a minimumChange has been set.
require(minimumChange != 0, "!minimum");
// Cannot be more than 100%.
Expand Down
25 changes: 15 additions & 10 deletions scripts/deploy_accountant.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,11 @@ def deploy_accountant():
print(f"Salt we are using {salt}")
print("Init balance:", deployer.balance / 1e18)

if (
input(
"Would you like to deploy a Generic Accountant or a HealthCheck Accountant? g/h "
).lower()
== "g"
):
version = input(
"Would you like to deploy a Generic Accountant, HealthCheck Accountant or a Refund Accountant? g/h/r "
).lower()

if version == "g":
print("Deploying a Generic accountant.")
print("Enter the default amounts to use in Base Points. (100% == 10_000)")

Expand All @@ -65,10 +64,15 @@ def deploy_accountant():
)

else:
print("Deploying a HealthCheck accountant.")
print("Enter the default amounts to use in Base Points. (100% == 10_000)")
if version == "h":
print("Deploying a HealthCheck accountant.")
accountant = project.HealthCheckAccountant

accountant = project.HealthCheckAccountant
else:
print("Deploying a Refund accountant.")
accountant = project.RefundAccountant

print("Enter the default amounts to use in Base Points. (100% == 10_000)")

management_fee = input("Default management fee? ")
assert int(management_fee) <= 200
Expand Down Expand Up @@ -112,9 +116,10 @@ def deploy_accountant():

address = event[0].addr

print("------------------")
print(f"Deployed the Accountant to {address}")
print("------------------")
print(f"Encoded Constructor to use for verifaction {constructor.hex()}")
print(f"Encoded Constructor to use for verifaction {constructor.hex()[2:]}")


def main():
Expand Down
3 changes: 2 additions & 1 deletion scripts/deploy_address_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,10 @@ def deploy_address_provider():

address = event[0].addr

print("------------------")
print(f"Deployed the address provider to {address}")
print("------------------")
print(f"Encoded Constructor to use for verifaction {constructor.hex()}")
print(f"Encoded Constructor to use for verifaction {constructor.hex()[2:]}")


def main():
Expand Down
2 changes: 2 additions & 0 deletions scripts/deploy_allocator_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ def deploy_allocator_factory():

address = event[0].addr

print("------------------")
print(f"Deployed the Factory to {address}")
print("------------------")


def main():
Expand Down
3 changes: 2 additions & 1 deletion scripts/deploy_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,10 @@ def deploy_release_and_factory():

deployed_factory = factory.at(factory_event[0].addr)

print("------------------")
print(f"Deployed Registry Factory to {deployed_factory.address}")
print("------------------")
print(f"Encoded Constructor to use for verifaction {factory_constructor.hex()}")
print(f"Encoded Constructor to use for verifaction {factory_constructor.hex()[2:]}")


def main():
Expand Down
File renamed without changes.
Loading

0 comments on commit 9c36607

Please sign in to comment.