creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "src/SmartVaultFactoryHpf.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.17;\n\nimport \"@openzeppelin/proxy/beacon/BeaconProxy.sol\";\nimport \"@openzeppelin/proxy/beacon/UpgradeableBeacon.sol\";\nimport \"./interfaces/IAction.sol\";\nimport \"./interfaces/IAssetGroupRegistry.sol\";\nimport \"./interfaces/IGuardManager.sol\";\nimport \"./interfaces/IRiskManager.sol\";\nimport \"./interfaces/ISmartVault.sol\";\nimport \"./interfaces/ISmartVaultManager.sol\";\nimport \"./interfaces/ISpoolAccessControl.sol\";\nimport \"./interfaces/IStrategy.sol\";\nimport \"./interfaces/CommonErrors.sol\";\nimport \"./interfaces/Constants.sol\";\nimport \"./interfaces/RequestType.sol\";\nimport \"./access/Roles.sol\";\nimport \"./access/SpoolAccessControllable.sol\";\nimport \"./SmartVault.sol\";\nimport \"./SmartVaultFactory.sol\";\n\n/* ========== CONSTANTS ========== */\n\n/**\n * @dev Maximal smart vault performance fee that can be set on a smart vault using this factory. Expressed in terms of FULL_PERCENT.\n */\nuint256 constant SV_PERFORMANCE_FEE_HIGH_MAX = 90_00;\n\n/**\n * @dev Grants permission to deploy smart vaults via the SmartVaultFactoryHpf.\n */\nbytes32 constant ROLE_HPF_SMART_VAULT_DEPLOYER = keccak256(\"HPF_SMART_VAULT_DEPLOYER\");\n\n/* ========== CONTRACTS ========== */\n\n/**\n * @notice Factory for deploying smart vaults with high performance fees.\n * @dev Requires roles:\n * - ROLE_SMART_VAULT_INTEGRATOR\n * - ADMIN_ROLE_SMART_VAULT_ALLOW_REDEEM\n */\ncontract SmartVaultFactoryHpf is UpgradeableBeacon, SpoolAccessControllable {\n    using uint16a16Lib for uint16a16;\n\n    /* ========== EVENTS ========== */\n\n    /**\n     * @notice Emitted when a new smart vault is deployed.\n     * @param smartVault Address of the newly deployed smart vault.\n     * @param deployer Address of the deployer.\n     */\n    event SmartVaultDeployed(address indexed smartVault, address indexed deployer);\n\n    /* ========== CONSTANTS ========== */\n\n    /**\n     * @notice Action manager contract.\n     */\n    IActionManager immutable _actionManager;\n\n    /**\n     * @notice Guard manager contract.\n     */\n    IGuardManager immutable _guardManager;\n\n    /**\n     * @notice Smart vault manager contract.\n     */\n    ISmartVaultRegistry immutable _smartVaultRegistry;\n\n    /**\n     * @notice Asset group registry contract.\n     */\n    IAssetGroupRegistry immutable _assetGroupRegistry;\n\n    /**\n     * @notice Risk manager contract.\n     */\n    IRiskManager immutable _riskManager;\n\n    /* ========== CONSTRUCTOR ========== */\n\n    constructor(\n        address implementation,\n        ISpoolAccessControl accessControl_,\n        IActionManager actionManager_,\n        IGuardManager guardManager_,\n        ISmartVaultRegistry smartVaultRegistry_,\n        IAssetGroupRegistry assetGroupRegistry_,\n        IRiskManager riskManager_\n    ) UpgradeableBeacon(implementation) SpoolAccessControllable(accessControl_) {\n        if (address(accessControl_) == address(0)) revert ConfigurationAddressZero();\n        if (address(actionManager_) == address(0)) revert ConfigurationAddressZero();\n        if (address(guardManager_) == address(0)) revert ConfigurationAddressZero();\n        if (address(smartVaultRegistry_) == address(0)) revert ConfigurationAddressZero();\n        if (address(assetGroupRegistry_) == address(0)) revert ConfigurationAddressZero();\n        if (address(riskManager_) == address(0)) revert ConfigurationAddressZero();\n\n        _actionManager = actionManager_;\n        _guardManager = guardManager_;\n        _smartVaultRegistry = smartVaultRegistry_;\n        _assetGroupRegistry = assetGroupRegistry_;\n        _riskManager = riskManager_;\n    }\n\n    /* ========== EXTERNAL MUTATIVE FUNCTIONS ========== */\n\n    /**\n     * @notice Deploys a new smart vault into the Spool ecosystem.\n     * @dev Requirements:\n     * - caller must have role ROLE_HPF_SMART_VAULT_DEPLOYER\n     * @param specification Specifications for the new smart vault.\n     * @return smartVault Deployed smart vault.\n     */\n    function deploySmartVault(SmartVaultSpecification calldata specification)\n        external\n        onlyRole(ROLE_HPF_SMART_VAULT_DEPLOYER, msg.sender)\n        returns (ISmartVault)\n    {\n        _validateSpecification(specification);\n\n        address smartVaultAddress = address(\n            new BeaconProxy(\n                address(this),\n                _encodeInitializationCalldata(specification)\n            )\n        );\n\n        _integrateSmartVault(smartVaultAddress, specification);\n\n        emit SmartVaultDeployed(smartVaultAddress, msg.sender);\n\n        return ISmartVault(smartVaultAddress);\n    }\n\n    /**\n     * @notice Deploys a new smart vault to a deterministic address.\n     * @dev Requirements:\n     * - caller must have role ROLE_HPF_SMART_VAULT_DEPLOYER\n     * @param specification Specifications for the new smart vault.\n     * @param salt Salt for address determination.\n     * @return smartVault Deployed smart vault.\n     */\n    function deploySmartVaultDeterministically(SmartVaultSpecification calldata specification, bytes32 salt)\n        external\n        onlyRole(ROLE_HPF_SMART_VAULT_DEPLOYER, msg.sender)\n        returns (ISmartVault)\n    {\n        _validateSpecification(specification);\n\n        address smartVaultAddress = address(\n            new BeaconProxy{salt: salt}(\n                address(this),\n                _encodeInitializationCalldata(specification)\n            )\n        );\n\n        _integrateSmartVault(smartVaultAddress, specification);\n\n        emit SmartVaultDeployed(smartVaultAddress, msg.sender);\n\n        return ISmartVault(smartVaultAddress);\n    }\n\n    /* ========== EXTERNAL VIEW FUNCTIONS ========== */\n\n    /**\n     * @notice Predicts deployment address deterministically deployed smart vault.\n     * @param specification Specifications for the new smart vault.\n     * @param salt Salt for address determination.\n     * @return predictedAddress Predicted address.\n     */\n    function predictDeterministicAddress(SmartVaultSpecification calldata specification, bytes32 salt)\n        external\n        view\n        returns (address)\n    {\n        return address(\n            uint160(\n                uint256(\n                    keccak256(\n                        abi.encodePacked(\n                            bytes1(0xff),\n                            address(this),\n                            salt,\n                            keccak256(\n                                abi.encodePacked(\n                                    type(BeaconProxy).creationCode,\n                                    abi.encode(address(this), _encodeInitializationCalldata(specification))\n                                )\n                            )\n                        )\n                    )\n                )\n            )\n        );\n    }\n\n    /* ========== INTERNAL FUNCTIONS ========== */\n\n    /**\n     * @notice Validates smart vault specification.\n     * @param specification Specifications for the new smart vault.\n     */\n    function _validateSpecification(SmartVaultSpecification calldata specification) private view {\n        _assetGroupRegistry.validateAssetGroup(specification.assetGroupId);\n\n        if (specification.strategies.length == 0) {\n            revert SmartVaultRegistrationNoStrategies();\n        }\n        if (specification.strategies.length > STRATEGY_COUNT_CAP) {\n            revert StrategyCapExceeded();\n        }\n\n        unchecked {\n            bool fixedAllocations = uint16a16.unwrap(specification.strategyAllocation) > 0;\n            uint256 fullAllocation;\n\n            if (specification.strategies.length == 1 && !fixedAllocations) {\n                revert SingleStrategyDynamicAllocation();\n            }\n\n            if (fixedAllocations) {\n                if (specification.riskProvider != address(0)) {\n                    revert StaticAllocationAndRiskProviderSet();\n                }\n\n                if (specification.riskTolerance != 0) {\n                    revert StaticAllocationAndRiskToleranceSet();\n                }\n\n                if (specification.allocationProvider != address(0)) {\n                    revert StaticAllocationAndAllocationProviderSet();\n                }\n            }\n\n            for (uint256 i; i < specification.strategies.length; ++i) {\n                if (fixedAllocations) {\n                    if (specification.strategyAllocation.get(i) == 0) {\n                        revert InvalidStrategyAllocationsLength();\n                    }\n                    fullAllocation += specification.strategyAllocation.get(i);\n                }\n\n                if (!_accessControl.hasRole(ROLE_STRATEGY, specification.strategies[i])) {\n                    revert InvalidStrategy(specification.strategies[i]);\n                }\n\n                if (IStrategy(specification.strategies[i]).assetGroupId() != specification.assetGroupId) {\n                    revert NotSameAssetGroup();\n                }\n\n                for (uint256 j = i + 1; j < specification.strategies.length; ++j) {\n                    if (specification.strategies[i] == specification.strategies[j]) {\n                        revert StrategiesNotUnique();\n                    }\n                }\n            }\n\n            if (fixedAllocations && fullAllocation != FULL_PERCENT) {\n                revert InvalidStaticAllocation();\n            }\n        }\n\n        if (specification.managementFeePct > MANAGEMENT_FEE_MAX) {\n            revert ManagementFeeTooLarge(specification.managementFeePct);\n        }\n        if (specification.depositFeePct > DEPOSIT_FEE_MAX) {\n            revert DepositFeeTooLarge(specification.depositFeePct);\n        }\n        if (specification.performanceFeePct > SV_PERFORMANCE_FEE_HIGH_MAX) {\n            revert PerformanceFeeTooLarge(specification.performanceFeePct);\n        }\n    }\n\n    /**\n     * @notice Encodes calldata for smart vault initialization.\n     * @param specification Specifications for the new smart vault.\n     * @return initializationCalldata Enoded initialization calldata.\n     */\n    function _encodeInitializationCalldata(SmartVaultSpecification calldata specification)\n        private\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodeWithSignature(\n            \"initialize(string,string,string,uint256)\",\n            specification.smartVaultName,\n            specification.svtSymbol,\n            specification.baseURI,\n            specification.assetGroupId\n        );\n    }\n\n    /**\n     * @notice Integrates newly created smart vault into the Spool ecosystem.\n     * @param smartVaultAddress Address of created smart vault.\n     * @param specification Specifications for the new smart vault.\n     */\n    function _integrateSmartVault(address smartVaultAddress, SmartVaultSpecification calldata specification) private {\n        _accessControl.grantSmartVaultOwnership(smartVaultAddress, msg.sender);\n        _actionManager.setActions(smartVaultAddress, specification.actions, specification.actionRequestTypes);\n        _guardManager.setGuards(smartVaultAddress, specification.guards, specification.guardRequestTypes);\n\n        if (specification.allowRedeemFor) {\n            _accessControl.grantRole(ROLE_SMART_VAULT_ALLOW_REDEEM, smartVaultAddress);\n        }\n\n        uint16a16 allocations = specification.strategyAllocation;\n\n        // set allocation\n        if (uint16a16.unwrap(allocations) == 0) {\n            _riskManager.setRiskProvider(smartVaultAddress, specification.riskProvider);\n            _riskManager.setRiskTolerance(smartVaultAddress, specification.riskTolerance);\n            _riskManager.setAllocationProvider(smartVaultAddress, specification.allocationProvider);\n\n            allocations = _riskManager.calculateAllocation(smartVaultAddress, specification.strategies);\n        }\n\n        _smartVaultRegistry.registerSmartVault(\n            smartVaultAddress,\n            SmartVaultRegistrationForm({\n                assetGroupId: specification.assetGroupId,\n                strategies: specification.strategies,\n                strategyAllocation: allocations,\n                managementFeePct: specification.managementFeePct,\n                depositFeePct: specification.depositFeePct,\n                performanceFeePct: specification.performanceFeePct\n            })\n        );\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/proxy/beacon/BeaconProxy.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts (last updated v4.7.0) (proxy/beacon/BeaconProxy.sol)\r\n\r\npragma solidity ^0.8.0;\r\n\r\nimport \"./IBeacon.sol\";\r\nimport \"../Proxy.sol\";\r\nimport \"../ERC1967/ERC1967Upgrade.sol\";\r\n\r\n/**\r\n * @dev This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}.\r\n *\r\n * The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't\r\n * conflict with the storage layout of the implementation behind the proxy.\r\n *\r\n * _Available since v3.4._\r\n */\r\ncontract BeaconProxy is Proxy, ERC1967Upgrade {\r\n    /**\r\n     * @dev Initializes the proxy with `beacon`.\r\n     *\r\n     * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This\r\n     * will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity\r\n     * constructor.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `beacon` must be a contract with the interface {IBeacon}.\r\n     */\r\n    constructor(address beacon, bytes memory data) payable {\r\n        _upgradeBeaconToAndCall(beacon, data, false);\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the current beacon address.\r\n     */\r\n    function _beacon() internal view virtual returns (address) {\r\n        return _getBeacon();\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the current implementation address of the associated beacon.\r\n     */\r\n    function _implementation() internal view virtual override returns (address) {\r\n        return IBeacon(_getBeacon()).implementation();\r\n    }\r\n\r\n    /**\r\n     * @dev Changes the proxy to use a new beacon. Deprecated: see {_upgradeBeaconToAndCall}.\r\n     *\r\n     * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `beacon` must be a contract.\r\n     * - The implementation returned by `beacon` must be a contract.\r\n     */\r\n    function _setBeacon(address beacon, bytes memory data) internal virtual {\r\n        _upgradeBeaconToAndCall(beacon, data, false);\r\n    }\r\n}\r\n"
      },
      "lib/openzeppelin-contracts/contracts/proxy/beacon/UpgradeableBeacon.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/UpgradeableBeacon.sol)\r\n\r\npragma solidity ^0.8.0;\r\n\r\nimport \"./IBeacon.sol\";\r\nimport \"../../access/Ownable.sol\";\r\nimport \"../../utils/Address.sol\";\r\n\r\n/**\r\n * @dev This contract is used in conjunction with one or more instances of {BeaconProxy} to determine their\r\n * implementation contract, which is where they will delegate all function calls.\r\n *\r\n * An owner is able to change the implementation the beacon points to, thus upgrading the proxies that use this beacon.\r\n */\r\ncontract UpgradeableBeacon is IBeacon, Ownable {\r\n    address private _implementation;\r\n\r\n    /**\r\n     * @dev Emitted when the implementation returned by the beacon is changed.\r\n     */\r\n    event Upgraded(address indexed implementation);\r\n\r\n    /**\r\n     * @dev Sets the address of the initial implementation, and the deployer account as the owner who can upgrade the\r\n     * beacon.\r\n     */\r\n    constructor(address implementation_) {\r\n        _setImplementation(implementation_);\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the current implementation address.\r\n     */\r\n    function implementation() public view virtual override returns (address) {\r\n        return _implementation;\r\n    }\r\n\r\n    /**\r\n     * @dev Upgrades the beacon to a new implementation.\r\n     *\r\n     * Emits an {Upgraded} event.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - msg.sender must be the owner of the contract.\r\n     * - `newImplementation` must be a contract.\r\n     */\r\n    function upgradeTo(address newImplementation) public virtual onlyOwner {\r\n        _setImplementation(newImplementation);\r\n        emit Upgraded(newImplementation);\r\n    }\r\n\r\n    /**\r\n     * @dev Sets the implementation contract address for this beacon\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `newImplementation` must be a contract.\r\n     */\r\n    function _setImplementation(address newImplementation) private {\r\n        require(Address.isContract(newImplementation), \"UpgradeableBeacon: implementation is not a contract\");\r\n        _implementation = newImplementation;\r\n    }\r\n}\r\n"
      },
      "src/interfaces/IAction.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.17;\n\nimport \"./RequestType.sol\";\n\n/**\n * @notice Used when trying to set an invalid action for a smart vault.\n * @param address_ Address of the invalid action.\n */\nerror InvalidAction(address address_);\n\n/**\n * @notice Used when trying to whitelist already whitelisted action.\n */\nerror ActionStatusAlreadySet();\n\n/**\n * @notice Used when trying to set actions for smart vault that already has actions set.\n */\nerror ActionsAlreadyInitialized(address smartVault);\n\n/**\n * @notice Too many actions have been passed when creating a vault.\n */\nerror TooManyActions();\n\n/**\n * @notice Used when wrong request type is set for an action.\n * @param requestType Wrong request type.\n */\nerror WrongActionRequestType(RequestType requestType);\n\n/**\n * @notice Represents a context that is sent to actions.\n * @custom:member smartVault Smart vault address\n * @custom:member recipient In case of deposit, recipient of deposit NFT; in case of withdrawal, recipient of assets.\n * @custom:member executor In case of deposit, executor of deposit action; in case of withdrawal, executor of claimWithdrawal action.\n * @custom:member owner In case of deposit, owner of assets; in case of withdrawal, owner of withdrawal NFT.\n * @custom:member requestType Request type that triggered the action.\n * @custom:member tokens Tokens involved.\n * @custom:member amount Amount of tokens.\n */\nstruct ActionContext {\n    address smartVault;\n    address recipient;\n    address executor;\n    address owner;\n    RequestType requestType;\n    address[] tokens;\n    uint256[] amounts;\n}\n\ninterface IAction {\n    /**\n     * @notice Executes the action.\n     * @param actionCtx Context for action execution.\n     */\n    function executeAction(ActionContext calldata actionCtx) external;\n}\n\ninterface IActionManager {\n    /**\n     * @notice Sets actions for a smart vault.\n     * @dev Requirements:\n     * - caller needs role ROLE_SMART_VAULT_INTEGRATOR\n     * @param smartVault Smart vault for which the actions will be set.\n     * @param actions Actions to set.\n     * @param requestTypes Specifies for each action, which request type triggers that action.\n     */\n    function setActions(address smartVault, IAction[] calldata actions, RequestType[] calldata requestTypes) external;\n\n    /**\n     * @notice Runs actions for a smart vault.\n     * @dev Requirements:\n     * - caller needs role ROLE_SMART_VAULT_MANAGER\n     * @param actionCtx Execution context for the actions.\n     */\n    function runActions(ActionContext calldata actionCtx) external;\n\n    /**\n     * @notice Adds or removes an action from the whitelist.\n     * @dev Requirements:\n     * - caller needs role ROLE_SPOOL_ADMIN\n     * @param action Address of an action to add or remove from the whitelist.\n     * @param whitelist If true, action will be added to the whitelist, if false, it will be removed from it.\n     */\n    function whitelistAction(address action, bool whitelist) external;\n\n    /**\n     * @notice Emitted when an action is added or removed from the whitelist.\n     * @param action Address of the action that was added or removed from the whitelist.\n     * @param whitelisted True if it was added, false if it was removed from the whitelist.\n     */\n    event ActionListed(address indexed action, bool whitelisted);\n\n    /**\n     * @notice Emitted when an action is set for a vault\n     * @param smartVault Address of the smart vault\n     * @param action Address of the action that was added\n     * @param requestType Trigger for executing the action\n     */\n    event ActionSet(address indexed smartVault, address indexed action, RequestType requestType);\n}\n"
      },
      "src/interfaces/IAssetGroupRegistry.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.17;\n\nimport \"@openzeppelin/token/ERC20/IERC20.sol\";\n\n/* ========== ERRORS ========== */\n\n/**\n * @notice Used when invalid ID for asset group is provided.\n * @param assetGroupId Invalid ID for asset group.\n */\nerror InvalidAssetGroup(uint256 assetGroupId);\n\n/**\n * @notice Used when no assets are provided for an asset group.\n */\nerror NoAssetsProvided();\n\n/**\n * @notice Used when token is not allowed to be used as an asset.\n * @param token Address of the token that is not allowed.\n */\nerror TokenNotAllowed(address token);\n\n/**\n * @notice Used when asset group already exists.\n * @param assetGroupId ID of the already existing asset group.\n */\nerror AssetGroupAlreadyExists(uint256 assetGroupId);\n\n/**\n * @notice Used when given array is unsorted.\n */\nerror UnsortedArray();\n\n/* ========== INTERFACES ========== */\n\ninterface IAssetGroupRegistry {\n    /* ========== EVENTS ========== */\n\n    /**\n     * @notice Emitted when token is allowed to be used as an asset.\n     * @param token Address of newly allowed token.\n     */\n    event TokenAllowed(address indexed token);\n\n    /**\n     * @notice Emitted when asset group is registered.\n     * @param assetGroupId ID of the newly registered asset group.\n     */\n    event AssetGroupRegistered(uint256 indexed assetGroupId);\n\n    /* ========== VIEW FUNCTIONS ========== */\n\n    /**\n     * @notice Checks if token is allowed to be used as an asset.\n     * @param token Address of token to check.\n     * @return isAllowed True if token is allowed, false otherwise.\n     */\n    function isTokenAllowed(address token) external view returns (bool isAllowed);\n\n    /**\n     * @notice Gets number of registered asset groups.\n     * @return count Number of registered asset groups.\n     */\n    function numberOfAssetGroups() external view returns (uint256 count);\n\n    /**\n     * @notice Gets asset group by its ID.\n     * @dev Requirements:\n     * - must provide a valid ID for the asset group\n     * @return assets Array of assets in the asset group.\n     */\n    function listAssetGroup(uint256 assetGroupId) external view returns (address[] memory assets);\n\n    /**\n     * @notice Gets asset group length.\n     * @dev Requirements:\n     * - must provide a valid ID for the asset group\n     * @return length\n     */\n    function assetGroupLength(uint256 assetGroupId) external view returns (uint256 length);\n\n    /**\n     * @notice Validates that provided ID represents an asset group.\n     * @dev Function reverts when ID does not represent an asset group.\n     * @param assetGroupId ID to validate.\n     */\n    function validateAssetGroup(uint256 assetGroupId) external view;\n\n    /**\n     * @notice Checks if asset group composed of assets already exists.\n     * Will revert if provided assets cannot form an asset group.\n     * @param assets Assets composing the asset group.\n     * @return Asset group ID if such asset group exists, 0 otherwise.\n     */\n    function checkAssetGroupExists(address[] calldata assets) external view returns (uint256);\n\n    /* ========== MUTATIVE FUNCTIONS ========== */\n\n    /**\n     * @notice Allows a token to be used as an asset.\n     * @dev Requirements:\n     * - can only be called by the ROLE_SPOOL_ADMIN\n     * @param token Address of token to be allowed.\n     */\n    function allowToken(address token) external;\n\n    /**\n     * @notice Allows tokens to be used as assets.\n     * @dev Requirements:\n     * - can only be called by the ROLE_SPOOL_ADMIN\n     * @param tokens Addresses of tokens to be allowed.\n     */\n    function allowTokenBatch(address[] calldata tokens) external;\n\n    /**\n     * @notice Registers a new asset group.\n     * @dev Requirements:\n     * - must provide at least one asset\n     * - all assets must be allowed\n     * - assets must be sorted\n     * - such asset group should not exist yet\n     * - can only be called by the ROLE_SPOOL_ADMIN\n     * @param assets Array of assets in the asset group.\n     * @return id Sequential ID assigned to the asset group.\n     */\n    function registerAssetGroup(address[] calldata assets) external returns (uint256 id);\n}\n"
      },
      "src/interfaces/IGuardManager.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.17;\n\nimport \"./ISmartVault.sol\";\nimport \"./RequestType.sol\";\n\nerror GuardsAlreadyInitialized();\nerror GuardsNotInitialized();\nerror GuardError();\n\n/**\n * @notice Used when a guard fails.\n * @param guardNum Sequential number of the guard that failed.\n */\nerror GuardFailed(uint256 guardNum);\n\nerror InvalidGuardParamType(uint256 paramType);\n\n/**\n * @notice Too many guard definitions have been passed when creating a vault.\n */\nerror TooManyGuards();\n\n/**\n * @notice The guard definition does not have all required inputs\n */\nerror IncompleteGuardDefinition();\n\n/**\n * @custom:member VaultAddress Address of the smart vault.\n * @custom:member Executor In case of deposit, executor of deposit action; in case of withdrawal, executor of redeem action.\n * @custom:member Receiver Receiver of receipt NFT.\n * @custom:member Owner In case of deposit, owner of assets; in case of withdrawal, owner of vault shares.\n * @custom:member Assets Amounts of assets involved.\n * @custom:member Tokens Addresses of assets involved.\n * @custom:member AssetGroup Asset group of the smart vault.\n * @custom:member CustomValue Custom value.\n * @custom:member DynamicCustomValue Dynamic custom value.\n */\nenum GuardParamType {\n    VaultAddress,\n    Executor,\n    Receiver,\n    Owner,\n    Assets,\n    Tokens,\n    AssetGroup,\n    CustomValue,\n    DynamicCustomValue\n}\n\n/**\n * @custom:member methodSignature Signature of the method to invoke\n * @custom:member contractAddress Address of the contract to invoke\n * @custom:member operator The operator to use when comparing expectedValue to guard's function result.\n * @custom:member expectedValue Value to use when comparing with the guard function result.\n * - System only supports guards with return values that can be cast to uint256.\n * @custom:member methodParamTypes Types of parameters that the guard function is expecting.\n * @custom:member methodParamValues Parameter values that will be passed into the guard function call.\n * - This array should only include fixed/static values. Parameters that are resolved at runtime should be omitted.\n * - All values should be encoded using \"abi.encode\" before passing them to the GuardManager contract.\n * - We assume that all static types are encoded to 32 bytes. Fixed-size static arrays and structs with only static\n *      type members are not supported.\n * - If empty, system will assume the expected value is bool(true).\n */\nstruct GuardDefinition {\n    string methodSignature;\n    address contractAddress;\n    bytes2 operator;\n    uint256 expectedValue;\n    GuardParamType[] methodParamTypes;\n    bytes[] methodParamValues;\n}\n\n/**\n * @custom:member receiver Receiver of receipt NFT.\n * @custom:member executor In case of deposit, executor of deposit action; in case of withdrawal, executor of redeem action.\n * @custom:member owner In case of deposit, owner of assets; in case of withdrawal, owner of vault shares.\n * @custom:member requestType Request type for which the guard is run.\n * @custom:member assets Amounts of assets involved.\n * @custom:member tokens Addresses of tokens involved.\n */\nstruct RequestContext {\n    address receiver;\n    address executor;\n    address owner;\n    RequestType requestType;\n    uint256[] assets;\n    address[] tokens;\n}\n\ninterface IGuardManager {\n    /**\n     * @notice Runs guards for a smart vault.\n     * @dev Reverts if any guard fails.\n     * The context.methodParamValues array should only include fixed/static values.\n     * Parameters that are resolved at runtime should be omitted. All values should be encoded using \"abi.encode\" before\n     * passing them to the GuardManager contract. We assume that all static types are encoded to 32 bytes. Fixed-size\n     * static arrays and structs with only static type members are not supported.\n     * @param smartVault Smart vault for which to run the guards.\n     * @param context Context for running the guards.\n     */\n    function runGuards(address smartVault, RequestContext calldata context) external view;\n\n    /**\n     * @notice Gets guards for smart vault and request type.\n     * @param smartVault Smart vault for which to get guards.\n     * @param requestType Request type for which to get guards.\n     * @return guards Guards for the smart vault and request type.\n     */\n    function readGuards(address smartVault, RequestType requestType)\n        external\n        view\n        returns (GuardDefinition[] memory guards);\n\n    /**\n     * @notice Sets guards for the smart vault.\n     * @dev\n     * @dev Requirements:\n     * - caller must have role ROLE_SMART_VAULT_INTEGRATOR\n     * - guards should not have been already set for the smart vault\n     * @param smartVault Smart vault for which to set the guards.\n     * @param guards Guards to set. Grouped by the request types.\n     * @param requestTypes Request types for groups of guards.\n     */\n    function setGuards(address smartVault, GuardDefinition[][] calldata guards, RequestType[] calldata requestTypes)\n        external;\n\n    /**\n     * @notice Emitted when guards are set for a smart vault.\n     * @param smartVault Smart vault for which guards were set.\n     * @param guards Guard definitions\n     * @param requestTypes Guard triggers\n     */\n    event GuardsInitialized(address indexed smartVault, GuardDefinition[][] guards, RequestType[] requestTypes);\n}\n"
      },
      "src/interfaces/IRiskManager.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.17;\n\nimport \"../libraries/uint16a16Lib.sol\";\n\nerror InvalidRiskInputLength();\nerror RiskScoreValueOutOfBounds(uint8 value);\nerror RiskToleranceValueOutOfBounds(int8 value);\nerror CannotSetRiskScoreForGhostStrategy(uint8 riskScore);\nerror InvalidAllocationSum(uint256 allocationsSum);\nerror InvalidRiskScores(address riskProvider, address strategy);\n\ninterface IRiskManager {\n    /* ========== VIEW FUNCTIONS ========== */\n\n    /**\n     * @notice Calculates allocation between strategies based on\n     * - risk scores of strategies\n     * - risk appetite\n     * @param smartVault Smart vault address.\n     * @param strategies Strategies.\n     * @return allocation Calculated allocation.\n     */\n    function calculateAllocation(address smartVault, address[] calldata strategies)\n        external\n        view\n        returns (uint16a16 allocation);\n\n    /**\n     * @notice Gets risk scores for strategies.\n     * @param riskProvider Requested risk provider.\n     * @param strategy Strategies.\n     * @return riskScores Risk scores for strategies.\n     */\n    function getRiskScores(address riskProvider, address[] memory strategy)\n        external\n        view\n        returns (uint8[] memory riskScores);\n\n    /**\n     * @notice Gets configured risk provider for a smart vault.\n     * @param smartVault Smart vault.\n     * @return riskProvider Risk provider for the smart vault.\n     */\n    function getRiskProvider(address smartVault) external view returns (address riskProvider);\n\n    /**\n     * @notice Gets configured allocation provider for a smart vault.\n     * @param smartVault Smart vault.\n     * @return allocationProvider Allocation provider for the smart vault.\n     */\n    function getAllocationProvider(address smartVault) external view returns (address allocationProvider);\n\n    /**\n     * @notice Gets configured risk tolerance for a smart vault.\n     * @param smartVault Smart vault.\n     * @return riskTolerance Risk tolerance for the smart vault.\n     */\n    function getRiskTolerance(address smartVault) external view returns (int8 riskTolerance);\n\n    /* ========== EXTERNAL MUTATIVE FUNCTIONS ========== */\n\n    /**\n     * @notice Sets risk provider for a smart vault.\n     * @dev Requirements:\n     * - caller must have role ROLE_SMART_VAULT_INTEGRATOR\n     * - risk provider must have role ROLE_RISK_PROVIDER\n     * @param smartVault Smart vault.\n     * @param riskProvider_ Risk provider to set.\n     */\n    function setRiskProvider(address smartVault, address riskProvider_) external;\n\n    /**\n     * @notice Sets allocation provider for a smart vault.\n     * @dev Requirements:\n     * - caller must have role ROLE_SMART_VAULT_INTEGRATOR\n     * - allocation provider must have role ROLE_ALLOCATION_PROVIDER\n     * @param smartVault Smart vault.\n     * @param allocationProvider Allocation provider to set.\n     */\n    function setAllocationProvider(address smartVault, address allocationProvider) external;\n\n    /**\n     * @notice Sets risk scores for strategies.\n     * @dev Requirements:\n     * - caller must have role ROLE_RISK_PROVIDER\n     * @param riskScores Risk scores to set for strategies.\n     * @param strategies Strategies for which to set risk scores.\n     */\n    function setRiskScores(uint8[] calldata riskScores, address[] calldata strategies) external;\n\n    /**\n     * @notice Sets risk tolerance for a smart vault.\n     * @dev Requirements:\n     * - caller must have role ROLE_SMART_VAULT_INTEGRATOR\n     * - risk tolerance must be within valid bounds\n     * @param smartVault Smart vault.\n     * @param riskTolerance Risk tolerance to set.\n     */\n    function setRiskTolerance(address smartVault, int8 riskTolerance) external;\n\n    /**\n     * @notice Risk scores updated\n     * @param riskProvider risk provider address\n     * @param strategies strategy addresses\n     * @param riskScores risk score values\n     */\n    event RiskScoresUpdated(address indexed riskProvider, address[] strategies, uint8[] riskScores);\n\n    /**\n     * @notice Smart vault risk provider set\n     * @param smartVault Smart vault address\n     * @param riskProvider New risk provider address\n     */\n    event RiskProviderSet(address indexed smartVault, address indexed riskProvider);\n\n    /**\n     * @notice Smart vault allocation provider set\n     * @param smartVault Smart vault address\n     * @param allocationProvider New allocation provider address\n     */\n    event AllocationProviderSet(address indexed smartVault, address indexed allocationProvider);\n\n    /**\n     * @notice Smart vault risk appetite\n     * @param smartVault Smart vault address\n     * @param riskTolerance risk appetite value\n     */\n    event RiskToleranceSet(address indexed smartVault, int8 riskTolerance);\n}\n"
      },
      "src/interfaces/ISmartVault.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.17;\n\nimport \"@openzeppelin-upgradeable/token/ERC1155/IERC1155Upgradeable.sol\";\nimport \"@openzeppelin-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport \"@openzeppelin-upgradeable/token/ERC1155/extensions/IERC1155MetadataURIUpgradeable.sol\";\nimport \"./Constants.sol\";\nimport \"./RequestType.sol\";\n\n/* ========== ERRORS ========== */\n\n/**\n * @notice Used when the ID for deposit NFTs overflows.\n * @dev Should never happen.\n */\nerror DepositIdOverflow();\n\n/**\n * @notice Used when the ID for withdrawal NFTs overflows.\n * @dev Should never happen.\n */\nerror WithdrawalIdOverflow();\n\n/**\n * @notice Used when ID does not represent a deposit NFT.\n * @param depositNftId Invalid ID for deposit NFT.\n */\nerror InvalidDepositNftId(uint256 depositNftId);\n\n/**\n * @notice Used when ID does not represent a withdrawal NFT.\n * @param withdrawalNftId Invalid ID for withdrawal NFT.\n */\nerror InvalidWithdrawalNftId(uint256 withdrawalNftId);\n\n/**\n * @notice Used when balance of the NFT is invalid.\n * @param balance Actual balance of the NFT.\n */\nerror InvalidNftBalance(uint256 balance);\n\n/**\n * @notice Used when someone wants to transfer invalid NFT shares amount.\n * @param transferAmount Amount of shares requested to be transferred.\n */\nerror InvalidNftTransferAmount(uint256 transferAmount);\n\n/**\n * @notice Used when user tries to send tokens to himself.\n */\nerror SenderEqualsRecipient();\n\n/* ========== STRUCTS ========== */\n\nstruct DepositMetadata {\n    uint256[] assets;\n    uint256 initiated;\n    uint256 flushIndex;\n}\n\n/**\n * @notice Holds metadata detailing the withdrawal behind the NFT.\n * @custom:member vaultShares Vault shares withdrawn.\n * @custom:member flushIndex Flush index into which withdrawal is included.\n */\nstruct WithdrawalMetadata {\n    uint256 vaultShares;\n    uint256 flushIndex;\n}\n\n/**\n * @notice Holds all smart vault fee percentages.\n * @custom:member managementFeePct Management fee of the smart vault.\n * @custom:member depositFeePct Deposit fee of the smart vault.\n * @custom:member performanceFeePct Performance fee of the smart vault.\n */\nstruct SmartVaultFees {\n    uint16 managementFeePct;\n    uint16 depositFeePct;\n    uint16 performanceFeePct;\n}\n\n/* ========== INTERFACES ========== */\n\ninterface ISmartVault is IERC20Upgradeable, IERC1155MetadataURIUpgradeable {\n    /* ========== EXTERNAL VIEW FUNCTIONS ========== */\n\n    /**\n     * @notice Fractional balance of a NFT (0 - NFT_MINTED_SHARES).\n     * @param account Account to check the balance for.\n     * @param id ID of the NFT to check.\n     * @return fractionalBalance Fractional balance of account for the NFT.\n     */\n    function balanceOfFractional(address account, uint256 id) external view returns (uint256 fractionalBalance);\n\n    /**\n     * @notice Fractional balance of a NFTs (0 - NFT_MINTED_SHARES).\n     * @param account Account to check the balance for.\n     * @param ids IDs of the NFTs to check.\n     * @return fractionalBalances Fractional balances of account for each requested NFT.\n     */\n    function balanceOfFractionalBatch(address account, uint256[] calldata ids)\n        external\n        view\n        returns (uint256[] memory fractionalBalances);\n    /**\n     * @notice Gets the asset group used by the smart vault.\n     * @return id ID of the asset group.\n     */\n    function assetGroupId() external view returns (uint256 id);\n\n    /**\n     * @notice Gets the name of the smart vault.\n     * @return name Name of the vault.\n     */\n    function vaultName() external view returns (string memory name);\n\n    /**\n     * @notice Gets metadata for NFTs.\n     * @param nftIds IDs of NFTs.\n     * @return metadata Metadata for each requested NFT.\n     */\n    function getMetadata(uint256[] calldata nftIds) external view returns (bytes[] memory metadata);\n\n    /* ========== EXTERNAL MUTATIVE FUNCTIONS ========== */\n\n    /**\n     * @notice Set a new base URI for ERC1155 metadata.\n     * @param uri_ new base URI value\n     */\n    function setBaseURI(string memory uri_) external;\n\n    /**\n     * @notice Mints smart vault tokens for receiver.\n     * @dev Requirements:\n     * - caller must have role ROLE_SMART_VAULT_MANAGER\n     * @param receiver REceiver of minted tokens.\n     * @param vaultShares Amount of tokens to mint.\n     */\n    function mintVaultShares(address receiver, uint256 vaultShares) external;\n\n    /**\n     * @notice Burns smart vault tokens and releases strategy shares back to strategies.\n     * @dev Requirements:\n     * - caller must have role ROLE_SMART_VAULT_MANAGER\n     * @param owner Address for which to burn the tokens.\n     * @param vaultShares Amount of tokens to burn.\n     * @param strategies Strategies for which to release the strategy shares.\n     * @param shares Amounts of strategy shares to release.\n     */\n    function burnVaultShares(\n        address owner,\n        uint256 vaultShares,\n        address[] calldata strategies,\n        uint256[] calldata shares\n    ) external;\n\n    /**\n     * @notice Mints a new withdrawal NFT.\n     * @dev Supply of minted NFT is NFT_MINTED_SHARES (for partial burning).\n     * Requirements:\n     * - caller must have role ROLE_SMART_VAULT_MANAGER\n     * @param receiver Address that will receive the NFT.\n     * @param metadata Metadata to store for minted NFT.\n     * @return id ID of the minted NFT.\n     */\n    function mintWithdrawalNFT(address receiver, WithdrawalMetadata calldata metadata) external returns (uint256 id);\n\n    /**\n     * @notice Mints a new deposit NFT.\n     * @dev Supply of minted NFT is NFT_MINTED_SHARES (for partial burning).\n     * Requirements:\n     * - caller must have role ROLE_SMART_VAULT_MANAGER\n     * @param receiver Address that will receive the NFT.\n     * @param metadata Metadata to store for minted NFT.\n     * @return id ID of the minted NFT.\n     */\n    function mintDepositNFT(address receiver, DepositMetadata calldata metadata) external returns (uint256 id);\n\n    /**\n     * @notice Burns NFTs and returns their metadata.\n     * Allows for partial burning.\n     * @dev Requirements:\n     * - caller must have role ROLE_SMART_VAULT_MANAGER\n     * @param owner Owner of NFTs to burn.\n     * @param nftIds IDs of NFTs to burn.\n     * @param nftAmounts NFT shares to burn (partial burn).\n     * @return metadata Metadata for each burned NFT.\n     */\n    function burnNFTs(address owner, uint256[] calldata nftIds, uint256[] calldata nftAmounts)\n        external\n        returns (bytes[] memory metadata);\n\n    /**\n     * @notice Transfers smart vault tokens.\n     * @dev Requirements:\n     * - caller must have role ROLE_SMART_VAULT_MANAGER\n     * @param from Spender and owner of tokens.\n     * @param to Address to which tokens will be transferred.\n     * @param amount Amount of tokens to transfer.\n     * @return success True if transfer was successful.\n     */\n    function transferFromSpender(address from, address to, uint256 amount) external returns (bool success);\n\n    /**\n     * @notice Transfers unclaimed shares to claimer.\n     * @dev Requirements:\n     * - caller must have role ROLE_SMART_VAULT_MANAGER\n     * @param claimer Address that claims the shares.\n     * @param amount Amount of shares to transfer.\n     */\n    function claimShares(address claimer, uint256 amount) external;\n\n    /// @notice Emitted when base URI is changed.\n    event BaseURIChanged(string baseUri);\n}\n"
      },
      "src/interfaces/ISmartVaultManager.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.17;\n\nimport \"./IDepositManager.sol\";\nimport \"./ISmartVault.sol\";\nimport \"./ISwapper.sol\";\nimport \"./IWithdrawalManager.sol\";\n\n/* ========== ERRORS ========== */\n\n/**\n * @notice Used when user has insufficient balance for redeemal of shares.\n */\nerror InsufficientBalance(uint256 available, uint256 required);\n\n/**\n * @notice Used when there is nothing to flush.\n */\nerror NothingToFlush();\n\n/**\n * @notice Used when trying to register a smart vault that was already registered.\n */\nerror SmartVaultAlreadyRegistered();\n\n/**\n * @notice Used when trying to perform an action for smart vault that was not registered yet.\n */\nerror SmartVaultNotRegisteredYet();\n\n/**\n * @notice Used when user tries to configure a vault with too large management fee.\n */\nerror ManagementFeeTooLarge(uint256 mgmtFeePct);\n\n/**\n * @notice Used when user tries to configure a vault with too large performance fee.\n */\nerror PerformanceFeeTooLarge(uint256 performanceFeePct);\n\n/**\n * @notice Used when smart vault in reallocation has statically set allocation.\n */\nerror StaticAllocationSmartVault();\n\n/**\n * @notice Used when user tries to configure a vault with too large deposit fee.\n */\nerror DepositFeeTooLarge(uint256 depositFeePct);\n\n/**\n * @notice Used when user tries redeem on behalf of another user, but the vault does not support it\n */\nerror RedeemForNotAllowed();\n\n/**\n * @notice Used when trying to flush a vault that still needs to be synced.\n */\nerror VaultNotSynced();\n\n/**\n * @notice Used when trying to deposit into, redeem from, or flush a smart vault that has only ghost strategies.\n */\nerror GhostVault();\n\n/**\n * @notice Used when reallocation is called with expired parameters.\n */\nerror ReallocationParametersExpired();\n\n/* ========== STRUCTS ========== */\n\n/**\n * @notice Struct holding all data for registration of smart vault.\n * @custom:member assetGroupId Underlying asset group of the smart vault.\n * @custom:member strategies Strategies used by the smart vault.\n * @custom:member strategyAllocation Optional. If empty array, values will be calculated on the spot.\n * @custom:member managementFeePct Management fee of the smart vault.\n * @custom:member depositFeePct Deposit fee of the smart vault.\n * @custom:member performanceFeePct Performance fee of the smart vault.\n */\nstruct SmartVaultRegistrationForm {\n    uint256 assetGroupId;\n    address[] strategies;\n    uint16a16 strategyAllocation;\n    uint16 managementFeePct;\n    uint16 depositFeePct;\n    uint16 performanceFeePct;\n}\n\n/**\n * @notice Parameters for reallocation.\n * @custom:member smartVaults Smart vaults to reallocate.\n * @custom:member strategies Set of strategies involved in the reallocation. Should not include ghost strategy, even if some smart vault uses it.\n * @custom:member swapInfo Information for swapping assets before depositing into the protocol.\n * @custom:member depositSlippages Slippages used to constrain depositing into the protocol.\n * @custom:member withdrawalSlippages Slippages used to contrain withdrawal from the protocol.\n * @custom:member exchangeRateSlippages Slippages used to constratrain exchange rates for asset tokens.\n * @custom:member validUntil Sets the maximum timestamp the user is willing to wait to start executing reallocation.\n */\nstruct ReallocateParamBag {\n    address[] smartVaults;\n    address[] strategies;\n    SwapInfo[][] swapInfo;\n    uint256[][] depositSlippages;\n    uint256[][] withdrawalSlippages;\n    uint256[2][] exchangeRateSlippages;\n    uint256 validUntil;\n}\n\nstruct FlushIndex {\n    uint128 current;\n    uint128 toSync;\n}\n\n/* ========== INTERFACES ========== */\n\ninterface ISmartVaultRegistry {\n    /**\n     * @notice Registers smart vault into the Spool protocol.\n     * @dev Requirements:\n     * - caller must have role ROLE_SMART_VAULT_INTEGRATOR\n     * @param smartVault Smart vault to register.\n     * @param registrationForm Form with information for registration.\n     */\n    function registerSmartVault(address smartVault, SmartVaultRegistrationForm calldata registrationForm) external;\n}\n\ninterface ISmartVaultManager is ISmartVaultRegistry {\n    /* ========== EXTERNAL VIEW FUNCTIONS ========== */\n\n    /**\n     * @notice Gets do-hard-work indexes.\n     * @param smartVault Smart vault.\n     * @param flushIndex Flush index.\n     * @return dhwIndexes Do-hard-work indexes for flush index of the smart vault.\n     */\n    function dhwIndexes(address smartVault, uint256 flushIndex) external view returns (uint16a16 dhwIndexes);\n\n    /**\n     * @notice Gets latest flush index for a smart vault.\n     * @param smartVault Smart vault.\n     * @return flushIndex Latest flush index for the smart vault.\n     */\n    function getLatestFlushIndex(address smartVault) external view returns (uint256 flushIndex);\n\n    /**\n     * @notice Gets strategy allocation for a smart vault.\n     * @param smartVault Smart vault.\n     * @return allocation Strategy allocation for the smart vault.\n     */\n    function allocations(address smartVault) external view returns (uint16a16 allocation);\n\n    /**\n     * @notice Gets strategies used by a smart vault.\n     * @param smartVault Smart vault.\n     * @return strategies Strategies for the smart vault.\n     */\n    function strategies(address smartVault) external view returns (address[] memory strategies);\n\n    /**\n     * @notice Gets asest group used by a smart vault.\n     * @param smartVault Smart vault.\n     * @return assetGroupId ID of the asset group used by the smart vault.\n     */\n    function assetGroupId(address smartVault) external view returns (uint256 assetGroupId);\n\n    /**\n     * @notice Gets required deposit ratio for a smart vault.\n     * @param smartVault Smart vault.\n     * @return ratio Required deposit ratio for the smart vault.\n     */\n    function depositRatio(address smartVault) external view returns (uint256[] memory ratio);\n\n    /* ========== EXTERNAL MUTATIVE FUNCTIONS ========== */\n\n    /**\n     * @notice Flushes deposits and withdrawal for the next do-hard-work.\n     * @param smartVault Smart vault to flush.\n     */\n    function flushSmartVault(address smartVault) external;\n\n    /**\n     * @notice Reallocates smart vaults.\n     * @dev Requirements:\n     * - caller must have a ROLE_REALLOCATOR role\n     * - smart vaults must be registered\n     * - smart vaults must use same asset group\n     * - strategies must represent a set of strategies used by smart vaults\n     * @param reallocateParams Paramaters for reallocation.\n     */\n    function reallocate(ReallocateParamBag calldata reallocateParams) external;\n\n    /**\n     * @notice Removes strategy from vaults, and optionally removes it from the system as well.\n     * @dev Requirements:\n     * - caller must have role ROLE_SPOOL_ADMIN\n     * - the strategy has to be active (requires ROLE_STRATEGY)\n     * @param strategy Strategy address to remove.\n     * @param vaults Array of vaults from which to remove the strategy\n     * @param disableStrategy Also disable the strategy across the system\n     */\n    function removeStrategyFromVaults(address strategy, address[] calldata vaults, bool disableStrategy) external;\n\n    /**\n     * @notice Syncs smart vault with strategies.\n     * @param smartVault Smart vault to sync.\n     * @param revertIfError If true, sync will revert if every flush index cannot be synced; if false it will sync all flush indexes it can.\n     */\n    function syncSmartVault(address smartVault, bool revertIfError) external;\n\n    /**\n     * @dev Calculate number of SVTs that haven't been synced yet after DHW runs\n     * DHW has minted strategy shares, but vaults haven't claimed them yet.\n     * Includes management fees (percentage of assets under management, distributed throughout a year) and deposit fees .\n     * Invariants:\n     * - There can't be more than once un-synced flush index per vault at any given time.\n     * - Flush index can't be synced, if all DHWs haven't been completed yet.\n     *\n     * Can be used to retrieve the number of SSTs the vault would claim during sync.\n     * @param smartVault SmartVault address\n     * @return oldTotalSVTs Amount of SVTs before sync\n     * @return mintedSVTs Amount of SVTs minted during sync\n     * @return feeSVTs Amount of SVTs pertaining to fees\n     * @return sstShares Amount of SSTs claimed per strategy\n     */\n    function simulateSync(address smartVault)\n        external\n        view\n        returns (uint256 oldTotalSVTs, uint256 mintedSVTs, uint256 feeSVTs, uint256[] calldata sstShares);\n\n    /**\n     * @dev Simulate sync when burning dNFTs and return their svts value.\n     *\n     * @param smartVault SmartVault address\n     * @param userAddress User address that owns dNFTs\n     * @param nftIds Ids of dNFTs\n     * @return svts Amount of svts user would get if he burns dNFTs\n     */\n    function simulateSyncWithBurn(address smartVault, address userAddress, uint256[] calldata nftIds)\n        external\n        view\n        returns (uint256 svts);\n\n    /**\n     * @notice Instantly redeems smart vault shares for assets.\n     * @param bag Parameters for fast redeemal.\n     * @param withdrawalSlippages Slippages guarding redeemal.\n     * @return withdrawnAssets Amount of assets withdrawn.\n     */\n    function redeemFast(RedeemBag calldata bag, uint256[][] calldata withdrawalSlippages)\n        external\n        returns (uint256[] memory withdrawnAssets);\n\n    /**\n     * @notice Simulates redeem fast of smart vault shares.\n     * @dev Should only be run by address zero to simulate the redeemal and parse logs.\n     * @param bag Parameters for fast redeemal.\n     * @param withdrawalSlippages Slippages guarding redeemal.\n     * @param redeemer Address of a user to simulate redeem for.\n     * @return withdrawnAssets Amount of assets withdrawn.\n     */\n    function redeemFastView(RedeemBag calldata bag, uint256[][] calldata withdrawalSlippages, address redeemer)\n        external\n        returns (uint256[] memory withdrawnAssets);\n\n    /**\n     * @notice Claims withdrawal of assets by burning withdrawal NFT.\n     * @dev Requirements:\n     * - withdrawal NFT must be valid\n     * @param smartVault Address of the smart vault that issued the withdrawal NFT.\n     * @param nftIds ID of withdrawal NFT to burn.\n     * @param nftAmounts amounts\n     * @param receiver Receiver of claimed assets.\n     * @return assetAmounts Amounts of assets claimed.\n     * @return assetGroupId ID of the asset group.\n     */\n    function claimWithdrawal(\n        address smartVault,\n        uint256[] calldata nftIds,\n        uint256[] calldata nftAmounts,\n        address receiver\n    ) external returns (uint256[] memory assetAmounts, uint256 assetGroupId);\n\n    /**\n     * @notice Claims smart vault tokens by burning the deposit NFT.\n     * @dev Requirements:\n     * - deposit NFT must be valid\n     * - flush must be synced\n     * @param smartVaultAddress Address of the smart vault that issued the deposit NFT.\n     * @param nftIds ID of the deposit NFT to burn.\n     * @param nftAmounts amounts\n     * @return claimedAmount Amount of smart vault tokens claimed.\n     */\n    function claimSmartVaultTokens(address smartVaultAddress, uint256[] calldata nftIds, uint256[] calldata nftAmounts)\n        external\n        returns (uint256 claimedAmount);\n\n    /**\n     * @notice Initiates a withdrawal process and mints a withdrawal NFT. Once all DHWs are executed, user can\n     * use the withdrawal NFT to claim the assets.\n     * Optionally, caller can pass a list of deposit NFTs to unwrap.\n     * @param bag smart vault address, amount of shares to redeem, nft ids and amounts to burn\n     * @param receiver address that will receive the withdrawal NFT\n     * @param doFlush optionally flush the smart vault\n     * @return receipt ID of the receipt withdrawal NFT.\n     */\n    function redeem(RedeemBag calldata bag, address receiver, bool doFlush) external returns (uint256 receipt);\n\n    /**\n     * @notice Initiates a withdrawal process and mints a withdrawal NFT. Once all DHWs are executed, user can\n     * use the withdrawal NFT to claim the assets.\n     * Optionally, caller can pass a list of deposit NFTs to unwrap.\n     * @param bag smart vault address, amount of shares to redeem, nft ids and amounts to burn\n     * @param owner address that owns the shares to be redeemed and will receive the withdrawal NFT\n     * @param doFlush optionally flush the smart vault\n     * @return receipt ID of the receipt withdrawal NFT.\n     */\n    function redeemFor(RedeemBag calldata bag, address owner, bool doFlush) external returns (uint256 receipt);\n\n    /**\n     * @notice Initiated a deposit and mints a deposit NFT. Once all DHWs are executed, user can\n     * unwrap the deposit NDF and claim his SVTs.\n     * @param bag smartVault address, assets, NFT receiver address, referral address, doFlush\n     * @return receipt ID of the receipt deposit NFT.\n     */\n    function deposit(DepositBag calldata bag) external returns (uint256 receipt);\n\n    /**\n     * @notice Recovers pending deposits from smart vault to emergency wallet.\n     * @dev Requirements:\n     * - caller must have role ROLE_SPOOL_ADMIN\n     * - all strategies of the smart vault need to be ghost strategies\n     * @param smartVault Smart vault from which to recover pending deposits.\n     */\n    function recoverPendingDeposits(address smartVault) external;\n\n    /* ========== EVENTS ========== */\n\n    /**\n     * @notice Smart vault has been flushed\n     * @param smartVault Smart vault address\n     * @param flushIndex Flush index\n     */\n    event SmartVaultFlushed(address indexed smartVault, uint256 flushIndex);\n\n    /**\n     * @notice Smart vault has been synced\n     * @param smartVault Smart vault address\n     * @param flushIndex Flush index\n     */\n    event SmartVaultSynced(address indexed smartVault, uint256 flushIndex);\n\n    /**\n     * @notice Smart vault has been registered\n     * @param smartVault Smart vault address\n     * @param registrationForm Smart vault configuration\n     */\n    event SmartVaultRegistered(address indexed smartVault, SmartVaultRegistrationForm registrationForm);\n\n    /**\n     * @notice Strategy was removed from the vault\n     * @param strategy Strategy address\n     * @param vault Vault to remove the strategy from\n     */\n    event StrategyRemovedFromVault(address indexed strategy, address indexed vault);\n\n    /**\n     * @notice Vault was reallocation executed\n     * @param smartVault Smart vault address\n     * @param newAllocations new vault strategy allocations\n     */\n    event SmartVaultReallocated(address indexed smartVault, uint16a16 newAllocations);\n}\n"
      },
      "src/interfaces/ISpoolAccessControl.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.17;\n\nimport \"@openzeppelin-upgradeable/access/IAccessControlUpgradeable.sol\";\n\n/**\n * @notice Used when an account is missing a required role.\n * @param role Required role.\n * @param account Account missing the required role.\n */\nerror MissingRole(bytes32 role, address account);\n\n/**\n * @notice Used when interacting with Spool when the system is paused.\n */\nerror SystemPaused();\n\n/**\n * @notice Used when setting smart vault owner\n */\nerror SmartVaultOwnerAlreadySet(address smartVault);\n\n/**\n * @notice Used when a contract tries to enter in a non-reentrant state.\n */\nerror ReentrantCall();\n\n/**\n * @notice Used when a contract tries to call in a non-reentrant function and doesn't have the correct role.\n */\nerror NoReentrantRole();\n\ninterface ISpoolAccessControl is IAccessControlUpgradeable {\n    /* ========== VIEW FUNCTIONS ========== */\n\n    /**\n     * @notice Gets owner of a smart vault.\n     * @param smartVault Smart vault.\n     * @return owner Owner of the smart vault.\n     */\n    function smartVaultOwner(address smartVault) external view returns (address owner);\n\n    /**\n     * @notice Looks if an account has a role for a smart vault.\n     * @param smartVault Address of the smart vault.\n     * @param role Role to look for.\n     * @param account Account to check.\n     * @return hasRole True if account has the role for the smart vault, false otherwise.\n     */\n    function hasSmartVaultRole(address smartVault, bytes32 role, address account)\n        external\n        view\n        returns (bool hasRole);\n\n    /**\n     * @notice Checks if an account is either Spool admin or admin for a smart vault.\n     * @dev The function reverts if account is neither.\n     * @param smartVault Address of the smart vault.\n     * @param account to check.\n     */\n    function checkIsAdminOrVaultAdmin(address smartVault, address account) external view;\n\n    /**\n     * @notice Checks if system is paused or not.\n     * @return isPaused True if system is paused, false otherwise.\n     */\n    function paused() external view returns (bool isPaused);\n\n    /* ========== MUTATIVE FUNCTIONS ========== */\n\n    /**\n     * @notice Pauses the whole system.\n     * @dev Requirements:\n     * - caller must have role ROLE_PAUSER\n     */\n    function pause() external;\n\n    /**\n     * @notice Unpauses the whole system.\n     * @dev Requirements:\n     * - caller must have role ROLE_UNPAUSER\n     */\n    function unpause() external;\n\n    /**\n     * @notice Grants role to an account for a smart vault.\n     * @dev Requirements:\n     * - caller must have either role ROLE_SPOOL_ADMIN or role ROLE_SMART_VAULT_ADMIN for the smart vault\n     * @param smartVault Address of the smart vault.\n     * @param role Role to grant.\n     * @param account Account to grant the role to.\n     */\n    function grantSmartVaultRole(address smartVault, bytes32 role, address account) external;\n\n    /**\n     * @notice Revokes role from an account for a smart vault.\n     * @dev Requirements:\n     * - caller must have either role ROLE_SPOOL_ADMIN or role ROLE_SMART_VAULT_ADMIN for the smart vault\n     * @param smartVault Address of the smart vault.\n     * @param role Role to revoke.\n     * @param account Account to revoke the role from.\n     */\n    function revokeSmartVaultRole(address smartVault, bytes32 role, address account) external;\n\n    /**\n     * @notice Renounce role for a smart vault.\n     * @param smartVault Address of the smart vault.\n     * @param role Role to renounce.\n     */\n    function renounceSmartVaultRole(address smartVault, bytes32 role) external;\n\n    /**\n     * @notice Grant ownership to smart vault and assigns admin role.\n     * @dev Ownership can only be granted once and it should be done at vault creation time.\n     * @param smartVault Address of the smart vault.\n     * @param owner address to which grant ownership to\n     */\n    function grantSmartVaultOwnership(address smartVault, address owner) external;\n\n    /**\n     * @notice Checks and reverts if a system has already entered in the non-reentrant state.\n     */\n    function checkNonReentrant() external view;\n\n    /**\n     * @notice Sets the entered flag to true when entering for the first time.\n     * @dev Reverts if a system has already entered before.\n     */\n    function nonReentrantBefore() external;\n\n    /**\n     * @notice Resets the entered flag after the call is finished.\n     */\n    function nonReentrantAfter() external;\n\n    /**\n     * @notice Emitted when ownership of a smart vault is granted to an address\n     * @param smartVault Smart vault address\n     * @param address_ Address of the new smart vault owner\n     */\n    event SmartVaultOwnershipGranted(address indexed smartVault, address indexed address_);\n\n    /**\n     * @notice Smart vault specific role was granted\n     * @param smartVault Smart vault address\n     * @param role Role ID\n     * @param account Account to which the role was granted\n     */\n    event SmartVaultRoleGranted(address indexed smartVault, bytes32 indexed role, address indexed account);\n\n    /**\n     * @notice Smart vault specific role was revoked\n     * @param smartVault Smart vault address\n     * @param role Role ID\n     * @param account Account for which the role was revoked\n     */\n    event SmartVaultRoleRevoked(address indexed smartVault, bytes32 indexed role, address indexed account);\n\n    /**\n     * @notice Smart vault specific role was renounced\n     * @param smartVault Smart vault address\n     * @param role Role ID\n     * @param account Account that renounced the role\n     */\n    event SmartVaultRoleRenounced(address indexed smartVault, bytes32 indexed role, address indexed account);\n}\n"
      },
      "src/interfaces/IStrategy.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.17;\n\nimport \"@openzeppelin/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport {PlatformFees} from \"./IStrategyRegistry.sol\";\nimport \"./ISwapper.sol\";\nimport \"./IUsdPriceFeedManager.sol\";\n\n/**\n * @notice Struct holding information how to swap the assets.\n * @custom:member slippage minumum output amount\n * @custom:member path swap path, first byte represents an action (e.g. Uniswap V2 custom swap), rest is swap specific path\n */\nstruct SwapData {\n    uint256 slippage; // min amount out\n    bytes path; // 1st byte is action, then path\n}\n\n/**\n * @notice Parameters for calling do hard work on strategy.\n * @custom:member swapInfo Information for swapping assets before depositing into the protocol.\n * @custom:member swapInfo Information for swapping rewards before depositing them back into the protocol.\n * @custom:member slippages Slippages used to constrain depositing and withdrawing from the protocol.\n * @custom:member assetGroup Asset group of the strategy.\n * @custom:member exchangeRates Exchange rates for assets.\n * @custom:member withdrawnShares Strategy shares withdrawn by smart vault.\n * @custom:member masterWallet Master wallet.\n * @custom:member priceFeedManager Price feed manager.\n * @custom:member baseYield Base yield value, manual input for specific strategies.\n * @custom:member platformFees Platform fees info.\n */\nstruct StrategyDhwParameterBag {\n    SwapInfo[] swapInfo;\n    SwapInfo[] compoundSwapInfo;\n    uint256[] slippages;\n    address[] assetGroup;\n    uint256[] exchangeRates;\n    uint256 withdrawnShares;\n    address masterWallet;\n    IUsdPriceFeedManager priceFeedManager;\n    int256 baseYield;\n    PlatformFees platformFees;\n}\n\n/**\n * @notice Information about results of the do hard work.\n * @custom:member sharesMinted Amount of strategy shares minted.\n * @custom:member assetsWithdrawn Amount of assets withdrawn.\n * @custom:member yieldPercentage Yield percentage from the previous DHW.\n * @custom:member valueAtDhw Value of the strategy at the end of DHW.\n * @custom:member totalSstsAtDhw Total SSTs at the end of DHW.\n */\nstruct DhwInfo {\n    uint256 sharesMinted;\n    uint256[] assetsWithdrawn;\n    int256 yieldPercentage;\n    uint256 valueAtDhw;\n    uint256 totalSstsAtDhw;\n}\n\n/**\n * @notice Used when ghost strategy is called.\n */\nerror IsGhostStrategy();\n\n/**\n * @notice Used when user is not allowed to redeem fast.\n * @param user User that tried to redeem fast.\n */\nerror NotFastRedeemer(address user);\n\n/**\n * @notice Used when asset group ID is not correctly initialized.\n */\nerror InvalidAssetGroupIdInitialization();\n\ninterface IStrategy is IERC20Upgradeable {\n    /* ========== EVENTS ========== */\n\n    event Deposited(\n        uint256 mintedShares, uint256 usdWorthDeposited, uint256[] assetsBeforeSwap, uint256[] assetsDeposited\n    );\n\n    event Withdrawn(uint256 withdrawnShares, uint256 usdWorthWithdrawn, uint256[] withdrawnAssets);\n\n    event PlatformFeesCollected(address indexed strategy, uint256 sharesMinted);\n\n    event Slippages(bool isDeposit, uint256 slippage, bytes data);\n\n    event BeforeDepositCheckSlippages(uint256[] amounts);\n\n    event BeforeRedeemalCheckSlippages(uint256 ssts);\n\n    /* ========== VIEW FUNCTIONS ========== */\n\n    /**\n     * @notice Gets strategy name.\n     * @return name Name of the strategy.\n     */\n    function strategyName() external view returns (string memory name);\n\n    /**\n     * @notice Gets required ratio between underlying assets.\n     * @return ratio Required asset ratio for the strategy.\n     */\n    function assetRatio() external view returns (uint256[] memory ratio);\n\n    /**\n     * @notice Gets asset group used by the strategy.\n     * @return id ID of the asset group.\n     */\n    function assetGroupId() external view returns (uint256 id);\n\n    /**\n     * @notice Gets underlying assets for the strategy.\n     * @return assets Addresses of the underlying assets.\n     */\n    function assets() external view returns (address[] memory assets);\n\n    /**\n     * @notice Gets underlying asset amounts for the strategy.\n     * @return amounts Amounts of the underlying assets.\n     */\n    function getUnderlyingAssetAmounts() external view returns (uint256[] memory amounts);\n\n    /* ========== MUTATIVE FUNCTIONS ========== */\n\n    /**\n     * @dev Performs slippages check before depositing.\n     * @param amounts Amounts to be deposited.\n     * @param slippages Slippages to check against.\n     */\n    function beforeDepositCheck(uint256[] memory amounts, uint256[] calldata slippages) external;\n\n    /**\n     * @dev Performs slippages check before redeemal.\n     * @param ssts Amount of strategy tokens to be redeemed.\n     * @param slippages Slippages to check against.\n     */\n    function beforeRedeemalCheck(uint256 ssts, uint256[] calldata slippages) external;\n\n    /**\n     * @notice Does hard work:\n     * - compounds rewards\n     * - deposits into the protocol\n     * - withdraws from the protocol\n     * @dev Requirements:\n     * - caller must have role ROLE_STRATEGY_REGISTRY\n     * @param dhwParams Parameters for the do hard work.\n     * @return info Information about do the performed hard work.\n     */\n    function doHardWork(StrategyDhwParameterBag calldata dhwParams) external returns (DhwInfo memory info);\n\n    /**\n     * @notice Claims strategy shares after do-hard-work.\n     * @dev Requirements:\n     * - caller must have role ROLE_SMART_VAULT_MANAGER\n     * @param smartVault Smart vault claiming shares.\n     * @param amount Amount of strategy shares to claim.\n     */\n    function claimShares(address smartVault, uint256 amount) external;\n\n    /**\n     * @notice Releases shares back to strategy.\n     * @dev Requirements:\n     * - caller must have role ROLE_SMART_VAULT_MANAGER\n     * @param smartVault Smart vault releasing shares.\n     * @param amount Amount of strategy shares to release.\n     */\n    function releaseShares(address smartVault, uint256 amount) external;\n\n    /**\n     * @notice Instantly redeems strategy shares for assets.\n     * @dev Requirements:\n     * - caller must have either role ROLE_SMART_VAULT_MANAGER or role ROLE_STRATEGY_REGISTRY\n     * @param shares Amount of shares to redeem.\n     * @param masterWallet Address of the master wallet.\n     * @param assetGroup Asset group of the strategy.\n     * @param slippages Slippages to guard redeeming.\n     * @return assetsWithdrawn Amount of assets withdrawn.\n     */\n    function redeemFast(\n        uint256 shares,\n        address masterWallet,\n        address[] calldata assetGroup,\n        uint256[] calldata slippages\n    ) external returns (uint256[] memory assetsWithdrawn);\n\n    /**\n     * @notice Instantly redeems strategy shares for assets.\n     * @param shares Amount of shares to redeem.\n     * @param redeemer Address of he redeemer, owner of SSTs.\n     * @param assetGroup Asset group of the strategy.\n     * @param slippages Slippages to guard redeeming.\n     * @return assetsWithdrawn Amount of assets withdrawn.\n     */\n    function redeemShares(uint256 shares, address redeemer, address[] calldata assetGroup, uint256[] calldata slippages)\n        external\n        returns (uint256[] memory assetsWithdrawn);\n\n    /**\n     * @notice Instantly deposits into the protocol.\n     * @dev Requirements:\n     * - caller must have role ROLE_SMART_VAULT_MANAGER\n     * @param assetGroup Asset group of the strategy.\n     * @param exchangeRates Asset to USD exchange rates.\n     * @param priceFeedManager Price feed manager contract.\n     * @param slippages Slippages to guard depositing.\n     * @param swapInfo Information for swapping assets before depositing into the protocol.\n     * @return sstsMinted Amount of SSTs minted.\n     */\n    function depositFast(\n        address[] calldata assetGroup,\n        uint256[] calldata exchangeRates,\n        IUsdPriceFeedManager priceFeedManager,\n        uint256[] calldata slippages,\n        SwapInfo[] calldata swapInfo\n    ) external returns (uint256 sstsMinted);\n\n    /**\n     * @notice Instantly withdraws assets, bypassing shares mechanism.\n     * Transfers withdrawn assets to the emergency withdrawal wallet.\n     * @dev Requirements:\n     * - caller must have role ROLE_STRATEGY_REGISTRY\n     * @param slippages Slippages to guard redeeming.\n     * @param recipient Recipient address\n     */\n    function emergencyWithdraw(uint256[] calldata slippages, address recipient) external;\n\n    /**\n     * @notice Gets USD worth of the strategy.\n     * @dev Requirements:\n     * - caller must have role ROLE_SMART_VAULT_MANAGER\n     * @param exchangeRates Asset to USD exchange rates.\n     * @param priceFeedManager Price feed manager contract.\n     */\n    function getUsdWorth(uint256[] memory exchangeRates, IUsdPriceFeedManager priceFeedManager)\n        external\n        returns (uint256 usdWorth);\n\n    /**\n     * @notice Gets protocol rewards.\n     * @dev Requirements:\n     * - can only be called in view-execution mode.\n     * @return tokens Addresses of reward tokens.\n     * @return amounts Amount of reward tokens available.\n     */\n    function getProtocolRewards() external returns (address[] memory tokens, uint256[] memory amounts);\n}\n"
      },
      "src/interfaces/CommonErrors.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.17;\n\n/**\n * @notice Used when an array has invalid length.\n */\nerror InvalidArrayLength();\n\n/**\n * @notice Used when group of smart vaults or strategies do not have same asset group.\n */\nerror NotSameAssetGroup();\n\n/**\n * @notice Used when configuring an address with a zero address.\n */\nerror ConfigurationAddressZero();\n\n/**\n * @notice Used when constructor or intializer parameters are invalid.\n */\nerror InvalidConfiguration();\n\n/**\n * @notice Used when fetched exchange rate is out of slippage range.\n */\nerror ExchangeRateOutOfSlippages();\n\n/**\n * @notice Used when an invalid strategy is provided.\n * @param address_ Address of the invalid strategy.\n */\nerror InvalidStrategy(address address_);\n\n/**\n * @notice Used when doing low-level call on an address that is not a contract.\n * @param address_ Address of the contract\n */\nerror AddressNotContract(address address_);\n\n/**\n * @notice Used when invoking an only view execution and tx.origin is not address zero.\n * @param address_ Address of the tx.origin\n */\nerror OnlyViewExecution(address address_);\n"
      },
      "src/interfaces/Constants.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.17;\n\n/// @dev Number of seconds in an average year.\nuint256 constant SECONDS_IN_YEAR = 31_556_926;\n\n/// @dev Number of seconds in an average year.\nint256 constant SECONDS_IN_YEAR_INT = 31_556_926;\n\n/// @dev Represents 100%.\nuint256 constant FULL_PERCENT = 100_00;\n\n/// @dev Represents 100%.\nint256 constant FULL_PERCENT_INT = 100_00;\n\n/// @dev Represents 100% for yield.\nint256 constant YIELD_FULL_PERCENT_INT = 10 ** 12;\n\n/// @dev Represents 100% for yield.\nuint256 constant YIELD_FULL_PERCENT = uint256(YIELD_FULL_PERCENT_INT);\n\n/// @dev Maximal management fee that can be set on a smart vault. Expressed in terms of FULL_PERCENT.\nuint256 constant MANAGEMENT_FEE_MAX = 5_00;\n\n/// @dev Maximal deposit fee that can be set on a smart vault. Expressed in terms of FULL_PERCENT.\nuint256 constant DEPOSIT_FEE_MAX = 5_00;\n\n/// @dev Maximal smart vault performance fee that can be set on a smart vault. Expressed in terms of FULL_PERCENT.\nuint256 constant SV_PERFORMANCE_FEE_MAX = 20_00;\n\n/// @dev Maximal ecosystem fee that can be set on the system. Expressed in terms of FULL_PERCENT.\nuint256 constant ECOSYSTEM_FEE_MAX = 20_00;\n\n/// @dev Maximal treasury fee that can be set on the system. Expressed in terms of FULL_PERCENT.\nuint256 constant TREASURY_FEE_MAX = 10_00;\n\n/// @dev Maximal risk score a strategy can be assigned.\nuint8 constant MAX_RISK_SCORE = 10_0;\n\n/// @dev Minimal risk score a strategy can be assigned.\nuint8 constant MIN_RISK_SCORE = 1;\n\n/// @dev Maximal value for risk tolerance a smart vautl can have.\nint8 constant MAX_RISK_TOLERANCE = 10;\n\n/// @dev Minimal value for risk tolerance a smart vault can have.\nint8 constant MIN_RISK_TOLERANCE = -10;\n\n/// @dev If set as risk provider, system will return fixed risk score values\naddress constant STATIC_RISK_PROVIDER = address(0xaaa);\n\n/// @dev Fixed values to use if risk provider is set to STATIC_RISK_PROVIDER\nuint8 constant STATIC_RISK_SCORE = 1;\n\n/// @dev Maximal value of deposit NFT ID.\nuint256 constant MAXIMAL_DEPOSIT_ID = 2 ** 255;\n\n/// @dev Maximal value of withdrawal NFT ID.\nuint256 constant MAXIMAL_WITHDRAWAL_ID = 2 ** 256 - 1;\n\n/// @dev How many shares will be minted with a NFT\nuint256 constant NFT_MINTED_SHARES = 10 ** 6;\n\n/// @dev Each smart vault can have up to STRATEGY_COUNT_CAP strategies.\nuint256 constant STRATEGY_COUNT_CAP = 16;\n\n/// @dev Maximal DHW base yield. Expressed in terms of FULL_PERCENT.\nuint256 constant MAX_DHW_BASE_YIELD_LIMIT = 10_00;\n\n/// @dev Smart vault and strategy share multiplier at first deposit.\nuint256 constant INITIAL_SHARE_MULTIPLIER = 1000;\n\n/// @dev Strategy initial locked shares. These shares will never be unlocked.\nuint256 constant INITIAL_LOCKED_SHARES = 10 ** 12;\n\n/// @dev Strategy initial locked shares address.\naddress constant INITIAL_LOCKED_SHARES_ADDRESS = address(0xdead);\n\n/// @dev Maximum number of guards a smart vault can be configured with\nuint256 constant MAX_GUARD_COUNT = 10;\n\n/// @dev Maximum number of actions a smart vault can be configured with\nuint256 constant MAX_ACTION_COUNT = 10;\n\n/// @dev ID of null asset group. Should not be used by any strategy or smart vault.\nuint256 constant NULL_ASSET_GROUP_ID = 0;\n"
      },
      "src/interfaces/RequestType.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.17;\n\n/**\n * @notice Different request types for guards and actions.\n * @custom:member Deposit User is depositing into a smart vault.\n * @custom:member Withdrawal User is requesting withdrawal from a smart vault.\n * @custom:member TransferNFT User is transfering deposit or withdrawal NFT.\n * @custom:member BurnNFT User is burning deposit or withdrawal NFT.\n * @custom:member TransferSVTs User is transferring smart vault tokens.\n */\nenum RequestType {\n    Deposit,\n    Withdrawal,\n    TransferNFT,\n    BurnNFT,\n    TransferSVTs\n}\n"
      },
      "src/access/Roles.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.17;\n\n/**\n * @dev Grants permission to:\n * - acts as a default admin for other roles,\n * - can whitelist an action with action manager,\n * - can manage asset group registry.\n *\n * Is granted to the deployer of the SpoolAccessControl contract.\n *\n * Equals to the DEFAULT_ADMIN_ROLE of the OpenZeppelin AccessControl.\n */\nbytes32 constant ROLE_SPOOL_ADMIN = 0x00;\n\n/**\n * @dev Grants permission to integrate a new smart vault into the Spool ecosystem.\n *\n * Should be granted to smart vault factory contracts.\n */\nbytes32 constant ROLE_SMART_VAULT_INTEGRATOR = keccak256(\"SMART_VAULT_INTEGRATOR\");\n\n/**\n * @dev Grants permission to\n * - manage rewards on smart vaults,\n * - manage roles on smart vaults,\n * - redeem for another user of a smart vault.\n */\nbytes32 constant ROLE_SMART_VAULT_ADMIN = keccak256(\"SMART_VAULT_ADMIN\");\n\n/**\n * @dev Grants permission to manage allowlists with AllowlistGuard for a smart vault.\n *\n * Should be granted to whoever is in charge of maintaining allowlists with AllowlistGuard for a smart vault.\n */\nbytes32 constant ROLE_GUARD_ALLOWLIST_MANAGER = keccak256(\"GUARD_ALLOWLIST_MANAGER\");\n\n/**\n * @dev Grants permission to manage assets on master wallet.\n *\n * Should be granted to:\n * - the SmartVaultManager contract,\n * - the StrategyRegistry contract,\n * - the DepositManager contract,\n * - the WithdrawalManager contract.\n */\nbytes32 constant ROLE_MASTER_WALLET_MANAGER = keccak256(\"MASTER_WALLET_MANAGER\");\n\n/**\n * @dev Marks a contract as a smart vault manager.\n *\n * Should be granted to:\n * - the SmartVaultManager contract,\n * - the DepositManager contract.\n */\nbytes32 constant ROLE_SMART_VAULT_MANAGER = keccak256(\"SMART_VAULT_MANAGER\");\n\n/**\n * @dev Marks a contract as a strategy registry.\n *\n * Should be granted to the StrategyRegistry contract.\n */\nbytes32 constant ROLE_STRATEGY_REGISTRY = keccak256(\"STRATEGY_REGISTRY\");\n\n/**\n * @dev Grants permission to act as a risk provider.\n *\n * Should be granted to whoever is allowed to provide risk scores.\n */\nbytes32 constant ROLE_RISK_PROVIDER = keccak256(\"RISK_PROVIDER\");\n\n/**\n * @dev Grants permission to act as an allocation provider.\n *\n * Should be granted to contracts that are allowed to calculate allocations.\n */\nbytes32 constant ROLE_ALLOCATION_PROVIDER = keccak256(\"ALLOCATION_PROVIDER\");\n\n/**\n * @dev Grants permission to pause the system.\n */\nbytes32 constant ROLE_PAUSER = keccak256(\"SYSTEM_PAUSER\");\n\n/**\n * @dev Grants permission to unpause the system.\n */\nbytes32 constant ROLE_UNPAUSER = keccak256(\"SYSTEM_UNPAUSER\");\n\n/**\n * @dev Grants permission to manage rewards payment pool.\n */\nbytes32 constant ROLE_REWARD_POOL_ADMIN = keccak256(\"REWARD_POOL_ADMIN\");\n\n/**\n * @dev Grants permission to reallocate smart vaults.\n */\nbytes32 constant ROLE_REALLOCATOR = keccak256(\"REALLOCATOR\");\n\n/**\n * @dev Grants permission to be used as a strategy.\n */\nbytes32 constant ROLE_STRATEGY = keccak256(\"STRATEGY\");\n\n/**\n * @dev Grants permission to manually set strategy apy.\n */\nbytes32 constant ROLE_STRATEGY_APY_SETTER = keccak256(\"STRATEGY_APY_SETTER\");\n\n/**\n * @dev Grants permission to manage role ROLE_STRATEGY.\n */\nbytes32 constant ADMIN_ROLE_STRATEGY = keccak256(\"ADMIN_STRATEGY\");\n\n/**\n * @dev Grants permission vault admins to allow redeem on behalf of other users.\n */\nbytes32 constant ROLE_SMART_VAULT_ALLOW_REDEEM = keccak256(\"SMART_VAULT_ALLOW_REDEEM\");\n\n/**\n * @dev Grants permission to manage role ROLE_SMART_VAULT_ALLOW_REDEEM.\n */\nbytes32 constant ADMIN_ROLE_SMART_VAULT_ALLOW_REDEEM = keccak256(\"ADMIN_SMART_VAULT_ALLOW_REDEEM\");\n\n/**\n * @dev Grants permission to run do hard work.\n */\nbytes32 constant ROLE_DO_HARD_WORKER = keccak256(\"DO_HARD_WORKER\");\n\n/**\n * @dev Grants permission to immediately withdraw assets in case of emergency.\n */\nbytes32 constant ROLE_EMERGENCY_WITHDRAWAL_EXECUTOR = keccak256(\"EMERGENCY_WITHDRAWAL_EXECUTOR\");\n\n/**\n * @dev Grants permission to swap with swapper.\n *\n * Should be granted to the DepositSwap contract.\n */\nbytes32 constant ROLE_SWAPPER = keccak256(\"SWAPPER\");\n"
      },
      "src/access/SpoolAccessControllable.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.17;\n\nimport \"../interfaces/ISpoolAccessControl.sol\";\nimport \"../interfaces/CommonErrors.sol\";\nimport \"./Roles.sol\";\n\n/**\n * @notice Account access role verification middleware\n */\nabstract contract SpoolAccessControllable {\n    /* ========== CONSTANTS ========== */\n\n    /**\n     * @dev Spool access control manager.\n     */\n    ISpoolAccessControl internal immutable _accessControl;\n\n    /* ========== CONSTRUCTOR ========== */\n\n    /**\n     * @param accessControl_ Spool access control manager.\n     */\n    constructor(ISpoolAccessControl accessControl_) {\n        if (address(accessControl_) == address(0)) revert ConfigurationAddressZero();\n\n        _accessControl = accessControl_;\n    }\n\n    /* ========== INTERNAL FUNCTIONS ========== */\n\n    /**\n     * @dev Reverts if an account is missing a role.\\\n     * @param role Role to check for.\n     * @param account Account to check.\n     */\n    function _checkRole(bytes32 role, address account) internal view virtual {\n        if (!_accessControl.hasRole(role, account)) {\n            revert MissingRole(role, account);\n        }\n    }\n\n    /**\n     * @dev Revert if an account is missing a role for a smartVault.\n     * @param smartVault Address of the smart vault.\n     * @param role Role to check for.\n     * @param account Account to check.\n     */\n    function _checkSmartVaultRole(address smartVault, bytes32 role, address account) internal view {\n        if (!_accessControl.hasSmartVaultRole(smartVault, role, account)) {\n            revert MissingRole(role, account);\n        }\n    }\n\n    /**\n     * @dev Throws if the contract is paused.\n     */\n    function _requireNotPaused() internal view virtual {\n        if (_accessControl.paused()) {\n            revert SystemPaused();\n        }\n    }\n\n    function _checkNonReentrant() internal view {\n        _accessControl.checkNonReentrant();\n    }\n\n    function _nonReentrantBefore() internal {\n        _accessControl.nonReentrantBefore();\n    }\n\n    function _nonReentrantAfter() internal {\n        _accessControl.nonReentrantAfter();\n    }\n\n    /* ========== MODIFIERS ========== */\n\n    /**\n     * @notice Only allows accounts with granted role.\n     * @dev Reverts when the account fails check.\n     * @param role Role to check for.\n     * @param account Account to check.\n     */\n    modifier onlyRole(bytes32 role, address account) {\n        _checkRole(role, account);\n        _;\n    }\n\n    /**\n     * @notice Only allows accounts with granted role for a smart vault.\n     * @dev Reverts when the account fails check.\n     * @param smartVault Address of the smart vault.\n     * @param role Role to check for.\n     * @param account Account to check.\n     */\n    modifier onlySmartVaultRole(address smartVault, bytes32 role, address account) {\n        _checkSmartVaultRole(smartVault, role, account);\n        _;\n    }\n\n    /**\n     * @notice Only allows accounts that are Spool admins or admins of a smart vault.\n     * @dev Reverts when the account fails check.\n     * @param smartVault Address of the smart vault.\n     * @param account Account to check.\n     */\n    modifier onlyAdminOrVaultAdmin(address smartVault, address account) {\n        _accessControl.checkIsAdminOrVaultAdmin(smartVault, account);\n        _;\n    }\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is not paused.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    modifier whenNotPaused() {\n        _requireNotPaused();\n        _;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, or other contracts using this modifier.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    /**\n     * @dev Check if a system has already entered in the non-reentrant state.\n     */\n    modifier checkNonReentrant() {\n        _checkNonReentrant();\n        _;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n"
      },
      "src/SmartVault.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.17;\n\nimport \"@openzeppelin/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/utils/Strings.sol\";\nimport \"@openzeppelin-upgradeable/token/ERC1155/ERC1155Upgradeable.sol\";\nimport \"@openzeppelin-upgradeable/token/ERC20/extensions/draft-ERC20PermitUpgradeable.sol\";\nimport \"./interfaces/IGuardManager.sol\";\nimport \"./interfaces/ISmartVault.sol\";\nimport \"./interfaces/CommonErrors.sol\";\nimport \"./interfaces/RequestType.sol\";\nimport \"./access/SpoolAccessControllable.sol\";\nimport \"./libraries/ArrayMapping.sol\";\n\ncontract SmartVault is ERC20PermitUpgradeable, ERC1155Upgradeable, SpoolAccessControllable, ISmartVault {\n    using SafeERC20 for IERC20;\n    using ArrayMappingUint256 for mapping(uint256 => uint256);\n\n    /* ========== CONSTANTS ========== */\n\n    /// @notice Guard manager\n    IGuardManager internal immutable _guardManager;\n\n    /// @notice Asset group ID\n    uint256 public assetGroupId;\n\n    /// @notice Vault name\n    string internal _vaultName;\n\n    /* ========== STATE VARIABLES ========== */\n\n    /// @notice Deposit metadata registry\n    mapping(uint256 => DepositMetadata) private _depositMetadata;\n\n    /// @notice Withdrawal metadata registry\n    mapping(uint256 => WithdrawalMetadata) private _withdrawalMetadata;\n\n    /// @notice Deposit NFT ID\n    uint256 private _lastDepositId;\n\n    /// @notice Withdrawal NFT ID\n    uint256 private _lastWithdrawalId;\n\n    /* ========== CONSTRUCTOR ========== */\n\n    constructor(ISpoolAccessControl accessControl_, IGuardManager guardManager_)\n        SpoolAccessControllable(accessControl_)\n    {\n        if (address(guardManager_) == address(0)) revert ConfigurationAddressZero();\n\n        _guardManager = guardManager_;\n\n        _disableInitializers();\n    }\n\n    function initialize(\n        string calldata vaultName_,\n        string calldata svtSymbol,\n        string calldata baseURI_,\n        uint256 assetGroupId_\n    ) external initializer {\n        if (bytes(vaultName_).length == 0) revert InvalidConfiguration();\n\n        __ERC1155_init(baseURI_);\n        __ERC20_init(vaultName_, svtSymbol);\n\n        _vaultName = vaultName_;\n        assetGroupId = assetGroupId_;\n\n        _lastDepositId = 0;\n        _lastWithdrawalId = MAXIMAL_DEPOSIT_ID;\n    }\n\n    /* ========== EXTERNAL VIEW FUNCTIONS ========== */\n\n    /**\n     * @dev Returns the URI for token type `id`.\n     * Base functionality is used to hold the base URI string.\n     * We override and append the token ID.\n     */\n    function uri(uint256 tokenId)\n        public\n        view\n        override(ERC1155Upgradeable, IERC1155MetadataURIUpgradeable)\n        returns (string memory)\n    {\n        return string(abi.encodePacked(super.uri(0), Strings.toString(tokenId), \".json\"));\n    }\n\n    /**\n     * @dev See {IERC1155-balanceOf}.\n     * Returns 1 if user has any balance, 0 otherwise.\n     *\n     * Requirements:\n     *\n     * - `account` cannot be the zero address.\n     */\n    function balanceOf(address account, uint256 id)\n        public\n        view\n        override(ERC1155Upgradeable, IERC1155Upgradeable)\n        returns (uint256)\n    {\n        return super.balanceOf(account, id) >= 1 ? 1 : 0;\n    }\n\n    function balanceOfFractional(address account, uint256 id) public view returns (uint256) {\n        return super.balanceOf(account, id);\n    }\n\n    /**\n     * @notice Returns user's NFT balance\n     * @dev 1 if user has any balance, 0 otherwise.\n     */\n    function balanceOfBatch(address[] memory accounts, uint256[] memory ids)\n        public\n        view\n        override(ERC1155Upgradeable, IERC1155Upgradeable)\n        returns (uint256[] memory)\n    {\n        require(accounts.length == ids.length, \"ERC1155: accounts and ids length mismatch\");\n        uint256[] memory batchBalances = new uint256[](accounts.length);\n\n        for (uint256 i; i < accounts.length; ++i) {\n            batchBalances[i] = balanceOf(accounts[i], ids[i]);\n        }\n\n        return batchBalances;\n    }\n\n    function balanceOfFractionalBatch(address account, uint256[] calldata ids) public view returns (uint256[] memory) {\n        uint256[] memory batchBalances = new uint256[](ids.length);\n\n        for (uint256 i; i < ids.length; ++i) {\n            batchBalances[i] = balanceOfFractional(account, ids[i]);\n        }\n\n        return batchBalances;\n    }\n\n    function vaultName() external view returns (string memory) {\n        return _vaultName;\n    }\n\n    function getMetadata(uint256[] calldata nftIds) public view returns (bytes[] memory) {\n        bytes[] memory metadata = new bytes[](nftIds.length);\n\n        for (uint256 i; i < nftIds.length; ++i) {\n            metadata[i] = nftIds[i] > MAXIMAL_DEPOSIT_ID\n                ? abi.encode(_withdrawalMetadata[nftIds[i]])\n                : abi.encode(_depositMetadata[nftIds[i]]);\n        }\n\n        return metadata;\n    }\n\n    /* ========== EXTERNAL MUTATIVE FUNCTIONS ========== */\n\n    /**\n     * @notice Set a new base URI for ERC1155 metadata and emits an event.\n     * @param uri_ new base URI value\n     */\n    function setBaseURI(string memory uri_) external onlyAdminOrVaultAdmin(address(this), msg.sender) {\n        _setURI(uri_);\n        emit BaseURIChanged(uri_);\n    }\n\n    function mintVaultShares(address receiver, uint256 vaultShares)\n        external\n        onlyRole(ROLE_SMART_VAULT_MANAGER, msg.sender)\n    {\n        _mint(receiver, vaultShares);\n    }\n\n    function burnVaultShares(\n        address owner,\n        uint256 vaultShares,\n        address[] calldata strategies,\n        uint256[] calldata shares\n    ) external onlyRole(ROLE_SMART_VAULT_MANAGER, msg.sender) {\n        // burn withdrawn vault shares\n        _burn(owner, vaultShares);\n\n        for (uint256 i; i < strategies.length; ++i) {\n            if (shares[i] > 0) {\n                IERC20(strategies[i]).safeTransfer(strategies[i], shares[i]);\n            }\n        }\n    }\n\n    function burnNFTs(address owner, uint256[] calldata nftIds, uint256[] calldata nftAmounts)\n        external\n        onlyRole(ROLE_SMART_VAULT_MANAGER, msg.sender)\n        returns (bytes[] memory)\n    {\n        _burnBatch(owner, nftIds, nftAmounts);\n        return getMetadata(nftIds);\n    }\n\n    function claimShares(address claimer, uint256 amount) external onlyRole(ROLE_SMART_VAULT_MANAGER, msg.sender) {\n        _transfer(address(this), claimer, amount);\n    }\n\n    function mintDepositNFT(address receiver, DepositMetadata calldata metadata)\n        external\n        onlyRole(ROLE_SMART_VAULT_MANAGER, msg.sender)\n        returns (uint256)\n    {\n        if (_lastDepositId >= MAXIMAL_DEPOSIT_ID) {\n            revert DepositIdOverflow();\n        }\n        _lastDepositId++;\n        _depositMetadata[_lastDepositId] = metadata;\n        _mint(receiver, _lastDepositId, NFT_MINTED_SHARES, \"\");\n\n        return _lastDepositId;\n    }\n\n    function mintWithdrawalNFT(address receiver, WithdrawalMetadata memory metadata)\n        external\n        onlyRole(ROLE_SMART_VAULT_MANAGER, msg.sender)\n        returns (uint256 receipt)\n    {\n        if (_lastWithdrawalId >= MAXIMAL_WITHDRAWAL_ID) {\n            revert WithdrawalIdOverflow();\n        }\n        _lastWithdrawalId++;\n        _withdrawalMetadata[_lastWithdrawalId] = metadata;\n        _mint(receiver, _lastWithdrawalId, NFT_MINTED_SHARES, \"\");\n\n        return _lastWithdrawalId;\n    }\n\n    function transferFromSpender(address from, address to, uint256 amount)\n        external\n        onlyRole(ROLE_SMART_VAULT_MANAGER, msg.sender)\n        returns (bool)\n    {\n        _transfer(from, to, amount);\n        return true;\n    }\n\n    /* ========== INTERNAL FUNCTIONS ========== */\n\n    function _beforeTokenTransfer(address from, address to, uint256 amount) internal view override {\n        _requireNotPaused();\n\n        // mint / burn / redeem\n        if (from == address(0) || to == address(0) || to == address(this)) return;\n        if (from == to) revert SenderEqualsRecipient();\n\n        uint256[] memory assets = new uint256[](1);\n        assets[0] = amount;\n\n        RequestContext memory context = RequestContext({\n            receiver: to,\n            executor: msg.sender,\n            owner: from,\n            requestType: RequestType.TransferSVTs,\n            assets: assets,\n            tokens: new address[](0)\n        });\n        _guardManager.runGuards(address(this), context);\n    }\n\n    function _beforeTokenTransfer(\n        address operator,\n        address from,\n        address to,\n        uint256[] memory ids,\n        uint256[] memory amounts,\n        bytes memory\n    ) internal view override {\n        _requireNotPaused();\n\n        // skip transfer checks when minting and burning\n        // they have their own checks made\n        if (from == address(0) || to == address(0)) return;\n        if (from == to) revert SenderEqualsRecipient();\n\n        // check that only full NFT can be transferred\n        for (uint256 i; i < ids.length; ++i) {\n            if (amounts[i] != NFT_MINTED_SHARES) {\n                revert InvalidNftTransferAmount(amounts[i]);\n            }\n        }\n\n        // NOTE:\n        // - here we are passing ids into the request context instead of amounts\n        // - here we passing empty array as tokens\n        RequestContext memory context = RequestContext({\n            receiver: to,\n            executor: operator,\n            owner: from,\n            requestType: RequestType.TransferNFT,\n            assets: ids,\n            tokens: new address[](0)\n        });\n        _guardManager.runGuards(address(this), context);\n    }\n}\n"
      },
      "src/SmartVaultFactory.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.17;\n\nimport \"@openzeppelin/proxy/beacon/BeaconProxy.sol\";\nimport \"@openzeppelin/proxy/beacon/UpgradeableBeacon.sol\";\nimport \"./interfaces/IAction.sol\";\nimport \"./interfaces/IAssetGroupRegistry.sol\";\nimport \"./interfaces/IGuardManager.sol\";\nimport \"./interfaces/IRiskManager.sol\";\nimport \"./interfaces/ISmartVault.sol\";\nimport \"./interfaces/ISmartVaultManager.sol\";\nimport \"./interfaces/ISpoolAccessControl.sol\";\nimport \"./interfaces/IStrategy.sol\";\nimport \"./interfaces/CommonErrors.sol\";\nimport \"./interfaces/Constants.sol\";\nimport \"./interfaces/RequestType.sol\";\nimport \"./access/Roles.sol\";\nimport \"./SmartVault.sol\";\n\n/* ========== ERRORS ========== */\n\n/**\n * @notice Used when no strategy was provided during smart vault registration.\n */\nerror SmartVaultRegistrationNoStrategies();\n\n/**\n * @notice Used when too many strategies were provided during smart vault registration.\n */\nerror StrategyCapExceeded();\n\n/**\n * @notice Used when user has duplicated strategies when creating a new vault\n */\nerror StrategiesNotUnique();\n\n/**\n * @notice Used when the number of allocation values is less than the number of strategies.\n */\nerror InvalidStrategyAllocationsLength();\n\n/**\n * @notice Used when provided static allocation does not sum to FULL_PERCENT.\n */\nerror InvalidStaticAllocation();\n\n/**\n * @notice Used when smart vault has set static allocation and risk provider.\n */\nerror StaticAllocationAndRiskProviderSet();\n\n/**\n * @notice Used when smart vault has set static allocation and risk tolerance.\n */\nerror StaticAllocationAndRiskToleranceSet();\n\n/**\n * @notice Used when smart vault has set static allocation and allocation provider.\n */\nerror StaticAllocationAndAllocationProviderSet();\n\n/**\n * @notice Used when smart vault has only one strategy but does not set static allocation.\n */\nerror SingleStrategyDynamicAllocation();\n\n/* ========== STRUCTS ========== */\n\n/**\n * @notice Specification for smart vault deployment.\n * @custom:member smartVaultName Name of the smart vault.\n * @custom:member assetGroupId ID of the asset group.\n * @custom:member strategies Strategies used by the smart vault.\n * @custom:member strategyAllocation Optional. If empty array, values will be calculated on the spot.\n * @custom:member riskTolerance Risk appetite of the smart vault.\n * @custom:member riskProvider Risk provider used by the smart vault.\n * @custom:member allocationProvider Allocation provider used by the smart vault.\n * @custom:member actions Actions to register for the smart vault.\n * @custom:member actionRequestTypes Request types for actions.\n * @custom:member guards Guards to register for the smart vault.\n * @custom:member guardRequestTypes Request types for the smart vault.\n * @custom:member managementFeePCt Management fee percentage.\n * @custom:member depositFeePct Deposit fee percentage.\n * @custom:member allowRedeemFor Allow vault owner to initiate redeem on behalf of others.\n */\nstruct SmartVaultSpecification {\n    string smartVaultName;\n    string svtSymbol;\n    string baseURI;\n    uint256 assetGroupId;\n    address[] strategies;\n    uint16a16 strategyAllocation;\n    int8 riskTolerance;\n    address riskProvider;\n    address allocationProvider;\n    IAction[] actions;\n    RequestType[] actionRequestTypes;\n    GuardDefinition[][] guards;\n    RequestType[] guardRequestTypes;\n    uint16 managementFeePct;\n    uint16 depositFeePct;\n    uint16 performanceFeePct;\n    bool allowRedeemFor;\n}\n\n/* ========== CONTRACTS ========== */\n\n/**\n * @dev Requires roles:\n * - ROLE_SMART_VAULT_INTEGRATOR\n * - ADMIN_ROLE_SMART_VAULT_ALLOW_REDEEM\n */\ncontract SmartVaultFactory is UpgradeableBeacon {\n    using uint16a16Lib for uint16a16;\n\n    /* ========== EVENTS ========== */\n\n    /**\n     * @notice Emitted when a new smart vault is deployed.\n     * @param smartVault Address of the newly deployed smart vault.\n     * @param deployer Address of the deployer.\n     */\n    event SmartVaultDeployed(address indexed smartVault, address indexed deployer);\n\n    /* ========== CONSTANTS ========== */\n\n    /**\n     * @notice Spool access control contract.\n     */\n    ISpoolAccessControl immutable _accessControl;\n\n    /**\n     * @notice Action manager contract.\n     */\n    IActionManager immutable _actionManager;\n\n    /**\n     * @notice Guard manager contract.\n     */\n    IGuardManager immutable _guardManager;\n\n    /**\n     * @notice Smart vault manager contract.\n     */\n    ISmartVaultRegistry immutable _smartVaultRegistry;\n\n    /**\n     * @notice Asset group registry contract.\n     */\n    IAssetGroupRegistry immutable _assetGroupRegistry;\n\n    /**\n     * @notice Risk manager contract.\n     */\n    IRiskManager immutable _riskManager;\n\n    /* ========== CONSTRUCTOR ========== */\n\n    constructor(\n        address implementation,\n        ISpoolAccessControl accessControl_,\n        IActionManager actionManager_,\n        IGuardManager guardManager_,\n        ISmartVaultRegistry smartVaultRegistry_,\n        IAssetGroupRegistry assetGroupRegistry_,\n        IRiskManager riskManager_\n    ) UpgradeableBeacon(implementation) {\n        if (address(accessControl_) == address(0)) revert ConfigurationAddressZero();\n        if (address(actionManager_) == address(0)) revert ConfigurationAddressZero();\n        if (address(guardManager_) == address(0)) revert ConfigurationAddressZero();\n        if (address(smartVaultRegistry_) == address(0)) revert ConfigurationAddressZero();\n        if (address(assetGroupRegistry_) == address(0)) revert ConfigurationAddressZero();\n        if (address(riskManager_) == address(0)) revert ConfigurationAddressZero();\n\n        _accessControl = accessControl_;\n        _actionManager = actionManager_;\n        _guardManager = guardManager_;\n        _smartVaultRegistry = smartVaultRegistry_;\n        _assetGroupRegistry = assetGroupRegistry_;\n        _riskManager = riskManager_;\n    }\n\n    /* ========== EXTERNAL MUTATIVE FUNCTIONS ========== */\n\n    /**\n     * @notice Deploys a new smart vault into the Spool ecosystem.\n     * @param specification Specifications for the new smart vault.\n     * @return smartVault Deployed smart vault.\n     */\n    function deploySmartVault(SmartVaultSpecification calldata specification) external returns (ISmartVault) {\n        _validateSpecification(specification);\n\n        address smartVaultAddress = address(\n            new BeaconProxy(\n                address(this),\n                _encodeInitializationCalldata(specification)\n            )\n        );\n\n        _integrateSmartVault(smartVaultAddress, specification);\n\n        emit SmartVaultDeployed(smartVaultAddress, msg.sender);\n\n        return ISmartVault(smartVaultAddress);\n    }\n\n    /**\n     * @notice Deploys a new smart vault to a deterministic address.\n     * @param specification Specifications for the new smart vault.\n     * @param salt Salt for address determination.\n     * @return smartVault Deployed smart vault.\n     */\n    function deploySmartVaultDeterministically(SmartVaultSpecification calldata specification, bytes32 salt)\n        external\n        returns (ISmartVault)\n    {\n        _validateSpecification(specification);\n\n        address smartVaultAddress = address(\n            new BeaconProxy{salt: salt}(\n                address(this),\n                _encodeInitializationCalldata(specification)\n            )\n        );\n\n        _integrateSmartVault(smartVaultAddress, specification);\n\n        emit SmartVaultDeployed(smartVaultAddress, msg.sender);\n\n        return ISmartVault(smartVaultAddress);\n    }\n\n    /* ========== EXTERNAL VIEW FUNCTIONS ========== */\n\n    /**\n     * @notice Predicts deployment address deterministically deployed smart vault.\n     * @param specification Specifications for the new smart vault.\n     * @param salt Salt for address determination.\n     * @return predictedAddress Predicted address.\n     */\n    function predictDeterministicAddress(SmartVaultSpecification calldata specification, bytes32 salt)\n        external\n        view\n        returns (address)\n    {\n        return address(\n            uint160(\n                uint256(\n                    keccak256(\n                        abi.encodePacked(\n                            bytes1(0xff),\n                            address(this),\n                            salt,\n                            keccak256(\n                                abi.encodePacked(\n                                    type(BeaconProxy).creationCode,\n                                    abi.encode(address(this), _encodeInitializationCalldata(specification))\n                                )\n                            )\n                        )\n                    )\n                )\n            )\n        );\n    }\n\n    /* ========== INTERNAL FUNCTIONS ========== */\n\n    /**\n     * @notice Validates smart vault specification.\n     * @param specification Specifications for the new smart vault.\n     */\n    function _validateSpecification(SmartVaultSpecification calldata specification) private view {\n        _assetGroupRegistry.validateAssetGroup(specification.assetGroupId);\n\n        if (specification.strategies.length == 0) {\n            revert SmartVaultRegistrationNoStrategies();\n        }\n        if (specification.strategies.length > STRATEGY_COUNT_CAP) {\n            revert StrategyCapExceeded();\n        }\n\n        unchecked {\n            bool fixedAllocations = uint16a16.unwrap(specification.strategyAllocation) > 0;\n            uint256 fullAllocation;\n\n            if (specification.strategies.length == 1 && !fixedAllocations) {\n                revert SingleStrategyDynamicAllocation();\n            }\n\n            if (fixedAllocations) {\n                if (specification.riskProvider != address(0)) {\n                    revert StaticAllocationAndRiskProviderSet();\n                }\n\n                if (specification.riskTolerance != 0) {\n                    revert StaticAllocationAndRiskToleranceSet();\n                }\n\n                if (specification.allocationProvider != address(0)) {\n                    revert StaticAllocationAndAllocationProviderSet();\n                }\n            }\n\n            for (uint256 i; i < specification.strategies.length; ++i) {\n                if (fixedAllocations) {\n                    if (specification.strategyAllocation.get(i) == 0) {\n                        revert InvalidStrategyAllocationsLength();\n                    }\n                    fullAllocation += specification.strategyAllocation.get(i);\n                }\n\n                if (!_accessControl.hasRole(ROLE_STRATEGY, specification.strategies[i])) {\n                    revert InvalidStrategy(specification.strategies[i]);\n                }\n\n                if (IStrategy(specification.strategies[i]).assetGroupId() != specification.assetGroupId) {\n                    revert NotSameAssetGroup();\n                }\n\n                for (uint256 j = i + 1; j < specification.strategies.length; ++j) {\n                    if (specification.strategies[i] == specification.strategies[j]) {\n                        revert StrategiesNotUnique();\n                    }\n                }\n            }\n\n            if (fixedAllocations && fullAllocation != FULL_PERCENT) {\n                revert InvalidStaticAllocation();\n            }\n        }\n\n        if (specification.managementFeePct > MANAGEMENT_FEE_MAX) {\n            revert ManagementFeeTooLarge(specification.managementFeePct);\n        }\n        if (specification.depositFeePct > DEPOSIT_FEE_MAX) {\n            revert DepositFeeTooLarge(specification.depositFeePct);\n        }\n        if (specification.performanceFeePct > SV_PERFORMANCE_FEE_MAX) {\n            revert PerformanceFeeTooLarge(specification.performanceFeePct);\n        }\n    }\n\n    /**\n     * @notice Encodes calldata for smart vault initialization.\n     * @param specification Specifications for the new smart vault.\n     * @return initializationCalldata Enoded initialization calldata.\n     */\n    function _encodeInitializationCalldata(SmartVaultSpecification calldata specification)\n        private\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodeWithSignature(\n            \"initialize(string,string,string,uint256)\",\n            specification.smartVaultName,\n            specification.svtSymbol,\n            specification.baseURI,\n            specification.assetGroupId\n        );\n    }\n\n    /**\n     * @notice Integrates newly created smart vault into the Spool ecosystem.\n     * @param smartVaultAddress Address of created smart vault.\n     * @param specification Specifications for the new smart vault.\n     */\n    function _integrateSmartVault(address smartVaultAddress, SmartVaultSpecification calldata specification) private {\n        _accessControl.grantSmartVaultOwnership(smartVaultAddress, msg.sender);\n        _actionManager.setActions(smartVaultAddress, specification.actions, specification.actionRequestTypes);\n        _guardManager.setGuards(smartVaultAddress, specification.guards, specification.guardRequestTypes);\n\n        if (specification.allowRedeemFor) {\n            _accessControl.grantRole(ROLE_SMART_VAULT_ALLOW_REDEEM, smartVaultAddress);\n        }\n\n        uint16a16 allocations = specification.strategyAllocation;\n\n        // set allocation\n        if (uint16a16.unwrap(allocations) == 0) {\n            _riskManager.setRiskProvider(smartVaultAddress, specification.riskProvider);\n            _riskManager.setRiskTolerance(smartVaultAddress, specification.riskTolerance);\n            _riskManager.setAllocationProvider(smartVaultAddress, specification.allocationProvider);\n\n            allocations = _riskManager.calculateAllocation(smartVaultAddress, specification.strategies);\n        }\n\n        _smartVaultRegistry.registerSmartVault(\n            smartVaultAddress,\n            SmartVaultRegistrationForm({\n                assetGroupId: specification.assetGroupId,\n                strategies: specification.strategies,\n                strategyAllocation: allocations,\n                managementFeePct: specification.managementFeePct,\n                depositFeePct: specification.depositFeePct,\n                performanceFeePct: specification.performanceFeePct\n            })\n        );\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/proxy/beacon/IBeacon.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\r\n\r\npragma solidity ^0.8.0;\r\n\r\n/**\r\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\r\n */\r\ninterface IBeacon {\r\n    /**\r\n     * @dev Must return an address that can be used as a delegate call target.\r\n     *\r\n     * {BeaconProxy} will check that this address is a contract.\r\n     */\r\n    function implementation() external view returns (address);\r\n}\r\n"
      },
      "lib/openzeppelin-contracts/contracts/proxy/Proxy.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol)\r\n\r\npragma solidity ^0.8.0;\r\n\r\n/**\r\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\r\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\r\n * be specified by overriding the virtual {_implementation} function.\r\n *\r\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\r\n * different contract through the {_delegate} function.\r\n *\r\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\r\n */\r\nabstract contract Proxy {\r\n    /**\r\n     * @dev Delegates the current call to `implementation`.\r\n     *\r\n     * This function does not return to its internal call site, it will return directly to the external caller.\r\n     */\r\n    function _delegate(address implementation) internal virtual {\r\n        assembly {\r\n            // Copy msg.data. We take full control of memory in this inline assembly\r\n            // block because it will not return to Solidity code. We overwrite the\r\n            // Solidity scratch pad at memory position 0.\r\n            calldatacopy(0, 0, calldatasize())\r\n\r\n            // Call the implementation.\r\n            // out and outsize are 0 because we don't know the size yet.\r\n            let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\r\n\r\n            // Copy the returned data.\r\n            returndatacopy(0, 0, returndatasize())\r\n\r\n            switch result\r\n            // delegatecall returns 0 on error.\r\n            case 0 {\r\n                revert(0, returndatasize())\r\n            }\r\n            default {\r\n                return(0, returndatasize())\r\n            }\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function\r\n     * and {_fallback} should delegate.\r\n     */\r\n    function _implementation() internal view virtual returns (address);\r\n\r\n    /**\r\n     * @dev Delegates the current call to the address returned by `_implementation()`.\r\n     *\r\n     * This function does not return to its internal call site, it will return directly to the external caller.\r\n     */\r\n    function _fallback() internal virtual {\r\n        _beforeFallback();\r\n        _delegate(_implementation());\r\n    }\r\n\r\n    /**\r\n     * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\r\n     * function in the contract matches the call data.\r\n     */\r\n    fallback() external payable virtual {\r\n        _fallback();\r\n    }\r\n\r\n    /**\r\n     * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\r\n     * is empty.\r\n     */\r\n    receive() external payable virtual {\r\n        _fallback();\r\n    }\r\n\r\n    /**\r\n     * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\r\n     * call, or as part of the Solidity `fallback` or `receive` functions.\r\n     *\r\n     * If overridden should call `super._beforeFallback()`.\r\n     */\r\n    function _beforeFallback() internal virtual {}\r\n}\r\n"
      },
      "lib/openzeppelin-contracts/contracts/proxy/ERC1967/ERC1967Upgrade.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol)\r\n\r\npragma solidity ^0.8.2;\r\n\r\nimport \"../beacon/IBeacon.sol\";\r\nimport \"../../interfaces/draft-IERC1822.sol\";\r\nimport \"../../utils/Address.sol\";\r\nimport \"../../utils/StorageSlot.sol\";\r\n\r\n/**\r\n * @dev This abstract contract provides getters and event emitting update functions for\r\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\r\n *\r\n * _Available since v4.1._\r\n *\r\n * @custom:oz-upgrades-unsafe-allow delegatecall\r\n */\r\nabstract contract ERC1967Upgrade {\r\n    // This is the keccak-256 hash of \"eip1967.proxy.rollback\" subtracted by 1\r\n    bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\r\n\r\n    /**\r\n     * @dev Storage slot with the address of the current implementation.\r\n     * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1, and is\r\n     * validated in the constructor.\r\n     */\r\n    bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\r\n\r\n    /**\r\n     * @dev Emitted when the implementation is upgraded.\r\n     */\r\n    event Upgraded(address indexed implementation);\r\n\r\n    /**\r\n     * @dev Returns the current implementation address.\r\n     */\r\n    function _getImplementation() internal view returns (address) {\r\n        return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\r\n    }\r\n\r\n    /**\r\n     * @dev Stores a new address in the EIP1967 implementation slot.\r\n     */\r\n    function _setImplementation(address newImplementation) private {\r\n        require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\r\n        StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\r\n    }\r\n\r\n    /**\r\n     * @dev Perform implementation upgrade\r\n     *\r\n     * Emits an {Upgraded} event.\r\n     */\r\n    function _upgradeTo(address newImplementation) internal {\r\n        _setImplementation(newImplementation);\r\n        emit Upgraded(newImplementation);\r\n    }\r\n\r\n    /**\r\n     * @dev Perform implementation upgrade with additional setup call.\r\n     *\r\n     * Emits an {Upgraded} event.\r\n     */\r\n    function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal {\r\n        _upgradeTo(newImplementation);\r\n        if (data.length > 0 || forceCall) {\r\n            Address.functionDelegateCall(newImplementation, data);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\r\n     *\r\n     * Emits an {Upgraded} event.\r\n     */\r\n    function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal {\r\n        // Upgrades from old implementations will perform a rollback test. This test requires the new\r\n        // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\r\n        // this special case will break upgrade paths from old UUPS implementation to new ones.\r\n        if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\r\n            _setImplementation(newImplementation);\r\n        } else {\r\n            try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\r\n                require(slot == _IMPLEMENTATION_SLOT, \"ERC1967Upgrade: unsupported proxiableUUID\");\r\n            } catch {\r\n                revert(\"ERC1967Upgrade: new implementation is not UUPS\");\r\n            }\r\n            _upgradeToAndCall(newImplementation, data, forceCall);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Storage slot with the admin of the contract.\r\n     * This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1, and is\r\n     * validated in the constructor.\r\n     */\r\n    bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\r\n\r\n    /**\r\n     * @dev Emitted when the admin account has changed.\r\n     */\r\n    event AdminChanged(address previousAdmin, address newAdmin);\r\n\r\n    /**\r\n     * @dev Returns the current admin.\r\n     */\r\n    function _getAdmin() internal view returns (address) {\r\n        return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\r\n    }\r\n\r\n    /**\r\n     * @dev Stores a new address in the EIP1967 admin slot.\r\n     */\r\n    function _setAdmin(address newAdmin) private {\r\n        require(newAdmin != address(0), \"ERC1967: new admin is the zero address\");\r\n        StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\r\n    }\r\n\r\n    /**\r\n     * @dev Changes the admin of the proxy.\r\n     *\r\n     * Emits an {AdminChanged} event.\r\n     */\r\n    function _changeAdmin(address newAdmin) internal {\r\n        emit AdminChanged(_getAdmin(), newAdmin);\r\n        _setAdmin(newAdmin);\r\n    }\r\n\r\n    /**\r\n     * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\r\n     * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\r\n     */\r\n    bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\r\n\r\n    /**\r\n     * @dev Emitted when the beacon is upgraded.\r\n     */\r\n    event BeaconUpgraded(address indexed beacon);\r\n\r\n    /**\r\n     * @dev Returns the current beacon.\r\n     */\r\n    function _getBeacon() internal view returns (address) {\r\n        return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\r\n    }\r\n\r\n    /**\r\n     * @dev Stores a new beacon in the EIP1967 beacon slot.\r\n     */\r\n    function _setBeacon(address newBeacon) private {\r\n        require(Address.isContract(newBeacon), \"ERC1967: new beacon is not a contract\");\r\n        require(\r\n            Address.isContract(IBeacon(newBeacon).implementation()),\r\n            \"ERC1967: beacon implementation is not a contract\"\r\n        );\r\n        StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\r\n    }\r\n\r\n    /**\r\n     * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\r\n     * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\r\n     *\r\n     * Emits a {BeaconUpgraded} event.\r\n     */\r\n    function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal {\r\n        _setBeacon(newBeacon);\r\n        emit BeaconUpgraded(newBeacon);\r\n        if (data.length > 0 || forceCall) {\r\n            Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\r\n        }\r\n    }\r\n}\r\n"
      },
      "lib/openzeppelin-contracts/contracts/access/Ownable.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\r\n\r\npragma solidity ^0.8.0;\r\n\r\nimport \"../utils/Context.sol\";\r\n\r\n/**\r\n * @dev Contract module which provides a basic access control mechanism, where\r\n * there is an account (an owner) that can be granted exclusive access to\r\n * specific functions.\r\n *\r\n * By default, the owner account will be the one that deploys the contract. This\r\n * can later be changed with {transferOwnership}.\r\n *\r\n * This module is used through inheritance. It will make available the modifier\r\n * `onlyOwner`, which can be applied to your functions to restrict their use to\r\n * the owner.\r\n */\r\nabstract contract Ownable is Context {\r\n    address private _owner;\r\n\r\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\r\n\r\n    /**\r\n     * @dev Initializes the contract setting the deployer as the initial owner.\r\n     */\r\n    constructor() {\r\n        _transferOwnership(_msgSender());\r\n    }\r\n\r\n    /**\r\n     * @dev Throws if called by any account other than the owner.\r\n     */\r\n    modifier onlyOwner() {\r\n        _checkOwner();\r\n        _;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the address of the current owner.\r\n     */\r\n    function owner() public view virtual returns (address) {\r\n        return _owner;\r\n    }\r\n\r\n    /**\r\n     * @dev Throws if the sender is not the owner.\r\n     */\r\n    function _checkOwner() internal view virtual {\r\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\r\n    }\r\n\r\n    /**\r\n     * @dev Leaves the contract without owner. It will not be possible to call\r\n     * `onlyOwner` functions anymore. Can only be called by the current owner.\r\n     *\r\n     * NOTE: Renouncing ownership will leave the contract without an owner,\r\n     * thereby removing any functionality that is only available to the owner.\r\n     */\r\n    function renounceOwnership() public virtual onlyOwner {\r\n        _transferOwnership(address(0));\r\n    }\r\n\r\n    /**\r\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\r\n     * Can only be called by the current owner.\r\n     */\r\n    function transferOwnership(address newOwner) public virtual onlyOwner {\r\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\r\n        _transferOwnership(newOwner);\r\n    }\r\n\r\n    /**\r\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\r\n     * Internal function without access restriction.\r\n     */\r\n    function _transferOwnership(address newOwner) internal virtual {\r\n        address oldOwner = _owner;\r\n        _owner = newOwner;\r\n        emit OwnershipTransferred(oldOwner, newOwner);\r\n    }\r\n}\r\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/Address.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\r\n\r\npragma solidity ^0.8.1;\r\n\r\n/**\r\n * @dev Collection of functions related to the address type\r\n */\r\nlibrary Address {\r\n    /**\r\n     * @dev Returns true if `account` is a contract.\r\n     *\r\n     * [IMPORTANT]\r\n     * ====\r\n     * It is unsafe to assume that an address for which this function returns\r\n     * false is an externally-owned account (EOA) and not a contract.\r\n     *\r\n     * Among others, `isContract` will return false for the following\r\n     * types of addresses:\r\n     *\r\n     *  - an externally-owned account\r\n     *  - a contract in construction\r\n     *  - an address where a contract will be created\r\n     *  - an address where a contract lived, but was destroyed\r\n     *\r\n     * Furthermore, `isContract` will also return true if the target contract within\r\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\r\n     * which only has an effect at the end of a transaction.\r\n     * ====\r\n     *\r\n     * [IMPORTANT]\r\n     * ====\r\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\r\n     *\r\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\r\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\r\n     * constructor.\r\n     * ====\r\n     */\r\n    function isContract(address account) internal view returns (bool) {\r\n        // This method relies on extcodesize/address.code.length, which returns 0\r\n        // for contracts in construction, since the code is only stored at the end\r\n        // of the constructor execution.\r\n\r\n        return account.code.length > 0;\r\n    }\r\n\r\n    /**\r\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\r\n     * `recipient`, forwarding all available gas and reverting on errors.\r\n     *\r\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\r\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\r\n     * imposed by `transfer`, making them unable to receive funds via\r\n     * `transfer`. {sendValue} removes this limitation.\r\n     *\r\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\r\n     *\r\n     * IMPORTANT: because control is transferred to `recipient`, care must be\r\n     * taken to not create reentrancy vulnerabilities. Consider using\r\n     * {ReentrancyGuard} or the\r\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\r\n     */\r\n    function sendValue(address payable recipient, uint256 amount) internal {\r\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\r\n\r\n        (bool success, ) = recipient.call{value: amount}(\"\");\r\n        require(success, \"Address: unable to send value, recipient may have reverted\");\r\n    }\r\n\r\n    /**\r\n     * @dev Performs a Solidity function call using a low level `call`. A\r\n     * plain `call` is an unsafe replacement for a function call: use this\r\n     * function instead.\r\n     *\r\n     * If `target` reverts with a revert reason, it is bubbled up by this\r\n     * function (like regular Solidity function calls).\r\n     *\r\n     * Returns the raw returned data. To convert to the expected return value,\r\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `target` must be a contract.\r\n     * - calling `target` with `data` must not revert.\r\n     *\r\n     * _Available since v3.1._\r\n     */\r\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\r\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\r\n    }\r\n\r\n    /**\r\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\r\n     * `errorMessage` as a fallback revert reason when `target` reverts.\r\n     *\r\n     * _Available since v3.1._\r\n     */\r\n    function functionCall(\r\n        address target,\r\n        bytes memory data,\r\n        string memory errorMessage\r\n    ) internal returns (bytes memory) {\r\n        return functionCallWithValue(target, data, 0, errorMessage);\r\n    }\r\n\r\n    /**\r\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\r\n     * but also transferring `value` wei to `target`.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - the calling contract must have an ETH balance of at least `value`.\r\n     * - the called Solidity function must be `payable`.\r\n     *\r\n     * _Available since v3.1._\r\n     */\r\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\r\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\r\n    }\r\n\r\n    /**\r\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\r\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\r\n     *\r\n     * _Available since v3.1._\r\n     */\r\n    function functionCallWithValue(\r\n        address target,\r\n        bytes memory data,\r\n        uint256 value,\r\n        string memory errorMessage\r\n    ) internal returns (bytes memory) {\r\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\r\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\r\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\r\n    }\r\n\r\n    /**\r\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\r\n     * but performing a static call.\r\n     *\r\n     * _Available since v3.3._\r\n     */\r\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\r\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\r\n    }\r\n\r\n    /**\r\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\r\n     * but performing a static call.\r\n     *\r\n     * _Available since v3.3._\r\n     */\r\n    function functionStaticCall(\r\n        address target,\r\n        bytes memory data,\r\n        string memory errorMessage\r\n    ) internal view returns (bytes memory) {\r\n        (bool success, bytes memory returndata) = target.staticcall(data);\r\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\r\n    }\r\n\r\n    /**\r\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\r\n     * but performing a delegate call.\r\n     *\r\n     * _Available since v3.4._\r\n     */\r\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\r\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\r\n    }\r\n\r\n    /**\r\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\r\n     * but performing a delegate call.\r\n     *\r\n     * _Available since v3.4._\r\n     */\r\n    function functionDelegateCall(\r\n        address target,\r\n        bytes memory data,\r\n        string memory errorMessage\r\n    ) internal returns (bytes memory) {\r\n        (bool success, bytes memory returndata) = target.delegatecall(data);\r\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\r\n    }\r\n\r\n    /**\r\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\r\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\r\n     *\r\n     * _Available since v4.8._\r\n     */\r\n    function verifyCallResultFromTarget(\r\n        address target,\r\n        bool success,\r\n        bytes memory returndata,\r\n        string memory errorMessage\r\n    ) internal view returns (bytes memory) {\r\n        if (success) {\r\n            if (returndata.length == 0) {\r\n                // only check isContract if the call was successful and the return data is empty\r\n                // otherwise we already know that it was a contract\r\n                require(isContract(target), \"Address: call to non-contract\");\r\n            }\r\n            return returndata;\r\n        } else {\r\n            _revert(returndata, errorMessage);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\r\n     * revert reason or using the provided one.\r\n     *\r\n     * _Available since v4.3._\r\n     */\r\n    function verifyCallResult(\r\n        bool success,\r\n        bytes memory returndata,\r\n        string memory errorMessage\r\n    ) internal pure returns (bytes memory) {\r\n        if (success) {\r\n            return returndata;\r\n        } else {\r\n            _revert(returndata, errorMessage);\r\n        }\r\n    }\r\n\r\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\r\n        // Look for revert reason and bubble it up if present\r\n        if (returndata.length > 0) {\r\n            // The easiest way to bubble the revert reason is using memory via assembly\r\n            /// @solidity memory-safe-assembly\r\n            assembly {\r\n                let returndata_size := mload(returndata)\r\n                revert(add(32, returndata), returndata_size)\r\n            }\r\n        } else {\r\n            revert(errorMessage);\r\n        }\r\n    }\r\n}\r\n"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\r\n\r\npragma solidity ^0.8.0;\r\n\r\n/**\r\n * @dev Interface of the ERC20 standard as defined in the EIP.\r\n */\r\ninterface IERC20 {\r\n    /**\r\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\r\n     * another (`to`).\r\n     *\r\n     * Note that `value` may be zero.\r\n     */\r\n    event Transfer(address indexed from, address indexed to, uint256 value);\r\n\r\n    /**\r\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\r\n     * a call to {approve}. `value` is the new allowance.\r\n     */\r\n    event Approval(address indexed owner, address indexed spender, uint256 value);\r\n\r\n    /**\r\n     * @dev Returns the amount of tokens in existence.\r\n     */\r\n    function totalSupply() external view returns (uint256);\r\n\r\n    /**\r\n     * @dev Returns the amount of tokens owned by `account`.\r\n     */\r\n    function balanceOf(address account) external view returns (uint256);\r\n\r\n    /**\r\n     * @dev Moves `amount` tokens from the caller's account to `to`.\r\n     *\r\n     * Returns a boolean value indicating whether the operation succeeded.\r\n     *\r\n     * Emits a {Transfer} event.\r\n     */\r\n    function transfer(address to, uint256 amount) external returns (bool);\r\n\r\n    /**\r\n     * @dev Returns the remaining number of tokens that `spender` will be\r\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\r\n     * zero by default.\r\n     *\r\n     * This value changes when {approve} or {transferFrom} are called.\r\n     */\r\n    function allowance(address owner, address spender) external view returns (uint256);\r\n\r\n    /**\r\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\r\n     *\r\n     * Returns a boolean value indicating whether the operation succeeded.\r\n     *\r\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\r\n     * that someone may use both the old and the new allowance by unfortunate\r\n     * transaction ordering. One possible solution to mitigate this race\r\n     * condition is to first reduce the spender's allowance to 0 and set the\r\n     * desired value afterwards:\r\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\r\n     *\r\n     * Emits an {Approval} event.\r\n     */\r\n    function approve(address spender, uint256 amount) external returns (bool);\r\n\r\n    /**\r\n     * @dev Moves `amount` tokens from `from` to `to` using the\r\n     * allowance mechanism. `amount` is then deducted from the caller's\r\n     * allowance.\r\n     *\r\n     * Returns a boolean value indicating whether the operation succeeded.\r\n     *\r\n     * Emits a {Transfer} event.\r\n     */\r\n    function transferFrom(address from, address to, uint256 amount) external returns (bool);\r\n}\r\n"
      },
      "src/libraries/uint16a16Lib.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ntype uint16a16 is uint256;\n\n/**\n * @notice This library enables packing of sixteen uint16 elements into one uint256 word.\n */\nlibrary uint16a16Lib {\n    /// @notice Number of bits per stored element.\n    uint256 constant bits = 16;\n\n    /// @notice Maximal number of elements stored.\n    uint256 constant elements = 16;\n\n    // must ensure that bits * elements <= 256\n\n    /// @notice Range covered by stored element.\n    uint256 constant range = 1 << bits;\n\n    /// @notice Maximal value of stored element.\n    uint256 constant max = range - 1;\n\n    /**\n     * @notice Gets element from packed array.\n     * @param va Packed array.\n     * @param index Index of element to get.\n     * @return element Element of va stored in index index.\n     */\n    function get(uint16a16 va, uint256 index) internal pure returns (uint256) {\n        require(index < elements);\n        return (uint16a16.unwrap(va) >> (bits * index)) & max;\n    }\n\n    /**\n     * @notice Sets element to packed array.\n     * @param va Packed array.\n     * @param index Index under which to store the element\n     * @param ev Element to store.\n     * @return va Packed array with stored element.\n     */\n    function set(uint16a16 va, uint256 index, uint256 ev) internal pure returns (uint16a16) {\n        require(index < elements);\n        require(ev < range);\n        index *= bits;\n        return uint16a16.wrap((uint16a16.unwrap(va) & ~(max << index)) | (ev << index));\n    }\n\n    /**\n     * @notice Sets elements to packed array.\n     * Elements are stored continuously from index 0 onwards.\n     * @param va Packed array.\n     * @param ev Elements to store.\n     * @return va Packed array with stored elements.\n     */\n    function set(uint16a16 va, uint256[] memory ev) internal pure returns (uint16a16) {\n        for (uint256 i; i < ev.length; ++i) {\n            va = set(va, i, ev[i]);\n        }\n\n        return va;\n    }\n}\n"
      },
      "lib/openzeppelin-contracts-upgradeable/contracts/token/ERC1155/IERC1155Upgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/IERC1155.sol)\r\n\r\npragma solidity ^0.8.0;\r\n\r\nimport \"../../utils/introspection/IERC165Upgradeable.sol\";\r\n\r\n/**\r\n * @dev Required interface of an ERC1155 compliant contract, as defined in the\r\n * https://eips.ethereum.org/EIPS/eip-1155[EIP].\r\n *\r\n * _Available since v3.1._\r\n */\r\ninterface IERC1155Upgradeable is IERC165Upgradeable {\r\n    /**\r\n     * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\r\n     */\r\n    event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\r\n\r\n    /**\r\n     * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\r\n     * transfers.\r\n     */\r\n    event TransferBatch(\r\n        address indexed operator,\r\n        address indexed from,\r\n        address indexed to,\r\n        uint256[] ids,\r\n        uint256[] values\r\n    );\r\n\r\n    /**\r\n     * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\r\n     * `approved`.\r\n     */\r\n    event ApprovalForAll(address indexed account, address indexed operator, bool approved);\r\n\r\n    /**\r\n     * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\r\n     *\r\n     * If an {URI} event was emitted for `id`, the standard\r\n     * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\r\n     * returned by {IERC1155MetadataURI-uri}.\r\n     */\r\n    event URI(string value, uint256 indexed id);\r\n\r\n    /**\r\n     * @dev Returns the amount of tokens of token type `id` owned by `account`.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `account` cannot be the zero address.\r\n     */\r\n    function balanceOf(address account, uint256 id) external view returns (uint256);\r\n\r\n    /**\r\n     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `accounts` and `ids` must have the same length.\r\n     */\r\n    function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)\r\n        external\r\n        view\r\n        returns (uint256[] memory);\r\n\r\n    /**\r\n     * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\r\n     *\r\n     * Emits an {ApprovalForAll} event.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `operator` cannot be the caller.\r\n     */\r\n    function setApprovalForAll(address operator, bool approved) external;\r\n\r\n    /**\r\n     * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\r\n     *\r\n     * See {setApprovalForAll}.\r\n     */\r\n    function isApprovedForAll(address account, address operator) external view returns (bool);\r\n\r\n    /**\r\n     * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\r\n     *\r\n     * Emits a {TransferSingle} event.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `to` cannot be the zero address.\r\n     * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\r\n     * - `from` must have a balance of tokens of type `id` of at least `amount`.\r\n     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\r\n     * acceptance magic value.\r\n     */\r\n    function safeTransferFrom(\r\n        address from,\r\n        address to,\r\n        uint256 id,\r\n        uint256 amount,\r\n        bytes calldata data\r\n    ) external;\r\n\r\n    /**\r\n     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\r\n     *\r\n     * Emits a {TransferBatch} event.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `ids` and `amounts` must have the same length.\r\n     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\r\n     * acceptance magic value.\r\n     */\r\n    function safeBatchTransferFrom(\r\n        address from,\r\n        address to,\r\n        uint256[] calldata ids,\r\n        uint256[] calldata amounts,\r\n        bytes calldata data\r\n    ) external;\r\n}\r\n"
      },
      "lib/openzeppelin-contracts-upgradeable/contracts/token/ERC20/IERC20Upgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\r\n\r\npragma solidity ^0.8.0;\r\n\r\n/**\r\n * @dev Interface of the ERC20 standard as defined in the EIP.\r\n */\r\ninterface IERC20Upgradeable {\r\n    /**\r\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\r\n     * another (`to`).\r\n     *\r\n     * Note that `value` may be zero.\r\n     */\r\n    event Transfer(address indexed from, address indexed to, uint256 value);\r\n\r\n    /**\r\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\r\n     * a call to {approve}. `value` is the new allowance.\r\n     */\r\n    event Approval(address indexed owner, address indexed spender, uint256 value);\r\n\r\n    /**\r\n     * @dev Returns the amount of tokens in existence.\r\n     */\r\n    function totalSupply() external view returns (uint256);\r\n\r\n    /**\r\n     * @dev Returns the amount of tokens owned by `account`.\r\n     */\r\n    function balanceOf(address account) external view returns (uint256);\r\n\r\n    /**\r\n     * @dev Moves `amount` tokens from the caller's account to `to`.\r\n     *\r\n     * Returns a boolean value indicating whether the operation succeeded.\r\n     *\r\n     * Emits a {Transfer} event.\r\n     */\r\n    function transfer(address to, uint256 amount) external returns (bool);\r\n\r\n    /**\r\n     * @dev Returns the remaining number of tokens that `spender` will be\r\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\r\n     * zero by default.\r\n     *\r\n     * This value changes when {approve} or {transferFrom} are called.\r\n     */\r\n    function allowance(address owner, address spender) external view returns (uint256);\r\n\r\n    /**\r\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\r\n     *\r\n     * Returns a boolean value indicating whether the operation succeeded.\r\n     *\r\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\r\n     * that someone may use both the old and the new allowance by unfortunate\r\n     * transaction ordering. One possible solution to mitigate this race\r\n     * condition is to first reduce the spender's allowance to 0 and set the\r\n     * desired value afterwards:\r\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\r\n     *\r\n     * Emits an {Approval} event.\r\n     */\r\n    function approve(address spender, uint256 amount) external returns (bool);\r\n\r\n    /**\r\n     * @dev Moves `amount` tokens from `from` to `to` using the\r\n     * allowance mechanism. `amount` is then deducted from the caller's\r\n     * allowance.\r\n     *\r\n     * Returns a boolean value indicating whether the operation succeeded.\r\n     *\r\n     * Emits a {Transfer} event.\r\n     */\r\n    function transferFrom(\r\n        address from,\r\n        address to,\r\n        uint256 amount\r\n    ) external returns (bool);\r\n}\r\n"
      },
      "lib/openzeppelin-contracts-upgradeable/contracts/token/ERC1155/extensions/IERC1155MetadataURIUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts v4.4.1 (token/ERC1155/extensions/IERC1155MetadataURI.sol)\r\n\r\npragma solidity ^0.8.0;\r\n\r\nimport \"../IERC1155Upgradeable.sol\";\r\n\r\n/**\r\n * @dev Interface of the optional ERC1155MetadataExtension interface, as defined\r\n * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP].\r\n *\r\n * _Available since v3.1._\r\n */\r\ninterface IERC1155MetadataURIUpgradeable is IERC1155Upgradeable {\r\n    /**\r\n     * @dev Returns the URI for token type `id`.\r\n     *\r\n     * If the `\\{id\\}` substring is present in the URI, it must be replaced by\r\n     * clients with the actual token type ID.\r\n     */\r\n    function uri(uint256 id) external view returns (string memory);\r\n}\r\n"
      },
      "src/interfaces/IDepositManager.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.17;\n\nimport \"./ISmartVault.sol\";\nimport \"../libraries/uint16a16Lib.sol\";\n\n/**\n * @notice Used when deposited assets are not the same length as underlying assets.\n */\nerror InvalidAssetLengths();\n\n/**\n * @notice Used when lengths of NFT id and amount arrays when claiming NFTs don't match.\n */\nerror InvalidNftArrayLength();\n\n/**\n * @notice Used when there are no pending deposits to recover.\n * E.g., they were already recovered or flushed.\n */\nerror NoDepositsToRecover();\n\n/**\n * @notice Used when trying to recover pending deposits from a smart vault that has non-ghost strategies.\n */\nerror NotGhostVault();\n\n/**\n * @notice Gathers input for depositing assets.\n * @custom:member smartVault Smart vault for which the deposit is made.\n * @custom:member assets Amounts of assets being deposited.\n * @custom:member receiver Receiver of the deposit NFT.\n * @custom:member referral Referral address.\n * @custom:member doFlush If true, the smart vault will be flushed after the deposit as part of same transaction.\n */\nstruct DepositBag {\n    address smartVault;\n    uint256[] assets;\n    address receiver;\n    address referral;\n    bool doFlush;\n}\n\n/**\n * @notice Gathers extra input for depositing assets.\n * @custom:member depositor Address making the deposit.\n * @custom:member tokens Tokens of the smart vault.\n * @custom:member strategies Strategies of the smart vault.\n * @custom:member allocations Set allocation of funds between strategies.\n * @custom:member flushIndex Current flush index of the smart vault.\n */\nstruct DepositExtras {\n    address depositor;\n    address[] tokens;\n    address[] strategies;\n    uint16a16 allocations;\n    uint256 flushIndex;\n}\n\n/**\n * @notice Gathers minted SVTs for a specific fee type.\n * @custom:member depositFees Minted SVTs for deposit fees.\n * @custom:member performanceFees Minted SVTs for performance fees.\n * @custom:member managementFees Minted SVTs for management fees.\n */\nstruct SmartVaultFeesCollected {\n    uint256 depositFees;\n    uint256 performanceFees;\n    uint256 managementFees;\n}\n\n/**\n * @notice Gathers return values of syncing deposits.\n * @custom:member mintedSVTs Amount of SVTs minted.\n * @custom:member dhwTimestamp Timestamp of the last DHW synced.\n * @custom:member feeSVTs Amount of SVTs minted as fees.\n * @custom:member feesCollected Breakdown of amount of SVTs minted as fees.\n * @custom:member initialLockedSVTs Amount of initial locked SVTs.\n * @custom:member sstShares Amount of SSTs claimed for each strategy.\n */\nstruct DepositSyncResult {\n    uint256 mintedSVTs;\n    uint256 dhwTimestamp;\n    uint256 feeSVTs;\n    SmartVaultFeesCollected feesCollected;\n    uint256 initialLockedSVTs;\n    uint256[] sstShares;\n}\n\n/**\n * @custom:member smartVault Smart Vault address\n * @custom:member bag flush index, lastDhwSyncedTimestamp\n * @custom:member strategies strategy addresses\n * @custom:member assetGroup vault asset group token addresses\n * @custom:member dhwIndexes DHW Indexes for given flush index\n * @custom:member dhwIndexesOld DHW Indexes for previous flush index\n * @custom:member fees smart vault fee configuration\n * @return syncResult Result of the smart vault sync.\n */\nstruct SimulateDepositParams {\n    address smartVault;\n    // bag[0]: flushIndex,\n    // bag[1]: lastDhwSyncedTimestamp,\n    uint256[2] bag;\n    address[] strategies;\n    address[] assetGroup;\n    uint16a16 dhwIndexes;\n    uint16a16 dhwIndexesOld;\n    SmartVaultFees fees;\n}\n\ninterface IDepositManager {\n    /**\n     * @notice User redeemed deposit NFTs for SVTs\n     * @param smartVault Smart vault address\n     * @param claimer Claimer address\n     * @param claimedVaultTokens Amount of SVTs claimed\n     * @param nftIds NFTs to burn\n     * @param nftAmounts NFT shares to burn\n     */\n    event SmartVaultTokensClaimed(\n        address indexed smartVault,\n        address indexed claimer,\n        uint256 claimedVaultTokens,\n        uint256[] nftIds,\n        uint256[] nftAmounts\n    );\n\n    /**\n     * @notice A deposit has been initiated\n     * @param smartVault Smart vault address\n     * @param receiver Beneficiary of the deposit\n     * @param depositId Deposit NFT ID for this deposit\n     * @param flushIndex Flush index the deposit was scheduled for\n     * @param assets Amount of assets to deposit\n     * @param depositor Address that initiated the deposit\n     * @param referral Referral address\n     */\n    event DepositInitiated(\n        address indexed smartVault,\n        address indexed receiver,\n        uint256 indexed depositId,\n        uint256 flushIndex,\n        uint256[] assets,\n        address depositor,\n        address referral\n    );\n\n    /**\n     * @notice Pending deposits were recovered.\n     * @param smartVault Smart vault address.\n     * @param recoveredAssets Amount of assets recovered.\n     */\n    event PendingDepositsRecovered(address indexed smartVault, uint256[] recoveredAssets);\n\n    /**\n     * @notice Smart vault fees collected.\n     * @param smartVault Smart vault address.\n     * @param smartVaultFeesCollected Collected smart vault fee amounts.\n     */\n    event SmartVaultFeesMinted(address indexed smartVault, SmartVaultFeesCollected smartVaultFeesCollected);\n\n    /**\n     * @notice Simulate vault synchronization (i.e. DHW was completed, but vault wasn't synced yet)\n     */\n    function syncDepositsSimulate(SimulateDepositParams calldata parameters)\n        external\n        view\n        returns (DepositSyncResult memory syncResult);\n\n    /**\n     * @notice Synchronize vault deposits for completed DHW runs\n     * @dev Requirements:\n     * - caller must have role ROLE_SMART_VAULT_MANAGER\n     * @param smartVault Smart Vault address\n     * @param bag flushIndex, lastDhwSyncedTimestamp\n     * @param strategies vault strategy addresses\n     * @param dhwIndexes dhw indexes for given and previous flushIndex\n     * @param assetGroup vault asset group token addresses\n     * @param fees smart vault fee configuration\n     * @return syncResult Result of the smart vault sync.\n     */\n    function syncDeposits(\n        address smartVault,\n        uint256[2] calldata bag,\n        // uint256 flushIndex,\n        // uint256 lastDhwSyncedTimestamp\n        address[] calldata strategies,\n        uint16a16[2] calldata dhwIndexes,\n        address[] calldata assetGroup,\n        SmartVaultFees calldata fees\n    ) external returns (DepositSyncResult memory syncResult);\n\n    /**\n     * @notice Adds deposits for the next flush cycle.\n     * @dev Requirements:\n     * - caller must have role ROLE_SMART_VAULT_MANAGER\n     * @param bag Deposit parameters.\n     * @param bag2 Extra parameters.\n     * @return nftId ID of the deposit NFT.\n     */\n    function depositAssets(DepositBag calldata bag, DepositExtras calldata bag2) external returns (uint256 nftId);\n\n    /**\n     * @notice Mark deposits ready to be processed in the next DHW cycle\n     * @dev Requirements:\n     * - caller must have role ROLE_SMART_VAULT_MANAGER\n     * @param smartVault Smart Vault address\n     * @param flushIndex index to flush\n     * @param strategies vault strategy addresses\n     * @param allocations vault strategy allocations\n     * @param tokens vault asset group token addresses\n     * @return dhwIndexes DHW indexes in which the deposits will be included\n     */\n    function flushSmartVault(\n        address smartVault,\n        uint256 flushIndex,\n        address[] calldata strategies,\n        uint16a16 allocations,\n        address[] calldata tokens\n    ) external returns (uint16a16 dhwIndexes);\n\n    /**\n     * @notice Get the number of SVTs that are available, but haven't been claimed yet, for the given NFT\n     * @param smartVaultAddress Smart Vault address\n     * @param data NFT deposit NFT metadata\n     * @param nftShares amount of NFT shares to burn for SVTs\n     * @param mintedSVTs amount of SVTs minted for this flush\n     * @param tokens vault asset group addresses\n     */\n    function getClaimedVaultTokensPreview(\n        address smartVaultAddress,\n        DepositMetadata memory data,\n        uint256 nftShares,\n        uint256 mintedSVTs,\n        address[] calldata tokens\n    ) external view returns (uint256);\n\n    /**\n     * @notice Fetch assets deposited in a given vault flush\n     */\n    function smartVaultDeposits(address smartVault, uint256 flushIdx, uint256 assetGroupLength)\n        external\n        view\n        returns (uint256[] memory);\n\n    /**\n     * @notice Claim SVTs by burning deposit NFTs.\n     * @dev Requirements:\n     * - caller must have role ROLE_SMART_VAULT_MANAGER\n     * @param smartVault Smart Vault address\n     * @param nftIds NFT ids to burn\n     * @param nftAmounts NFT amounts to burn (support for partial burn)\n     * @param tokens vault asset group token addresses\n     * @param owner address owning NFTs\n     * @param executor address executing the claim transaction\n     * @param flushIndexToSync next flush index to sync for the smart vault\n     * @return claimedTokens Amount of smart vault tokens claimed.\n     */\n    function claimSmartVaultTokens(\n        address smartVault,\n        uint256[] calldata nftIds,\n        uint256[] calldata nftAmounts,\n        address[] calldata tokens,\n        address owner,\n        address executor,\n        uint256 flushIndexToSync\n    ) external returns (uint256 claimedTokens);\n\n    /**\n     * @notice Recovers pending deposits from smart vault.\n     * @dev Requirements:\n     * - caller must have role ROLE_SMART_VAULT_MANAGER\n     * @param smartVault Smart vault from which to recover pending deposits.\n     * @param flushIndex Flush index for which to recover pending deposits.\n     * @param strategies Addresses of smart vault's strategies.\n     * @param tokens Asset group token addresses.\n     * @param emergencyWallet Address of emergency withdraw wallet.\n     */\n    function recoverPendingDeposits(\n        address smartVault,\n        uint256 flushIndex,\n        address[] calldata strategies,\n        address[] calldata tokens,\n        address emergencyWallet\n    ) external;\n\n    /**\n     * @notice Gets current required deposit ratio of a smart vault.\n     * @param tokens Asset tokens of the smart vault.\n     * @param allocations Allocation between strategies of the smart vault.\n     * @param strategies Strategies of the smart vault.\n     * @return ratio Required deposit ratio of the smart vault.\n     */\n    function getDepositRatio(address[] memory tokens, uint16a16 allocations, address[] memory strategies)\n        external\n        view\n        returns (uint256[] memory ratio);\n}\n"
      },
      "src/interfaces/ISwapper.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.17;\n\n/* ========== STRUCTS ========== */\n\n/**\n * @notice Information needed to make a swap of assets.\n * @custom:member swapTarget Contract executing the swap.\n * @custom:member token Token to be swapped.\n * @custom:member swapCallData Calldata describing the swap itself.\n */\nstruct SwapInfo {\n    address swapTarget;\n    address token;\n    bytes swapCallData;\n}\n\n/* ========== ERRORS ========== */\n\n/**\n * @notice Used when trying to do a swap via an exchange that is not allowed to execute a swap.\n * @param exchange Exchange used.\n */\nerror ExchangeNotAllowed(address exchange);\n\n/**\n * @notice Used when trying to execute a swap but are not authorized.\n * @param caller Caller of the swap method.\n */\nerror NotSwapper(address caller);\n\n/* ========== INTERFACES ========== */\n\ninterface ISwapper {\n    /* ========== EVENTS ========== */\n\n    /**\n     * @notice Emitted when the exchange allowlist is updated.\n     * @param exchange Exchange that was updated.\n     * @param isAllowed Whether the exchange is allowed to be used in a swap or not after the update.\n     */\n    event ExchangeAllowlistUpdated(address indexed exchange, bool isAllowed);\n\n    event Swapped(\n        address indexed receiver, address[] tokensIn, address[] tokensOut, uint256[] amountsIn, uint256[] amountsOut\n    );\n\n    /* ========== EXTERNAL MUTATIVE FUNCTIONS ========== */\n\n    /**\n     * @notice Performs a swap of tokens with external contracts.\n     * - deposit tokens into the swapper contract\n     * - swapper will swap tokens based on swap info provided\n     * - swapper will return unswapped tokens to the receiver\n     * @param tokensIn Addresses of tokens available for the swap.\n     * @param swapInfo Information needed to perform the swap.\n     * @param tokensOut Addresses of tokens to swap to.\n     * @param receiver Receiver of unswapped tokens.\n     * @return amountsOut Amounts of `tokensOut` sent from the swapper to the receiver.\n     */\n    function swap(\n        address[] calldata tokensIn,\n        SwapInfo[] calldata swapInfo,\n        address[] calldata tokensOut,\n        address receiver\n    ) external returns (uint256[] memory amountsOut);\n\n    /**\n     * @notice Updates list of exchanges that can be used in a swap.\n     * @dev Requirements:\n     *   - can only be called by user granted ROLE_SPOOL_ADMIN\n     *   - exchanges and allowed arrays need to be of same length\n     * @param exchanges Addresses of exchanges.\n     * @param allowed Whether an exchange is allowed to be used in a swap.\n     */\n    function updateExchangeAllowlist(address[] calldata exchanges, bool[] calldata allowed) external;\n\n    /* ========== EXTERNAL VIEW FUNCTIONS ========== */\n\n    /**\n     * @notice Checks if an exchange is allowed to be used in a swap.\n     * @param exchange Exchange to check.\n     * @return isAllowed True if the exchange is allowed to be used in a swap, false otherwise.\n     */\n    function isExchangeAllowed(address exchange) external view returns (bool isAllowed);\n}\n"
      },
      "src/interfaces/IWithdrawalManager.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.17;\n\nimport \"../libraries/uint16a16Lib.sol\";\n\n/**\n * @notice Used when trying to burn withdrawal NFT that was not synced yet.\n * @param id ID of the NFT.\n */\nerror WithdrawalNftNotSyncedYet(uint256 id);\n\n/**\n * @notice Base information for redeemal.\n * @custom:member smartVault Smart vault from which to redeem.\n * @custom:member shares Amount of smart vault shares to redeem.\n * @custom:member nftIds IDs of deposit NFTs to burn before redeemal.\n * @custom:member nftAmounts Amounts of NFT shares to burn.\n */\nstruct RedeemBag {\n    address smartVault;\n    uint256 shares;\n    uint256[] nftIds;\n    uint256[] nftAmounts;\n}\n\n/**\n * @notice Extra information for fast redeemal.\n * @custom:member strategies Strategies of the smart vault.\n * @custom:member assetGroup Asset group of the smart vault.\n * @custom:member assetGroupId ID of the asset group of the smart vault.\n * @custom:member redeemer Address that initiated the redeemal.\n * @custom:member withdrawalSlippages Slippages used to guard redeemal.\n */\nstruct RedeemFastExtras {\n    address[] strategies;\n    address[] assetGroup;\n    uint256 assetGroupId;\n    address redeemer;\n    uint256[][] withdrawalSlippages;\n}\n\n/**\n * @notice Extra information for redeemal.\n * @custom:member receiver Receiver of the withdraw NFT.\n * @custom:member owner Address that owns the shares being redeemed.\n * @custom:member executor Address that initiated the redeemal.\n * @custom:member flushIndex Current flush index of the smart vault.\n */\nstruct RedeemExtras {\n    address receiver;\n    address owner;\n    address executor;\n    uint256 flushIndex;\n}\n\n/**\n * @notice Information used to claim withdrawal.\n * @custom:member smartVault Smart vault from which to claim withdrawal.\n * @custom:member nftIds Withdrawal NFTs to burn while claiming withdrawal.\n * @custom:member nftAmounts Amounts of NFT shares to burn.\n * @custom:member receiver Receiver of withdrawn assets.\n * @custom:member executor Address that initiated the withdrawal claim.\n * @custom:member assetGroupId ID of the asset group of the smart vault.\n * @custom:member assetGroup Asset group of the smart vault.\n * @custom:member flushIndexToSync Next flush index to sync for the smart vault.\n */\nstruct WithdrawalClaimBag {\n    address smartVault;\n    uint256[] nftIds;\n    uint256[] nftAmounts;\n    address receiver;\n    address executor;\n    uint256 assetGroupId;\n    address[] assetGroup;\n    uint256 flushIndexToSync;\n}\n\ninterface IWithdrawalManager {\n    /**\n     * @notice User redeemed withdrawal NFTs for underlying assets\n     * @param smartVault Smart vault address\n     * @param claimer Claimer address\n     * @param nftIds NFTs to burn\n     * @param nftAmounts NFT shares to burn\n     * @param withdrawnAssets Amount of underlying assets withdrawn\n     */\n    event WithdrawalClaimed(\n        address indexed smartVault,\n        address indexed claimer,\n        uint256 assetGroupId,\n        uint256[] nftIds,\n        uint256[] nftAmounts,\n        uint256[] withdrawnAssets\n    );\n\n    /**\n     * @notice A deposit has been initiated\n     * @param smartVault Smart vault address\n     * @param owner Owner of shares to be redeemed\n     * @param redeemId Withdrawal NFT ID for this redeemal\n     * @param flushIndex Flush index the redeem was scheduled for\n     * @param shares Amount of vault shares to redeem\n     * @param receiver Beneficiary that will be able to claim the underlying assets\n     */\n    event RedeemInitiated(\n        address indexed smartVault,\n        address indexed owner,\n        uint256 indexed redeemId,\n        uint256 flushIndex,\n        uint256 shares,\n        address receiver\n    );\n\n    /**\n     * @notice A deposit has been initiated\n     * @param smartVault Smart vault address\n     * @param redeemer Redeem initiator and owner of shares\n     * @param shares Amount of vault shares to redeem\n     * @param nftIds NFTs to burn\n     * @param nftAmounts NFT shares to burn\n     * @param assetsWithdrawn Amount of underlying assets withdrawn\n     */\n    event FastRedeemInitiated(\n        address indexed smartVault,\n        address indexed redeemer,\n        uint256 shares,\n        uint256[] nftIds,\n        uint256[] nftAmounts,\n        uint256[] assetsWithdrawn\n    );\n\n    /**\n     * @notice Flushes smart vaults deposits and withdrawals to the strategies.\n     * @dev Requirements:\n     *   - can only be called by user granted ROLE_SMART_VAULT_MANAGER\n     * @param smartVault Smart vault to flush.\n     * @param flushIndex Current flush index of the smart vault.\n     * @param strategies Strategies of the smart vault.\n     * @return dhwIndexes current do-hard-work indexes of the strategies.\n     */\n    function flushSmartVault(address smartVault, uint256 flushIndex, address[] calldata strategies)\n        external\n        returns (uint16a16 dhwIndexes);\n\n    /**\n     * @notice Claims withdrawal.\n     * @dev Requirements:\n     *   - can only be called by user granted ROLE_SMART_VAULT_MANAGER\n     * @param bag Parameters for claiming withdrawal.\n     * @return withdrawnAssets Amount of assets withdrawn.\n     * @return assetGroupId ID of the asset group.\n     */\n    function claimWithdrawal(WithdrawalClaimBag calldata bag)\n        external\n        returns (uint256[] memory withdrawnAssets, uint256 assetGroupId);\n\n    /**\n     * @notice Syncs withdrawals between strategies and smart vault after do-hard-works.\n     * @dev Requirements:\n     *   - can only be called by user granted ROLE_SMART_VAULT_MANAGER\n     * @param smartVault Smart vault to sync.\n     * @param flushIndex Smart vault's flush index to sync.\n     * @param strategies Strategies of the smart vault.\n     * @param dhwIndexes_ Strategies' do-hard-work indexes to sync.\n     */\n    function syncWithdrawals(\n        address smartVault,\n        uint256 flushIndex,\n        address[] calldata strategies,\n        uint16a16 dhwIndexes_\n    ) external;\n\n    /**\n     * @notice Redeems smart vault shares.\n     * @dev Requirements:\n     *   - can only be called by user granted ROLE_SMART_VAULT_MANAGER\n     * @param bag Base information for redeemal.\n     * @param bag2 Extra information for redeemal.\n     * @return nftId ID of the withdrawal NFT.\n     */\n    function redeem(RedeemBag calldata bag, RedeemExtras calldata bag2) external returns (uint256 nftId);\n\n    /**\n     * @notice Instantly redeems smart vault shares.\n     * @dev Requirements:\n     *   - can only be called by user granted ROLE_SMART_VAULT_MANAGER\n     * @param bag Base information for redeemal.\n     * @param bag Extra information for fast redeemal.\n     * @return assets Amount of assets withdrawn.\n     */\n    function redeemFast(RedeemBag calldata bag, RedeemFastExtras memory bag2)\n        external\n        returns (uint256[] memory assets);\n}\n"
      },
      "lib/openzeppelin-contracts-upgradeable/contracts/access/IAccessControlUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\r\n\r\npragma solidity ^0.8.0;\r\n\r\n/**\r\n * @dev External interface of AccessControl declared to support ERC165 detection.\r\n */\r\ninterface IAccessControlUpgradeable {\r\n    /**\r\n     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\r\n     *\r\n     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\r\n     * {RoleAdminChanged} not being emitted signaling this.\r\n     *\r\n     * _Available since v3.1._\r\n     */\r\n    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\r\n\r\n    /**\r\n     * @dev Emitted when `account` is granted `role`.\r\n     *\r\n     * `sender` is the account that originated the contract call, an admin role\r\n     * bearer except when using {AccessControl-_setupRole}.\r\n     */\r\n    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\r\n\r\n    /**\r\n     * @dev Emitted when `account` is revoked `role`.\r\n     *\r\n     * `sender` is the account that originated the contract call:\r\n     *   - if using `revokeRole`, it is the admin role bearer\r\n     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)\r\n     */\r\n    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\r\n\r\n    /**\r\n     * @dev Returns `true` if `account` has been granted `role`.\r\n     */\r\n    function hasRole(bytes32 role, address account) external view returns (bool);\r\n\r\n    /**\r\n     * @dev Returns the admin role that controls `role`. See {grantRole} and\r\n     * {revokeRole}.\r\n     *\r\n     * To change a role's admin, use {AccessControl-_setRoleAdmin}.\r\n     */\r\n    function getRoleAdmin(bytes32 role) external view returns (bytes32);\r\n\r\n    /**\r\n     * @dev Grants `role` to `account`.\r\n     *\r\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\r\n     * event.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - the caller must have ``role``'s admin role.\r\n     */\r\n    function grantRole(bytes32 role, address account) external;\r\n\r\n    /**\r\n     * @dev Revokes `role` from `account`.\r\n     *\r\n     * If `account` had been granted `role`, emits a {RoleRevoked} event.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - the caller must have ``role``'s admin role.\r\n     */\r\n    function revokeRole(bytes32 role, address account) external;\r\n\r\n    /**\r\n     * @dev Revokes `role` from the calling account.\r\n     *\r\n     * Roles are often managed via {grantRole} and {revokeRole}: this function's\r\n     * purpose is to provide a mechanism for accounts to lose their privileges\r\n     * if they are compromised (such as when a trusted device is misplaced).\r\n     *\r\n     * If the calling account had been granted `role`, emits a {RoleRevoked}\r\n     * event.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - the caller must be `account`.\r\n     */\r\n    function renounceRole(bytes32 role, address account) external;\r\n}\r\n"
      },
      "src/interfaces/IStrategyRegistry.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.17;\n\nimport \"./ISwapper.sol\";\nimport {DhwInfo} from \"./IStrategy.sol\";\nimport \"../libraries/uint16a16Lib.sol\";\n\n/* ========== ERRORS ========== */\n\n/**\n * @notice Used when trying to register an already registered strategy.\n * @param address_ Address of already registered strategy.\n */\nerror StrategyAlreadyRegistered(address address_);\n\n/**\n * @notice Used when DHW was not run yet for a strategy index.\n * @param strategy Address of the strategy.\n * @param strategyIndex Index of the strategy.\n */\nerror DhwNotRunYetForIndex(address strategy, uint256 strategyIndex);\n\n/**\n * @notice Used when provided token list is invalid.\n */\nerror InvalidTokenList();\n\n/**\n * @notice Used when ghost strategy is used.\n */\nerror GhostStrategyUsed();\n\n/**\n * @notice Used when syncing vault that is already fully synced.\n */\nerror NothingToSync();\n\n/**\n * @notice Used when system tries to configure a too large ecosystem fee.\n * @param ecosystemFeePct Requested ecosystem fee.\n */\nerror EcosystemFeeTooLarge(uint256 ecosystemFeePct);\n\n/**\n * @notice Used when system tries to configure a too large treasury fee.\n * @param treasuryFeePct Requested treasury fee.\n */\nerror TreasuryFeeTooLarge(uint256 treasuryFeePct);\n\n/**\n * @notice Used when user tries to re-add a strategy that was previously removed from the system.\n * @param strategy Strategy address\n */\nerror StrategyPreviouslyRemoved(address strategy);\n\n/**\n * @notice Represents change of state for a strategy during a DHW.\n * @custom:member exchangeRates Exchange rates between assets and USD.\n * @custom:member assetsDeposited Amount of assets deposited into the strategy.\n * @custom:member sharesMinted Amount of strategy shares minted.\n * @custom:member totalSSTs Amount of strategy shares at the end of the DHW.\n * @custom:member totalStrategyValue Total strategy value at the end of the DHW.\n * @custom:member dhwYields DHW yield percentage from the previous DHW.\n */\nstruct StrategyAtIndex {\n    uint256[] exchangeRates;\n    uint256[] assetsDeposited;\n    uint256 sharesMinted;\n    uint256 totalSSTs;\n    uint256 totalStrategyValue;\n    int256 dhwYields;\n}\n\n/**\n * @notice Parameters for calling do hard work.\n * @custom:member strategies Strategies to do-hard-worked upon, grouped by their asset group.\n * @custom:member swapInfo Information for swapping assets before depositing into protocol. SwapInfo[] per each strategy.\n * @custom:member compoundSwapInfo Information for swapping rewards before depositing them back into the protocol. SwapInfo[] per each strategy.\n * @custom:member strategySlippages Slippages used to constrain depositing into and withdrawing from the protocol. uint256[] per strategy.\n * @custom:member baseYields Base yield percentage the strategy created in the DHW period (applicable only for some strategies).\n * @custom:member tokens List of all asset tokens involved in the do hard work.\n * @custom:member exchangeRateSlippages Slippages used to constrain exchange rates for asset tokens. uint256[2] for each token.\n * @custom:member validUntil Sets the maximum timestamp the user is willing to wait to start executing 'do hard work'.\n */\nstruct DoHardWorkParameterBag {\n    address[][] strategies;\n    SwapInfo[][][] swapInfo;\n    SwapInfo[][][] compoundSwapInfo;\n    uint256[][][] strategySlippages;\n    int256[][] baseYields;\n    address[] tokens;\n    uint256[2][] exchangeRateSlippages;\n    uint256 validUntil;\n}\n\n/**\n * @notice Parameters for calling redeem fast.\n * @custom:member strategies Addresses of strategies.\n * @custom:member strategyShares Amount of shares to redeem.\n * @custom:member assetGroup Asset group of the smart vault.\n * @custom:member slippages Slippages to guard withdrawal.\n */\nstruct RedeemFastParameterBag {\n    address[] strategies;\n    uint256[] strategyShares;\n    address[] assetGroup;\n    uint256[][] withdrawalSlippages;\n}\n\n/**\n * @notice Group of platform fees.\n * @custom:member ecosystemFeeReciever Receiver of the ecosystem fees.\n * @custom:member ecosystemFeePct Ecosystem fees. Expressed in FULL_PERCENT.\n * @custom:member treasuryFeeReciever Receiver of the treasury fees.\n * @custom:member treasuryFeePct Treasury fees. Expressed in FULL_PERCENT.\n */\nstruct PlatformFees {\n    address ecosystemFeeReceiver;\n    uint96 ecosystemFeePct;\n    address treasuryFeeReceiver;\n    uint96 treasuryFeePct;\n}\n\n/* ========== INTERFACES ========== */\n\ninterface IStrategyRegistry {\n    /* ========== EXTERNAL VIEW FUNCTIONS ========== */\n\n    /**\n     * @notice Returns address of emergency withdrawal wallet.\n     * @return emergencyWithdrawalWallet Address of the emergency withdrawal wallet.\n     */\n    function emergencyWithdrawalWallet() external view returns (address emergencyWithdrawalWallet);\n\n    /**\n     * @notice Returns current do-hard-work indexes for strategies.\n     * @param strategies Strategies.\n     * @return dhwIndexes Current do-hard-work indexes for strategies.\n     */\n    function currentIndex(address[] calldata strategies) external view returns (uint256[] memory dhwIndexes);\n\n    /**\n     * @notice Returns current strategy APYs.\n     * @param strategies Strategies.\n     */\n    function strategyAPYs(address[] calldata strategies) external view returns (int256[] memory apys);\n\n    /**\n     * @notice Returns assets deposited into a do-hard-work index for a strategy.\n     * @param strategy Strategy.\n     * @param dhwIndex Do-hard-work index.\n     * @return assets Assets deposited into the do-hard-work index for the strategy.\n     */\n    function depositedAssets(address strategy, uint256 dhwIndex) external view returns (uint256[] memory assets);\n\n    /**\n     * @notice Returns shares redeemed in a do-hard-work index for a strategy.\n     * @param strategy Strategy.\n     * @param dhwIndex Do-hard-work index.\n     * @return shares Shares redeemed in a do-hard-work index for the strategy.\n     */\n    function sharesRedeemed(address strategy, uint256 dhwIndex) external view returns (uint256 shares);\n\n    /**\n     * @notice Gets timestamps when do-hard-works were performed.\n     * @param strategies Strategies.\n     * @param dhwIndexes Do-hard-work indexes.\n     * @return timestamps Timestamp for each pair of strategies and do-hard-work indexes.\n     */\n    function dhwTimestamps(address[] calldata strategies, uint16a16 dhwIndexes)\n        external\n        view\n        returns (uint256[] memory timestamps);\n\n    function getDhwYield(address[] calldata strategies, uint16a16 dhwIndexes)\n        external\n        view\n        returns (int256[] memory yields);\n\n    /**\n     * @notice Returns state of strategies at do-hard-work indexes.\n     * @param strategies Strategies.\n     * @param dhwIndexes Do-hard-work indexes.\n     * @return states State of each strategy at corresponding do-hard-work index.\n     */\n    function strategyAtIndexBatch(address[] calldata strategies, uint16a16 dhwIndexes, uint256 assetGroupLength)\n        external\n        view\n        returns (StrategyAtIndex[] memory states);\n\n    /**\n     * @notice Gets required asset ratio for strategy at last DHW.\n     * @param strategy Address of the strategy.\n     * @return assetRatio Asset ratio.\n     */\n    function assetRatioAtLastDhw(address strategy) external view returns (uint256[] memory assetRatio);\n\n    /**\n     * @notice Gets set platform fees.\n     * @return fees Set platform fees.\n     */\n    function platformFees() external view returns (PlatformFees memory fees);\n\n    /* ========== EXTERNAL MUTATIVE FUNCTIONS ========== */\n\n    /**\n     * @notice Registers a strategy into the system.\n     * @dev Requirements:\n     * - caller must have role ROLE_SPOOL_ADMIN\n     * @param strategy Address of strategy to register.\n     * @param apy Apy of the strategy at the time of the registration.\n     */\n    function registerStrategy(address strategy, int256 apy) external;\n\n    /**\n     * @notice Removes strategy from the system.\n     * @dev Requirements:\n     * - caller must have role ROLE_SMART_VAULT_MANAGER\n     * @param strategy Strategy to remove.\n     */\n    function removeStrategy(address strategy) external;\n\n    /**\n     * @notice Sets ecosystem fee.\n     * @dev Requirements:\n     * - caller must have role ROLE_SPOOL_ADMIN\n     * @param ecosystemFeePct Ecosystem fee to set. Expressed in terms of FULL_PERCENT.\n     */\n    function setEcosystemFee(uint96 ecosystemFeePct) external;\n\n    /**\n     * @notice Sets receiver of the ecosystem fees.\n     * @dev Requirements:\n     * - caller must have role ROLE_SPOOL_ADMIN\n     * @param ecosystemFeeReceiver Receiver to set.\n     */\n    function setEcosystemFeeReceiver(address ecosystemFeeReceiver) external;\n\n    /**\n     * @notice Sets treasury fee.\n     * @dev Requirements:\n     * - caller must have role ROLE_SPOOL_ADMIN\n     * @param treasuryFeePct Treasury fee to set. Expressed in terms of FULL_PERCENT.\n     */\n    function setTreasuryFee(uint96 treasuryFeePct) external;\n\n    /**\n     * @notice Sets treasury fee receiver.\n     * @dev Requirements:\n     * - caller must have role ROLE_SPOOL_ADMIN\n     * @param treasuryFeeReceiver Receiver to set.\n     */\n    function setTreasuryFeeReceiver(address treasuryFeeReceiver) external;\n\n    /**\n     * @notice Does hard work on multiple strategies.\n     * @dev Requirements:\n     * - caller must have role ROLE_DO_HARD_WORKER\n     * @param dhwParams Parameters for do hard work.\n     */\n    function doHardWork(DoHardWorkParameterBag calldata dhwParams) external;\n\n    /**\n     * @notice Adds deposits to strategies to be processed at next do-hard-work.\n     * @dev Requirements:\n     * - caller must have role ROLE_SMART_VAULT_MANAGER\n     * @param strategies Strategies to which to add deposit.\n     * @param amounts Amounts of assets to add to each strategy.\n     * @return strategyIndexes Current do-hard-work indexes for the strategies.\n     */\n    function addDeposits(address[] calldata strategies, uint256[][] calldata amounts)\n        external\n        returns (uint16a16 strategyIndexes);\n\n    /**\n     * @notice Adds withdrawals to strategies to be processed at next do-hard-work.\n     * @dev Requirements:\n     * - caller must have role ROLE_SMART_VAULT_MANAGER\n     * @param strategies Strategies to which to add withdrawal.\n     * @param strategyShares Amounts of strategy shares to add to each strategy.\n     * @return strategyIndexes Current do-hard-work indexes for the strategies.\n     */\n    function addWithdrawals(address[] calldata strategies, uint256[] calldata strategyShares)\n        external\n        returns (uint16a16 strategyIndexes);\n\n    /**\n     * @notice Instantly redeems strategy shares for assets.\n     * @dev Requirements:\n     * - caller must have role ROLE_SMART_VAULT_MANAGER\n     * @param redeemFastParams Parameters for fast redeem.\n     * @return withdrawnAssets Amount of assets withdrawn.\n     */\n    function redeemFast(RedeemFastParameterBag calldata redeemFastParams)\n        external\n        returns (uint256[] memory withdrawnAssets);\n\n    /**\n     * @notice Claims withdrawals from the strategies.\n     * @dev Requirements:\n     * - caller must have role ROLE_SMART_VAULT_MANAGER\n     * - DHWs must be run for withdrawal indexes.\n     * @param strategies Addresses if strategies from which to claim withdrawal.\n     * @param dhwIndexes Indexes of strategies when withdrawal was made.\n     * @param strategyShares Amount of strategy shares that was withdrawn.\n     * @return assetsWithdrawn Amount of assets withdrawn from strategies.\n     */\n    function claimWithdrawals(address[] calldata strategies, uint16a16 dhwIndexes, uint256[] calldata strategyShares)\n        external\n        returns (uint256[] memory assetsWithdrawn);\n\n    /**\n     * @notice Redeems strategy shares.\n     * Used by recipients of platform fees.\n     * @param strategies Strategies from which to redeem.\n     * @param shares Amount of shares to redeem from each strategy.\n     * @param withdrawalSlippages Slippages to guard redeemal process.\n     */\n    function redeemStrategyShares(\n        address[] calldata strategies,\n        uint256[] calldata shares,\n        uint256[][] calldata withdrawalSlippages\n    ) external;\n\n    /**\n     * @notice Strategy was registered\n     * @param strategy Strategy address\n     */\n    event StrategyRegistered(address indexed strategy);\n\n    /**\n     * @notice Strategy was removed\n     * @param strategy Strategy address\n     */\n    event StrategyRemoved(address indexed strategy);\n\n    /**\n     * @notice Strategy DHW was executed\n     * @param strategy Strategy address\n     * @param dhwIndex DHW index\n     * @param dhwInfo DHW info\n     */\n    event StrategyDhw(address indexed strategy, uint256 dhwIndex, DhwInfo dhwInfo);\n\n    /**\n     * @notice Ecosystem fee configuration was changed\n     * @param feePct Fee percentage value\n     */\n    event EcosystemFeeSet(uint256 feePct);\n\n    /**\n     * @notice Ecosystem fee receiver was changed\n     * @param ecosystemFeeReceiver Receiver address\n     */\n    event EcosystemFeeReceiverSet(address indexed ecosystemFeeReceiver);\n\n    /**\n     * @notice Treasury fee configuration was changed\n     * @param feePct Fee percentage value\n     */\n    event TreasuryFeeSet(uint256 feePct);\n\n    /**\n     * @notice Treasury fee receiver was changed\n     * @param treasuryFeeReceiver Receiver address\n     */\n    event TreasuryFeeReceiverSet(address indexed treasuryFeeReceiver);\n\n    /**\n     * @notice Emergency withdrawal wallet changed\n     * @param wallet Emergency withdrawal wallet address\n     */\n    event EmergencyWithdrawalWalletSet(address indexed wallet);\n\n    /**\n     * @notice Strategy shares have been redeemed\n     * @param strategy Strategy address\n     * @param owner Address that owns the shares\n     * @param recipient Address that received the withdrawn funds\n     * @param shares Amount of shares that were redeemed\n     * @param assetsWithdrawn Amounts of withdrawn assets\n     */\n    event StrategySharesRedeemed(\n        address indexed strategy,\n        address indexed owner,\n        address indexed recipient,\n        uint256 shares,\n        uint256[] assetsWithdrawn\n    );\n\n    /**\n     * @notice Strategy shares were fast redeemed\n     * @param strategy Strategy address\n     * @param shares Amount of shares redeemed\n     * @param assetsWithdrawn Amounts of withdrawn assets\n     */\n    event StrategySharesFastRedeemed(address indexed strategy, uint256 shares, uint256[] assetsWithdrawn);\n\n    /**\n     * @notice Strategy APY value was updated\n     * @param strategy Strategy address\n     * @param apy New APY value\n     */\n    event StrategyApyUpdated(address indexed strategy, int256 apy);\n}\n\ninterface IEmergencyWithdrawal {\n    /**\n     * @notice Emitted when a strategy is emergency withdrawn from.\n     * @param strategy Strategy that was emergency withdrawn from.\n     */\n    event StrategyEmergencyWithdrawn(address indexed strategy);\n\n    /**\n     * @notice Set a new address that will receive assets withdrawn if emergency withdrawal is executed.\n     * @dev Requirements:\n     * - caller must have role ROLE_SPOOL_ADMIN\n     * @param wallet Address to set as the emergency withdrawal wallet.\n     */\n    function setEmergencyWithdrawalWallet(address wallet) external;\n\n    /**\n     * @notice Instantly withdraws assets from a strategy, bypassing shares mechanism.\n     * @dev Requirements:\n     * - caller must have role ROLE_EMERGENCY_WITHDRAWAL_EXECUTOR\n     * @param strategies Addresses of strategies.\n     * @param withdrawalSlippages Slippages to guard withdrawal.\n     * @param removeStrategies Whether to remove strategies from the system after withdrawal.\n     */\n    function emergencyWithdraw(\n        address[] calldata strategies,\n        uint256[][] calldata withdrawalSlippages,\n        bool removeStrategies\n    ) external;\n}\n"
      },
      "src/interfaces/IUsdPriceFeedManager.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.17;\n\n/// @dev Number of decimals used for USD values.\nuint256 constant USD_DECIMALS = 18;\n\n/**\n * @notice Emitted when asset is invalid.\n * @param asset Invalid asset.\n */\nerror InvalidAsset(address asset);\n\n/**\n * @notice Emitted when price returned by price aggregator is negative or zero.\n * @param price Actual price returned by price aggregator.\n */\nerror NonPositivePrice(int256 price);\n\n/**\n * @notice Emitted when pricing data returned by price aggregator is not from the current\n * round or the round hasn't finished.\n */\nerror StalePriceData();\n\ninterface IUsdPriceFeedManager {\n    /**\n     * @notice Gets number of decimals for an asset.\n     * @param asset Address of the asset.\n     * @return assetDecimals Number of decimals for the asset.\n     */\n    function assetDecimals(address asset) external view returns (uint256 assetDecimals);\n\n    /**\n     * @notice Gets number of decimals for USD.\n     * @return usdDecimals Number of decimals for USD.\n     */\n    function usdDecimals() external view returns (uint256 usdDecimals);\n\n    /**\n     * @notice Calculates asset value in USD using current price.\n     * @param asset Address of asset.\n     * @param assetAmount Amount of asset in asset decimals.\n     * @return usdValue Value in USD in USD decimals.\n     */\n    function assetToUsd(address asset, uint256 assetAmount) external view returns (uint256 usdValue);\n\n    /**\n     * @notice Calculates USD value in asset using current price.\n     * @param asset Address of asset.\n     * @param usdAmount Amount of USD in USD decimals.\n     * @return assetValue Value in asset in asset decimals.\n     */\n    function usdToAsset(address asset, uint256 usdAmount) external view returns (uint256 assetValue);\n\n    /**\n     * @notice Calculates asset value in USD using provided price.\n     * @param asset Address of asset.\n     * @param assetAmount Amount of asset in asset decimals.\n     * @param price Price of asset in USD.\n     * @return usdValue Value in USD in USD decimals.\n     */\n    function assetToUsdCustomPrice(address asset, uint256 assetAmount, uint256 price)\n        external\n        view\n        returns (uint256 usdValue);\n\n    /**\n     * @notice Calculates assets value in USD using provided prices.\n     * @param assets Addresses of assets.\n     * @param assetAmounts Amounts of assets in asset decimals.\n     * @param prices Prices of asset in USD.\n     * @return usdValue Value in USD in USD decimals.\n     */\n    function assetToUsdCustomPriceBulk(\n        address[] calldata assets,\n        uint256[] calldata assetAmounts,\n        uint256[] calldata prices\n    ) external view returns (uint256 usdValue);\n\n    /**\n     * @notice Calculates USD value in asset using provided price.\n     * @param asset Address of asset.\n     * @param usdAmount Amount of USD in USD decimals.\n     * @param price Price of asset in USD.\n     * @return assetValue Value in asset in asset decimals.\n     */\n    function usdToAssetCustomPrice(address asset, uint256 usdAmount, uint256 price)\n        external\n        view\n        returns (uint256 assetValue);\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/ERC20.sol)\r\n\r\npragma solidity ^0.8.0;\r\n\r\nimport \"./IERC20.sol\";\r\nimport \"./extensions/IERC20Metadata.sol\";\r\nimport \"../../utils/Context.sol\";\r\n\r\n/**\r\n * @dev Implementation of the {IERC20} interface.\r\n *\r\n * This implementation is agnostic to the way tokens are created. This means\r\n * that a supply mechanism has to be added in a derived contract using {_mint}.\r\n * For a generic mechanism see {ERC20PresetMinterPauser}.\r\n *\r\n * TIP: For a detailed writeup see our guide\r\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\r\n * to implement supply mechanisms].\r\n *\r\n * The default value of {decimals} is 18. To change this, you should override\r\n * this function so it returns a different value.\r\n *\r\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\r\n * instead returning `false` on failure. This behavior is nonetheless\r\n * conventional and does not conflict with the expectations of ERC20\r\n * applications.\r\n *\r\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\r\n * This allows applications to reconstruct the allowance for all accounts just\r\n * by listening to said events. Other implementations of the EIP may not emit\r\n * these events, as it isn't required by the specification.\r\n *\r\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\r\n * functions have been added to mitigate the well-known issues around setting\r\n * allowances. See {IERC20-approve}.\r\n */\r\ncontract ERC20 is Context, IERC20, IERC20Metadata {\r\n    mapping(address => uint256) private _balances;\r\n\r\n    mapping(address => mapping(address => uint256)) private _allowances;\r\n\r\n    uint256 private _totalSupply;\r\n\r\n    string private _name;\r\n    string private _symbol;\r\n\r\n    /**\r\n     * @dev Sets the values for {name} and {symbol}.\r\n     *\r\n     * All two of these values are immutable: they can only be set once during\r\n     * construction.\r\n     */\r\n    constructor(string memory name_, string memory symbol_) {\r\n        _name = name_;\r\n        _symbol = symbol_;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the name of the token.\r\n     */\r\n    function name() public view virtual override returns (string memory) {\r\n        return _name;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the symbol of the token, usually a shorter version of the\r\n     * name.\r\n     */\r\n    function symbol() public view virtual override returns (string memory) {\r\n        return _symbol;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the number of decimals used to get its user representation.\r\n     * For example, if `decimals` equals `2`, a balance of `505` tokens should\r\n     * be displayed to a user as `5.05` (`505 / 10 ** 2`).\r\n     *\r\n     * Tokens usually opt for a value of 18, imitating the relationship between\r\n     * Ether and Wei. This is the default value returned by this function, unless\r\n     * it's overridden.\r\n     *\r\n     * NOTE: This information is only used for _display_ purposes: it in\r\n     * no way affects any of the arithmetic of the contract, including\r\n     * {IERC20-balanceOf} and {IERC20-transfer}.\r\n     */\r\n    function decimals() public view virtual override returns (uint8) {\r\n        return 18;\r\n    }\r\n\r\n    /**\r\n     * @dev See {IERC20-totalSupply}.\r\n     */\r\n    function totalSupply() public view virtual override returns (uint256) {\r\n        return _totalSupply;\r\n    }\r\n\r\n    /**\r\n     * @dev See {IERC20-balanceOf}.\r\n     */\r\n    function balanceOf(address account) public view virtual override returns (uint256) {\r\n        return _balances[account];\r\n    }\r\n\r\n    /**\r\n     * @dev See {IERC20-transfer}.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `to` cannot be the zero address.\r\n     * - the caller must have a balance of at least `amount`.\r\n     */\r\n    function transfer(address to, uint256 amount) public virtual override returns (bool) {\r\n        address owner = _msgSender();\r\n        _transfer(owner, to, amount);\r\n        return true;\r\n    }\r\n\r\n    /**\r\n     * @dev See {IERC20-allowance}.\r\n     */\r\n    function allowance(address owner, address spender) public view virtual override returns (uint256) {\r\n        return _allowances[owner][spender];\r\n    }\r\n\r\n    /**\r\n     * @dev See {IERC20-approve}.\r\n     *\r\n     * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\r\n     * `transferFrom`. This is semantically equivalent to an infinite approval.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `spender` cannot be the zero address.\r\n     */\r\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\r\n        address owner = _msgSender();\r\n        _approve(owner, spender, amount);\r\n        return true;\r\n    }\r\n\r\n    /**\r\n     * @dev See {IERC20-transferFrom}.\r\n     *\r\n     * Emits an {Approval} event indicating the updated allowance. This is not\r\n     * required by the EIP. See the note at the beginning of {ERC20}.\r\n     *\r\n     * NOTE: Does not update the allowance if the current allowance\r\n     * is the maximum `uint256`.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `from` and `to` cannot be the zero address.\r\n     * - `from` must have a balance of at least `amount`.\r\n     * - the caller must have allowance for ``from``'s tokens of at least\r\n     * `amount`.\r\n     */\r\n    function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {\r\n        address spender = _msgSender();\r\n        _spendAllowance(from, spender, amount);\r\n        _transfer(from, to, amount);\r\n        return true;\r\n    }\r\n\r\n    /**\r\n     * @dev Atomically increases the allowance granted to `spender` by the caller.\r\n     *\r\n     * This is an alternative to {approve} that can be used as a mitigation for\r\n     * problems described in {IERC20-approve}.\r\n     *\r\n     * Emits an {Approval} event indicating the updated allowance.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `spender` cannot be the zero address.\r\n     */\r\n    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\r\n        address owner = _msgSender();\r\n        _approve(owner, spender, allowance(owner, spender) + addedValue);\r\n        return true;\r\n    }\r\n\r\n    /**\r\n     * @dev Atomically decreases the allowance granted to `spender` by the caller.\r\n     *\r\n     * This is an alternative to {approve} that can be used as a mitigation for\r\n     * problems described in {IERC20-approve}.\r\n     *\r\n     * Emits an {Approval} event indicating the updated allowance.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `spender` cannot be the zero address.\r\n     * - `spender` must have allowance for the caller of at least\r\n     * `subtractedValue`.\r\n     */\r\n    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\r\n        address owner = _msgSender();\r\n        uint256 currentAllowance = allowance(owner, spender);\r\n        require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\r\n        unchecked {\r\n            _approve(owner, spender, currentAllowance - subtractedValue);\r\n        }\r\n\r\n        return true;\r\n    }\r\n\r\n    /**\r\n     * @dev Moves `amount` of tokens from `from` to `to`.\r\n     *\r\n     * This internal function is equivalent to {transfer}, and can be used to\r\n     * e.g. implement automatic token fees, slashing mechanisms, etc.\r\n     *\r\n     * Emits a {Transfer} event.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `from` cannot be the zero address.\r\n     * - `to` cannot be the zero address.\r\n     * - `from` must have a balance of at least `amount`.\r\n     */\r\n    function _transfer(address from, address to, uint256 amount) internal virtual {\r\n        require(from != address(0), \"ERC20: transfer from the zero address\");\r\n        require(to != address(0), \"ERC20: transfer to the zero address\");\r\n\r\n        _beforeTokenTransfer(from, to, amount);\r\n\r\n        uint256 fromBalance = _balances[from];\r\n        require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\r\n        unchecked {\r\n            _balances[from] = fromBalance - amount;\r\n            // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\r\n            // decrementing then incrementing.\r\n            _balances[to] += amount;\r\n        }\r\n\r\n        emit Transfer(from, to, amount);\r\n\r\n        _afterTokenTransfer(from, to, amount);\r\n    }\r\n\r\n    /** @dev Creates `amount` tokens and assigns them to `account`, increasing\r\n     * the total supply.\r\n     *\r\n     * Emits a {Transfer} event with `from` set to the zero address.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `account` cannot be the zero address.\r\n     */\r\n    function _mint(address account, uint256 amount) internal virtual {\r\n        require(account != address(0), \"ERC20: mint to the zero address\");\r\n\r\n        _beforeTokenTransfer(address(0), account, amount);\r\n\r\n        _totalSupply += amount;\r\n        unchecked {\r\n            // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\r\n            _balances[account] += amount;\r\n        }\r\n        emit Transfer(address(0), account, amount);\r\n\r\n        _afterTokenTransfer(address(0), account, amount);\r\n    }\r\n\r\n    /**\r\n     * @dev Destroys `amount` tokens from `account`, reducing the\r\n     * total supply.\r\n     *\r\n     * Emits a {Transfer} event with `to` set to the zero address.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `account` cannot be the zero address.\r\n     * - `account` must have at least `amount` tokens.\r\n     */\r\n    function _burn(address account, uint256 amount) internal virtual {\r\n        require(account != address(0), \"ERC20: burn from the zero address\");\r\n\r\n        _beforeTokenTransfer(account, address(0), amount);\r\n\r\n        uint256 accountBalance = _balances[account];\r\n        require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\r\n        unchecked {\r\n            _balances[account] = accountBalance - amount;\r\n            // Overflow not possible: amount <= accountBalance <= totalSupply.\r\n            _totalSupply -= amount;\r\n        }\r\n\r\n        emit Transfer(account, address(0), amount);\r\n\r\n        _afterTokenTransfer(account, address(0), amount);\r\n    }\r\n\r\n    /**\r\n     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\r\n     *\r\n     * This internal function is equivalent to `approve`, and can be used to\r\n     * e.g. set automatic allowances for certain subsystems, etc.\r\n     *\r\n     * Emits an {Approval} event.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `owner` cannot be the zero address.\r\n     * - `spender` cannot be the zero address.\r\n     */\r\n    function _approve(address owner, address spender, uint256 amount) internal virtual {\r\n        require(owner != address(0), \"ERC20: approve from the zero address\");\r\n        require(spender != address(0), \"ERC20: approve to the zero address\");\r\n\r\n        _allowances[owner][spender] = amount;\r\n        emit Approval(owner, spender, amount);\r\n    }\r\n\r\n    /**\r\n     * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\r\n     *\r\n     * Does not update the allowance amount in case of infinite allowance.\r\n     * Revert if not enough allowance is available.\r\n     *\r\n     * Might emit an {Approval} event.\r\n     */\r\n    function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {\r\n        uint256 currentAllowance = allowance(owner, spender);\r\n        if (currentAllowance != type(uint256).max) {\r\n            require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\r\n            unchecked {\r\n                _approve(owner, spender, currentAllowance - amount);\r\n            }\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Hook that is called before any transfer of tokens. This includes\r\n     * minting and burning.\r\n     *\r\n     * Calling conditions:\r\n     *\r\n     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\r\n     * will be transferred to `to`.\r\n     * - when `from` is zero, `amount` tokens will be minted for `to`.\r\n     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\r\n     * - `from` and `to` are never both zero.\r\n     *\r\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\r\n     */\r\n    function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}\r\n\r\n    /**\r\n     * @dev Hook that is called after any transfer of tokens. This includes\r\n     * minting and burning.\r\n     *\r\n     * Calling conditions:\r\n     *\r\n     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\r\n     * has been transferred to `to`.\r\n     * - when `from` is zero, `amount` tokens have been minted for `to`.\r\n     * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\r\n     * - `from` and `to` are never both zero.\r\n     *\r\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\r\n     */\r\n    function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}\r\n}\r\n"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\r\n\r\npragma solidity ^0.8.0;\r\n\r\nimport \"../IERC20.sol\";\r\nimport \"../extensions/IERC20Permit.sol\";\r\nimport \"../../../utils/Address.sol\";\r\n\r\n/**\r\n * @title SafeERC20\r\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\r\n * contract returns false). Tokens that return no value (and instead revert or\r\n * throw on failure) are also supported, non-reverting calls are assumed to be\r\n * successful.\r\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\r\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\r\n */\r\nlibrary SafeERC20 {\r\n    using Address for address;\r\n\r\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\r\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\r\n    }\r\n\r\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\r\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\r\n    }\r\n\r\n    /**\r\n     * @dev Deprecated. This function has issues similar to the ones found in\r\n     * {IERC20-approve}, and its usage is discouraged.\r\n     *\r\n     * Whenever possible, use {safeIncreaseAllowance} and\r\n     * {safeDecreaseAllowance} instead.\r\n     */\r\n    function safeApprove(IERC20 token, address spender, uint256 value) internal {\r\n        // safeApprove should only be called when setting an initial allowance,\r\n        // or when resetting it to zero. To increase and decrease it, use\r\n        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\r\n        require(\r\n            (value == 0) || (token.allowance(address(this), spender) == 0),\r\n            \"SafeERC20: approve from non-zero to non-zero allowance\"\r\n        );\r\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\r\n    }\r\n\r\n    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\r\n        uint256 newAllowance = token.allowance(address(this), spender) + value;\r\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\r\n    }\r\n\r\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\r\n        unchecked {\r\n            uint256 oldAllowance = token.allowance(address(this), spender);\r\n            require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\r\n            uint256 newAllowance = oldAllowance - value;\r\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\r\n        }\r\n    }\r\n\r\n    function safePermit(\r\n        IERC20Permit token,\r\n        address owner,\r\n        address spender,\r\n        uint256 value,\r\n        uint256 deadline,\r\n        uint8 v,\r\n        bytes32 r,\r\n        bytes32 s\r\n    ) internal {\r\n        uint256 nonceBefore = token.nonces(owner);\r\n        token.permit(owner, spender, value, deadline, v, r, s);\r\n        uint256 nonceAfter = token.nonces(owner);\r\n        require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\r\n    }\r\n\r\n    /**\r\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\r\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\r\n     * @param token The token targeted by the call.\r\n     * @param data The call data (encoded using abi.encode or one of its variants).\r\n     */\r\n    function _callOptionalReturn(IERC20 token, bytes memory data) private {\r\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\r\n        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\r\n        // the target address contains contract code and also asserts for success in the low-level call.\r\n\r\n        bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\r\n        if (returndata.length > 0) {\r\n            // Return data is optional\r\n            require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\r\n        }\r\n    }\r\n}\r\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/Strings.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\r\n\r\npragma solidity ^0.8.0;\r\n\r\nimport \"./math/Math.sol\";\r\nimport \"./math/SignedMath.sol\";\r\n\r\n/**\r\n * @dev String operations.\r\n */\r\nlibrary Strings {\r\n    bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\r\n    uint8 private constant _ADDRESS_LENGTH = 20;\r\n\r\n    /**\r\n     * @dev Converts a `uint256` to its ASCII `string` decimal representation.\r\n     */\r\n    function toString(uint256 value) internal pure returns (string memory) {\r\n        unchecked {\r\n            uint256 length = Math.log10(value) + 1;\r\n            string memory buffer = new string(length);\r\n            uint256 ptr;\r\n            /// @solidity memory-safe-assembly\r\n            assembly {\r\n                ptr := add(buffer, add(32, length))\r\n            }\r\n            while (true) {\r\n                ptr--;\r\n                /// @solidity memory-safe-assembly\r\n                assembly {\r\n                    mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\r\n                }\r\n                value /= 10;\r\n                if (value == 0) break;\r\n            }\r\n            return buffer;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Converts a `int256` to its ASCII `string` decimal representation.\r\n     */\r\n    function toString(int256 value) internal pure returns (string memory) {\r\n        return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\r\n    }\r\n\r\n    /**\r\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\r\n     */\r\n    function toHexString(uint256 value) internal pure returns (string memory) {\r\n        unchecked {\r\n            return toHexString(value, Math.log256(value) + 1);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\r\n     */\r\n    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\r\n        bytes memory buffer = new bytes(2 * length + 2);\r\n        buffer[0] = \"0\";\r\n        buffer[1] = \"x\";\r\n        for (uint256 i = 2 * length + 1; i > 1; --i) {\r\n            buffer[i] = _SYMBOLS[value & 0xf];\r\n            value >>= 4;\r\n        }\r\n        require(value == 0, \"Strings: hex length insufficient\");\r\n        return string(buffer);\r\n    }\r\n\r\n    /**\r\n     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\r\n     */\r\n    function toHexString(address addr) internal pure returns (string memory) {\r\n        return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\r\n    }\r\n\r\n    /**\r\n     * @dev Returns true if the two strings are equal.\r\n     */\r\n    function equal(string memory a, string memory b) internal pure returns (bool) {\r\n        return keccak256(bytes(a)) == keccak256(bytes(b));\r\n    }\r\n}\r\n"
      },
      "lib/openzeppelin-contracts-upgradeable/contracts/token/ERC1155/ERC1155Upgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/ERC1155.sol)\r\n\r\npragma solidity ^0.8.0;\r\n\r\nimport \"./IERC1155Upgradeable.sol\";\r\nimport \"./IERC1155ReceiverUpgradeable.sol\";\r\nimport \"./extensions/IERC1155MetadataURIUpgradeable.sol\";\r\nimport \"../../utils/AddressUpgradeable.sol\";\r\nimport \"../../utils/ContextUpgradeable.sol\";\r\nimport \"../../utils/introspection/ERC165Upgradeable.sol\";\r\nimport \"../../proxy/utils/Initializable.sol\";\r\n\r\n/**\r\n * @dev Implementation of the basic standard multi-token.\r\n * See https://eips.ethereum.org/EIPS/eip-1155\r\n * Originally based on code by Enjin: https://github.com/enjin/erc-1155\r\n *\r\n * _Available since v3.1._\r\n */\r\ncontract ERC1155Upgradeable is Initializable, ContextUpgradeable, ERC165Upgradeable, IERC1155Upgradeable, IERC1155MetadataURIUpgradeable {\r\n    using AddressUpgradeable for address;\r\n\r\n    // Mapping from token ID to account balances\r\n    mapping(uint256 => mapping(address => uint256)) private _balances;\r\n\r\n    // Mapping from account to operator approvals\r\n    mapping(address => mapping(address => bool)) private _operatorApprovals;\r\n\r\n    // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json\r\n    string private _uri;\r\n\r\n    /**\r\n     * @dev See {_setURI}.\r\n     */\r\n    function __ERC1155_init(string memory uri_) internal onlyInitializing {\r\n        __ERC1155_init_unchained(uri_);\r\n    }\r\n\r\n    function __ERC1155_init_unchained(string memory uri_) internal onlyInitializing {\r\n        _setURI(uri_);\r\n    }\r\n\r\n    /**\r\n     * @dev See {IERC165-supportsInterface}.\r\n     */\r\n    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165Upgradeable, IERC165Upgradeable) returns (bool) {\r\n        return\r\n            interfaceId == type(IERC1155Upgradeable).interfaceId ||\r\n            interfaceId == type(IERC1155MetadataURIUpgradeable).interfaceId ||\r\n            super.supportsInterface(interfaceId);\r\n    }\r\n\r\n    /**\r\n     * @dev See {IERC1155MetadataURI-uri}.\r\n     *\r\n     * This implementation returns the same URI for *all* token types. It relies\r\n     * on the token type ID substitution mechanism\r\n     * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\r\n     *\r\n     * Clients calling this function must replace the `\\{id\\}` substring with the\r\n     * actual token type ID.\r\n     */\r\n    function uri(uint256) public view virtual override returns (string memory) {\r\n        return _uri;\r\n    }\r\n\r\n    /**\r\n     * @dev See {IERC1155-balanceOf}.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `account` cannot be the zero address.\r\n     */\r\n    function balanceOf(address account, uint256 id) public view virtual override returns (uint256) {\r\n        require(account != address(0), \"ERC1155: address zero is not a valid owner\");\r\n        return _balances[id][account];\r\n    }\r\n\r\n    /**\r\n     * @dev See {IERC1155-balanceOfBatch}.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `accounts` and `ids` must have the same length.\r\n     */\r\n    function balanceOfBatch(address[] memory accounts, uint256[] memory ids)\r\n        public\r\n        view\r\n        virtual\r\n        override\r\n        returns (uint256[] memory)\r\n    {\r\n        require(accounts.length == ids.length, \"ERC1155: accounts and ids length mismatch\");\r\n\r\n        uint256[] memory batchBalances = new uint256[](accounts.length);\r\n\r\n        for (uint256 i = 0; i < accounts.length; ++i) {\r\n            batchBalances[i] = balanceOf(accounts[i], ids[i]);\r\n        }\r\n\r\n        return batchBalances;\r\n    }\r\n\r\n    /**\r\n     * @dev See {IERC1155-setApprovalForAll}.\r\n     */\r\n    function setApprovalForAll(address operator, bool approved) public virtual override {\r\n        _setApprovalForAll(_msgSender(), operator, approved);\r\n    }\r\n\r\n    /**\r\n     * @dev See {IERC1155-isApprovedForAll}.\r\n     */\r\n    function isApprovedForAll(address account, address operator) public view virtual override returns (bool) {\r\n        return _operatorApprovals[account][operator];\r\n    }\r\n\r\n    /**\r\n     * @dev See {IERC1155-safeTransferFrom}.\r\n     */\r\n    function safeTransferFrom(\r\n        address from,\r\n        address to,\r\n        uint256 id,\r\n        uint256 amount,\r\n        bytes memory data\r\n    ) public virtual override {\r\n        require(\r\n            from == _msgSender() || isApprovedForAll(from, _msgSender()),\r\n            \"ERC1155: caller is not token owner or approved\"\r\n        );\r\n        _safeTransferFrom(from, to, id, amount, data);\r\n    }\r\n\r\n    /**\r\n     * @dev See {IERC1155-safeBatchTransferFrom}.\r\n     */\r\n    function safeBatchTransferFrom(\r\n        address from,\r\n        address to,\r\n        uint256[] memory ids,\r\n        uint256[] memory amounts,\r\n        bytes memory data\r\n    ) public virtual override {\r\n        require(\r\n            from == _msgSender() || isApprovedForAll(from, _msgSender()),\r\n            \"ERC1155: caller is not token owner or approved\"\r\n        );\r\n        _safeBatchTransferFrom(from, to, ids, amounts, data);\r\n    }\r\n\r\n    /**\r\n     * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\r\n     *\r\n     * Emits a {TransferSingle} event.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `to` cannot be the zero address.\r\n     * - `from` must have a balance of tokens of type `id` of at least `amount`.\r\n     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\r\n     * acceptance magic value.\r\n     */\r\n    function _safeTransferFrom(\r\n        address from,\r\n        address to,\r\n        uint256 id,\r\n        uint256 amount,\r\n        bytes memory data\r\n    ) internal virtual {\r\n        require(to != address(0), \"ERC1155: transfer to the zero address\");\r\n\r\n        address operator = _msgSender();\r\n        uint256[] memory ids = _asSingletonArray(id);\r\n        uint256[] memory amounts = _asSingletonArray(amount);\r\n\r\n        _beforeTokenTransfer(operator, from, to, ids, amounts, data);\r\n\r\n        uint256 fromBalance = _balances[id][from];\r\n        require(fromBalance >= amount, \"ERC1155: insufficient balance for transfer\");\r\n        unchecked {\r\n            _balances[id][from] = fromBalance - amount;\r\n        }\r\n        _balances[id][to] += amount;\r\n\r\n        emit TransferSingle(operator, from, to, id, amount);\r\n\r\n        _afterTokenTransfer(operator, from, to, ids, amounts, data);\r\n\r\n        _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);\r\n    }\r\n\r\n    /**\r\n     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}.\r\n     *\r\n     * Emits a {TransferBatch} event.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\r\n     * acceptance magic value.\r\n     */\r\n    function _safeBatchTransferFrom(\r\n        address from,\r\n        address to,\r\n        uint256[] memory ids,\r\n        uint256[] memory amounts,\r\n        bytes memory data\r\n    ) internal virtual {\r\n        require(ids.length == amounts.length, \"ERC1155: ids and amounts length mismatch\");\r\n        require(to != address(0), \"ERC1155: transfer to the zero address\");\r\n\r\n        address operator = _msgSender();\r\n\r\n        _beforeTokenTransfer(operator, from, to, ids, amounts, data);\r\n\r\n        for (uint256 i = 0; i < ids.length; ++i) {\r\n            uint256 id = ids[i];\r\n            uint256 amount = amounts[i];\r\n\r\n            uint256 fromBalance = _balances[id][from];\r\n            require(fromBalance >= amount, \"ERC1155: insufficient balance for transfer\");\r\n            unchecked {\r\n                _balances[id][from] = fromBalance - amount;\r\n            }\r\n            _balances[id][to] += amount;\r\n        }\r\n\r\n        emit TransferBatch(operator, from, to, ids, amounts);\r\n\r\n        _afterTokenTransfer(operator, from, to, ids, amounts, data);\r\n\r\n        _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data);\r\n    }\r\n\r\n    /**\r\n     * @dev Sets a new URI for all token types, by relying on the token type ID\r\n     * substitution mechanism\r\n     * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\r\n     *\r\n     * By this mechanism, any occurrence of the `\\{id\\}` substring in either the\r\n     * URI or any of the amounts in the JSON file at said URI will be replaced by\r\n     * clients with the token type ID.\r\n     *\r\n     * For example, the `https://token-cdn-domain/\\{id\\}.json` URI would be\r\n     * interpreted by clients as\r\n     * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json`\r\n     * for token type ID 0x4cce0.\r\n     *\r\n     * See {uri}.\r\n     *\r\n     * Because these URIs cannot be meaningfully represented by the {URI} event,\r\n     * this function emits no events.\r\n     */\r\n    function _setURI(string memory newuri) internal virtual {\r\n        _uri = newuri;\r\n    }\r\n\r\n    /**\r\n     * @dev Creates `amount` tokens of token type `id`, and assigns them to `to`.\r\n     *\r\n     * Emits a {TransferSingle} event.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `to` cannot be the zero address.\r\n     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\r\n     * acceptance magic value.\r\n     */\r\n    function _mint(\r\n        address to,\r\n        uint256 id,\r\n        uint256 amount,\r\n        bytes memory data\r\n    ) internal virtual {\r\n        require(to != address(0), \"ERC1155: mint to the zero address\");\r\n\r\n        address operator = _msgSender();\r\n        uint256[] memory ids = _asSingletonArray(id);\r\n        uint256[] memory amounts = _asSingletonArray(amount);\r\n\r\n        _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);\r\n\r\n        _balances[id][to] += amount;\r\n        emit TransferSingle(operator, address(0), to, id, amount);\r\n\r\n        _afterTokenTransfer(operator, address(0), to, ids, amounts, data);\r\n\r\n        _doSafeTransferAcceptanceCheck(operator, address(0), to, id, amount, data);\r\n    }\r\n\r\n    /**\r\n     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}.\r\n     *\r\n     * Emits a {TransferBatch} event.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `ids` and `amounts` must have the same length.\r\n     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\r\n     * acceptance magic value.\r\n     */\r\n    function _mintBatch(\r\n        address to,\r\n        uint256[] memory ids,\r\n        uint256[] memory amounts,\r\n        bytes memory data\r\n    ) internal virtual {\r\n        require(to != address(0), \"ERC1155: mint to the zero address\");\r\n        require(ids.length == amounts.length, \"ERC1155: ids and amounts length mismatch\");\r\n\r\n        address operator = _msgSender();\r\n\r\n        _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);\r\n\r\n        for (uint256 i = 0; i < ids.length; i++) {\r\n            _balances[ids[i]][to] += amounts[i];\r\n        }\r\n\r\n        emit TransferBatch(operator, address(0), to, ids, amounts);\r\n\r\n        _afterTokenTransfer(operator, address(0), to, ids, amounts, data);\r\n\r\n        _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);\r\n    }\r\n\r\n    /**\r\n     * @dev Destroys `amount` tokens of token type `id` from `from`\r\n     *\r\n     * Emits a {TransferSingle} event.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `from` cannot be the zero address.\r\n     * - `from` must have at least `amount` tokens of token type `id`.\r\n     */\r\n    function _burn(\r\n        address from,\r\n        uint256 id,\r\n        uint256 amount\r\n    ) internal virtual {\r\n        require(from != address(0), \"ERC1155: burn from the zero address\");\r\n\r\n        address operator = _msgSender();\r\n        uint256[] memory ids = _asSingletonArray(id);\r\n        uint256[] memory amounts = _asSingletonArray(amount);\r\n\r\n        _beforeTokenTransfer(operator, from, address(0), ids, amounts, \"\");\r\n\r\n        uint256 fromBalance = _balances[id][from];\r\n        require(fromBalance >= amount, \"ERC1155: burn amount exceeds balance\");\r\n        unchecked {\r\n            _balances[id][from] = fromBalance - amount;\r\n        }\r\n\r\n        emit TransferSingle(operator, from, address(0), id, amount);\r\n\r\n        _afterTokenTransfer(operator, from, address(0), ids, amounts, \"\");\r\n    }\r\n\r\n    /**\r\n     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}.\r\n     *\r\n     * Emits a {TransferBatch} event.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `ids` and `amounts` must have the same length.\r\n     */\r\n    function _burnBatch(\r\n        address from,\r\n        uint256[] memory ids,\r\n        uint256[] memory amounts\r\n    ) internal virtual {\r\n        require(from != address(0), \"ERC1155: burn from the zero address\");\r\n        require(ids.length == amounts.length, \"ERC1155: ids and amounts length mismatch\");\r\n\r\n        address operator = _msgSender();\r\n\r\n        _beforeTokenTransfer(operator, from, address(0), ids, amounts, \"\");\r\n\r\n        for (uint256 i = 0; i < ids.length; i++) {\r\n            uint256 id = ids[i];\r\n            uint256 amount = amounts[i];\r\n\r\n            uint256 fromBalance = _balances[id][from];\r\n            require(fromBalance >= amount, \"ERC1155: burn amount exceeds balance\");\r\n            unchecked {\r\n                _balances[id][from] = fromBalance - amount;\r\n            }\r\n        }\r\n\r\n        emit TransferBatch(operator, from, address(0), ids, amounts);\r\n\r\n        _afterTokenTransfer(operator, from, address(0), ids, amounts, \"\");\r\n    }\r\n\r\n    /**\r\n     * @dev Approve `operator` to operate on all of `owner` tokens\r\n     *\r\n     * Emits an {ApprovalForAll} event.\r\n     */\r\n    function _setApprovalForAll(\r\n        address owner,\r\n        address operator,\r\n        bool approved\r\n    ) internal virtual {\r\n        require(owner != operator, \"ERC1155: setting approval status for self\");\r\n        _operatorApprovals[owner][operator] = approved;\r\n        emit ApprovalForAll(owner, operator, approved);\r\n    }\r\n\r\n    /**\r\n     * @dev Hook that is called before any token transfer. This includes minting\r\n     * and burning, as well as batched variants.\r\n     *\r\n     * The same hook is called on both single and batched variants. For single\r\n     * transfers, the length of the `ids` and `amounts` arrays will be 1.\r\n     *\r\n     * Calling conditions (for each `id` and `amount` pair):\r\n     *\r\n     * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens\r\n     * of token type `id` will be  transferred to `to`.\r\n     * - When `from` is zero, `amount` tokens of token type `id` will be minted\r\n     * for `to`.\r\n     * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`\r\n     * will be burned.\r\n     * - `from` and `to` are never both zero.\r\n     * - `ids` and `amounts` have the same, non-zero length.\r\n     *\r\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\r\n     */\r\n    function _beforeTokenTransfer(\r\n        address operator,\r\n        address from,\r\n        address to,\r\n        uint256[] memory ids,\r\n        uint256[] memory amounts,\r\n        bytes memory data\r\n    ) internal virtual {}\r\n\r\n    /**\r\n     * @dev Hook that is called after any token transfer. This includes minting\r\n     * and burning, as well as batched variants.\r\n     *\r\n     * The same hook is called on both single and batched variants. For single\r\n     * transfers, the length of the `id` and `amount` arrays will be 1.\r\n     *\r\n     * Calling conditions (for each `id` and `amount` pair):\r\n     *\r\n     * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens\r\n     * of token type `id` will be  transferred to `to`.\r\n     * - When `from` is zero, `amount` tokens of token type `id` will be minted\r\n     * for `to`.\r\n     * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`\r\n     * will be burned.\r\n     * - `from` and `to` are never both zero.\r\n     * - `ids` and `amounts` have the same, non-zero length.\r\n     *\r\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\r\n     */\r\n    function _afterTokenTransfer(\r\n        address operator,\r\n        address from,\r\n        address to,\r\n        uint256[] memory ids,\r\n        uint256[] memory amounts,\r\n        bytes memory data\r\n    ) internal virtual {}\r\n\r\n    function _doSafeTransferAcceptanceCheck(\r\n        address operator,\r\n        address from,\r\n        address to,\r\n        uint256 id,\r\n        uint256 amount,\r\n        bytes memory data\r\n    ) private {\r\n        if (to.isContract()) {\r\n            try IERC1155ReceiverUpgradeable(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) {\r\n                if (response != IERC1155ReceiverUpgradeable.onERC1155Received.selector) {\r\n                    revert(\"ERC1155: ERC1155Receiver rejected tokens\");\r\n                }\r\n            } catch Error(string memory reason) {\r\n                revert(reason);\r\n            } catch {\r\n                revert(\"ERC1155: transfer to non-ERC1155Receiver implementer\");\r\n            }\r\n        }\r\n    }\r\n\r\n    function _doSafeBatchTransferAcceptanceCheck(\r\n        address operator,\r\n        address from,\r\n        address to,\r\n        uint256[] memory ids,\r\n        uint256[] memory amounts,\r\n        bytes memory data\r\n    ) private {\r\n        if (to.isContract()) {\r\n            try IERC1155ReceiverUpgradeable(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (\r\n                bytes4 response\r\n            ) {\r\n                if (response != IERC1155ReceiverUpgradeable.onERC1155BatchReceived.selector) {\r\n                    revert(\"ERC1155: ERC1155Receiver rejected tokens\");\r\n                }\r\n            } catch Error(string memory reason) {\r\n                revert(reason);\r\n            } catch {\r\n                revert(\"ERC1155: transfer to non-ERC1155Receiver implementer\");\r\n            }\r\n        }\r\n    }\r\n\r\n    function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) {\r\n        uint256[] memory array = new uint256[](1);\r\n        array[0] = element;\r\n\r\n        return array;\r\n    }\r\n\r\n    /**\r\n     * @dev This empty reserved space is put in place to allow future versions to add new\r\n     * variables without shifting down storage in the inheritance chain.\r\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\r\n     */\r\n    uint256[47] private __gap;\r\n}\r\n"
      },
      "lib/openzeppelin-contracts-upgradeable/contracts/token/ERC20/extensions/draft-ERC20PermitUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/extensions/draft-ERC20Permit.sol)\r\n\r\npragma solidity ^0.8.0;\r\n\r\nimport \"./draft-IERC20PermitUpgradeable.sol\";\r\nimport \"../ERC20Upgradeable.sol\";\r\nimport \"../../../utils/cryptography/ECDSAUpgradeable.sol\";\r\nimport \"../../../utils/cryptography/EIP712Upgradeable.sol\";\r\nimport \"../../../utils/CountersUpgradeable.sol\";\r\nimport \"../../../proxy/utils/Initializable.sol\";\r\n\r\n/**\r\n * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\r\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\r\n *\r\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\r\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\r\n * need to send a transaction, and thus is not required to hold Ether at all.\r\n *\r\n * _Available since v3.4._\r\n *\r\n * @custom:storage-size 51\r\n */\r\nabstract contract ERC20PermitUpgradeable is Initializable, ERC20Upgradeable, IERC20PermitUpgradeable, EIP712Upgradeable {\r\n    using CountersUpgradeable for CountersUpgradeable.Counter;\r\n\r\n    mapping(address => CountersUpgradeable.Counter) private _nonces;\r\n\r\n    // solhint-disable-next-line var-name-mixedcase\r\n    bytes32 private constant _PERMIT_TYPEHASH =\r\n        keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\r\n    /**\r\n     * @dev In previous versions `_PERMIT_TYPEHASH` was declared as `immutable`.\r\n     * However, to ensure consistency with the upgradeable transpiler, we will continue\r\n     * to reserve a slot.\r\n     * @custom:oz-renamed-from _PERMIT_TYPEHASH\r\n     */\r\n    // solhint-disable-next-line var-name-mixedcase\r\n    bytes32 private _PERMIT_TYPEHASH_DEPRECATED_SLOT;\r\n\r\n    /**\r\n     * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `\"1\"`.\r\n     *\r\n     * It's a good idea to use the same `name` that is defined as the ERC20 token name.\r\n     */\r\n    function __ERC20Permit_init(string memory name) internal onlyInitializing {\r\n        __EIP712_init_unchained(name, \"1\");\r\n    }\r\n\r\n    function __ERC20Permit_init_unchained(string memory) internal onlyInitializing {}\r\n\r\n    /**\r\n     * @dev See {IERC20Permit-permit}.\r\n     */\r\n    function permit(\r\n        address owner,\r\n        address spender,\r\n        uint256 value,\r\n        uint256 deadline,\r\n        uint8 v,\r\n        bytes32 r,\r\n        bytes32 s\r\n    ) public virtual override {\r\n        require(block.timestamp <= deadline, \"ERC20Permit: expired deadline\");\r\n\r\n        bytes32 structHash = keccak256(abi.encode(_PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline));\r\n\r\n        bytes32 hash = _hashTypedDataV4(structHash);\r\n\r\n        address signer = ECDSAUpgradeable.recover(hash, v, r, s);\r\n        require(signer == owner, \"ERC20Permit: invalid signature\");\r\n\r\n        _approve(owner, spender, value);\r\n    }\r\n\r\n    /**\r\n     * @dev See {IERC20Permit-nonces}.\r\n     */\r\n    function nonces(address owner) public view virtual override returns (uint256) {\r\n        return _nonces[owner].current();\r\n    }\r\n\r\n    /**\r\n     * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.\r\n     */\r\n    // solhint-disable-next-line func-name-mixedcase\r\n    function DOMAIN_SEPARATOR() external view override returns (bytes32) {\r\n        return _domainSeparatorV4();\r\n    }\r\n\r\n    /**\r\n     * @dev \"Consume a nonce\": return the current value and increment.\r\n     *\r\n     * _Available since v4.1._\r\n     */\r\n    function _useNonce(address owner) internal virtual returns (uint256 current) {\r\n        CountersUpgradeable.Counter storage nonce = _nonces[owner];\r\n        current = nonce.current();\r\n        nonce.increment();\r\n    }\r\n\r\n    /**\r\n     * @dev This empty reserved space is put in place to allow future versions to add new\r\n     * variables without shifting down storage in the inheritance chain.\r\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\r\n     */\r\n    uint256[49] private __gap;\r\n}\r\n"
      },
      "src/libraries/ArrayMapping.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.17;\n\nlibrary ArrayMappingUint256 {\n    /**\n     * @notice Map mapping(uint256 => uint256)) values to an array.\n     */\n    function toArray(mapping(uint256 => uint256) storage _self, uint256 length)\n        external\n        view\n        returns (uint256[] memory)\n    {\n        uint256[] memory arrayOut = new uint256[](length);\n        for (uint256 i; i < length; ++i) {\n            arrayOut[i] = _self[i];\n        }\n        return arrayOut;\n    }\n\n    /**\n     * @notice Set array values to mapping slots.\n     */\n    function setValues(mapping(uint256 => uint256) storage _self, uint256[] calldata values) external {\n        for (uint256 i; i < values.length; ++i) {\n            _self[i] = values[i];\n        }\n    }\n}\n\nlibrary ArrayMappingAddress {\n    /**\n     * @notice Map mapping(uint256 => address)) values to an array.\n     */\n    function toArray(mapping(uint256 => address) storage _self, uint256 length)\n        external\n        view\n        returns (address[] memory)\n    {\n        address[] memory arrayOut = new address[](length);\n        for (uint256 i; i < length; ++i) {\n            arrayOut[i] = _self[i];\n        }\n        return arrayOut;\n    }\n\n    /**\n     * @notice Set array values to mapping slots.\n     */\n    function setValues(mapping(uint256 => address) storage _self, address[] calldata values) external {\n        for (uint256 i; i < values.length; ++i) {\n            _self[i] = values[i];\n        }\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/interfaces/draft-IERC1822.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)\r\n\r\npragma solidity ^0.8.0;\r\n\r\n/**\r\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\r\n * proxy whose upgrades are fully controlled by the current implementation.\r\n */\r\ninterface IERC1822Proxiable {\r\n    /**\r\n     * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\r\n     * address.\r\n     *\r\n     * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\r\n     * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\r\n     * function revert if invoked through a proxy.\r\n     */\r\n    function proxiableUUID() external view returns (bytes32);\r\n}\r\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol)\r\n\r\npragma solidity ^0.8.0;\r\n\r\n/**\r\n * @dev Library for reading and writing primitive types to specific storage slots.\r\n *\r\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\r\n * This library helps with reading and writing to such slots without the need for inline assembly.\r\n *\r\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\r\n *\r\n * Example usage to set ERC1967 implementation slot:\r\n * ```\r\n * contract ERC1967 {\r\n *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\r\n *\r\n *     function _getImplementation() internal view returns (address) {\r\n *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\r\n *     }\r\n *\r\n *     function _setImplementation(address newImplementation) internal {\r\n *         require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\r\n *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\r\n *     }\r\n * }\r\n * ```\r\n *\r\n * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._\r\n */\r\nlibrary StorageSlot {\r\n    struct AddressSlot {\r\n        address value;\r\n    }\r\n\r\n    struct BooleanSlot {\r\n        bool value;\r\n    }\r\n\r\n    struct Bytes32Slot {\r\n        bytes32 value;\r\n    }\r\n\r\n    struct Uint256Slot {\r\n        uint256 value;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns an `AddressSlot` with member `value` located at `slot`.\r\n     */\r\n    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\r\n        /// @solidity memory-safe-assembly\r\n        assembly {\r\n            r.slot := slot\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\r\n     */\r\n    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\r\n        /// @solidity memory-safe-assembly\r\n        assembly {\r\n            r.slot := slot\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\r\n     */\r\n    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\r\n        /// @solidity memory-safe-assembly\r\n        assembly {\r\n            r.slot := slot\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\r\n     */\r\n    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\r\n        /// @solidity memory-safe-assembly\r\n        assembly {\r\n            r.slot := slot\r\n        }\r\n    }\r\n}\r\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/Context.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\r\n\r\npragma solidity ^0.8.0;\r\n\r\n/**\r\n * @dev Provides information about the current execution context, including the\r\n * sender of the transaction and its data. While these are generally available\r\n * via msg.sender and msg.data, they should not be accessed in such a direct\r\n * manner, since when dealing with meta-transactions the account sending and\r\n * paying for execution may not be the actual sender (as far as an application\r\n * is concerned).\r\n *\r\n * This contract is only required for intermediate, library-like contracts.\r\n */\r\nabstract contract Context {\r\n    function _msgSender() internal view virtual returns (address) {\r\n        return msg.sender;\r\n    }\r\n\r\n    function _msgData() internal view virtual returns (bytes calldata) {\r\n        return msg.data;\r\n    }\r\n}\r\n"
      },
      "lib/openzeppelin-contracts-upgradeable/contracts/utils/introspection/IERC165Upgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\r\n\r\npragma solidity ^0.8.0;\r\n\r\n/**\r\n * @dev Interface of the ERC165 standard, as defined in the\r\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\r\n *\r\n * Implementers can declare support of contract interfaces, which can then be\r\n * queried by others ({ERC165Checker}).\r\n *\r\n * For an implementation, see {ERC165}.\r\n */\r\ninterface IERC165Upgradeable {\r\n    /**\r\n     * @dev Returns true if this contract implements the interface defined by\r\n     * `interfaceId`. See the corresponding\r\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\r\n     * to learn more about how these ids are created.\r\n     *\r\n     * This function call must use less than 30 000 gas.\r\n     */\r\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\r\n}\r\n"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\r\n\r\npragma solidity ^0.8.0;\r\n\r\nimport \"../IERC20.sol\";\r\n\r\n/**\r\n * @dev Interface for the optional metadata functions from the ERC20 standard.\r\n *\r\n * _Available since v4.1._\r\n */\r\ninterface IERC20Metadata is IERC20 {\r\n    /**\r\n     * @dev Returns the name of the token.\r\n     */\r\n    function name() external view returns (string memory);\r\n\r\n    /**\r\n     * @dev Returns the symbol of the token.\r\n     */\r\n    function symbol() external view returns (string memory);\r\n\r\n    /**\r\n     * @dev Returns the decimals places of the token.\r\n     */\r\n    function decimals() external view returns (uint8);\r\n}\r\n"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Permit.sol)\r\n\r\npragma solidity ^0.8.0;\r\n\r\n/**\r\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\r\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\r\n *\r\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\r\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\r\n * need to send a transaction, and thus is not required to hold Ether at all.\r\n */\r\ninterface IERC20Permit {\r\n    /**\r\n     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\r\n     * given ``owner``'s signed approval.\r\n     *\r\n     * IMPORTANT: The same issues {IERC20-approve} has related to transaction\r\n     * ordering also apply here.\r\n     *\r\n     * Emits an {Approval} event.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `spender` cannot be the zero address.\r\n     * - `deadline` must be a timestamp in the future.\r\n     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\r\n     * over the EIP712-formatted function arguments.\r\n     * - the signature must use ``owner``'s current nonce (see {nonces}).\r\n     *\r\n     * For more information on the signature format, see the\r\n     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\r\n     * section].\r\n     */\r\n    function permit(\r\n        address owner,\r\n        address spender,\r\n        uint256 value,\r\n        uint256 deadline,\r\n        uint8 v,\r\n        bytes32 r,\r\n        bytes32 s\r\n    ) external;\r\n\r\n    /**\r\n     * @dev Returns the current nonce for `owner`. This value must be\r\n     * included whenever a signature is generated for {permit}.\r\n     *\r\n     * Every successful call to {permit} increases ``owner``'s nonce by one. This\r\n     * prevents a signature from being used multiple times.\r\n     */\r\n    function nonces(address owner) external view returns (uint256);\r\n\r\n    /**\r\n     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\r\n     */\r\n    // solhint-disable-next-line func-name-mixedcase\r\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\r\n}\r\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\r\n\r\npragma solidity ^0.8.0;\r\n\r\n/**\r\n * @dev Standard math utilities missing in the Solidity language.\r\n */\r\nlibrary Math {\r\n    enum Rounding {\r\n        Down, // Toward negative infinity\r\n        Up, // Toward infinity\r\n        Zero // Toward zero\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the largest of two numbers.\r\n     */\r\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\r\n        return a > b ? a : b;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the smallest of two numbers.\r\n     */\r\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\r\n        return a < b ? a : b;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the average of two numbers. The result is rounded towards\r\n     * zero.\r\n     */\r\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\r\n        // (a + b) / 2 can overflow.\r\n        return (a & b) + (a ^ b) / 2;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the ceiling of the division of two numbers.\r\n     *\r\n     * This differs from standard division with `/` in that it rounds up instead\r\n     * of rounding down.\r\n     */\r\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\r\n        // (a + b - 1) / b can overflow on addition, so we distribute.\r\n        return a == 0 ? 0 : (a - 1) / b + 1;\r\n    }\r\n\r\n    /**\r\n     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\r\n     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\r\n     * with further edits by Uniswap Labs also under MIT license.\r\n     */\r\n    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\r\n        unchecked {\r\n            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\r\n            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\r\n            // variables such that product = prod1 * 2^256 + prod0.\r\n            uint256 prod0; // Least significant 256 bits of the product\r\n            uint256 prod1; // Most significant 256 bits of the product\r\n            assembly {\r\n                let mm := mulmod(x, y, not(0))\r\n                prod0 := mul(x, y)\r\n                prod1 := sub(sub(mm, prod0), lt(mm, prod0))\r\n            }\r\n\r\n            // Handle non-overflow cases, 256 by 256 division.\r\n            if (prod1 == 0) {\r\n                return prod0 / denominator;\r\n            }\r\n\r\n            // Make sure the result is less than 2^256. Also prevents denominator == 0.\r\n            require(denominator > prod1, \"Math: mulDiv overflow\");\r\n\r\n            ///////////////////////////////////////////////\r\n            // 512 by 256 division.\r\n            ///////////////////////////////////////////////\r\n\r\n            // Make division exact by subtracting the remainder from [prod1 prod0].\r\n            uint256 remainder;\r\n            assembly {\r\n                // Compute remainder using mulmod.\r\n                remainder := mulmod(x, y, denominator)\r\n\r\n                // Subtract 256 bit number from 512 bit number.\r\n                prod1 := sub(prod1, gt(remainder, prod0))\r\n                prod0 := sub(prod0, remainder)\r\n            }\r\n\r\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\r\n            // See https://cs.stackexchange.com/q/138556/92363.\r\n\r\n            // Does not overflow because the denominator cannot be zero at this stage in the function.\r\n            uint256 twos = denominator & (~denominator + 1);\r\n            assembly {\r\n                // Divide denominator by twos.\r\n                denominator := div(denominator, twos)\r\n\r\n                // Divide [prod1 prod0] by twos.\r\n                prod0 := div(prod0, twos)\r\n\r\n                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\r\n                twos := add(div(sub(0, twos), twos), 1)\r\n            }\r\n\r\n            // Shift in bits from prod1 into prod0.\r\n            prod0 |= prod1 * twos;\r\n\r\n            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\r\n            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\r\n            // four bits. That is, denominator * inv = 1 mod 2^4.\r\n            uint256 inverse = (3 * denominator) ^ 2;\r\n\r\n            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\r\n            // in modular arithmetic, doubling the correct bits in each step.\r\n            inverse *= 2 - denominator * inverse; // inverse mod 2^8\r\n            inverse *= 2 - denominator * inverse; // inverse mod 2^16\r\n            inverse *= 2 - denominator * inverse; // inverse mod 2^32\r\n            inverse *= 2 - denominator * inverse; // inverse mod 2^64\r\n            inverse *= 2 - denominator * inverse; // inverse mod 2^128\r\n            inverse *= 2 - denominator * inverse; // inverse mod 2^256\r\n\r\n            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\r\n            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\r\n            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\r\n            // is no longer required.\r\n            result = prod0 * inverse;\r\n            return result;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\r\n     */\r\n    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\r\n        uint256 result = mulDiv(x, y, denominator);\r\n        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\r\n            result += 1;\r\n        }\r\n        return result;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\r\n     *\r\n     * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\r\n     */\r\n    function sqrt(uint256 a) internal pure returns (uint256) {\r\n        if (a == 0) {\r\n            return 0;\r\n        }\r\n\r\n        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\r\n        //\r\n        // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\r\n        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\r\n        //\r\n        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\r\n        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\r\n        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\r\n        //\r\n        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\r\n        uint256 result = 1 << (log2(a) >> 1);\r\n\r\n        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\r\n        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\r\n        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\r\n        // into the expected uint128 result.\r\n        unchecked {\r\n            result = (result + a / result) >> 1;\r\n            result = (result + a / result) >> 1;\r\n            result = (result + a / result) >> 1;\r\n            result = (result + a / result) >> 1;\r\n            result = (result + a / result) >> 1;\r\n            result = (result + a / result) >> 1;\r\n            result = (result + a / result) >> 1;\r\n            return min(result, a / result);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @notice Calculates sqrt(a), following the selected rounding direction.\r\n     */\r\n    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\r\n        unchecked {\r\n            uint256 result = sqrt(a);\r\n            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Return the log in base 2, rounded down, of a positive value.\r\n     * Returns 0 if given 0.\r\n     */\r\n    function log2(uint256 value) internal pure returns (uint256) {\r\n        uint256 result = 0;\r\n        unchecked {\r\n            if (value >> 128 > 0) {\r\n                value >>= 128;\r\n                result += 128;\r\n            }\r\n            if (value >> 64 > 0) {\r\n                value >>= 64;\r\n                result += 64;\r\n            }\r\n            if (value >> 32 > 0) {\r\n                value >>= 32;\r\n                result += 32;\r\n            }\r\n            if (value >> 16 > 0) {\r\n                value >>= 16;\r\n                result += 16;\r\n            }\r\n            if (value >> 8 > 0) {\r\n                value >>= 8;\r\n                result += 8;\r\n            }\r\n            if (value >> 4 > 0) {\r\n                value >>= 4;\r\n                result += 4;\r\n            }\r\n            if (value >> 2 > 0) {\r\n                value >>= 2;\r\n                result += 2;\r\n            }\r\n            if (value >> 1 > 0) {\r\n                result += 1;\r\n            }\r\n        }\r\n        return result;\r\n    }\r\n\r\n    /**\r\n     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\r\n     * Returns 0 if given 0.\r\n     */\r\n    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\r\n        unchecked {\r\n            uint256 result = log2(value);\r\n            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Return the log in base 10, rounded down, of a positive value.\r\n     * Returns 0 if given 0.\r\n     */\r\n    function log10(uint256 value) internal pure returns (uint256) {\r\n        uint256 result = 0;\r\n        unchecked {\r\n            if (value >= 10 ** 64) {\r\n                value /= 10 ** 64;\r\n                result += 64;\r\n            }\r\n            if (value >= 10 ** 32) {\r\n                value /= 10 ** 32;\r\n                result += 32;\r\n            }\r\n            if (value >= 10 ** 16) {\r\n                value /= 10 ** 16;\r\n                result += 16;\r\n            }\r\n            if (value >= 10 ** 8) {\r\n                value /= 10 ** 8;\r\n                result += 8;\r\n            }\r\n            if (value >= 10 ** 4) {\r\n                value /= 10 ** 4;\r\n                result += 4;\r\n            }\r\n            if (value >= 10 ** 2) {\r\n                value /= 10 ** 2;\r\n                result += 2;\r\n            }\r\n            if (value >= 10 ** 1) {\r\n                result += 1;\r\n            }\r\n        }\r\n        return result;\r\n    }\r\n\r\n    /**\r\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\r\n     * Returns 0 if given 0.\r\n     */\r\n    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\r\n        unchecked {\r\n            uint256 result = log10(value);\r\n            return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Return the log in base 256, rounded down, of a positive value.\r\n     * Returns 0 if given 0.\r\n     *\r\n     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\r\n     */\r\n    function log256(uint256 value) internal pure returns (uint256) {\r\n        uint256 result = 0;\r\n        unchecked {\r\n            if (value >> 128 > 0) {\r\n                value >>= 128;\r\n                result += 16;\r\n            }\r\n            if (value >> 64 > 0) {\r\n                value >>= 64;\r\n                result += 8;\r\n            }\r\n            if (value >> 32 > 0) {\r\n                value >>= 32;\r\n                result += 4;\r\n            }\r\n            if (value >> 16 > 0) {\r\n                value >>= 16;\r\n                result += 2;\r\n            }\r\n            if (value >> 8 > 0) {\r\n                result += 1;\r\n            }\r\n        }\r\n        return result;\r\n    }\r\n\r\n    /**\r\n     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\r\n     * Returns 0 if given 0.\r\n     */\r\n    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\r\n        unchecked {\r\n            uint256 result = log256(value);\r\n            return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\r\n        }\r\n    }\r\n}\r\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\r\n\r\npragma solidity ^0.8.0;\r\n\r\n/**\r\n * @dev Standard signed math utilities missing in the Solidity language.\r\n */\r\nlibrary SignedMath {\r\n    /**\r\n     * @dev Returns the largest of two signed numbers.\r\n     */\r\n    function max(int256 a, int256 b) internal pure returns (int256) {\r\n        return a > b ? a : b;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the smallest of two signed numbers.\r\n     */\r\n    function min(int256 a, int256 b) internal pure returns (int256) {\r\n        return a < b ? a : b;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the average of two signed numbers without overflow.\r\n     * The result is rounded towards zero.\r\n     */\r\n    function average(int256 a, int256 b) internal pure returns (int256) {\r\n        // Formula from the book \"Hacker's Delight\"\r\n        int256 x = (a & b) + ((a ^ b) >> 1);\r\n        return x + (int256(uint256(x) >> 255) & (a ^ b));\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the absolute unsigned value of a signed value.\r\n     */\r\n    function abs(int256 n) internal pure returns (uint256) {\r\n        unchecked {\r\n            // must be unchecked in order to support `n = type(int256).min`\r\n            return uint256(n >= 0 ? n : -n);\r\n        }\r\n    }\r\n}\r\n"
      },
      "lib/openzeppelin-contracts-upgradeable/contracts/token/ERC1155/IERC1155ReceiverUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\r\n\r\npragma solidity ^0.8.0;\r\n\r\nimport \"../../utils/introspection/IERC165Upgradeable.sol\";\r\n\r\n/**\r\n * @dev _Available since v3.1._\r\n */\r\ninterface IERC1155ReceiverUpgradeable is IERC165Upgradeable {\r\n    /**\r\n     * @dev Handles the receipt of a single ERC1155 token type. This function is\r\n     * called at the end of a `safeTransferFrom` after the balance has been updated.\r\n     *\r\n     * NOTE: To accept the transfer, this must return\r\n     * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\r\n     * (i.e. 0xf23a6e61, or its own function selector).\r\n     *\r\n     * @param operator The address which initiated the transfer (i.e. msg.sender)\r\n     * @param from The address which previously owned the token\r\n     * @param id The ID of the token being transferred\r\n     * @param value The amount of tokens being transferred\r\n     * @param data Additional data with no specified format\r\n     * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\r\n     */\r\n    function onERC1155Received(\r\n        address operator,\r\n        address from,\r\n        uint256 id,\r\n        uint256 value,\r\n        bytes calldata data\r\n    ) external returns (bytes4);\r\n\r\n    /**\r\n     * @dev Handles the receipt of a multiple ERC1155 token types. This function\r\n     * is called at the end of a `safeBatchTransferFrom` after the balances have\r\n     * been updated.\r\n     *\r\n     * NOTE: To accept the transfer(s), this must return\r\n     * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\r\n     * (i.e. 0xbc197c81, or its own function selector).\r\n     *\r\n     * @param operator The address which initiated the batch transfer (i.e. msg.sender)\r\n     * @param from The address which previously owned the token\r\n     * @param ids An array containing ids of each token being transferred (order and length must match values array)\r\n     * @param values An array containing amounts of each token being transferred (order and length must match ids array)\r\n     * @param data Additional data with no specified format\r\n     * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\r\n     */\r\n    function onERC1155BatchReceived(\r\n        address operator,\r\n        address from,\r\n        uint256[] calldata ids,\r\n        uint256[] calldata values,\r\n        bytes calldata data\r\n    ) external returns (bytes4);\r\n}\r\n"
      },
      "lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)\r\n\r\npragma solidity ^0.8.1;\r\n\r\n/**\r\n * @dev Collection of functions related to the address type\r\n */\r\nlibrary AddressUpgradeable {\r\n    /**\r\n     * @dev Returns true if `account` is a contract.\r\n     *\r\n     * [IMPORTANT]\r\n     * ====\r\n     * It is unsafe to assume that an address for which this function returns\r\n     * false is an externally-owned account (EOA) and not a contract.\r\n     *\r\n     * Among others, `isContract` will return false for the following\r\n     * types of addresses:\r\n     *\r\n     *  - an externally-owned account\r\n     *  - a contract in construction\r\n     *  - an address where a contract will be created\r\n     *  - an address where a contract lived, but was destroyed\r\n     * ====\r\n     *\r\n     * [IMPORTANT]\r\n     * ====\r\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\r\n     *\r\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\r\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\r\n     * constructor.\r\n     * ====\r\n     */\r\n    function isContract(address account) internal view returns (bool) {\r\n        // This method relies on extcodesize/address.code.length, which returns 0\r\n        // for contracts in construction, since the code is only stored at the end\r\n        // of the constructor execution.\r\n\r\n        return account.code.length > 0;\r\n    }\r\n\r\n    /**\r\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\r\n     * `recipient`, forwarding all available gas and reverting on errors.\r\n     *\r\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\r\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\r\n     * imposed by `transfer`, making them unable to receive funds via\r\n     * `transfer`. {sendValue} removes this limitation.\r\n     *\r\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\r\n     *\r\n     * IMPORTANT: because control is transferred to `recipient`, care must be\r\n     * taken to not create reentrancy vulnerabilities. Consider using\r\n     * {ReentrancyGuard} or the\r\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\r\n     */\r\n    function sendValue(address payable recipient, uint256 amount) internal {\r\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\r\n\r\n        (bool success, ) = recipient.call{value: amount}(\"\");\r\n        require(success, \"Address: unable to send value, recipient may have reverted\");\r\n    }\r\n\r\n    /**\r\n     * @dev Performs a Solidity function call using a low level `call`. A\r\n     * plain `call` is an unsafe replacement for a function call: use this\r\n     * function instead.\r\n     *\r\n     * If `target` reverts with a revert reason, it is bubbled up by this\r\n     * function (like regular Solidity function calls).\r\n     *\r\n     * Returns the raw returned data. To convert to the expected return value,\r\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `target` must be a contract.\r\n     * - calling `target` with `data` must not revert.\r\n     *\r\n     * _Available since v3.1._\r\n     */\r\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\r\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\r\n    }\r\n\r\n    /**\r\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\r\n     * `errorMessage` as a fallback revert reason when `target` reverts.\r\n     *\r\n     * _Available since v3.1._\r\n     */\r\n    function functionCall(\r\n        address target,\r\n        bytes memory data,\r\n        string memory errorMessage\r\n    ) internal returns (bytes memory) {\r\n        return functionCallWithValue(target, data, 0, errorMessage);\r\n    }\r\n\r\n    /**\r\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\r\n     * but also transferring `value` wei to `target`.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - the calling contract must have an ETH balance of at least `value`.\r\n     * - the called Solidity function must be `payable`.\r\n     *\r\n     * _Available since v3.1._\r\n     */\r\n    function functionCallWithValue(\r\n        address target,\r\n        bytes memory data,\r\n        uint256 value\r\n    ) internal returns (bytes memory) {\r\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\r\n    }\r\n\r\n    /**\r\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\r\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\r\n     *\r\n     * _Available since v3.1._\r\n     */\r\n    function functionCallWithValue(\r\n        address target,\r\n        bytes memory data,\r\n        uint256 value,\r\n        string memory errorMessage\r\n    ) internal returns (bytes memory) {\r\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\r\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\r\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\r\n    }\r\n\r\n    /**\r\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\r\n     * but performing a static call.\r\n     *\r\n     * _Available since v3.3._\r\n     */\r\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\r\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\r\n    }\r\n\r\n    /**\r\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\r\n     * but performing a static call.\r\n     *\r\n     * _Available since v3.3._\r\n     */\r\n    function functionStaticCall(\r\n        address target,\r\n        bytes memory data,\r\n        string memory errorMessage\r\n    ) internal view returns (bytes memory) {\r\n        (bool success, bytes memory returndata) = target.staticcall(data);\r\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\r\n    }\r\n\r\n    /**\r\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\r\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\r\n     *\r\n     * _Available since v4.8._\r\n     */\r\n    function verifyCallResultFromTarget(\r\n        address target,\r\n        bool success,\r\n        bytes memory returndata,\r\n        string memory errorMessage\r\n    ) internal view returns (bytes memory) {\r\n        if (success) {\r\n            if (returndata.length == 0) {\r\n                // only check isContract if the call was successful and the return data is empty\r\n                // otherwise we already know that it was a contract\r\n                require(isContract(target), \"Address: call to non-contract\");\r\n            }\r\n            return returndata;\r\n        } else {\r\n            _revert(returndata, errorMessage);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\r\n     * revert reason or using the provided one.\r\n     *\r\n     * _Available since v4.3._\r\n     */\r\n    function verifyCallResult(\r\n        bool success,\r\n        bytes memory returndata,\r\n        string memory errorMessage\r\n    ) internal pure returns (bytes memory) {\r\n        if (success) {\r\n            return returndata;\r\n        } else {\r\n            _revert(returndata, errorMessage);\r\n        }\r\n    }\r\n\r\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\r\n        // Look for revert reason and bubble it up if present\r\n        if (returndata.length > 0) {\r\n            // The easiest way to bubble the revert reason is using memory via assembly\r\n            /// @solidity memory-safe-assembly\r\n            assembly {\r\n                let returndata_size := mload(returndata)\r\n                revert(add(32, returndata), returndata_size)\r\n            }\r\n        } else {\r\n            revert(errorMessage);\r\n        }\r\n    }\r\n}\r\n"
      },
      "lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\r\n\r\npragma solidity ^0.8.0;\r\nimport \"../proxy/utils/Initializable.sol\";\r\n\r\n/**\r\n * @dev Provides information about the current execution context, including the\r\n * sender of the transaction and its data. While these are generally available\r\n * via msg.sender and msg.data, they should not be accessed in such a direct\r\n * manner, since when dealing with meta-transactions the account sending and\r\n * paying for execution may not be the actual sender (as far as an application\r\n * is concerned).\r\n *\r\n * This contract is only required for intermediate, library-like contracts.\r\n */\r\nabstract contract ContextUpgradeable is Initializable {\r\n    function __Context_init() internal onlyInitializing {\r\n    }\r\n\r\n    function __Context_init_unchained() internal onlyInitializing {\r\n    }\r\n    function _msgSender() internal view virtual returns (address) {\r\n        return msg.sender;\r\n    }\r\n\r\n    function _msgData() internal view virtual returns (bytes calldata) {\r\n        return msg.data;\r\n    }\r\n\r\n    /**\r\n     * @dev This empty reserved space is put in place to allow future versions to add new\r\n     * variables without shifting down storage in the inheritance chain.\r\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\r\n     */\r\n    uint256[50] private __gap;\r\n}\r\n"
      },
      "lib/openzeppelin-contracts-upgradeable/contracts/utils/introspection/ERC165Upgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\r\n\r\npragma solidity ^0.8.0;\r\n\r\nimport \"./IERC165Upgradeable.sol\";\r\nimport \"../../proxy/utils/Initializable.sol\";\r\n\r\n/**\r\n * @dev Implementation of the {IERC165} interface.\r\n *\r\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\r\n * for the additional interface id that will be supported. For example:\r\n *\r\n * ```solidity\r\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\r\n *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\r\n * }\r\n * ```\r\n *\r\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\r\n */\r\nabstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable {\r\n    function __ERC165_init() internal onlyInitializing {\r\n    }\r\n\r\n    function __ERC165_init_unchained() internal onlyInitializing {\r\n    }\r\n    /**\r\n     * @dev See {IERC165-supportsInterface}.\r\n     */\r\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\r\n        return interfaceId == type(IERC165Upgradeable).interfaceId;\r\n    }\r\n\r\n    /**\r\n     * @dev This empty reserved space is put in place to allow future versions to add new\r\n     * variables without shifting down storage in the inheritance chain.\r\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\r\n     */\r\n    uint256[50] private __gap;\r\n}\r\n"
      },
      "lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol)\r\n\r\npragma solidity ^0.8.2;\r\n\r\nimport \"../../utils/AddressUpgradeable.sol\";\r\n\r\n/**\r\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\r\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\r\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\r\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\r\n *\r\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\r\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\r\n * case an upgrade adds a module that needs to be initialized.\r\n *\r\n * For example:\r\n *\r\n * [.hljs-theme-light.nopadding]\r\n * ```\r\n * contract MyToken is ERC20Upgradeable {\r\n *     function initialize() initializer public {\r\n *         __ERC20_init(\"MyToken\", \"MTK\");\r\n *     }\r\n * }\r\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\r\n *     function initializeV2() reinitializer(2) public {\r\n *         __ERC20Permit_init(\"MyToken\");\r\n *     }\r\n * }\r\n * ```\r\n *\r\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\r\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\r\n *\r\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\r\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\r\n *\r\n * [CAUTION]\r\n * ====\r\n * Avoid leaving a contract uninitialized.\r\n *\r\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\r\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\r\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\r\n *\r\n * [.hljs-theme-light.nopadding]\r\n * ```\r\n * /// @custom:oz-upgrades-unsafe-allow constructor\r\n * constructor() {\r\n *     _disableInitializers();\r\n * }\r\n * ```\r\n * ====\r\n */\r\nabstract contract Initializable {\r\n    /**\r\n     * @dev Indicates that the contract has been initialized.\r\n     * @custom:oz-retyped-from bool\r\n     */\r\n    uint8 private _initialized;\r\n\r\n    /**\r\n     * @dev Indicates that the contract is in the process of being initialized.\r\n     */\r\n    bool private _initializing;\r\n\r\n    /**\r\n     * @dev Triggered when the contract has been initialized or reinitialized.\r\n     */\r\n    event Initialized(uint8 version);\r\n\r\n    /**\r\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\r\n     * `onlyInitializing` functions can be used to initialize parent contracts.\r\n     *\r\n     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\r\n     * constructor.\r\n     *\r\n     * Emits an {Initialized} event.\r\n     */\r\n    modifier initializer() {\r\n        bool isTopLevelCall = !_initializing;\r\n        require(\r\n            (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\r\n            \"Initializable: contract is already initialized\"\r\n        );\r\n        _initialized = 1;\r\n        if (isTopLevelCall) {\r\n            _initializing = true;\r\n        }\r\n        _;\r\n        if (isTopLevelCall) {\r\n            _initializing = false;\r\n            emit Initialized(1);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\r\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\r\n     * used to initialize parent contracts.\r\n     *\r\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\r\n     * are added through upgrades and that require initialization.\r\n     *\r\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\r\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\r\n     *\r\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\r\n     * a contract, executing them in the right order is up to the developer or operator.\r\n     *\r\n     * WARNING: setting the version to 255 will prevent any future reinitialization.\r\n     *\r\n     * Emits an {Initialized} event.\r\n     */\r\n    modifier reinitializer(uint8 version) {\r\n        require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\r\n        _initialized = version;\r\n        _initializing = true;\r\n        _;\r\n        _initializing = false;\r\n        emit Initialized(version);\r\n    }\r\n\r\n    /**\r\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\r\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\r\n     */\r\n    modifier onlyInitializing() {\r\n        require(_initializing, \"Initializable: contract is not initializing\");\r\n        _;\r\n    }\r\n\r\n    /**\r\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\r\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\r\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\r\n     * through proxies.\r\n     *\r\n     * Emits an {Initialized} event the first time it is successfully executed.\r\n     */\r\n    function _disableInitializers() internal virtual {\r\n        require(!_initializing, \"Initializable: contract is initializing\");\r\n        if (_initialized != type(uint8).max) {\r\n            _initialized = type(uint8).max;\r\n            emit Initialized(type(uint8).max);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Internal function that returns the initialized version. Returns `_initialized`\r\n     */\r\n    function _getInitializedVersion() internal view returns (uint8) {\r\n        return _initialized;\r\n    }\r\n\r\n    /**\r\n     * @dev Internal function that returns the initialized version. Returns `_initializing`\r\n     */\r\n    function _isInitializing() internal view returns (bool) {\r\n        return _initializing;\r\n    }\r\n}\r\n"
      },
      "lib/openzeppelin-contracts-upgradeable/contracts/token/ERC20/extensions/draft-IERC20PermitUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\r\n\r\npragma solidity ^0.8.0;\r\n\r\n/**\r\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\r\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\r\n *\r\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\r\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\r\n * need to send a transaction, and thus is not required to hold Ether at all.\r\n */\r\ninterface IERC20PermitUpgradeable {\r\n    /**\r\n     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\r\n     * given ``owner``'s signed approval.\r\n     *\r\n     * IMPORTANT: The same issues {IERC20-approve} has related to transaction\r\n     * ordering also apply here.\r\n     *\r\n     * Emits an {Approval} event.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `spender` cannot be the zero address.\r\n     * - `deadline` must be a timestamp in the future.\r\n     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\r\n     * over the EIP712-formatted function arguments.\r\n     * - the signature must use ``owner``'s current nonce (see {nonces}).\r\n     *\r\n     * For more information on the signature format, see the\r\n     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\r\n     * section].\r\n     */\r\n    function permit(\r\n        address owner,\r\n        address spender,\r\n        uint256 value,\r\n        uint256 deadline,\r\n        uint8 v,\r\n        bytes32 r,\r\n        bytes32 s\r\n    ) external;\r\n\r\n    /**\r\n     * @dev Returns the current nonce for `owner`. This value must be\r\n     * included whenever a signature is generated for {permit}.\r\n     *\r\n     * Every successful call to {permit} increases ``owner``'s nonce by one. This\r\n     * prevents a signature from being used multiple times.\r\n     */\r\n    function nonces(address owner) external view returns (uint256);\r\n\r\n    /**\r\n     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\r\n     */\r\n    // solhint-disable-next-line func-name-mixedcase\r\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\r\n}\r\n"
      },
      "lib/openzeppelin-contracts-upgradeable/contracts/token/ERC20/ERC20Upgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/ERC20.sol)\r\n\r\npragma solidity ^0.8.0;\r\n\r\nimport \"./IERC20Upgradeable.sol\";\r\nimport \"./extensions/IERC20MetadataUpgradeable.sol\";\r\nimport \"../../utils/ContextUpgradeable.sol\";\r\nimport \"../../proxy/utils/Initializable.sol\";\r\n\r\n/**\r\n * @dev Implementation of the {IERC20} interface.\r\n *\r\n * This implementation is agnostic to the way tokens are created. This means\r\n * that a supply mechanism has to be added in a derived contract using {_mint}.\r\n * For a generic mechanism see {ERC20PresetMinterPauser}.\r\n *\r\n * TIP: For a detailed writeup see our guide\r\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\r\n * to implement supply mechanisms].\r\n *\r\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\r\n * instead returning `false` on failure. This behavior is nonetheless\r\n * conventional and does not conflict with the expectations of ERC20\r\n * applications.\r\n *\r\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\r\n * This allows applications to reconstruct the allowance for all accounts just\r\n * by listening to said events. Other implementations of the EIP may not emit\r\n * these events, as it isn't required by the specification.\r\n *\r\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\r\n * functions have been added to mitigate the well-known issues around setting\r\n * allowances. See {IERC20-approve}.\r\n */\r\ncontract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeable, IERC20MetadataUpgradeable {\r\n    mapping(address => uint256) private _balances;\r\n\r\n    mapping(address => mapping(address => uint256)) private _allowances;\r\n\r\n    uint256 private _totalSupply;\r\n\r\n    string private _name;\r\n    string private _symbol;\r\n\r\n    /**\r\n     * @dev Sets the values for {name} and {symbol}.\r\n     *\r\n     * The default value of {decimals} is 18. To select a different value for\r\n     * {decimals} you should overload it.\r\n     *\r\n     * All two of these values are immutable: they can only be set once during\r\n     * construction.\r\n     */\r\n    function __ERC20_init(string memory name_, string memory symbol_) internal onlyInitializing {\r\n        __ERC20_init_unchained(name_, symbol_);\r\n    }\r\n\r\n    function __ERC20_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing {\r\n        _name = name_;\r\n        _symbol = symbol_;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the name of the token.\r\n     */\r\n    function name() public view virtual override returns (string memory) {\r\n        return _name;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the symbol of the token, usually a shorter version of the\r\n     * name.\r\n     */\r\n    function symbol() public view virtual override returns (string memory) {\r\n        return _symbol;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the number of decimals used to get its user representation.\r\n     * For example, if `decimals` equals `2`, a balance of `505` tokens should\r\n     * be displayed to a user as `5.05` (`505 / 10 ** 2`).\r\n     *\r\n     * Tokens usually opt for a value of 18, imitating the relationship between\r\n     * Ether and Wei. This is the value {ERC20} uses, unless this function is\r\n     * overridden;\r\n     *\r\n     * NOTE: This information is only used for _display_ purposes: it in\r\n     * no way affects any of the arithmetic of the contract, including\r\n     * {IERC20-balanceOf} and {IERC20-transfer}.\r\n     */\r\n    function decimals() public view virtual override returns (uint8) {\r\n        return 18;\r\n    }\r\n\r\n    /**\r\n     * @dev See {IERC20-totalSupply}.\r\n     */\r\n    function totalSupply() public view virtual override returns (uint256) {\r\n        return _totalSupply;\r\n    }\r\n\r\n    /**\r\n     * @dev See {IERC20-balanceOf}.\r\n     */\r\n    function balanceOf(address account) public view virtual override returns (uint256) {\r\n        return _balances[account];\r\n    }\r\n\r\n    /**\r\n     * @dev See {IERC20-transfer}.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `to` cannot be the zero address.\r\n     * - the caller must have a balance of at least `amount`.\r\n     */\r\n    function transfer(address to, uint256 amount) public virtual override returns (bool) {\r\n        address owner = _msgSender();\r\n        _transfer(owner, to, amount);\r\n        return true;\r\n    }\r\n\r\n    /**\r\n     * @dev See {IERC20-allowance}.\r\n     */\r\n    function allowance(address owner, address spender) public view virtual override returns (uint256) {\r\n        return _allowances[owner][spender];\r\n    }\r\n\r\n    /**\r\n     * @dev See {IERC20-approve}.\r\n     *\r\n     * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\r\n     * `transferFrom`. This is semantically equivalent to an infinite approval.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `spender` cannot be the zero address.\r\n     */\r\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\r\n        address owner = _msgSender();\r\n        _approve(owner, spender, amount);\r\n        return true;\r\n    }\r\n\r\n    /**\r\n     * @dev See {IERC20-transferFrom}.\r\n     *\r\n     * Emits an {Approval} event indicating the updated allowance. This is not\r\n     * required by the EIP. See the note at the beginning of {ERC20}.\r\n     *\r\n     * NOTE: Does not update the allowance if the current allowance\r\n     * is the maximum `uint256`.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `from` and `to` cannot be the zero address.\r\n     * - `from` must have a balance of at least `amount`.\r\n     * - the caller must have allowance for ``from``'s tokens of at least\r\n     * `amount`.\r\n     */\r\n    function transferFrom(\r\n        address from,\r\n        address to,\r\n        uint256 amount\r\n    ) public virtual override returns (bool) {\r\n        address spender = _msgSender();\r\n        _spendAllowance(from, spender, amount);\r\n        _transfer(from, to, amount);\r\n        return true;\r\n    }\r\n\r\n    /**\r\n     * @dev Atomically increases the allowance granted to `spender` by the caller.\r\n     *\r\n     * This is an alternative to {approve} that can be used as a mitigation for\r\n     * problems described in {IERC20-approve}.\r\n     *\r\n     * Emits an {Approval} event indicating the updated allowance.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `spender` cannot be the zero address.\r\n     */\r\n    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\r\n        address owner = _msgSender();\r\n        _approve(owner, spender, allowance(owner, spender) + addedValue);\r\n        return true;\r\n    }\r\n\r\n    /**\r\n     * @dev Atomically decreases the allowance granted to `spender` by the caller.\r\n     *\r\n     * This is an alternative to {approve} that can be used as a mitigation for\r\n     * problems described in {IERC20-approve}.\r\n     *\r\n     * Emits an {Approval} event indicating the updated allowance.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `spender` cannot be the zero address.\r\n     * - `spender` must have allowance for the caller of at least\r\n     * `subtractedValue`.\r\n     */\r\n    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\r\n        address owner = _msgSender();\r\n        uint256 currentAllowance = allowance(owner, spender);\r\n        require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\r\n        unchecked {\r\n            _approve(owner, spender, currentAllowance - subtractedValue);\r\n        }\r\n\r\n        return true;\r\n    }\r\n\r\n    /**\r\n     * @dev Moves `amount` of tokens from `from` to `to`.\r\n     *\r\n     * This internal function is equivalent to {transfer}, and can be used to\r\n     * e.g. implement automatic token fees, slashing mechanisms, etc.\r\n     *\r\n     * Emits a {Transfer} event.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `from` cannot be the zero address.\r\n     * - `to` cannot be the zero address.\r\n     * - `from` must have a balance of at least `amount`.\r\n     */\r\n    function _transfer(\r\n        address from,\r\n        address to,\r\n        uint256 amount\r\n    ) internal virtual {\r\n        require(from != address(0), \"ERC20: transfer from the zero address\");\r\n        require(to != address(0), \"ERC20: transfer to the zero address\");\r\n\r\n        _beforeTokenTransfer(from, to, amount);\r\n\r\n        uint256 fromBalance = _balances[from];\r\n        require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\r\n        unchecked {\r\n            _balances[from] = fromBalance - amount;\r\n            // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\r\n            // decrementing then incrementing.\r\n            _balances[to] += amount;\r\n        }\r\n\r\n        emit Transfer(from, to, amount);\r\n\r\n        _afterTokenTransfer(from, to, amount);\r\n    }\r\n\r\n    /** @dev Creates `amount` tokens and assigns them to `account`, increasing\r\n     * the total supply.\r\n     *\r\n     * Emits a {Transfer} event with `from` set to the zero address.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `account` cannot be the zero address.\r\n     */\r\n    function _mint(address account, uint256 amount) internal virtual {\r\n        require(account != address(0), \"ERC20: mint to the zero address\");\r\n\r\n        _beforeTokenTransfer(address(0), account, amount);\r\n\r\n        _totalSupply += amount;\r\n        unchecked {\r\n            // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\r\n            _balances[account] += amount;\r\n        }\r\n        emit Transfer(address(0), account, amount);\r\n\r\n        _afterTokenTransfer(address(0), account, amount);\r\n    }\r\n\r\n    /**\r\n     * @dev Destroys `amount` tokens from `account`, reducing the\r\n     * total supply.\r\n     *\r\n     * Emits a {Transfer} event with `to` set to the zero address.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `account` cannot be the zero address.\r\n     * - `account` must have at least `amount` tokens.\r\n     */\r\n    function _burn(address account, uint256 amount) internal virtual {\r\n        require(account != address(0), \"ERC20: burn from the zero address\");\r\n\r\n        _beforeTokenTransfer(account, address(0), amount);\r\n\r\n        uint256 accountBalance = _balances[account];\r\n        require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\r\n        unchecked {\r\n            _balances[account] = accountBalance - amount;\r\n            // Overflow not possible: amount <= accountBalance <= totalSupply.\r\n            _totalSupply -= amount;\r\n        }\r\n\r\n        emit Transfer(account, address(0), amount);\r\n\r\n        _afterTokenTransfer(account, address(0), amount);\r\n    }\r\n\r\n    /**\r\n     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\r\n     *\r\n     * This internal function is equivalent to `approve`, and can be used to\r\n     * e.g. set automatic allowances for certain subsystems, etc.\r\n     *\r\n     * Emits an {Approval} event.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `owner` cannot be the zero address.\r\n     * - `spender` cannot be the zero address.\r\n     */\r\n    function _approve(\r\n        address owner,\r\n        address spender,\r\n        uint256 amount\r\n    ) internal virtual {\r\n        require(owner != address(0), \"ERC20: approve from the zero address\");\r\n        require(spender != address(0), \"ERC20: approve to the zero address\");\r\n\r\n        _allowances[owner][spender] = amount;\r\n        emit Approval(owner, spender, amount);\r\n    }\r\n\r\n    /**\r\n     * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\r\n     *\r\n     * Does not update the allowance amount in case of infinite allowance.\r\n     * Revert if not enough allowance is available.\r\n     *\r\n     * Might emit an {Approval} event.\r\n     */\r\n    function _spendAllowance(\r\n        address owner,\r\n        address spender,\r\n        uint256 amount\r\n    ) internal virtual {\r\n        uint256 currentAllowance = allowance(owner, spender);\r\n        if (currentAllowance != type(uint256).max) {\r\n            require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\r\n            unchecked {\r\n                _approve(owner, spender, currentAllowance - amount);\r\n            }\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Hook that is called before any transfer of tokens. This includes\r\n     * minting and burning.\r\n     *\r\n     * Calling conditions:\r\n     *\r\n     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\r\n     * will be transferred to `to`.\r\n     * - when `from` is zero, `amount` tokens will be minted for `to`.\r\n     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\r\n     * - `from` and `to` are never both zero.\r\n     *\r\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\r\n     */\r\n    function _beforeTokenTransfer(\r\n        address from,\r\n        address to,\r\n        uint256 amount\r\n    ) internal virtual {}\r\n\r\n    /**\r\n     * @dev Hook that is called after any transfer of tokens. This includes\r\n     * minting and burning.\r\n     *\r\n     * Calling conditions:\r\n     *\r\n     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\r\n     * has been transferred to `to`.\r\n     * - when `from` is zero, `amount` tokens have been minted for `to`.\r\n     * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\r\n     * - `from` and `to` are never both zero.\r\n     *\r\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\r\n     */\r\n    function _afterTokenTransfer(\r\n        address from,\r\n        address to,\r\n        uint256 amount\r\n    ) internal virtual {}\r\n\r\n    /**\r\n     * @dev This empty reserved space is put in place to allow future versions to add new\r\n     * variables without shifting down storage in the inheritance chain.\r\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\r\n     */\r\n    uint256[45] private __gap;\r\n}\r\n"
      },
      "lib/openzeppelin-contracts-upgradeable/contracts/utils/cryptography/ECDSAUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/cryptography/ECDSA.sol)\r\n\r\npragma solidity ^0.8.0;\r\n\r\nimport \"../StringsUpgradeable.sol\";\r\n\r\n/**\r\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\r\n *\r\n * These functions can be used to verify that a message was signed by the holder\r\n * of the private keys of a given address.\r\n */\r\nlibrary ECDSAUpgradeable {\r\n    enum RecoverError {\r\n        NoError,\r\n        InvalidSignature,\r\n        InvalidSignatureLength,\r\n        InvalidSignatureS,\r\n        InvalidSignatureV // Deprecated in v4.8\r\n    }\r\n\r\n    function _throwError(RecoverError error) private pure {\r\n        if (error == RecoverError.NoError) {\r\n            return; // no error: do nothing\r\n        } else if (error == RecoverError.InvalidSignature) {\r\n            revert(\"ECDSA: invalid signature\");\r\n        } else if (error == RecoverError.InvalidSignatureLength) {\r\n            revert(\"ECDSA: invalid signature length\");\r\n        } else if (error == RecoverError.InvalidSignatureS) {\r\n            revert(\"ECDSA: invalid signature 's' value\");\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the address that signed a hashed message (`hash`) with\r\n     * `signature` or error string. This address can then be used for verification purposes.\r\n     *\r\n     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\r\n     * this function rejects them by requiring the `s` value to be in the lower\r\n     * half order, and the `v` value to be either 27 or 28.\r\n     *\r\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\r\n     * verification to be secure: it is possible to craft signatures that\r\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\r\n     * this is by receiving a hash of the original message (which may otherwise\r\n     * be too long), and then calling {toEthSignedMessageHash} on it.\r\n     *\r\n     * Documentation for signature generation:\r\n     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\r\n     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\r\n     *\r\n     * _Available since v4.3._\r\n     */\r\n    function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\r\n        if (signature.length == 65) {\r\n            bytes32 r;\r\n            bytes32 s;\r\n            uint8 v;\r\n            // ecrecover takes the signature parameters, and the only way to get them\r\n            // currently is to use assembly.\r\n            /// @solidity memory-safe-assembly\r\n            assembly {\r\n                r := mload(add(signature, 0x20))\r\n                s := mload(add(signature, 0x40))\r\n                v := byte(0, mload(add(signature, 0x60)))\r\n            }\r\n            return tryRecover(hash, v, r, s);\r\n        } else {\r\n            return (address(0), RecoverError.InvalidSignatureLength);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the address that signed a hashed message (`hash`) with\r\n     * `signature`. This address can then be used for verification purposes.\r\n     *\r\n     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\r\n     * this function rejects them by requiring the `s` value to be in the lower\r\n     * half order, and the `v` value to be either 27 or 28.\r\n     *\r\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\r\n     * verification to be secure: it is possible to craft signatures that\r\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\r\n     * this is by receiving a hash of the original message (which may otherwise\r\n     * be too long), and then calling {toEthSignedMessageHash} on it.\r\n     */\r\n    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\r\n        (address recovered, RecoverError error) = tryRecover(hash, signature);\r\n        _throwError(error);\r\n        return recovered;\r\n    }\r\n\r\n    /**\r\n     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\r\n     *\r\n     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\r\n     *\r\n     * _Available since v4.3._\r\n     */\r\n    function tryRecover(\r\n        bytes32 hash,\r\n        bytes32 r,\r\n        bytes32 vs\r\n    ) internal pure returns (address, RecoverError) {\r\n        bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\r\n        uint8 v = uint8((uint256(vs) >> 255) + 27);\r\n        return tryRecover(hash, v, r, s);\r\n    }\r\n\r\n    /**\r\n     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\r\n     *\r\n     * _Available since v4.2._\r\n     */\r\n    function recover(\r\n        bytes32 hash,\r\n        bytes32 r,\r\n        bytes32 vs\r\n    ) internal pure returns (address) {\r\n        (address recovered, RecoverError error) = tryRecover(hash, r, vs);\r\n        _throwError(error);\r\n        return recovered;\r\n    }\r\n\r\n    /**\r\n     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\r\n     * `r` and `s` signature fields separately.\r\n     *\r\n     * _Available since v4.3._\r\n     */\r\n    function tryRecover(\r\n        bytes32 hash,\r\n        uint8 v,\r\n        bytes32 r,\r\n        bytes32 s\r\n    ) internal pure returns (address, RecoverError) {\r\n        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\r\n        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\r\n        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\r\n        // signatures from current libraries generate a unique signature with an s-value in the lower half order.\r\n        //\r\n        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\r\n        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\r\n        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\r\n        // these malleable signatures as well.\r\n        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\r\n            return (address(0), RecoverError.InvalidSignatureS);\r\n        }\r\n\r\n        // If the signature is valid (and not malleable), return the signer address\r\n        address signer = ecrecover(hash, v, r, s);\r\n        if (signer == address(0)) {\r\n            return (address(0), RecoverError.InvalidSignature);\r\n        }\r\n\r\n        return (signer, RecoverError.NoError);\r\n    }\r\n\r\n    /**\r\n     * @dev Overload of {ECDSA-recover} that receives the `v`,\r\n     * `r` and `s` signature fields separately.\r\n     */\r\n    function recover(\r\n        bytes32 hash,\r\n        uint8 v,\r\n        bytes32 r,\r\n        bytes32 s\r\n    ) internal pure returns (address) {\r\n        (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\r\n        _throwError(error);\r\n        return recovered;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns an Ethereum Signed Message, created from a `hash`. This\r\n     * produces hash corresponding to the one signed with the\r\n     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\r\n     * JSON-RPC method as part of EIP-191.\r\n     *\r\n     * See {recover}.\r\n     */\r\n    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\r\n        // 32 is the length in bytes of hash,\r\n        // enforced by the type signature above\r\n        return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\r\n    }\r\n\r\n    /**\r\n     * @dev Returns an Ethereum Signed Message, created from `s`. This\r\n     * produces hash corresponding to the one signed with the\r\n     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\r\n     * JSON-RPC method as part of EIP-191.\r\n     *\r\n     * See {recover}.\r\n     */\r\n    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\r\n        return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", StringsUpgradeable.toString(s.length), s));\r\n    }\r\n\r\n    /**\r\n     * @dev Returns an Ethereum Signed Typed Data, created from a\r\n     * `domainSeparator` and a `structHash`. This produces hash corresponding\r\n     * to the one signed with the\r\n     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\r\n     * JSON-RPC method as part of EIP-712.\r\n     *\r\n     * See {recover}.\r\n     */\r\n    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\r\n        return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\r\n    }\r\n}\r\n"
      },
      "lib/openzeppelin-contracts-upgradeable/contracts/utils/cryptography/EIP712Upgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n\r\npragma solidity ^0.8.0;\r\n\r\nimport \"./ECDSAUpgradeable.sol\";\r\nimport \"../../proxy/utils/Initializable.sol\";\r\n\r\n/**\r\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\r\n *\r\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\r\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\r\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\r\n *\r\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\r\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\r\n * ({_hashTypedDataV4}).\r\n *\r\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\r\n * the chain id to protect against replay attacks on an eventual fork of the chain.\r\n *\r\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\r\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\r\n *\r\n * _Available since v3.4._\r\n *\r\n * @custom:storage-size 52\r\n */\r\nabstract contract EIP712Upgradeable is Initializable {\r\n    /* solhint-disable var-name-mixedcase */\r\n    bytes32 private _HASHED_NAME;\r\n    bytes32 private _HASHED_VERSION;\r\n    bytes32 private constant _TYPE_HASH = keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\");\r\n\r\n    /* solhint-enable var-name-mixedcase */\r\n\r\n    /**\r\n     * @dev Initializes the domain separator and parameter caches.\r\n     *\r\n     * The meaning of `name` and `version` is specified in\r\n     * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\r\n     *\r\n     * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\r\n     * - `version`: the current major version of the signing domain.\r\n     *\r\n     * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\r\n     * contract upgrade].\r\n     */\r\n    function __EIP712_init(string memory name, string memory version) internal onlyInitializing {\r\n        __EIP712_init_unchained(name, version);\r\n    }\r\n\r\n    function __EIP712_init_unchained(string memory name, string memory version) internal onlyInitializing {\r\n        bytes32 hashedName = keccak256(bytes(name));\r\n        bytes32 hashedVersion = keccak256(bytes(version));\r\n        _HASHED_NAME = hashedName;\r\n        _HASHED_VERSION = hashedVersion;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the domain separator for the current chain.\r\n     */\r\n    function _domainSeparatorV4() internal view returns (bytes32) {\r\n        return _buildDomainSeparator(_TYPE_HASH, _EIP712NameHash(), _EIP712VersionHash());\r\n    }\r\n\r\n    function _buildDomainSeparator(\r\n        bytes32 typeHash,\r\n        bytes32 nameHash,\r\n        bytes32 versionHash\r\n    ) private view returns (bytes32) {\r\n        return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\r\n    }\r\n\r\n    /**\r\n     * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\r\n     * function returns the hash of the fully encoded EIP712 message for this domain.\r\n     *\r\n     * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\r\n     *\r\n     * ```solidity\r\n     * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\r\n     *     keccak256(\"Mail(address to,string contents)\"),\r\n     *     mailTo,\r\n     *     keccak256(bytes(mailContents))\r\n     * )));\r\n     * address signer = ECDSA.recover(digest, signature);\r\n     * ```\r\n     */\r\n    function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\r\n        return ECDSAUpgradeable.toTypedDataHash(_domainSeparatorV4(), structHash);\r\n    }\r\n\r\n    /**\r\n     * @dev The hash of the name parameter for the EIP712 domain.\r\n     *\r\n     * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs\r\n     * are a concern.\r\n     */\r\n    function _EIP712NameHash() internal virtual view returns (bytes32) {\r\n        return _HASHED_NAME;\r\n    }\r\n\r\n    /**\r\n     * @dev The hash of the version parameter for the EIP712 domain.\r\n     *\r\n     * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs\r\n     * are a concern.\r\n     */\r\n    function _EIP712VersionHash() internal virtual view returns (bytes32) {\r\n        return _HASHED_VERSION;\r\n    }\r\n\r\n    /**\r\n     * @dev This empty reserved space is put in place to allow future versions to add new\r\n     * variables without shifting down storage in the inheritance chain.\r\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\r\n     */\r\n    uint256[50] private __gap;\r\n}\r\n"
      },
      "lib/openzeppelin-contracts-upgradeable/contracts/utils/CountersUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)\r\n\r\npragma solidity ^0.8.0;\r\n\r\n/**\r\n * @title Counters\r\n * @author Matt Condon (@shrugs)\r\n * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number\r\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\r\n *\r\n * Include with `using Counters for Counters.Counter;`\r\n */\r\nlibrary CountersUpgradeable {\r\n    struct Counter {\r\n        // This variable should never be directly accessed by users of the library: interactions must be restricted to\r\n        // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\r\n        // this feature: see https://github.com/ethereum/solidity/issues/4637\r\n        uint256 _value; // default: 0\r\n    }\r\n\r\n    function current(Counter storage counter) internal view returns (uint256) {\r\n        return counter._value;\r\n    }\r\n\r\n    function increment(Counter storage counter) internal {\r\n        unchecked {\r\n            counter._value += 1;\r\n        }\r\n    }\r\n\r\n    function decrement(Counter storage counter) internal {\r\n        uint256 value = counter._value;\r\n        require(value > 0, \"Counter: decrement overflow\");\r\n        unchecked {\r\n            counter._value = value - 1;\r\n        }\r\n    }\r\n\r\n    function reset(Counter storage counter) internal {\r\n        counter._value = 0;\r\n    }\r\n}\r\n"
      },
      "lib/openzeppelin-contracts-upgradeable/contracts/token/ERC20/extensions/IERC20MetadataUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\r\n\r\npragma solidity ^0.8.0;\r\n\r\nimport \"../IERC20Upgradeable.sol\";\r\n\r\n/**\r\n * @dev Interface for the optional metadata functions from the ERC20 standard.\r\n *\r\n * _Available since v4.1._\r\n */\r\ninterface IERC20MetadataUpgradeable is IERC20Upgradeable {\r\n    /**\r\n     * @dev Returns the name of the token.\r\n     */\r\n    function name() external view returns (string memory);\r\n\r\n    /**\r\n     * @dev Returns the symbol of the token.\r\n     */\r\n    function symbol() external view returns (string memory);\r\n\r\n    /**\r\n     * @dev Returns the decimals places of the token.\r\n     */\r\n    function decimals() external view returns (uint8);\r\n}\r\n"
      },
      "lib/openzeppelin-contracts-upgradeable/contracts/utils/StringsUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)\r\n\r\npragma solidity ^0.8.0;\r\n\r\nimport \"./math/MathUpgradeable.sol\";\r\n\r\n/**\r\n * @dev String operations.\r\n */\r\nlibrary StringsUpgradeable {\r\n    bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\r\n    uint8 private constant _ADDRESS_LENGTH = 20;\r\n\r\n    /**\r\n     * @dev Converts a `uint256` to its ASCII `string` decimal representation.\r\n     */\r\n    function toString(uint256 value) internal pure returns (string memory) {\r\n        unchecked {\r\n            uint256 length = MathUpgradeable.log10(value) + 1;\r\n            string memory buffer = new string(length);\r\n            uint256 ptr;\r\n            /// @solidity memory-safe-assembly\r\n            assembly {\r\n                ptr := add(buffer, add(32, length))\r\n            }\r\n            while (true) {\r\n                ptr--;\r\n                /// @solidity memory-safe-assembly\r\n                assembly {\r\n                    mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\r\n                }\r\n                value /= 10;\r\n                if (value == 0) break;\r\n            }\r\n            return buffer;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\r\n     */\r\n    function toHexString(uint256 value) internal pure returns (string memory) {\r\n        unchecked {\r\n            return toHexString(value, MathUpgradeable.log256(value) + 1);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\r\n     */\r\n    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\r\n        bytes memory buffer = new bytes(2 * length + 2);\r\n        buffer[0] = \"0\";\r\n        buffer[1] = \"x\";\r\n        for (uint256 i = 2 * length + 1; i > 1; --i) {\r\n            buffer[i] = _SYMBOLS[value & 0xf];\r\n            value >>= 4;\r\n        }\r\n        require(value == 0, \"Strings: hex length insufficient\");\r\n        return string(buffer);\r\n    }\r\n\r\n    /**\r\n     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\r\n     */\r\n    function toHexString(address addr) internal pure returns (string memory) {\r\n        return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\r\n    }\r\n}\r\n"
      },
      "lib/openzeppelin-contracts-upgradeable/contracts/utils/math/MathUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/math/Math.sol)\r\n\r\npragma solidity ^0.8.0;\r\n\r\n/**\r\n * @dev Standard math utilities missing in the Solidity language.\r\n */\r\nlibrary MathUpgradeable {\r\n    enum Rounding {\r\n        Down, // Toward negative infinity\r\n        Up, // Toward infinity\r\n        Zero // Toward zero\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the largest of two numbers.\r\n     */\r\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\r\n        return a > b ? a : b;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the smallest of two numbers.\r\n     */\r\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\r\n        return a < b ? a : b;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the average of two numbers. The result is rounded towards\r\n     * zero.\r\n     */\r\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\r\n        // (a + b) / 2 can overflow.\r\n        return (a & b) + (a ^ b) / 2;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the ceiling of the division of two numbers.\r\n     *\r\n     * This differs from standard division with `/` in that it rounds up instead\r\n     * of rounding down.\r\n     */\r\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\r\n        // (a + b - 1) / b can overflow on addition, so we distribute.\r\n        return a == 0 ? 0 : (a - 1) / b + 1;\r\n    }\r\n\r\n    /**\r\n     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\r\n     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\r\n     * with further edits by Uniswap Labs also under MIT license.\r\n     */\r\n    function mulDiv(\r\n        uint256 x,\r\n        uint256 y,\r\n        uint256 denominator\r\n    ) internal pure returns (uint256 result) {\r\n        unchecked {\r\n            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\r\n            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\r\n            // variables such that product = prod1 * 2^256 + prod0.\r\n            uint256 prod0; // Least significant 256 bits of the product\r\n            uint256 prod1; // Most significant 256 bits of the product\r\n            assembly {\r\n                let mm := mulmod(x, y, not(0))\r\n                prod0 := mul(x, y)\r\n                prod1 := sub(sub(mm, prod0), lt(mm, prod0))\r\n            }\r\n\r\n            // Handle non-overflow cases, 256 by 256 division.\r\n            if (prod1 == 0) {\r\n                return prod0 / denominator;\r\n            }\r\n\r\n            // Make sure the result is less than 2^256. Also prevents denominator == 0.\r\n            require(denominator > prod1);\r\n\r\n            ///////////////////////////////////////////////\r\n            // 512 by 256 division.\r\n            ///////////////////////////////////////////////\r\n\r\n            // Make division exact by subtracting the remainder from [prod1 prod0].\r\n            uint256 remainder;\r\n            assembly {\r\n                // Compute remainder using mulmod.\r\n                remainder := mulmod(x, y, denominator)\r\n\r\n                // Subtract 256 bit number from 512 bit number.\r\n                prod1 := sub(prod1, gt(remainder, prod0))\r\n                prod0 := sub(prod0, remainder)\r\n            }\r\n\r\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\r\n            // See https://cs.stackexchange.com/q/138556/92363.\r\n\r\n            // Does not overflow because the denominator cannot be zero at this stage in the function.\r\n            uint256 twos = denominator & (~denominator + 1);\r\n            assembly {\r\n                // Divide denominator by twos.\r\n                denominator := div(denominator, twos)\r\n\r\n                // Divide [prod1 prod0] by twos.\r\n                prod0 := div(prod0, twos)\r\n\r\n                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\r\n                twos := add(div(sub(0, twos), twos), 1)\r\n            }\r\n\r\n            // Shift in bits from prod1 into prod0.\r\n            prod0 |= prod1 * twos;\r\n\r\n            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\r\n            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\r\n            // four bits. That is, denominator * inv = 1 mod 2^4.\r\n            uint256 inverse = (3 * denominator) ^ 2;\r\n\r\n            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\r\n            // in modular arithmetic, doubling the correct bits in each step.\r\n            inverse *= 2 - denominator * inverse; // inverse mod 2^8\r\n            inverse *= 2 - denominator * inverse; // inverse mod 2^16\r\n            inverse *= 2 - denominator * inverse; // inverse mod 2^32\r\n            inverse *= 2 - denominator * inverse; // inverse mod 2^64\r\n            inverse *= 2 - denominator * inverse; // inverse mod 2^128\r\n            inverse *= 2 - denominator * inverse; // inverse mod 2^256\r\n\r\n            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\r\n            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\r\n            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\r\n            // is no longer required.\r\n            result = prod0 * inverse;\r\n            return result;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\r\n     */\r\n    function mulDiv(\r\n        uint256 x,\r\n        uint256 y,\r\n        uint256 denominator,\r\n        Rounding rounding\r\n    ) internal pure returns (uint256) {\r\n        uint256 result = mulDiv(x, y, denominator);\r\n        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\r\n            result += 1;\r\n        }\r\n        return result;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\r\n     *\r\n     * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\r\n     */\r\n    function sqrt(uint256 a) internal pure returns (uint256) {\r\n        if (a == 0) {\r\n            return 0;\r\n        }\r\n\r\n        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\r\n        //\r\n        // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\r\n        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\r\n        //\r\n        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\r\n        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\r\n        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\r\n        //\r\n        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\r\n        uint256 result = 1 << (log2(a) >> 1);\r\n\r\n        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\r\n        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\r\n        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\r\n        // into the expected uint128 result.\r\n        unchecked {\r\n            result = (result + a / result) >> 1;\r\n            result = (result + a / result) >> 1;\r\n            result = (result + a / result) >> 1;\r\n            result = (result + a / result) >> 1;\r\n            result = (result + a / result) >> 1;\r\n            result = (result + a / result) >> 1;\r\n            result = (result + a / result) >> 1;\r\n            return min(result, a / result);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @notice Calculates sqrt(a), following the selected rounding direction.\r\n     */\r\n    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\r\n        unchecked {\r\n            uint256 result = sqrt(a);\r\n            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Return the log in base 2, rounded down, of a positive value.\r\n     * Returns 0 if given 0.\r\n     */\r\n    function log2(uint256 value) internal pure returns (uint256) {\r\n        uint256 result = 0;\r\n        unchecked {\r\n            if (value >> 128 > 0) {\r\n                value >>= 128;\r\n                result += 128;\r\n            }\r\n            if (value >> 64 > 0) {\r\n                value >>= 64;\r\n                result += 64;\r\n            }\r\n            if (value >> 32 > 0) {\r\n                value >>= 32;\r\n                result += 32;\r\n            }\r\n            if (value >> 16 > 0) {\r\n                value >>= 16;\r\n                result += 16;\r\n            }\r\n            if (value >> 8 > 0) {\r\n                value >>= 8;\r\n                result += 8;\r\n            }\r\n            if (value >> 4 > 0) {\r\n                value >>= 4;\r\n                result += 4;\r\n            }\r\n            if (value >> 2 > 0) {\r\n                value >>= 2;\r\n                result += 2;\r\n            }\r\n            if (value >> 1 > 0) {\r\n                result += 1;\r\n            }\r\n        }\r\n        return result;\r\n    }\r\n\r\n    /**\r\n     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\r\n     * Returns 0 if given 0.\r\n     */\r\n    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\r\n        unchecked {\r\n            uint256 result = log2(value);\r\n            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Return the log in base 10, rounded down, of a positive value.\r\n     * Returns 0 if given 0.\r\n     */\r\n    function log10(uint256 value) internal pure returns (uint256) {\r\n        uint256 result = 0;\r\n        unchecked {\r\n            if (value >= 10**64) {\r\n                value /= 10**64;\r\n                result += 64;\r\n            }\r\n            if (value >= 10**32) {\r\n                value /= 10**32;\r\n                result += 32;\r\n            }\r\n            if (value >= 10**16) {\r\n                value /= 10**16;\r\n                result += 16;\r\n            }\r\n            if (value >= 10**8) {\r\n                value /= 10**8;\r\n                result += 8;\r\n            }\r\n            if (value >= 10**4) {\r\n                value /= 10**4;\r\n                result += 4;\r\n            }\r\n            if (value >= 10**2) {\r\n                value /= 10**2;\r\n                result += 2;\r\n            }\r\n            if (value >= 10**1) {\r\n                result += 1;\r\n            }\r\n        }\r\n        return result;\r\n    }\r\n\r\n    /**\r\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\r\n     * Returns 0 if given 0.\r\n     */\r\n    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\r\n        unchecked {\r\n            uint256 result = log10(value);\r\n            return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Return the log in base 256, rounded down, of a positive value.\r\n     * Returns 0 if given 0.\r\n     *\r\n     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\r\n     */\r\n    function log256(uint256 value) internal pure returns (uint256) {\r\n        uint256 result = 0;\r\n        unchecked {\r\n            if (value >> 128 > 0) {\r\n                value >>= 128;\r\n                result += 16;\r\n            }\r\n            if (value >> 64 > 0) {\r\n                value >>= 64;\r\n                result += 8;\r\n            }\r\n            if (value >> 32 > 0) {\r\n                value >>= 32;\r\n                result += 4;\r\n            }\r\n            if (value >> 16 > 0) {\r\n                value >>= 16;\r\n                result += 2;\r\n            }\r\n            if (value >> 8 > 0) {\r\n                result += 1;\r\n            }\r\n        }\r\n        return result;\r\n    }\r\n\r\n    /**\r\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\r\n     * Returns 0 if given 0.\r\n     */\r\n    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\r\n        unchecked {\r\n            uint256 result = log256(value);\r\n            return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\r\n        }\r\n    }\r\n}\r\n"
      }
    },
    "settings": {
      "remappings": [
        "ds-test/=lib/forge-std/lib/ds-test/src/",
        "forge-std/=lib/forge-std/src/",
        "@openzeppelin/=lib/openzeppelin-contracts/contracts/",
        "@openzeppelin-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
        "@solmate/=lib/solmate/src/",
        "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
        "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
        "openzeppelin-contracts/=lib/openzeppelin-contracts/",
        "solmate/=lib/solmate/src/"
      ],
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "metadata": {
        "useLiteralContent": false,
        "bytecodeHash": "ipfs"
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "evmVersion": "london",
      "libraries": {}
    }
  }}