From 56a1c6d0cbbccfd7e74ce51b9f050af97cb9ffa7 Mon Sep 17 00:00:00 2001 From: Schlag <89420541+Schlagonia@users.noreply.github.com> Date: Thu, 12 Oct 2023 16:39:34 -0600 Subject: [PATCH] feat: 3.0.1 (#24) * 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 --- .gitmodules | 10 ++-- lib/tokenized-strategy | 2 +- lib/yearn-vaults-v3 | 2 +- script/Deploy.s.sol | 10 ++-- script/Deploy2.s.sol | 46 ------------------- src/AprOracle/AprOracle.sol | 25 ++++------ src/AprOracle/AprOracleBase.sol | 4 +- src/HealthCheck/BaseHealthCheck.sol | 25 ++-------- src/ReportTrigger/CommonReportTrigger.sol | 38 +++++++-------- .../CustomStrategyTriggerBase.sol | 4 +- src/ReportTrigger/CustomVaultTriggerBase.sol | 4 +- src/interfaces/IStrategy.sol | 22 --------- src/interfaces/IVault.sol | 37 --------------- src/swappers/SolidlySwapper.sol | 10 ++-- src/swappers/UniswapV2Swapper.sol | 8 ++-- src/swappers/UniswapV3Swapper.sol | 16 +++---- src/test/CommonTrigger.t.sol | 20 +++++--- src/test/HealthCheck.sol | 8 ++-- src/test/SolidlySwapper.t.sol | 2 +- src/test/UniV2Swapper.t.sol | 2 +- src/test/UniV3Swapper.t.sol | 2 +- src/test/mocks/MockHealthCheck.sol | 13 ++---- src/test/mocks/MockSolidlySwapper.sol | 10 ++-- src/test/mocks/MockStrategy.sol | 14 ++---- src/test/mocks/MockUniswapV2Swapper.sol | 10 ++-- src/test/mocks/MockUniswapV3Swapper.sol | 10 ++-- src/test/utils/Setup.sol | 42 ++++++++--------- src/utils/Governance.sol | 2 +- 28 files changed, 128 insertions(+), 270 deletions(-) delete mode 100644 script/Deploy2.s.sol delete mode 100644 src/interfaces/IStrategy.sol delete mode 100644 src/interfaces/IVault.sol diff --git a/.gitmodules b/.gitmodules index 930bbb0..40e17ab 100644 --- a/.gitmodules +++ b/.gitmodules @@ -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 \ No newline at end of file diff --git a/lib/tokenized-strategy b/lib/tokenized-strategy index 0bd2a0a..718194e 160000 --- a/lib/tokenized-strategy +++ b/lib/tokenized-strategy @@ -1 +1 @@ -Subproject commit 0bd2a0a81805719bf0c1d4f3574d1b2753f8b0e7 +Subproject commit 718194eeb58768aa168969c882dfef80252c477c diff --git a/lib/yearn-vaults-v3 b/lib/yearn-vaults-v3 index 1e6bc67..45b5d6b 160000 --- a/lib/yearn-vaults-v3 +++ b/lib/yearn-vaults-v3 @@ -1 +1 @@ -Subproject commit 1e6bc67cf70352e9567e67404d73856cc343b634 +Subproject commit 45b5d6b48da5b875dc9b7997275f8708d9e41656 diff --git a/script/Deploy.s.sol b/script/Deploy.s.sol index 9addc7c..952aef5 100644 --- a/script/Deploy.s.sol +++ b/script/Deploy.s.sol @@ -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) diff --git a/script/Deploy2.s.sol b/script/Deploy2.s.sol deleted file mode 100644 index 1d1394d..0000000 --- a/script/Deploy2.s.sol +++ /dev/null @@ -1,46 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0 -pragma solidity 0.8.18; - -import "forge-std/Script.sol"; - -// Deploy a contract to a deterministic address with create2 -contract Deploy2 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 = 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) external returns (address) { - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), salt) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - emit Deployed(addr, salt); - return addr; - } -} \ No newline at end of file diff --git a/src/AprOracle/AprOracle.sol b/src/AprOracle/AprOracle.sol index 047d094..ba5e929 100644 --- a/src/AprOracle/AprOracle.sol +++ b/src/AprOracle/AprOracle.sol @@ -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( @@ -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. * @@ -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; @@ -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, @@ -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`. diff --git a/src/AprOracle/AprOracleBase.sol b/src/AprOracle/AprOracleBase.sol index 5c5bb0a..b9b0472 100644 --- a/src/AprOracle/AprOracleBase.sol +++ b/src/AprOracle/AprOracleBase.sol @@ -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. diff --git a/src/HealthCheck/BaseHealthCheck.sol b/src/HealthCheck/BaseHealthCheck.sol index 0bf1895..e55e93e 100644 --- a/src/HealthCheck/BaseHealthCheck.sol +++ b/src/HealthCheck/BaseHealthCheck.sol @@ -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 @@ -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; @@ -46,7 +38,7 @@ abstract contract BaseHealthCheck is BaseTokenizedStrategy { constructor( address _asset, string memory _name - ) BaseTokenizedStrategy(_asset, _name) {} + ) BaseStrategy(_asset, _name) {} /** * @notice Returns the current profit limit ratio. @@ -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. @@ -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) { diff --git a/src/ReportTrigger/CommonReportTrigger.sol b/src/ReportTrigger/CommonReportTrigger.sol index c672e02..7619534 100644 --- a/src/ReportTrigger/CommonReportTrigger.sol +++ b/src/ReportTrigger/CommonReportTrigger.sol @@ -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( @@ -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`. @@ -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; @@ -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( @@ -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. * @@ -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( @@ -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. @@ -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")); @@ -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. * @@ -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. @@ -376,7 +376,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")); @@ -384,7 +384,7 @@ contract CommonReportTrigger is Governance { 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) ); @@ -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(); } /** @@ -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. * diff --git a/src/ReportTrigger/CustomStrategyTriggerBase.sol b/src/ReportTrigger/CustomStrategyTriggerBase.sol index 6172dbd..1f58a29 100644 --- a/src/ReportTrigger/CustomStrategyTriggerBase.sol +++ b/src/ReportTrigger/CustomStrategyTriggerBase.sol @@ -9,13 +9,13 @@ abstract contract CustomStrategyTriggerBase { /** * @notice Returns if a strategy should report any accrued profits/losses. * @dev This can be used to implement a custom trigger if the default - * flow is not desired by a strategies managent. + * flow is not desired by a strategies management. * * Should complete any needed checks and then return `true` if the strategy * should report and `false` if not. * * @param _strategy The address of the strategy to check. - * @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 reportTrigger( diff --git a/src/ReportTrigger/CustomVaultTriggerBase.sol b/src/ReportTrigger/CustomVaultTriggerBase.sol index 8d52ac3..bdcfb77 100644 --- a/src/ReportTrigger/CustomVaultTriggerBase.sol +++ b/src/ReportTrigger/CustomVaultTriggerBase.sol @@ -10,14 +10,14 @@ abstract contract CustomVaultTriggerBase { * @notice Returns if a strategy should report any accrued profits/losses * to a vault. * @dev This can be used to implement a custom trigger if the default - * flow is not desired by a vaults managent. + * flow is not desired by a vaults management. * * Should complete any needed checks and then return `true` if the strategy * should report and `false` if not. * * @param _vault The address of the vault. * @param _strategy The address of the strategy that would report. - * @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 reportTrigger( diff --git a/src/interfaces/IStrategy.sol b/src/interfaces/IStrategy.sol deleted file mode 100644 index 472e84a..0000000 --- a/src/interfaces/IStrategy.sol +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity 0.8.18; - -interface IStrategy { - function asset() external view returns (address); - - function management() external view returns (address); - - function totalAssets() external view returns (uint256); - - function lastReport() external view returns (uint256); - - function profitMaxUnlockTime() external view returns (uint256); - - function isShutdown() external view returns (bool); - - function report() external returns (uint256, uint256); - - function tend() external; - - function tendTrigger() external view returns (bool); -} diff --git a/src/interfaces/IVault.sol b/src/interfaces/IVault.sol deleted file mode 100644 index 512c52c..0000000 --- a/src/interfaces/IVault.sol +++ /dev/null @@ -1,37 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity 0.8.18; - -interface IVault { - struct StrategyParams { - uint256 activation; - uint256 lastReport; - uint256 currentDebt; - uint256 maxDebt; - } - - function strategies( - address _strategy - ) external view returns (StrategyParams memory); - - function set_role(address, uint256) external; - - function roles(address _address) external view returns (uint256); - - function profitMaxUnlockTime() external view returns (uint256); - - function add_strategy(address) external; - - function update_max_debt_for_strategy(address, uint256) external; - - function update_debt(address, uint256) external; - - function process_report( - address _strategy - ) external returns (uint256, uint256); - - function set_deposit_limit(uint256) external; - - function shutdown_vault() external; - - function shutdown() external view returns (bool); -} diff --git a/src/swappers/SolidlySwapper.sol b/src/swappers/SolidlySwapper.sol index f2cd040..adeeaa9 100644 --- a/src/swappers/SolidlySwapper.sol +++ b/src/swappers/SolidlySwapper.sol @@ -12,7 +12,7 @@ import {ISolidly} from "../interfaces/Solidly/ISolidly.sol"; * strategy that would like to use a Solidly fork for swaps. It holds all needed * logic to perform exact input swaps. * - * The global addres variables defualt to the ETH mainnet addresses but + * The global address variables default to the ETH mainnet addresses but * remain settable by the inheriting contract to allow for customization * based on needs or chain its used on. * @@ -22,7 +22,7 @@ import {ISolidly} from "../interfaces/Solidly/ISolidly.sol"; contract SolidlySwapper { // Optional Variable to be set to not sell dust. uint256 public minAmountToSell; - // Defualts to WETH on mainnet. + // Defaults to WETH on mainnet. address public base = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; // Will need to set the router to use. @@ -34,10 +34,10 @@ contract SolidlySwapper { mapping(address => mapping(address => bool)) public stable; /** - * @dev Internal funciton to set the `stable` mapping for any + * @dev Internal function to set the `stable` mapping for any * pair of tokens if a the route should go through a stable pool. * This function is to help set the mapping. It can be called - * internally during intialization, through permisioned functions etc. + * internally during initialization, through permissioned functions etc. */ function _setStable( address _token0, @@ -50,7 +50,7 @@ contract SolidlySwapper { /** * @dev Used to swap a specific amount of `_from` to `_to`. - * This will check and handle all allownaces as well as not swapping + * This will check and handle all allowances as well as not swapping * unless `_amountIn` is greater than the set `_minAmountToSell` * * If one of the tokens matches with the `base` token it will do only diff --git a/src/swappers/UniswapV2Swapper.sol b/src/swappers/UniswapV2Swapper.sol index 50741b6..b1e9520 100644 --- a/src/swappers/UniswapV2Swapper.sol +++ b/src/swappers/UniswapV2Swapper.sol @@ -12,22 +12,22 @@ import {IUniswapV2Router02} from "../interfaces/Uniswap/V2/IUniswapV2Router02.so * strategy that would like to use Uniswap V2 for swaps. It holds all needed * logic to perform exact input swaps. * - * The global addres variables defualt to the ETH mainnet addresses but + * The global address variables default to the ETH mainnet addresses but * remain settable by the inheriting contract to allow for customization * based on needs or chain its used on. */ contract UniswapV2Swapper { // Optional Variable to be set to not sell dust. uint256 public minAmountToSell; - // Defualts to WETH on mainnet. + // Defaults to WETH on mainnet. address public base = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; - // Defualts to Uniswap V2 router on mainnet. + // Defaults to Uniswap V2 router on mainnet. address public router = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D; /** * @dev Used to swap a specific amount of `_from` to `_to`. - * This will check and handle all allownaces as well as not swapping + * This will check and handle all allowances as well as not swapping * unless `_amountIn` is greater than the set `_minAmountToSell` * * If one of the tokens matches with the `base` token it will do only diff --git a/src/swappers/UniswapV3Swapper.sol b/src/swappers/UniswapV3Swapper.sol index 17cbf9c..b094e10 100644 --- a/src/swappers/UniswapV3Swapper.sol +++ b/src/swappers/UniswapV3Swapper.sol @@ -12,7 +12,7 @@ import {ISwapRouter} from "../interfaces/Uniswap/V3/ISwapRouter.sol"; * strategy that would like to use Uniswap V3 for swaps. It hold all needed * logic to perform both exact input and exact output swaps. * - * The global addres variables defualt to the ETH mainnet addresses but + * The global address variables default to the ETH mainnet addresses but * remain settable by the inheriting contract to allow for customization * based on needs or chain its used on. * @@ -23,10 +23,10 @@ import {ISwapRouter} from "../interfaces/Uniswap/V3/ISwapRouter.sol"; contract UniswapV3Swapper { // Optional Variable to be set to not sell dust. uint256 public minAmountToSell; - // Defualts to WETH on mainnet. + // Defaults to WETH on mainnet. address public base = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; - // Defualts to Uniswap V3 router on mainnet. + // Defaults to Uniswap V3 router on mainnet. address public router = 0xE592427A0AEce92De3Edee1F18E0157C05861564; // Fees for the Uni V3 pools. Each fee should get set each way in @@ -35,10 +35,10 @@ contract UniswapV3Swapper { mapping(address => mapping(address => uint24)) public uniFees; /** - * @dev All fess will defualt to 0 on creation. A strategist will need + * @dev All fess will default to 0 on creation. A strategist will need * To set the mapping for the tokens expected to swap. This function * is to help set the mapping. It can be called internally during - * intialization, through permisioned functions etc. + * initialization, through permissioned functions etc. */ function _setUniFees( address _token0, @@ -51,7 +51,7 @@ contract UniswapV3Swapper { /** * @dev Used to swap a specific amount of `_from` to `_to`. - * This will check and handle all allownaces as well as not swapping + * This will check and handle all allowances as well as not swapping * unless `_amountIn` is greater than the set `_minAmountOut` * * If one of the tokens matches with the `base` token it will do only @@ -114,7 +114,7 @@ contract UniswapV3Swapper { * @dev Used to swap a specific amount of `_to` from `_from` unless * it takes more than `_maxAmountFrom`. * - * This will check and handle all allownaces as well as not swapping + * This will check and handle all allowances as well as not swapping * unless `_maxAmountFrom` is greater than the set `minAmountToSell` * * If one of the tokens matches with the `base` token it will do only @@ -127,7 +127,7 @@ contract UniswapV3Swapper { * @param _to The token we are swapping to. * @param _amountTo The amount of `_to` we need out. * @param _maxAmountFrom The max of `_from` we will swap. - * @return _amountIn The actual amouont of `_from` swapped. + * @return _amountIn The actual amount of `_from` swapped. */ function _swapTo( address _from, diff --git a/src/test/CommonTrigger.t.sol b/src/test/CommonTrigger.t.sol index 289f558..a9071b5 100644 --- a/src/test/CommonTrigger.t.sol +++ b/src/test/CommonTrigger.t.sol @@ -8,10 +8,6 @@ import {CommonReportTrigger, IBaseFee} from "../ReportTrigger/CommonReportTrigge import {MockCustomStrategyTrigger} from "./mocks/MockCustomStrategyTrigger.sol"; import {MockCustomVaultTrigger} from "./mocks/MockCustomVaultTrigger.sol"; -interface IStrategys { - function report() external returns (uint256, uint256); -} - contract CommonTriggerTest is Setup { CommonReportTrigger public commonTrigger; MockCustomStrategyTrigger public customStrategyTrigger; @@ -28,6 +24,9 @@ contract CommonTriggerTest is Setup { } function test_setup() public { + // Deploy a vault. + vault = setUpVault(); + assertEq(commonTrigger.governance(), address(daddy)); assertEq(commonTrigger.baseFeeProvider(), address(0)); assertEq(commonTrigger.acceptableBaseFee(), 0); @@ -144,6 +143,9 @@ contract CommonTriggerTest is Setup { function test_setCustomVaultTrigger(address _address) public { vm.assume(_address != vaultManagement); + // Deploy a vault. + vault = setUpVault(); + assertEq( commonTrigger.customVaultTrigger( address(vault), @@ -215,6 +217,9 @@ contract CommonTriggerTest is Setup { vm.assume(_address != vaultManagement); vm.assume(_baseFee != 0); + // Deploy a vault. + vault = setUpVault(); + assertEq( commonTrigger.customVaultBaseFee( address(vault), @@ -255,7 +260,7 @@ contract CommonTriggerTest is Setup { ); } - function test_defualtStrategyTrigger(uint256 _amount) public { + function test_defaultStrategyTrigger(uint256 _amount) public { vm.assume(_amount >= minFuzzAmount && _amount <= maxFuzzAmount); bytes memory _calldata = abi.encodeWithSelector( @@ -349,9 +354,12 @@ contract CommonTriggerTest is Setup { assertEq(data, bytes("Shutdown")); } - function test_defualtVaultTrigger(uint256 _amount) public { + function test_defaultVaultTrigger(uint256 _amount) public { vm.assume(_amount >= minFuzzAmount && _amount <= maxFuzzAmount); + // Deploy a vault. + vault = setUpVault(); + bytes memory _calldata = abi.encodeWithSelector( vault.process_report.selector, address(mockStrategy) diff --git a/src/test/HealthCheck.sol b/src/test/HealthCheck.sol index 78c0884..78b1c9e 100644 --- a/src/test/HealthCheck.sol +++ b/src/test/HealthCheck.sol @@ -18,7 +18,7 @@ contract HealthCheckTest is Setup { healthCheck.setKeeper(keeper); healthCheck.setPerformanceFeeRecipient(performanceFeeRecipient); healthCheck.setPendingManagement(management); - // Accept mangagement. + // Accept management. vm.prank(management); healthCheck.acceptManagement(); } @@ -162,7 +162,7 @@ contract HealthCheckTest is Setup { assertEq(healthCheck.lossLimitRatio(), 0, "lossLimitRatio should be 0"); } - function test_reportTurnsHealtCheckBackOn(uint256 _amount) public { + function test_reportTurnsHealthCheckBackOn(uint256 _amount) public { vm.assume(_amount >= minFuzzAmount && _amount <= maxFuzzAmount); // deposit @@ -220,7 +220,7 @@ contract HealthCheckTest is Setup { // Make sure we reported the correct profit assertEq(profit, realProfit, "Reported profit mismatch"); - // Healtch Check should still be on + // Health Check should still be on assertEq( healthCheck.doHealthCheck(), true, @@ -465,7 +465,7 @@ contract HealthCheckTest is Setup { // Make sure we reported the correct profit assertEq(0, realProfit, "Reported profit mismatch"); - // Healtch Check should still be on + // Health Check should still be on assertEq( healthCheck.doHealthCheck(), true, diff --git a/src/test/SolidlySwapper.t.sol b/src/test/SolidlySwapper.t.sol index 06a85c5..58bbdea 100644 --- a/src/test/SolidlySwapper.t.sol +++ b/src/test/SolidlySwapper.t.sol @@ -38,7 +38,7 @@ contract SolidlySwapperTest is Setup { solidlySwapper.setBase(0x40379a439D4F6795B6fc9aa5687dB461677A2dBa); solidlySwapper.setRouter(0x06374F57991CDc836E5A318569A910FE6456D230); - // Accept mangagement. + // Accept management. vm.prank(management); solidlySwapper.acceptManagement(); } diff --git a/src/test/UniV2Swapper.t.sol b/src/test/UniV2Swapper.t.sol index 3847591..bc3d5fd 100644 --- a/src/test/UniV2Swapper.t.sol +++ b/src/test/UniV2Swapper.t.sol @@ -27,7 +27,7 @@ contract UniswapV2SwapperTest is Setup { uniV2Swapper.setPerformanceFeeRecipient(performanceFeeRecipient); uniV2Swapper.setPendingManagement(management); - // Accept mangagement. + // Accept management. vm.prank(management); uniV2Swapper.acceptManagement(); } diff --git a/src/test/UniV3Swapper.t.sol b/src/test/UniV3Swapper.t.sol index 30876fd..36246c5 100644 --- a/src/test/UniV3Swapper.t.sol +++ b/src/test/UniV3Swapper.t.sol @@ -25,7 +25,7 @@ contract UniswapV3SwapperTest is Setup { uniV3Swapper.setKeeper(keeper); uniV3Swapper.setPerformanceFeeRecipient(performanceFeeRecipient); uniV3Swapper.setPendingManagement(management); - // Accept mangagement. + // Accept management. vm.prank(management); uniV3Swapper.acceptManagement(); } diff --git a/src/test/mocks/MockHealthCheck.sol b/src/test/mocks/MockHealthCheck.sol index 93cedf8..a37faa0 100644 --- a/src/test/mocks/MockHealthCheck.sol +++ b/src/test/mocks/MockHealthCheck.sol @@ -1,9 +1,7 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.18; -import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; - -import {BaseHealthCheck} from "../../HealthCheck/BaseHealthCheck.sol"; +import {BaseHealthCheck, ERC20} from "../../HealthCheck/BaseHealthCheck.sol"; contract MockHealthCheck is BaseHealthCheck { bool public healthy = true; @@ -22,10 +20,11 @@ contract MockHealthCheck is BaseHealthCheck { function _harvestAndReport() internal override - checkHealth returns (uint256 _totalAssets) { - _totalAssets = ERC20(asset).balanceOf(address(this)); + require(_healthy(), "unhealthy"); + + _totalAssets = asset.balanceOf(address(this)); _executeHealthCheck(_totalAssets); } @@ -48,10 +47,6 @@ contract MockHealthCheck is BaseHealthCheck { return super.availableWithdrawLimit(_owner); } - function _checkHealth() internal view override { - require(_healthy(), "unhealthy"); - } - function _healthy() internal view returns (bool) { return healthy; } diff --git a/src/test/mocks/MockSolidlySwapper.sol b/src/test/mocks/MockSolidlySwapper.sol index 6d2f6c3..b4ece85 100644 --- a/src/test/mocks/MockSolidlySwapper.sol +++ b/src/test/mocks/MockSolidlySwapper.sol @@ -1,13 +1,11 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.18; -import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; - import {SolidlySwapper} from "../../swappers/SolidlySwapper.sol"; -import {BaseTokenizedStrategy} from "@tokenized-strategy/BaseTokenizedStrategy.sol"; +import {BaseStrategy, ERC20} from "@tokenized-strategy/BaseStrategy.sol"; -contract MockSolidlySwapper is BaseTokenizedStrategy, SolidlySwapper { - constructor(address _asset) BaseTokenizedStrategy(_asset, "Mock Uni V3") {} +contract MockSolidlySwapper is BaseStrategy, SolidlySwapper { + constructor(address _asset) BaseStrategy(_asset, "Mock Uni V3") {} function _deployFunds(uint256) internal override {} @@ -18,7 +16,7 @@ contract MockSolidlySwapper is BaseTokenizedStrategy, SolidlySwapper { override returns (uint256 _totalAssets) { - _totalAssets = ERC20(asset).balanceOf(address(this)); + _totalAssets = asset.balanceOf(address(this)); } function setMinAmountToSell(uint256 _minAmountToSell) external { diff --git a/src/test/mocks/MockStrategy.sol b/src/test/mocks/MockStrategy.sol index c67d116..a1beb56 100644 --- a/src/test/mocks/MockStrategy.sol +++ b/src/test/mocks/MockStrategy.sol @@ -1,16 +1,12 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.18; -import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import {BaseStrategy, ERC20} from "@tokenized-strategy/BaseStrategy.sol"; -import {BaseTokenizedStrategy} from "@tokenized-strategy/BaseTokenizedStrategy.sol"; - -contract MockStrategy is BaseTokenizedStrategy { +contract MockStrategy is BaseStrategy { bool public tendStatus; - constructor( - address _asset - ) BaseTokenizedStrategy(_asset, "Mock Basic Strategy") {} + constructor(address _asset) BaseStrategy(_asset, "Mock Basic Strategy") {} function _deployFunds(uint256) internal override {} @@ -21,10 +17,10 @@ contract MockStrategy is BaseTokenizedStrategy { override returns (uint256 _totalAssets) { - _totalAssets = ERC20(asset).balanceOf(address(this)); + _totalAssets = asset.balanceOf(address(this)); } - function tendTrigger() external view override returns (bool) { + function _tendTrigger() internal view override returns (bool) { return tendStatus; } diff --git a/src/test/mocks/MockUniswapV2Swapper.sol b/src/test/mocks/MockUniswapV2Swapper.sol index fccbea7..776c1cd 100644 --- a/src/test/mocks/MockUniswapV2Swapper.sol +++ b/src/test/mocks/MockUniswapV2Swapper.sol @@ -1,13 +1,11 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.18; -import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; - import {UniswapV2Swapper} from "../../swappers/UniswapV2Swapper.sol"; -import {BaseTokenizedStrategy} from "@tokenized-strategy/BaseTokenizedStrategy.sol"; +import {BaseStrategy, ERC20} from "@tokenized-strategy/BaseStrategy.sol"; -contract MockUniswapV2Swapper is BaseTokenizedStrategy, UniswapV2Swapper { - constructor(address _asset) BaseTokenizedStrategy(_asset, "Mock Uni V3") {} +contract MockUniswapV2Swapper is BaseStrategy, UniswapV2Swapper { + constructor(address _asset) BaseStrategy(_asset, "Mock Uni V3") {} function _deployFunds(uint256) internal override {} @@ -18,7 +16,7 @@ contract MockUniswapV2Swapper is BaseTokenizedStrategy, UniswapV2Swapper { override returns (uint256 _totalAssets) { - _totalAssets = ERC20(asset).balanceOf(address(this)); + _totalAssets = asset.balanceOf(address(this)); } function setMinAmountToSell(uint256 _minAmountToSell) external { diff --git a/src/test/mocks/MockUniswapV3Swapper.sol b/src/test/mocks/MockUniswapV3Swapper.sol index e5ae90a..ee4f792 100644 --- a/src/test/mocks/MockUniswapV3Swapper.sol +++ b/src/test/mocks/MockUniswapV3Swapper.sol @@ -1,13 +1,11 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.18; -import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; - import {UniswapV3Swapper} from "../../swappers/UniswapV3Swapper.sol"; -import {BaseTokenizedStrategy} from "@tokenized-strategy/BaseTokenizedStrategy.sol"; +import {BaseStrategy, ERC20} from "@tokenized-strategy/BaseStrategy.sol"; -contract MockUniswapV3Swapper is BaseTokenizedStrategy, UniswapV3Swapper { - constructor(address _asset) BaseTokenizedStrategy(_asset, "Mock Uni V3") {} +contract MockUniswapV3Swapper is BaseStrategy, UniswapV3Swapper { + constructor(address _asset) BaseStrategy(_asset, "Mock Uni V3") {} function _deployFunds(uint256) internal override {} @@ -18,7 +16,7 @@ contract MockUniswapV3Swapper is BaseTokenizedStrategy, UniswapV3Swapper { override returns (uint256 _totalAssets) { - _totalAssets = ERC20(asset).balanceOf(address(this)); + _totalAssets = asset.balanceOf(address(this)); } function setMinAmountToSell(uint256 _minAmountToSell) external { diff --git a/src/test/utils/Setup.sol b/src/test/utils/Setup.sol index e5d4afe..5c0708c 100644 --- a/src/test/utils/Setup.sol +++ b/src/test/utils/Setup.sol @@ -8,26 +8,24 @@ import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import {VyperDeployer} from "./VyperDeployer.sol"; import {IStrategy} from "@tokenized-strategy/interfaces/IStrategy.sol"; -import {IVault} from "../../interfaces/IVault.sol"; +import {IVault} from "@yearn-vaults/interfaces/IVault.sol"; +import {VaultConstants, Roles} from "@yearn-vaults/interfaces/VaultConstants.sol"; +import {IVaultFactory} from "@yearn-vaults/interfaces/IVaultFactory.sol"; import {MockStrategy} from "../mocks/MockStrategy.sol"; - -interface IFactory { - function governance() external view returns (address); - - function set_protocol_fee_bps(uint16) external; - - function set_protocol_fee_recipient(address) external; -} +import {Governance} from "../../utils/Governance.sol"; contract Setup is ExtendedTest { VyperDeployer public vyperDeployer = new VyperDeployer(); - // Contract instancees that we will use repeatedly. + + // Contract instances that we will use repeatedly. ERC20 public asset; IStrategy public mockStrategy; - IVault public vault; - mapping(string => address) public tokenAddrs; + // Vault contracts to test with. + IVault public vault; + IVaultFactory public vaultFactory; + VaultConstants public vaultConstants = new VaultConstants(); // Addresses for different roles we will use repeatedly. address public user = address(10); @@ -37,8 +35,7 @@ contract Setup is ExtendedTest { address public vaultManagement = address(2); address public performanceFeeRecipient = address(3); - // Address of the real deployed Factory - address public factory = 0x85E2861b3b1a70c90D28DfEc30CE6E07550d83e9; + mapping(string => address) public tokenAddrs; // Integer variables that will be used repeatedly. uint256 public decimals; @@ -48,7 +45,7 @@ contract Setup is ExtendedTest { uint256 public maxFuzzAmount = 1e24; uint256 public minFuzzAmount = 100_000; - // Default prfot max unlock time is set for 10 days + // Default profit max unlock time is set for 10 days uint256 public profitMaxUnlockTime = 10 days; function setUp() public virtual { @@ -62,17 +59,16 @@ contract Setup is ExtendedTest { mockStrategy = setUpStrategy(); - vault = setUpVault(); + vaultFactory = IVaultFactory(mockStrategy.FACTORY()); // label all the used addresses for traces vm.label(daddy, "daddy"); vm.label(keeper, "keeper"); - vm.label(factory, "factory"); - vm.label(address(vault), "vault"); vm.label(address(asset), "asset"); vm.label(management, "management"); vm.label(address(mockStrategy), "strategy"); vm.label(vaultManagement, "vault management"); + vm.label(address(vaultFactory), " vault factory"); vm.label(performanceFeeRecipient, "performanceFeeRecipient"); } @@ -95,7 +91,7 @@ contract Setup is ExtendedTest { vm.prank(management); // Give the vault manager all the roles - _vault.set_role(vaultManagement, 8191); + _vault.set_role(vaultManagement, 16383); vm.prank(vaultManagement); _vault.set_deposit_limit(type(uint256).max); @@ -115,7 +111,7 @@ contract Setup is ExtendedTest { _strategy.setPerformanceFeeRecipient(performanceFeeRecipient); // set management of the strategy _strategy.setPendingManagement(management); - // Accept mangagement. + // Accept management. vm.prank(management); _strategy.acceptManagement(); @@ -193,14 +189,14 @@ contract Setup is ExtendedTest { } function setFees(uint16 _protocolFee, uint16 _performanceFee) public { - address gov = IFactory(factory).governance(); + address gov = Governance(address(vaultFactory)).governance(); // Need to make sure there is a protocol fee recipient to set the fee. vm.prank(gov); - IFactory(factory).set_protocol_fee_recipient(gov); + vaultFactory.set_protocol_fee_recipient(gov); vm.prank(gov); - IFactory(factory).set_protocol_fee_bps(_protocolFee); + vaultFactory.set_protocol_fee_bps(_protocolFee); vm.prank(management); mockStrategy.setPerformanceFee(_performanceFee); diff --git a/src/utils/Governance.sol b/src/utils/Governance.sol index a65e3ba..7c216b4 100644 --- a/src/utils/Governance.sol +++ b/src/utils/Governance.sol @@ -16,7 +16,7 @@ contract Governance { require(governance == msg.sender, "!governance"); } - // Address that can set the defualt base fee and provider + // Address that can set the default base fee and provider address public governance; constructor(address _governance) {