Skip to content

Commit

Permalink
build: update to 303 (#40)
Browse files Browse the repository at this point in the history
* build: add factory

* chore: install new version

* chore: update periphery

* fix: factory
  • Loading branch information
Schlagonia authored Sep 24, 2024
1 parent d185c78 commit f8afbce
Show file tree
Hide file tree
Showing 7 changed files with 141 additions and 17 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.9.5
[submodule "lib/tokenized-strategy-periphery"]
path = lib/tokenized-strategy-periphery
url = https://github.com/yearn/tokenized-strategy-periphery
branch = master
[submodule "lib/tokenized-strategy"]
path = lib/tokenized-strategy
url = https://github.com/yearn/tokenized-strategy
branch = v3.0.2-1
branch = v3.0.3
[submodule "lib/tokenized-strategy-periphery"]
path = lib/tokenized-strategy-periphery
url = https://github.com/yearn/tokenized-strategy-periphery
branch = master
80 changes: 80 additions & 0 deletions src/StrategyFactory.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.18;

import {Strategy, ERC20} from "./Strategy.sol";

Check warning on line 4 in src/StrategyFactory.sol

View workflow job for this annotation

GitHub Actions / solidity

imported name ERC20 is not used
import {IStrategyInterface} from "./interfaces/IStrategyInterface.sol";

contract StrategyFactory {
event NewStrategy(address indexed strategy, address indexed asset);

address public immutable emergencyAdmin;

Check warning on line 10 in src/StrategyFactory.sol

View workflow job for this annotation

GitHub Actions / solidity

Immutable variables name are set to be in capitalized SNAKE_CASE

address public immutable lendingPool;

Check warning on line 12 in src/StrategyFactory.sol

View workflow job for this annotation

GitHub Actions / solidity

Immutable variables name are set to be in capitalized SNAKE_CASE
address public immutable router;

Check warning on line 13 in src/StrategyFactory.sol

View workflow job for this annotation

GitHub Actions / solidity

Immutable variables name are set to be in capitalized SNAKE_CASE
address public immutable base;

Check warning on line 14 in src/StrategyFactory.sol

View workflow job for this annotation

GitHub Actions / solidity

Immutable variables name are set to be in capitalized SNAKE_CASE

address public management;
address public performanceFeeRecipient;
address public keeper;

/// @notice Track the deployments. asset => pool => strategy
mapping(address => address) public deployments;

constructor(
address _management,
address _performanceFeeRecipient,
address _keeper,
address _emergencyAdmin
) {
management = _management;
performanceFeeRecipient = _performanceFeeRecipient;
keeper = _keeper;
emergencyAdmin = _emergencyAdmin;
}

/**
* @notice Deploy a new Strategy.
* @param _asset The underlying asset for the strategy to use.
* @return . The address of the new strategy.
*/
function newStrategy(
address _asset,
string calldata _name
) external virtual returns (address) {
// tokenized strategies available setters.
IStrategyInterface _newStrategy = IStrategyInterface(
address(new Strategy(_asset, _name))
);

_newStrategy.setPerformanceFeeRecipient(performanceFeeRecipient);

_newStrategy.setKeeper(keeper);

_newStrategy.setPendingManagement(management);

_newStrategy.setEmergencyAdmin(emergencyAdmin);

emit NewStrategy(address(_newStrategy), _asset);

deployments[_asset] = address(_newStrategy);
return address(_newStrategy);
}

function setAddresses(
address _management,
address _performanceFeeRecipient,
address _keeper
) external {
require(msg.sender == management, "!management");
management = _management;
performanceFeeRecipient = _performanceFeeRecipient;
keeper = _keeper;
}

function isDeployedStrategy(
address _strategy
) external view returns (bool) {
address _asset = IStrategyInterface(_strategy).asset();
return deployments[_asset] == _strategy;
}
}
2 changes: 1 addition & 1 deletion src/test/FunctionSignature.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ contract FunctionSignatureTest is Setup {
assertEq(strategy.totalSupply(), 0, "total supply");
assertEq(strategy.unlockedShares(), 0, "unlocked shares");
assertEq(strategy.asset(), address(asset), "asset");
assertEq(strategy.apiVersion(), "3.0.2", "api");
assertEq(strategy.apiVersion(), "3.0.3", "api");
assertEq(strategy.MAX_FEE(), 5_000, "max fee");
assertEq(strategy.fullProfitUnlockDate(), 0, "unlock date");
assertEq(strategy.profitUnlockingRate(), 0, "unlock rate");
Expand Down
37 changes: 36 additions & 1 deletion src/test/Shutdown.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ contract ShutdownTest is Setup {
skip(1 days);

// Shutdown the strategy
vm.prank(management);
vm.prank(emergencyAdmin);
strategy.shutdownStrategy();

assertEq(strategy.totalAssets(), _amount, "!totalAssets");
Expand All @@ -39,5 +39,40 @@ contract ShutdownTest is Setup {
);
}

function test_emergencyWithdraw_maxUint(uint256 _amount) public {
vm.assume(_amount > minFuzzAmount && _amount < maxFuzzAmount);

// Deposit into strategy
mintAndDepositIntoStrategy(strategy, user, _amount);

assertEq(strategy.totalAssets(), _amount, "!totalAssets");

// Earn Interest
skip(1 days);

// Shutdown the strategy
vm.prank(emergencyAdmin);
strategy.shutdownStrategy();

assertEq(strategy.totalAssets(), _amount, "!totalAssets");

// should be able to pass uint 256 max and not revert.
vm.prank(emergencyAdmin);
strategy.emergencyWithdraw(type(uint256).max);

// Make sure we can still withdraw the full amount
uint256 balanceBefore = asset.balanceOf(user);

// Withdraw all funds
vm.prank(user);
strategy.redeem(_amount, user, user);

assertGe(
asset.balanceOf(user),
balanceBefore + _amount,
"!final balance"
);
}

// TODO: Add tests for any emergency function added.
}
25 changes: 17 additions & 8 deletions src/test/utils/Setup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import "forge-std/console2.sol";
import {ExtendedTest} from "./ExtendedTest.sol";

import {Strategy, ERC20} from "../../Strategy.sol";
import {StrategyFactory} from "../../StrategyFactory.sol";
import {IStrategyInterface} from "../../interfaces/IStrategyInterface.sol";

// Inherit the events so they can be checked if desired.
Expand All @@ -23,13 +24,16 @@ contract Setup is ExtendedTest, IEvents {
ERC20 public asset;
IStrategyInterface public strategy;

StrategyFactory public strategyFactory;

mapping(string => address) public tokenAddrs;

// Addresses for different roles we will use repeatedly.
address public user = address(10);
address public keeper = address(4);
address public management = address(1);
address public performanceFeeRecipient = address(3);
address public emergencyAdmin = address(5);

// Address of the real deployed Factory
address public factory;
Expand All @@ -54,6 +58,13 @@ contract Setup is ExtendedTest, IEvents {
// Set decimals
decimals = asset.decimals();

strategyFactory = new StrategyFactory(
management,
performanceFeeRecipient,
keeper,
emergencyAdmin
);

// Deploy strategy and set variables
strategy = IStrategyInterface(setUpStrategy());

Expand All @@ -71,16 +82,14 @@ contract Setup is ExtendedTest, IEvents {
function setUpStrategy() public returns (address) {
// we save the strategy as a IStrategyInterface to give it the needed interface
IStrategyInterface _strategy = IStrategyInterface(
address(new Strategy(address(asset), "Tokenized Strategy"))
address(
strategyFactory.newStrategy(
address(asset),
"Tokenized Strategy"
)
)
);

// set keeper
_strategy.setKeeper(keeper);
// set treasury
_strategy.setPerformanceFeeRecipient(performanceFeeRecipient);
// set management of the strategy
_strategy.setPendingManagement(management);

vm.prank(management);
_strategy.acceptManagement();

Expand Down

0 comments on commit f8afbce

Please sign in to comment.