diff --git a/.gitmodules b/.gitmodules
index 37f73502..63378a86 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -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
\ No newline at end of file
+	branch = v3.0.3
+[submodule "lib/tokenized-strategy-periphery"]
+	path = lib/tokenized-strategy-periphery
+	url = https://github.com/yearn/tokenized-strategy-periphery
+	branch = master
\ No newline at end of file
diff --git a/lib/tokenized-strategy b/lib/tokenized-strategy
index 7bf18701..6e12ce08 160000
--- a/lib/tokenized-strategy
+++ b/lib/tokenized-strategy
@@ -1 +1 @@
-Subproject commit 7bf187015f5f7159276f80cd52204431ab1b3b8b
+Subproject commit 6e12ce08584b49c7560227e94810d2f0e3dec8b2
diff --git a/lib/tokenized-strategy-periphery b/lib/tokenized-strategy-periphery
index 6ce8d29b..03dfef66 160000
--- a/lib/tokenized-strategy-periphery
+++ b/lib/tokenized-strategy-periphery
@@ -1 +1 @@
-Subproject commit 6ce8d29b1e107a89754dd9f17337582734989b4d
+Subproject commit 03dfef66bf046ddccee885bd634a928606601b35
diff --git a/src/StrategyFactory.sol b/src/StrategyFactory.sol
new file mode 100644
index 00000000..79b78054
--- /dev/null
+++ b/src/StrategyFactory.sol
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: GPL-3.0
+pragma solidity ^0.8.18;
+
+import {Strategy, ERC20} from "./Strategy.sol";
+import {IStrategyInterface} from "./interfaces/IStrategyInterface.sol";
+
+contract StrategyFactory {
+    event NewStrategy(address indexed strategy, address indexed asset);
+
+    address public immutable emergencyAdmin;
+
+    address public immutable lendingPool;
+    address public immutable router;
+    address public immutable base;
+
+    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;
+    }
+}
diff --git a/src/test/FunctionSignature.t.sol b/src/test/FunctionSignature.t.sol
index 0389a271..2d447353 100644
--- a/src/test/FunctionSignature.t.sol
+++ b/src/test/FunctionSignature.t.sol
@@ -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");
diff --git a/src/test/Shutdown.t.sol b/src/test/Shutdown.t.sol
index a9ce1e5e..5e498b9f 100644
--- a/src/test/Shutdown.t.sol
+++ b/src/test/Shutdown.t.sol
@@ -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");
@@ -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.
 }
diff --git a/src/test/utils/Setup.sol b/src/test/utils/Setup.sol
index a24c4dc5..42042f1d 100644
--- a/src/test/utils/Setup.sol
+++ b/src/test/utils/Setup.sol
@@ -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.
@@ -23,6 +24,8 @@ 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.
@@ -30,6 +33,7 @@ contract Setup is ExtendedTest, IEvents {
     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;
@@ -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());
 
@@ -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();