Skip to content

Commit

Permalink
feat: update vault version (#40)
Browse files Browse the repository at this point in the history
* feat: update vault version

* fix: rename accountant

* fix: node version

* chore: update to new changes

* fix: readme

* fix: ape build

* chore: downgrade ape

---------

Co-authored-by: FP <[email protected]>
  • Loading branch information
Schlagonia and fp-crypto authored Mar 6, 2024
1 parent 117461a commit 0997196
Show file tree
Hide file tree
Showing 20 changed files with 240 additions and 373 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18
- uses: ApeWorX/[email protected]
with:
python-version: '3.10'
Expand Down
6 changes: 0 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,6 @@

ape test

### Set your environment Variables

export WEB3_INFURA_PROJECT_ID=your_infura_api_key

export ETHERSCAN_API_KEY=your_api_key

### Deployment

Deployment of periphery contracts such as the [Registry Factory](https://github.com/yearn/vault-periphery/blob/master/contracts/registry/RegistryFactory.sol) or [Address Provider](https://github.com/yearn/vault-periphery/blob/master/contracts/AddressProvider.vy) are done using a create2 factory in order to get a deterministic address that is the same on each EVM chain.
Expand Down
18 changes: 9 additions & 9 deletions ape-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,35 +17,35 @@ default_ecosystem: ethereum
dependencies:
- name: openzeppelin
github: OpenZeppelin/openzeppelin-contracts
ref: 4.7.3
ref: 4.9.5

- name: yearn-vaults
github: yearn/yearn-vaults-v3
ref: v3.0.1
ref: v3.0.2
exclude:
- test/**/*

- name: tokenized-strategy
github: yearn/tokenized-strategy
ref: v3.0.1
ref: v3.0.2
contracts_folder: src
exclude:
- test/**/*

- name: periphery
github: yearn/tokenized-strategy-periphery
ref: v3.0.1
ref: master
contracts_folder: src
exclude:
- test/**/*

solidity:
import_remapping:
- "@openzeppelin/contracts=openzeppelin/v4.7.3"
- "@yearn-vaults=yearn-vaults/v3.0.1"
- "@tokenized-strategy=tokenized-strategy/v3.0.1"
- "@periphery=periphery/v3.0.1"
- "@openzeppelin/contracts=openzeppelin/v4.9.5"
- "@yearn-vaults=yearn-vaults/v3.0.2"
- "@tokenized-strategy=tokenized-strategy/v3.0.2"
- "@periphery=periphery/master"

ethereum:
local:
default_provider: hardhat
default_provider: hardhat
6 changes: 3 additions & 3 deletions contracts/Managers/RoleManager.sol
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
// SPDX-License-Identifier: AGPL-3.0
pragma solidity 0.8.18;

import {Roles} from "../libraries/Roles.sol";
import {Registry} from "../registry/Registry.sol";
import {Accountant} from "../accountants/Accountant.sol";
import {Roles} from "@yearn-vaults/interfaces/Roles.sol";
import {IVault} from "@yearn-vaults/interfaces/IVault.sol";
import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {Governance2Step} from "@periphery/utils/Governance2Step.sol";
import {HealthCheckAccountant} from "../accountants/HealthCheckAccountant.sol";
import {DebtAllocatorFactory} from "../debtAllocators/DebtAllocatorFactory.sol";

/// @title Yearn V3 Vault Role Manager.
Expand Down Expand Up @@ -410,7 +410,7 @@ contract RoleManager is Governance2Step {
IVault(_vault).remove_role(address(this), Roles.ACCOUNTANT_MANAGER);

// Whitelist the vault in the accountant.
HealthCheckAccountant(accountant).addVault(_vault);
Accountant(accountant).addVault(_vault);
}
}

Expand Down
9 changes: 1 addition & 8 deletions contracts/Mocks/MockERC20.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,4 @@ pragma solidity 0.8.18;

import "@openzeppelin/contracts/mocks/ERC20Mock.sol";

contract MockERC20 is ERC20Mock {
constructor(
string memory _name,
string memory _symbol,
address _initialUser,
uint256 _initialAmount
) ERC20Mock(_name, _symbol, _initialUser, _initialAmount) {}
}
contract MockERC20 is ERC20Mock {}
11 changes: 2 additions & 9 deletions contracts/Mocks/MockStrategy.sol
Original file line number Diff line number Diff line change
@@ -1,19 +1,12 @@
// SPDX-License-Identifier: AGPL-3.0
pragma solidity 0.8.18;

import {ERC4626Mock, IERC20Metadata} from "@openzeppelin/contracts/mocks/ERC4626Mock.sol";

interface IRegistry {
function newStrategy(address, address) external;
}
import {ERC4626Mock} from "@openzeppelin/contracts/mocks/ERC4626Mock.sol";

contract MockStrategy is ERC4626Mock {
string public apiVersion;

constructor(
IERC20Metadata _asset,
string memory _apiVersion
) ERC4626Mock(_asset, "test strategy", "tsStrat") {
constructor(address _asset, string memory _apiVersion) ERC4626Mock(_asset) {
apiVersion = _apiVersion;
}
}
35 changes: 12 additions & 23 deletions contracts/Mocks/MockTokenizedStrategy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,15 @@ contract MockTokenizedStrategy is TokenizedStrategy {
uint256 public minDebt;
uint256 public maxDebt = type(uint256).max;

// Private variables and functions used in this mock.
bytes32 public constant BASE_STRATEGY_STORAGE =
bytes32(uint256(keccak256("yearn.base.strategy.storage")) - 1);

function strategyStorage() internal pure returns (StrategyData storage S) {
// Since STORAGE_SLOT is a constant, we have to put a variable
// on the stack to access it from an inline assembly block.
bytes32 slot = BASE_STRATEGY_STORAGE;
assembly {
S.slot := slot
}
}

constructor(
address _factory,
address _asset,
string memory _name,
address _management,
address _keeper
) {
) TokenizedStrategy(_factory) {
// Cache storage pointer
StrategyData storage S = strategyStorage();
StrategyData storage S = _strategyStorage();

// Set the strategy's underlying asset
S.asset = ERC20(_asset);
Expand All @@ -37,7 +25,7 @@ contract MockTokenizedStrategy is TokenizedStrategy {
S.decimals = ERC20(_asset).decimals();

// Set last report to this block.
S.lastReport = uint128(block.timestamp);
S.lastReport = uint96(block.timestamp);

// Set the default management address. Can't be 0.
require(_management != address(0), "ZERO ADDRESS");
Expand All @@ -58,7 +46,7 @@ contract MockTokenizedStrategy is TokenizedStrategy {
function availableDepositLimit(
address
) public view virtual returns (uint256) {
uint256 _totalAssets = strategyStorage().totalIdle;
uint256 _totalAssets = _strategyStorage().totalAssets;
uint256 _maxDebt = maxDebt;
return _maxDebt > _totalAssets ? _maxDebt - _totalAssets : 0;
}
Expand All @@ -74,7 +62,7 @@ contract MockTokenizedStrategy is TokenizedStrategy {
function freeFunds(uint256 _amount) external virtual {}

function harvestAndReport() external virtual returns (uint256) {
return strategyStorage().asset.balanceOf(address(this));
return _strategyStorage().asset.balanceOf(address(this));
}
}

Expand All @@ -84,12 +72,13 @@ contract MockTokenized is MockTokenizedStrategy {
uint256 public limit;

constructor(
address _factory,
address _asset,
string memory _name,
address _management,
address _keeper,
uint256 _apr
) MockTokenizedStrategy(_asset, _name, _management, _keeper) {
) MockTokenizedStrategy(_factory, _asset, _name, _management, _keeper) {
apr = _apr;
}

Expand All @@ -105,9 +94,9 @@ contract MockTokenized is MockTokenizedStrategy {
}

function realizeLoss(uint256 _amount) external {
strategyStorage().asset.transfer(msg.sender, _amount);
strategyStorage().totalIdle -= _amount;
strategyStorage().totalDebt += _amount;
_strategyStorage().asset.transfer(msg.sender, _amount);
//strategyStorage().totalIdle -= _amount;
//strategyStorage().totalDebt += _amount;
}

function tendThis(uint256) external {}
Expand All @@ -116,7 +105,7 @@ contract MockTokenized is MockTokenizedStrategy {
address _owner
) public view virtual override returns (uint256) {
if (limit != 0) {
uint256 _totalAssets = strategyStorage().totalIdle;
uint256 _totalAssets = _strategyStorage().totalAssets;
return _totalAssets > limit ? _totalAssets - limit : 0;
} else {
return super.availableWithdrawLimit(_owner);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
// SPDX-License-Identifier: GNU AGPLv3
pragma solidity 0.8.18;

import {IVault} from "@yearn-vaults/interfaces/IVault.sol";
import {Math} from "@openzeppelin/contracts/utils/math/Math.sol";
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

import {IVault} from "@yearn-vaults/interfaces/IVault.sol";

/// @title Health Check Accountant.
/// @title Accountant.
/// @dev Will charge fees, issue refunds, and run health check on any reported
/// gains or losses during a strategy's report.
contract HealthCheckAccountant {
contract Accountant {
using SafeERC20 for ERC20;

/// @notice An event emitted when a vault is added or removed.
Expand Down Expand Up @@ -61,6 +60,7 @@ contract HealthCheckAccountant {
uint16 maxFee; // Max fee allowed as a percent of gain.
uint16 maxGain; // Max percent gain a strategy can report.
uint16 maxLoss; // Max percent loss a strategy can report.
bool custom; // Flag to set for custom configs.
}

modifier onlyFeeManager() {
Expand Down Expand Up @@ -141,9 +141,6 @@ contract HealthCheckAccountant {
/// @notice Mapping vault => custom Fee config if any.
mapping(address => Fee) public customConfig;

/// @notice Mapping vault => flag to use a custom config.
mapping(address => uint256) internal _useCustomConfig;

/// @notice Mapping vault => strategy => flag for one time healthcheck skips.
mapping(address => mapping(address => bool)) skipHealthCheck;

Expand Down Expand Up @@ -192,13 +189,11 @@ contract HealthCheckAccountant {
onlyAddedVaults
returns (uint256 totalFees, uint256 totalRefunds)
{
// Declare the config to use
Fee memory fee;
// Declare the config to use as the custom.
Fee memory fee = customConfig[msg.sender];

// Check if there is a custom config to use.
if (_useCustomConfig[msg.sender] != 0) {
fee = customConfig[msg.sender];
} else {
if (!fee.custom) {
// Otherwise use the default.
fee = defaultConfig;
}
Expand Down Expand Up @@ -368,7 +363,8 @@ contract HealthCheckAccountant {
refundRatio: defaultRefund,
maxFee: defaultMaxFee,
maxGain: defaultMaxGain,
maxLoss: defaultMaxLoss
maxLoss: defaultMaxLoss,
custom: false
});

emit UpdateDefaultFeeConfig(defaultConfig);
Expand Down Expand Up @@ -413,15 +409,13 @@ contract HealthCheckAccountant {
refundRatio: customRefund,
maxFee: customMaxFee,
maxGain: customMaxGain,
maxLoss: customMaxLoss
maxLoss: customMaxLoss,
custom: true
});

// Store the config.
customConfig[vault] = _config;

// Set the custom flag.
_useCustomConfig[vault] = 1;

emit UpdateCustomFeeConfig(vault, _config);
}

Expand All @@ -431,14 +425,11 @@ contract HealthCheckAccountant {
*/
function removeCustomConfig(address vault) external virtual onlyFeeManager {
// Ensure custom fees are set for the specified vault.
require(_useCustomConfig[vault] != 0, "No custom fees set");
require(customConfig[vault].custom, "No custom fees set");

// Set all the vaults's custom fees to 0.
delete customConfig[vault];

// Clear the custom flag.
_useCustomConfig[vault] = 0;

// Emit relevant event.
emit RemovedCustomFeeConfig(vault);
}
Expand Down Expand Up @@ -470,7 +461,7 @@ contract HealthCheckAccountant {
function useCustomConfig(
address vault
) external view virtual returns (bool) {
return _useCustomConfig[vault] != 0;
return customConfig[vault].custom;
}

/**
Expand All @@ -481,10 +472,10 @@ contract HealthCheckAccountant {
function getVaultConfig(
address vault
) external view returns (Fee memory fee) {
// Check if custom config is set.
if (_useCustomConfig[vault] != 0) {
fee = customConfig[vault];
} else {
fee = customConfig[vault];

// Check if there is a custom config to use.
if (!fee.custom) {
// Otherwise use the default.
fee = defaultConfig;
}
Expand Down
6 changes: 3 additions & 3 deletions contracts/accountants/RefundAccountant.sol
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
// SPDX-License-Identifier: GNU AGPLv3
pragma solidity 0.8.18;

import {HealthCheckAccountant, ERC20, SafeERC20, IVault} from "./HealthCheckAccountant.sol";
import {Accountant, ERC20, SafeERC20, IVault} from "./Accountant.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 {
contract RefundAccountant is Accountant {
using SafeERC20 for ERC20;

/// @notice An event emitted when a refund is added for a strategy.
Expand All @@ -30,7 +30,7 @@ contract RefundAccountant is HealthCheckAccountant {
uint16 defaultMaxGain,
uint16 defaultMaxLoss
)
HealthCheckAccountant(
Accountant(
_feeManager,
_feeRecipient,
defaultManagement,
Expand Down
Loading

0 comments on commit 0997196

Please sign in to comment.