{
    "Function": "slitherConstructorConstantVariables",
    "File": "contracts/StrategyProxyFactory.sol",
    "Parent Contracts": [
        "contracts/helpers/StringUtils.sol",
        "contracts/helpers/AddressUtils.sol",
        "node_modules/@openzeppelin/contracts/proxy/Initializable.sol",
        "contracts/StrategyProxyFactoryStorage.sol",
        "contracts/interfaces/IStrategyProxyFactory.sol",
        "contracts/helpers/StrategyTypes.sol"
    ],
    "High-Level Calls": [],
    "Internal Calls": [],
    "Library Calls": [],
    "Low-Level Calls": [],
    "Code": "contract StrategyProxyFactory is IStrategyProxyFactory, StrategyProxyFactoryStorage, Initializable, AddressUtils, StringUtils {\n    address public immutable override controller;\n\n    /**\n     * @notice Log the address of an implementation contract update\n     */\n    event Update(address newImplementation, string version);\n\n    /**\n     * @notice Log the creation of a new strategy\n     */\n    event NewStrategy(\n        address strategy,\n        address manager,\n        string name,\n        string symbol,\n        StrategyItem[] items\n    );\n\n    /**\n     * @notice Log the new Oracle for the strategys\n     */\n    event NewOracle(address newOracle);\n\n    /**\n     * @notice New default whitelist address\n     */\n    event NewWhitelist(address newWhitelist);\n\n    /**\n     * @notice New default pool address\n     */\n    event NewPool(address newPool);\n\n    /**\n     * @notice Log ownership transfer\n     */\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @notice Initialize constructor to disable implementation\n     */\n    constructor(address controller_) initializer {\n        controller = controller_;\n    }\n\n    function initialize(\n        address owner_,\n        address implementation_,\n        address oracle_,\n        address registry_,\n        address whitelist_,\n        address pool_\n    ) external\n        initializer\n        noZeroAddress(owner_)\n        noZeroAddress(implementation_)\n        noZeroAddress(oracle_)\n        noZeroAddress(registry_)\n        noZeroAddress(whitelist_)\n        noZeroAddress(pool_)\n        returns (bool)\n    {\n        admin = address(new StrategyProxyAdmin());\n        owner = owner_;\n        _implementation = implementation_;\n        _oracle = oracle_;\n        _registry = registry_;\n        _whitelist = whitelist_;\n        _pool = pool_;\n        _version = \"1\";\n        emit Update(_implementation, _version);\n        emit NewOracle(_oracle);\n        emit NewWhitelist(_whitelist);\n        emit NewPool(_pool);\n        emit OwnershipTransferred(address(0), owner);\n        return true;\n    }\n\n    modifier onlyOwner() {\n        require(owner == msg.sender, \"Not owner\");\n        _;\n    }\n\n    /**\n        @notice Entry point for creating new Strategies.\n        @notice Creates a new proxy for the current implementation and initializes the strategy with the provided input\n        @dev Can send ETH with this call to automatically deposit items into the strategy\n    */\n    function createStrategy(\n        address manager,\n        string memory name,\n        string memory symbol,\n        StrategyItem[] memory strategyItems,\n        InitialState memory strategyState,\n        address router,\n        bytes memory data\n    ) external payable override returns (address){\n        address strategy = _createProxy(manager, name, symbol, strategyItems);\n        emit NewStrategy(\n            strategy,\n            manager,\n            name,\n            symbol,\n            strategyItems\n        );\n        _setupStrategy(\n           manager,\n           strategy,\n           strategyState,\n           router,\n           data\n        );\n        return strategy;\n    }\n\n    function updateImplementation(address newImplementation, string memory newVersion) external noZeroAddress(newImplementation) onlyOwner {\n        require(parseInt(newVersion) > parseInt(_version), \"Invalid version\");\n        _implementation = newImplementation;\n        _version = newVersion;\n        emit Update(newImplementation, _version);\n    }\n\n    function updateOracle(address newOracle) external noZeroAddress(newOracle) onlyOwner {\n        _oracle = newOracle;\n        emit NewOracle(newOracle);\n    }\n\n    function updateWhitelist(address newWhitelist) external noZeroAddress(newWhitelist) onlyOwner {\n        _whitelist = newWhitelist;\n        emit NewWhitelist(newWhitelist);\n    }\n\n    function updatePool(address newPool) external noZeroAddress(newPool) onlyOwner {\n        _pool = newPool;\n        emit NewPool(newPool);\n    }\n\n    /*\n     * @dev This function is called by StrategyProxyAdmin\n     */\n    function updateProxyVersion(address proxy) external override {\n        require(msg.sender == admin, \"Only admin\");\n        IStrategyManagement(proxy).updateVersion(_version);\n    }\n\n    function addEstimatorToRegistry(uint256 estimatorCategoryIndex, address estimator) external onlyOwner {\n        ITokenRegistry(_registry).addEstimator(estimatorCategoryIndex, estimator);\n    }\n\n    function addItemsToRegistry(uint256[] calldata itemCategoryIndex, uint256[] calldata estimatorCategoryIndex, address[] calldata tokens) external onlyOwner {\n        ITokenRegistry(_registry).addItems(itemCategoryIndex, estimatorCategoryIndex, tokens);\n    }\n\n    function addItemToRegistry(\n        uint256 itemCategoryIndex,\n        uint256 estimatorCategoryIndex,\n        address token\n    ) external onlyOwner {\n        _addItemToRegistry(itemCategoryIndex, estimatorCategoryIndex, token);\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions anymore. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby removing any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public onlyOwner {\n        emit OwnershipTransferred(owner, address(0));\n        owner = address(0);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public noZeroAddress(newOwner) onlyOwner {\n        emit OwnershipTransferred(owner, newOwner);\n        owner = newOwner;\n    }\n\n    function salt(address manager, string memory name, string memory symbol) public pure override returns (bytes32) {\n      return keccak256(abi.encode(manager, name, symbol));\n    }\n\n    /*\n     * @dev This function is called by Strategy and StrategyController\n     */\n    function whitelist() external view override returns (address) {\n        return _whitelist;\n    }\n\n    /*\n     * @dev This function is called by  Strategy and StrategyController\n     */\n    function oracle() external view override returns (address) {\n        return _oracle;\n    }\n\n    function pool() external view override returns (address) {\n        return _pool;\n    }\n\n    /*\n     * @dev This function is called by StrategyProxyAdmin\n     */\n    function implementation() external view override returns (address) {\n        return _implementation;\n    }\n\n    function version() external view override returns (string memory) {\n        return _version;\n    }\n\n    /*\n     * @dev This function is called by StrategyProxyAdmin\n     */\n    function getManager(address proxy) external view override returns (address) {\n        return IStrategyManagement(proxy).manager();\n    }\n\n    /**\n        @notice Creates a Strategy proxy and makes a delegate call to initialize items + percentages on the proxy\n    */\n    function _createProxy(\n        address manager, string memory name, string memory symbol, StrategyItem[] memory strategyItems\n    ) internal returns (address) {\n        bytes32 salt_ = salt(manager, name, symbol);\n        require(!_proxyExists[salt_], \"_createProxy: proxy already exists.\");\n        TransparentUpgradeableProxy proxy =\n            new TransparentUpgradeableProxy{salt: salt_}(\n                    _implementation,\n                    admin,\n                    new bytes(0) // We greatly simplify CREATE2 when we don't pass initialization data\n                  );\n        _proxyExists[salt_] = true;\n        _addItemToRegistry(uint256(ItemCategory.BASIC), uint256(EstimatorCategory.STRATEGY), address(proxy));\n        // Instead we initialize it directly in the Strategy contract\n        IStrategyManagement(address(proxy)).initialize(\n            name,\n            symbol,\n            _version,\n            manager,\n            strategyItems\n        );\n        return address(proxy);\n    }\n\n    function _setupStrategy(\n        address manager,\n        address strategy,\n        InitialState memory strategyState,\n        address router,\n        bytes memory data\n    ) internal {\n        IStrategyController strategyController = IStrategyController(controller);\n        strategyController.setupStrategy{value: msg.value}(\n            manager,\n            strategy,\n            strategyState,\n            router,\n            data\n        );\n    }\n\n    function _addItemToRegistry(\n        uint256 itemCategoryIndex,\n        uint256 estimatorCategoryIndex,\n        address token\n    ) internal {\n        ITokenRegistry(_registry).addItem(itemCategoryIndex, estimatorCategoryIndex, token);\n    }\n\n}"
}