Skip to content

Commit

Permalink
feat: 3.0.1 (#24)
Browse files Browse the repository at this point in the history
* chore: remove old depend

* forge install: tokenized-strategy

v3.0.1

* forge install: yearn-vaults-v3

v3.0.1

* feat: update to new version

* chore: move vault setup

* fix: vault deploy

* fix: vault setup

* fix: asset is erc20
  • Loading branch information
Schlagonia authored Oct 12, 2023
1 parent afc8007 commit 56a1c6d
Show file tree
Hide file tree
Showing 28 changed files with 128 additions and 270 deletions.
10 changes: 5 additions & 5 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
path = lib/openzeppelin-contracts
url = https://github.com/OpenZeppelin/openzeppelin-contracts
branch = v4.8.2
[submodule "lib/yearn-vaults-v3"]
path = lib/yearn-vaults-v3
url = https://github.com/yearn/yearn-vaults-v3
branch = v3.0.0
[submodule "lib/tokenized-strategy"]
path = lib/tokenized-strategy
url = https://github.com/yearn/tokenized-strategy
branch = v3.0.0
branch = v3.0.1
[submodule "lib/yearn-vaults-v3"]
path = lib/yearn-vaults-v3
url = https://github.com/yearn/yearn-vaults-v3
branch = v3.0.1
2 changes: 1 addition & 1 deletion lib/yearn-vaults-v3
Submodule yearn-vaults-v3 updated 37 files
+3 −1 .solhint.json
+4 −1 README.md
+9 −0 SECURITY.md
+41 −23 TECH_SPEC.md
+10 −10 contracts/VaultFactory.vy
+350 −105 contracts/VaultV3.vy
+8 −0 contracts/interfaces/IDeployer.sol
+0 −25 contracts/interfaces/IStrategyERC4626.sol
+241 −3 contracts/interfaces/IVault.sol
+55 −0 contracts/interfaces/IVaultFactory.sol
+32 −0 contracts/interfaces/VaultConstants.sol
+7 −24 contracts/test/ERC4626BaseStrategy.sol
+1 −1 contracts/test/Token.sol
+2 −10 contracts/test/mocks/ERC4626/BaseStrategyMock.sol
+19 −1 contracts/test/mocks/ERC4626/FaultyStrategy.sol
+1 −1 contracts/test/mocks/ERC4626/Generic4626.sol
+1 −8 contracts/test/mocks/ERC4626/LiquidStrategy.sol
+9 −7 contracts/test/mocks/ERC4626/LockedStrategy.sol
+33 −19 contracts/test/mocks/ERC4626/LossyStrategy.sol
+2 −5 contracts/test/mocks/periphery/Accountant.vy
+2 −5 contracts/test/mocks/periphery/FaultyAccountant.vy
+2 −5 contracts/test/mocks/periphery/FlexibleAccountant.vy
+55 −0 contracts/test/mocks/periphery/LimitModule.vy
+1 −1 package.json
+95 −0 scripts/deploy.py
+14 −0 tests/conftest.py
+63 −13 tests/unit/vault/test_buy_debt.py
+109 −25 tests/unit/vault/test_debt_management.py
+51 −6 tests/unit/vault/test_emergency_shutdown.py
+733 −2 tests/unit/vault/test_erc4626.py
+279 −1 tests/unit/vault/test_profit_unlocking.py
+238 −17 tests/unit/vault/test_role_base_access.py
+152 −1 tests/unit/vault/test_role_permissioned_access.py
+7 −7 tests/unit/vault/test_shares.py
+683 −5 tests/unit/vault/test_strategy_withdraw.py
+6 −4 tests/utils/constants.py
+4 −4 yarn.lock
10 changes: 7 additions & 3 deletions script/Deploy.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,33 @@ import "forge-std/Script.sol";
// Deploy a contract to a deterministic address with create2
contract Deploy is Script {

Deployer public deployer = Deployer(0x8D85e7c9A4e369E53Acc8d5426aE1568198b0112);

function run() external {
uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
vm.startBroadcast(deployerPrivateKey);

// Encode constructor arguments
bytes memory construct = abi.encode();

// Append constructor args to the bytecode
bytes memory bytecode = abi.encodePacked(vm.getCode("CommonReportTrigger.sol:CommonReportTrigger"), construct);

// Pick an unique salt
uint256 salt = uint256(keccak256("v3.0.0"));

address contractAddress = deploy(bytecode, salt);
address contractAddress = deployer.deploy(bytecode, salt);

console.log("Address is ", contractAddress);

vm.stopBroadcast();
}
}

contract Deployer {
event Deployed(address addr, uint256 salt);

function deploy(bytes memory code, uint256 salt) public returns (address) {
function deploy(bytes memory code, uint256 salt) external returns (address) {
address addr;
assembly {
addr := create2(0, add(code, 0x20), mload(code), salt)
Expand Down
46 changes: 0 additions & 46 deletions script/Deploy2.s.sol

This file was deleted.

25 changes: 8 additions & 17 deletions src/AprOracle/AprOracle.sol
Original file line number Diff line number Diff line change
@@ -1,17 +1,8 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.18;

import {IStrategy} from "../interfaces/IStrategy.sol";

interface IVault {
function totalAssets() external view returns (uint256);

function profitUnlockingRate() external view returns (uint256);

function fullProfitUnlockDate() external view returns (uint256);

function convertToAssets(uint256) external view returns (uint256);
}
import {IVault} from "@yearn-vaults/interfaces/IVault.sol";
import {IStrategy} from "@tokenized-strategy/interfaces/IStrategy.sol";

interface IOracle {
function aprAfterDebtChange(
Expand All @@ -30,7 +21,7 @@ interface IOracle {
* based on the current profit unlocking rate. As well as the
* expected APR given some change in totalAssets.
*
* This can also be used to retreive the expexted APR a strategy
* This can also be used to retrieve the expected APR a strategy
* is making, thats yet to be reported, if a strategy specific
* oracle has been added.
*
Expand All @@ -41,7 +32,7 @@ contract AprOracle {
// Mapping of a strategy to its specific apr oracle.
mapping(address => address) public oracles;

// Used to get the Current and Expexted APRS.
// Used to get the Current and Expected APR'S.
uint256 internal constant MAX_BPS_EXTENDED = 1_000_000_000_000;
uint256 internal constant SECONDS_PER_YEAR = 31_556_952;

Expand All @@ -50,15 +41,15 @@ contract AprOracle {
* @dev Will revert if an oracle has not been set for that strategy.
*
* This will be different than the {getExpectedApr()} which returns
* the current APR bassed off of previously reported profits that
* the current APR based off of previously reported profits that
* are currently unlocking.
*
* This will return the APR the stratey is currently earning that
* This will return the APR the strategy is currently earning that
* has yet to be reported.
*
* @param _strategy Address of the strategy to check.
* @param _debtChange Positive or negative change in debt.
* @return . The expected APR it will be earning repersented as 1e18.
* @return . The expected APR it will be earning represented as 1e18.
*/
function getStrategyApr(
address _strategy,
Expand Down Expand Up @@ -122,7 +113,7 @@ contract AprOracle {
* Will return 0 if there is no profit unlocking or no assets.
*
* This can be used to predict the change in current apr given some
* deposit or withdra to the vault.
* deposit or withdraw to the vault.
*
* @param _vault The address of the vault or strategy.
* @param _delta The positive or negative change in `totalAssets`.
Expand Down
4 changes: 2 additions & 2 deletions src/AprOracle/AprOracleBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ abstract contract AprOracleBase is Governance {

/**
* @notice Will return the expected Apr of a strategy post a debt change.
* @dev _delta is a signed integer so that it can also repersent a debt
* @dev _delta is a signed integer so that it can also represent a debt
* decrease.
*
* _delta will be == 0 to get the current apr.
*
* This will potentially be called during non-view functions so gas
* effeciency should be taken into account.
* efficiency should be taken into account.
*
* @param _strategy The strategy to get the apr for.
* @param _delta The difference in debt.
Expand Down
25 changes: 4 additions & 21 deletions src/HealthCheck/BaseHealthCheck.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.18;

import {BaseTokenizedStrategy} from "@tokenized-strategy/BaseTokenizedStrategy.sol";
import {BaseStrategy, ERC20} from "@tokenized-strategy/BaseStrategy.sol";

/**
* @title Base Health Check
Expand All @@ -22,15 +22,7 @@ import {BaseTokenizedStrategy} from "@tokenized-strategy/BaseTokenizedStrategy.s
* losses, but rather can make sure manual intervention is
* needed before reporting an unexpected loss or profit.
*/
abstract contract BaseHealthCheck is BaseTokenizedStrategy {
// Optional modifier that can be placed on any function
// to perform checks such as debt/PPS before running.
// Must override `_checkHealth()` for this to work.
modifier checkHealth() {
_checkHealth();
_;
}

abstract contract BaseHealthCheck is BaseStrategy {
// Can be used to determine if a healthcheck should be called.
// Defaults to true;
bool public doHealthCheck = true;
Expand All @@ -46,7 +38,7 @@ abstract contract BaseHealthCheck is BaseTokenizedStrategy {
constructor(
address _asset,
string memory _name
) BaseTokenizedStrategy(_asset, _name) {}
) BaseStrategy(_asset, _name) {}

Check warning on line 41 in src/HealthCheck/BaseHealthCheck.sol

View workflow job for this annotation

GitHub Actions / solidity

Code contains empty blocks

/**
* @notice Returns the current profit limit ratio.
Expand Down Expand Up @@ -117,15 +109,6 @@ abstract contract BaseHealthCheck is BaseTokenizedStrategy {
doHealthCheck = _doHealthCheck;
}

/**
* @notice Check important invariants for the strategy.
* @dev This can be overriden to check any important strategy
* specific invariants.
*
* NOTE: Should revert if unhealthy for the modifier to work.
*/
function _checkHealth() internal virtual {}

/**
* @dev To be called during a report to make sure the profit
* or loss being recorded is within the acceptable bound.
Expand All @@ -138,7 +121,7 @@ abstract contract BaseHealthCheck is BaseTokenizedStrategy {
return;
}

// Get the curent total assets from the implementation.
// Get the current total assets from the implementation.
uint256 currentTotalAssets = TokenizedStrategy.totalAssets();

if (_newTotalAssets > currentTotalAssets) {
Expand Down
38 changes: 17 additions & 21 deletions src/ReportTrigger/CommonReportTrigger.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ pragma solidity 0.8.18;

import {Governance} from "../utils/Governance.sol";

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

interface ICustomStrategyTrigger {
function reportTrigger(
Expand Down Expand Up @@ -72,7 +72,7 @@ contract CommonReportTrigger is Governance {

string public name = "Yearn Common Report Trigger";

// Address to retreive the current base fee on the network from.
// Address to retrieve the current base fee on the network from.
address public baseFeeProvider;

// Default base fee the trigger will accept for a trigger to return `true`.
Expand All @@ -88,7 +88,7 @@ contract CommonReportTrigger is Governance {
// `acceptableBaseFee` will be used.
mapping(address => uint256) public customStrategyBaseFee;

// Mapping of a vault adddress and one of its strategies address to a
// Mapping of a vault address and one of its strategies address to a
// custom report trigger. If address(0) the default trigger will be used.
// vaultAddress => strategyAddress => customTriggerContract.
mapping(address => mapping(address => address)) public customVaultTrigger;
Expand Down Expand Up @@ -227,7 +227,7 @@ contract CommonReportTrigger is Governance {
* the default trigger flow.
*
* @param _strategy The address of the strategy to check the trigger for.
* @return . Bool repersenting if the strategy is ready to report.
* @return . Bool representing if the strategy is ready to report.
* @return . Bytes with either the calldata or reason why False.
*/
function strategyReportTrigger(
Expand All @@ -246,7 +246,7 @@ contract CommonReportTrigger is Governance {

/**
* @notice The default trigger logic for a strategy.
* @dev This is kept in a seperate function so it can still
* @dev This is kept in a separate function so it can still
* be used by custom triggers even if extra checks are needed
* first or after.
*
Expand All @@ -261,7 +261,7 @@ contract CommonReportTrigger is Governance {
* 4. The time since the last report be > the strategies `profitMaxUnlockTime`.
*
* @param _strategy The address of the strategy to check the trigger for.
* @return . Bool repersenting if the strategy is ready to report.
* @return . Bool representing if the strategy is ready to report.
* @return . Bytes with either the calldata or reason why False.
*/
function defaultStrategyReportTrigger(
Expand All @@ -273,7 +273,7 @@ contract CommonReportTrigger is Governance {
// Don't report if the strategy is shutdown.
if (strategy.isShutdown()) return (false, bytes("Shutdown"));

// Dont't report if the strategy has no assets.
// Don't report if the strategy has no assets.
if (strategy.totalAssets() == 0) return (false, bytes("Zero Assets"));

// Check if a `baseFeeProvider` is set.
Expand All @@ -285,7 +285,7 @@ contract CommonReportTrigger is Governance {
? customAcceptableBaseFee
: acceptableBaseFee;

// Dont report if the base fee is to high.
// Don't report if the base fee is to high.
if (
IBaseFee(_baseFeeProvider).basefee_global() > _acceptableBaseFee
) return (false, bytes("Base Fee"));
Expand Down Expand Up @@ -329,7 +329,7 @@ contract CommonReportTrigger is Governance {

/**
* @notice The default trigger logic for a vault.
* @dev This is kept in a seperate function so it can still
* @dev This is kept in a separate function so it can still
* be used by custom triggers even if extra checks are needed
* before or after.
*
Expand Down Expand Up @@ -361,8 +361,8 @@ contract CommonReportTrigger is Governance {
// Cache the strategy parameters.
IVault.StrategyParams memory params = vault.strategies(_strategy);

// Don't report if the strategy is not acitve or has no funds.
if (params.activation == 0 || params.currentDebt == 0)
// Don't report if the strategy is not active or has no funds.
if (params.activation == 0 || params.current_debt == 0)
return (false, bytes("Not Active"));

// Check if a `baseFeeProvider` is set.
Expand All @@ -376,15 +376,15 @@ contract CommonReportTrigger is Governance {
? customAcceptableBaseFee
: acceptableBaseFee;

// Dont report if the base fee is to high.
// Don't report if the base fee is to high.
if (
IBaseFee(_baseFeeProvider).basefee_global() > _acceptableBaseFee
) return (false, bytes("Base Fee"));
}

return (
// Return true is the full profit unlock time has passed since the last report.
block.timestamp - params.lastReport > vault.profitMaxUnlockTime(),
block.timestamp - params.last_report > vault.profitMaxUnlockTime(),
// Return the function selector and the strategy as the parameter to use.
abi.encodeCall(vault.process_report, _strategy)
);
Expand All @@ -405,12 +405,8 @@ contract CommonReportTrigger is Governance {
function strategyTendTrigger(
address _strategy
) external view returns (bool, bytes memory) {
return (
// Return the status of the tend trigger.
IStrategy(_strategy).tendTrigger(),
// And the needed calldata either way.
abi.encodeWithSelector(IStrategy.tend.selector)
);
// Return the status of the tend trigger.
return IStrategy(_strategy).tendTrigger();
}

/**
Expand All @@ -427,7 +423,7 @@ contract CommonReportTrigger is Governance {

/**
* @notice Returns wether or not the current base fee is acceptable
* baseed on the default `acceptableBaseFee`.
* based on the default `acceptableBaseFee`.
* @dev Can be used in custom triggers to easily still use this contracts
* fee provider and acceptableBaseFee. And makes it backwards compatible to V2.
*
Expand Down
Loading

0 comments on commit 56a1c6d

Please sign in to comment.