fluid-contracts-public/deployments/mainnet/solcInputs/efdd2a5c55bd6e967261f15aacf56e11.json

498 lines
1.0 MiB
JSON
Raw Permalink Normal View History

{
"language": "Solidity",
"sources": {
"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n function __Ownable_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal onlyInitializing {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\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"
},
"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.1) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts.\n *\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n * constructor.\n *\n * Emits an {Initialized} event.\n */\n modifier initializer() {\n bool isTopLevelCall = !_initializing;\n require(\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n \"Initializable: contract is already initialized\"\n );\n _initialized = 1;\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInit
},
"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string
},
"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\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[50] private __gap;\n}\n"
},
"@openzeppelin/contracts/interfaces/draft-IERC1822.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\n * proxy whose upgrades are fully controlled by the current implementation.\n */\ninterface IERC1822Proxiable {\n /**\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\n * address.\n *\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n * function revert if invoked through a proxy.\n */\n function proxiableUUID() external view returns (bytes32);\n}\n"
},
"@openzeppelin/contracts/interfaces/IERC20.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (interfaces/IERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../token/ERC20/IERC20.sol\";\n"
},
"@openzeppelin/contracts/interfaces/IERC4626.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (interfaces/IERC4626.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../token/ERC20/IERC20.sol\";\nimport \"../token/ERC20/extensions/IERC20Metadata.sol\";\n\n/**\n * @dev Interface of the ERC4626 \"Tokenized Vault Standard\", as defined in\n * https://eips.ethereum.org/EIPS/eip-4626[ERC-4626].\n *\n * _Available since v4.7._\n */\ninterface IERC4626 is IERC20, IERC20Metadata {\n event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);\n\n event Withdraw(\n address indexed sender,\n address indexed receiver,\n address indexed owner,\n uint256 assets,\n uint256 shares\n );\n\n /**\n * @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.\n *\n * - MUST be an ERC-20 token contract.\n * - MUST NOT revert.\n */\n function asset() external view returns (address assetTokenAddress);\n\n /**\n * @dev Returns the total amount of the underlying asset that is “managed” by Vault.\n *\n * - SHOULD include any compounding that occurs from yield.\n * - MUST be inclusive of any fees that are charged against assets in the Vault.\n * - MUST NOT revert.\n */\n function totalAssets() external view returns (uint256 totalManagedAssets);\n\n /**\n * @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal\n * scenario where all the conditions are met.\n *\n * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.\n * - MUST NOT show any variations depending on the caller.\n * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.\n * - MUST NOT revert.\n *\n * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the\n * “average-users” price-per-share, meaning what the average user should expect to see when exchanging to and\n * from.\n */\n function convertToShares(uint256 assets) external view returns (uint256 shares);\n\n /**\n * @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal\n * scenario where all the conditions are met.\n *\n * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.\n * - MUST NOT show any variations depending on the caller.\n * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.\n * - MUST NOT revert.\n *\n * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the\n * “average-users” price-per-share, meaning what the average user should expect to see when exchanging to and\n * from.\n */\n function convertToAssets(uint256 shares) external view returns (uint256 assets);\n\n /**\n * @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,\n * through a deposit call.\n *\n * - MUST return a limited value if receiver is subject to some deposit limit.\n * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.\n * - MUST NOT revert.\n */\n function maxDeposit(address receiver) external view returns (uint256 maxAssets);\n\n /**\n * @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given\n * current on-chain conditions.\n *\n * - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit\n * call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called\n * in the same transaction.\n * - MUST NOT account for deposit limits like those returned from maxDeposit
},
"@openzeppelin/contracts/proxy/beacon/IBeacon.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\n */\ninterface IBeacon {\n /**\n * @dev Must return an address that can be used as a delegate call target.\n *\n * {BeaconProxy} will check that this address is a contract.\n */\n function implementation() external view returns (address);\n}\n"
},
"@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../beacon/IBeacon.sol\";\nimport \"../../interfaces/draft-IERC1822.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/StorageSlot.sol\";\n\n/**\n * @dev This abstract contract provides getters and event emitting update functions for\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\n *\n * _Available since v4.1._\n *\n * @custom:oz-upgrades-unsafe-allow delegatecall\n */\nabstract contract ERC1967Upgrade {\n // This is the keccak-256 hash of \"eip1967.proxy.rollback\" subtracted by 1\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\n\n /**\n * @dev Storage slot with the address of the current implementation.\n * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n /**\n * @dev Emitted when the implementation is upgraded.\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @dev Returns the current implementation address.\n */\n function _getImplementation() internal view returns (address) {\n return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 implementation slot.\n */\n function _setImplementation(address newImplementation) private {\n require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n }\n\n /**\n * @dev Perform implementation upgrade\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeTo(address newImplementation) internal {\n _setImplementation(newImplementation);\n emit Upgraded(newImplementation);\n }\n\n /**\n * @dev Perform implementation upgrade with additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCall(\n address newImplementation,\n bytes memory data,\n bool forceCall\n ) internal {\n _upgradeTo(newImplementation);\n if (data.length > 0 || forceCall) {\n Address.functionDelegateCall(newImplementation, data);\n }\n }\n\n /**\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCallUUPS(\n address newImplementation,\n bytes memory data,\n bool forceCall\n ) internal {\n // Upgrades from old implementations will perform a rollback test. This test requires the new\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\n // this special case will break upgrade paths from old UUPS implementation to new ones.\n if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\n _setImplementation(newImplementation);\n } else {\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\n require(slot == _IMPLEMENTATION_SLOT, \"ERC1967Upgrade: unsupported proxiableUUID\");\n } catch {\n revert(\"ERC1967Upgrade: new implementation is not UUPS\");\n }\n _upgradeToAndCall(newImplementation, data, forceCall);\n }\n }\n\n /**\n * @dev Storage slot with the admin of the contract.\n * This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n /**\n * @dev Emitted when the a
},
"@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (proxy/utils/UUPSUpgradeable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../interfaces/draft-IERC1822.sol\";\nimport \"../ERC1967/ERC1967Upgrade.sol\";\n\n/**\n * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an\n * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.\n *\n * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is\n * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing\n * `UUPSUpgradeable` with a custom implementation of upgrades.\n *\n * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.\n *\n * _Available since v4.1._\n */\nabstract contract UUPSUpgradeable is IERC1822Proxiable, ERC1967Upgrade {\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment\n address private immutable __self = address(this);\n\n /**\n * @dev Check that the execution is being performed through a delegatecall call and that the execution context is\n * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case\n * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a\n * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to\n * fail.\n */\n modifier onlyProxy() {\n require(address(this) != __self, \"Function must be called through delegatecall\");\n require(_getImplementation() == __self, \"Function must be called through active proxy\");\n _;\n }\n\n /**\n * @dev Check that the execution is not being performed through a delegate call. This allows a function to be\n * callable on the implementing contract but not through proxies.\n */\n modifier notDelegated() {\n require(address(this) == __self, \"UUPSUpgradeable: must not be called through delegatecall\");\n _;\n }\n\n /**\n * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the\n * implementation. It is used to validate the implementation's compatibility when performing an upgrade.\n *\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.\n */\n function proxiableUUID() external view virtual override notDelegated returns (bytes32) {\n return _IMPLEMENTATION_SLOT;\n }\n\n /**\n * @dev Upgrade the implementation of the proxy to `newImplementation`.\n *\n * Calls {_authorizeUpgrade}.\n *\n * Emits an {Upgraded} event.\n */\n function upgradeTo(address newImplementation) external virtual onlyProxy {\n _authorizeUpgrade(newImplementation);\n _upgradeToAndCallUUPS(newImplementation, new bytes(0), false);\n }\n\n /**\n * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call\n * encoded in `data`.\n *\n * Calls {_authorizeUpgrade}.\n *\n * Emits an {Upgraded} event.\n */\n function upgradeToAndCall(address newImplementation, bytes memory data) external payable virtual onlyProxy {\n _authorizeUpgrade(newImplementation);\n _upgradeToAndCallUUPS(newImplementation, data, true);\n }\n\n /**\n * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by\n * {upgradeTo} and {upgradeToAndCall}.\n *\n * Normally, this function will use an xref:access.adoc[access c
},
"@openzeppelin/contracts/security/Pausable.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract Pausable is Context {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n constructor() {\n _paused = false;\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 Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n _requirePaused();\n _;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Throws if the contract is paused.\n */\n function _requireNotPaused() internal view virtual {\n require(!paused(), \"Pausable: paused\");\n }\n\n /**\n * @dev Throws if the contract is not paused.\n */\n function _requirePaused() internal view virtual {\n require(paused(), \"Pausable: not paused\");\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n}\n"
},
"@openzeppelin/contracts/token/ERC20/ERC20.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n mapping(address => uint256) private _balances;\n\n mapping(address => mapping(address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * The default value of {decimals} is 18. To select a different value for\n * {decimals} you should overload it.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\n * overridden;\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-al
},
"@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/extensions/draft-ERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./draft-IERC20Permit.sol\";\nimport \"../ERC20.sol\";\nimport \"../../../utils/cryptography/ECDSA.sol\";\nimport \"../../../utils/cryptography/EIP712.sol\";\nimport \"../../../utils/Counters.sol\";\n\n/**\n * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * _Available since v3.4._\n */\nabstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 {\n using Counters for Counters.Counter;\n\n mapping(address => Counters.Counter) private _nonces;\n\n // solhint-disable-next-line var-name-mixedcase\n bytes32 private constant _PERMIT_TYPEHASH =\n keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n /**\n * @dev In previous versions `_PERMIT_TYPEHASH` was declared as `immutable`.\n * However, to ensure consistency with the upgradeable transpiler, we will continue\n * to reserve a slot.\n * @custom:oz-renamed-from _PERMIT_TYPEHASH\n */\n // solhint-disable-next-line var-name-mixedcase\n bytes32 private _PERMIT_TYPEHASH_DEPRECATED_SLOT;\n\n /**\n * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `\"1\"`.\n *\n * It's a good idea to use the same `name` that is defined as the ERC20 token name.\n */\n constructor(string memory name) EIP712(name, \"1\") {}\n\n /**\n * @dev See {IERC20Permit-permit}.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override {\n require(block.timestamp <= deadline, \"ERC20Permit: expired deadline\");\n\n bytes32 structHash = keccak256(abi.encode(_PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline));\n\n bytes32 hash = _hashTypedDataV4(structHash);\n\n address signer = ECDSA.recover(hash, v, r, s);\n require(signer == owner, \"ERC20Permit: invalid signature\");\n\n _approve(owner, spender, value);\n }\n\n /**\n * @dev See {IERC20Permit-nonces}.\n */\n function nonces(address owner) public view virtual override returns (uint256) {\n return _nonces[owner].current();\n }\n\n /**\n * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view override returns (bytes32) {\n return _domainSeparatorV4();\n }\n\n /**\n * @dev \"Consume a nonce\": return the current value and increment.\n *\n * _Available since v4.1._\n */\n function _useNonce(address owner) internal virtual returns (uint256 current) {\n Counters.Counter storage nonce = _nonces[owner];\n current = nonce.current();\n nonce.increment();\n }\n}\n"
},
"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n"
},
"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n"
},
"@openzeppelin/contracts/token/ERC20/IERC20.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n"
},
"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n function safeTransfer(\n IERC20 token,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(\n IERC20 token,\n address from,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n uint256 newAllowance = token.allowance(address(this), spender) + value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n uint256 newAllowance = oldAllowance - value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n }\n\n function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implem
},
"@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Enumerable is IERC721 {\n /**\n * @dev Returns the total amount of tokens stored by the contract.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\n * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\n */\n function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);\n\n /**\n * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\n * Use along with {totalSupply} to enumerate all tokens.\n */\n function tokenByIndex(uint256 index) external view returns (uint256);\n}\n"
},
"@openzeppelin/contracts/token/ERC721/IERC721.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId,\n bytes calldata data\n ) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId\n ) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 tokenId\n ) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approv
},
"@openzeppelin/contracts/utils/Address.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory err
},
"@openzeppelin/contracts/utils/Context.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n"
},
"@openzeppelin/contracts/utils/Counters.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title Counters\n * @author Matt Condon (@shrugs)\n * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\n *\n * Include with `using Counters for Counters.Counter;`\n */\nlibrary Counters {\n struct Counter {\n // This variable should never be directly accessed by users of the library: interactions must be restricted to\n // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\n // this feature: see https://github.com/ethereum/solidity/issues/4637\n uint256 _value; // default: 0\n }\n\n function current(Counter storage counter) internal view returns (uint256) {\n return counter._value;\n }\n\n function increment(Counter storage counter) internal {\n unchecked {\n counter._value += 1;\n }\n }\n\n function decrement(Counter storage counter) internal {\n uint256 value = counter._value;\n require(value > 0, \"Counter: decrement overflow\");\n unchecked {\n counter._value = value - 1;\n }\n }\n\n function reset(Counter storage counter) internal {\n counter._value = 0;\n }\n}\n"
},
"@openzeppelin/contracts/utils/cryptography/ECDSA.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` sho
},
"@openzeppelin/contracts/utils/cryptography/EIP712.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with
},
"@openzeppelin/contracts/utils/cryptography/MerkleProof.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(\n bytes32[] memory proof,\n bytes32 root,\n bytes32 leaf\n ) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Calldata version of {verify}\n *\n * _Available since v4.7._\n */\n function verifyCalldata(\n bytes32[] calldata proof,\n bytes32 root,\n bytes32 leaf\n ) internal pure returns (bool) {\n return processProofCalldata(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Calldata version of {processProof}\n *\n * _Available since v4.7._\n */\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerify(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProof(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Calldata version of {multiProofVerify}\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerifyCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n * proceeds by incrementally reconstr
},
"@openzeppelin/contracts/utils/introspection/IERC165.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"
},
"@openzeppelin/contracts/utils/math/Math.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 denominator\n ) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1);\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes on
},
"@openzeppelin/contracts/utils/math/SafeCast.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n
},
"@openzeppelin/contracts/utils/StorageSlot.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC1967 implementation slot:\n * ```\n * contract ERC1967 {\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n * function _getImplementation() internal view returns (address) {\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n * }\n *\n * function _setImplementation(address newImplementation) internal {\n * require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n * }\n * }\n * ```\n *\n * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._\n */\nlibrary StorageSlot {\n struct AddressSlot {\n address value;\n }\n\n struct BooleanSlot {\n bool value;\n }\n\n struct Bytes32Slot {\n bytes32 value;\n }\n\n struct Uint256Slot {\n uint256 value;\n }\n\n /**\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n */\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\n */\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\n */\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\n */\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n}\n"
},
"@openzeppelin/contracts/utils/Strings.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n}\n"
},
"@openzeppelin/contracts/utils/structs/EnumerableSet.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position of the value in the `values` array, plus 1 because index 0\n // means a value is not in the set.\n mapping(bytes32 => uint256) _indexes;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._indexes[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We read and store the value's index to prevent multiple reads from the same storage slot\n uint256 valueIndex = set._indexes[value];\n\n if (valueIndex != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 toDeleteIndex = valueIndex - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (lastIndex != toDeleteIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the last value to the index where the value to delete is\n set._values[toDeleteIndex] = lastValue;\n // Update the index for the moved value\n set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex\n }\n\n // Delete the slot where the moved value was stored\n set
},
"contracts/config/bufferRateHandler/main.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IFluidLiquidity } from \"../../liquidity/interfaces/iLiquidity.sol\";\nimport { LiquiditySlotsLink } from \"../../libraries/liquiditySlotsLink.sol\";\nimport { IFluidReserveContract } from \"../../reserve/interfaces/iReserveContract.sol\";\nimport { Error } from \"../error.sol\";\nimport { ErrorTypes } from \"../errorTypes.sol\";\nimport { FluidConfigHandler } from \"../fluidConfigHandler.sol\";\n\nimport { BigMathMinified } from \"../../libraries/bigMathMinified.sol\";\nimport { Structs as AdminModuleStructs } from \"../../liquidity/adminModule/structs.sol\";\n\nabstract contract Constants {\n IFluidReserveContract public immutable RESERVE_CONTRACT;\n IFluidLiquidity public immutable LIQUIDITY;\n\n /// @notice supply token at Liquidity which borrow rate is based on\n address public immutable SUPPLY_TOKEN;\n /// @notice borrow token at Liquidity for which the borrow rate is managed\n address public immutable BORROW_TOKEN;\n\n /// @notice buffer at kink1 for the rate. borrow rate = supply rate + buffer. In percent (100 = 1%, 1 = 0.01%)\n int256 public immutable RATE_BUFFER_KINK1;\n /// @notice buffer at kink2 for the rate. borrow rate = supply rate + buffer. In percent (100 = 1%, 1 = 0.01%)\n /// @dev only used if CURRENT borrow rate mode at Liquidity is V2 (with 2 kinks).\n int256 public immutable RATE_BUFFER_KINK2;\n\n /// @dev minimum percent difference to trigger an update. In percent (100 = 1%, 1 = 0.01%)\n uint256 public immutable MIN_UPDATE_DIFF;\n\n bytes32 internal immutable _LIQUDITY_SUPPLY_TOTAL_AMOUNTS_SLOT;\n bytes32 internal immutable _LIQUDITY_SUPPLY_EXCHANGE_PRICES_AND_CONFIG_SLOT;\n\n bytes32 internal immutable _LIQUDITY_BORROW_RATE_DATA_SLOT;\n\n uint256 internal constant EXCHANGE_PRICES_PRECISION = 1e12;\n\n uint256 internal constant DEFAULT_EXPONENT_SIZE = 8;\n uint256 internal constant DEFAULT_EXPONENT_MASK = 0xff;\n\n uint256 internal constant X14 = 0x3fff;\n uint256 internal constant X16 = 0xffff;\n uint256 internal constant X64 = 0xffffffffffffffff;\n uint256 internal constant FOUR_DECIMALS = 10000;\n}\n\nabstract contract Events {\n /// @notice emitted when borrow rate for `BORROW_TOKEN` is updated based on\n /// supply rate of `SUPPLY_TOKEN` + buffer.\n event LogUpdateRate(\n uint256 supplyRate,\n uint256 oldRateKink1,\n uint256 newRateKink1,\n uint256 oldRateKink2,\n uint256 newRateKink2\n );\n}\n\n/// @notice Sets borrow rate for `BORROW_TOKEN` at Liquidaty based on supply rate of `SUPPLY_TOKEN` + buffer.\ncontract FluidBufferRateHandler is Constants, Error, Events, FluidConfigHandler {\n /// @dev Validates that an address is not the zero address\n modifier validAddress(address value_) {\n if (value_ == address(0)) {\n revert FluidConfigError(ErrorTypes.BufferRateConfigHandler__AddressZero);\n }\n _;\n }\n\n /// @dev Validates that an address is a rebalancer (taken from reserve contract)\n modifier onlyRebalancer() {\n if (!RESERVE_CONTRACT.isRebalancer(msg.sender)) {\n revert FluidConfigError(ErrorTypes.BufferRateConfigHandler__Unauthorized);\n }\n _;\n }\n\n constructor(\n IFluidReserveContract reserveContract_,\n IFluidLiquidity liquidity_,\n address supplyToken_,\n address borrowToken_,\n int256 rateBufferKink1_,\n int256 rateBufferKink2_,\n uint256 minUpdateDiff_\n )\n validAddress(address(reserveContract_))\n validAddress(address(liquidity_))\n validAddress(supplyToken_)\n validAddress(borrowToken_)\n {\n if (\n minUpdateDiff_ == 0 ||\n // rate buffer should be within +100% to - 100%\n rateBufferKink1_ > 1e4 ||\n rateBufferKink1_ < -int256(1e4) ||\n rateBufferKink2_ > 1e4 ||\n rateBufferKink2_ < -int256(1e4)\n ) {\n reve
},
"contracts/config/error.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\ncontract Error {\n error FluidConfigError(uint256 errorId_);\n}\n"
},
"contracts/config/errorTypes.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nlibrary ErrorTypes {\n /***********************************|\n | ExpandPercentConfigHandler | \n |__________________________________*/\n\n /// @notice thrown when an input address is zero\n uint256 internal constant ExpandPercentConfigHandler__AddressZero = 100001;\n\n /// @notice thrown when an unauthorized `msg.sender` calls a protected method\n uint256 internal constant ExpandPercentConfigHandler__Unauthorized = 100002;\n\n /// @notice thrown when invalid params are passed into a method\n uint256 internal constant ExpandPercentConfigHandler__InvalidParams = 100003;\n\n /// @notice thrown when no update is currently needed\n uint256 internal constant ExpandPercentConfigHandler__NoUpdate = 100004;\n\n /// @notice thrown when slot is not used, e.g. when borrow token is 0 there is no borrow data\n uint256 internal constant ExpandPercentConfigHandler__SlotDoesNotExist = 100005;\n\n /***********************************|\n | EthenaRateConfigHandler | \n |__________________________________*/\n\n /// @notice thrown when an input address is zero\n uint256 internal constant EthenaRateConfigHandler__AddressZero = 100011;\n\n /// @notice thrown when an unauthorized `msg.sender` calls a protected method\n uint256 internal constant EthenaRateConfigHandler__Unauthorized = 100012;\n\n /// @notice thrown when invalid params are passed into a method\n uint256 internal constant EthenaRateConfigHandler__InvalidParams = 100013;\n\n /// @notice thrown when no update is currently needed\n uint256 internal constant EthenaRateConfigHandler__NoUpdate = 100014;\n\n /***********************************|\n | MaxBorrowConfigHandler | \n |__________________________________*/\n\n /// @notice thrown when an input address is zero\n uint256 internal constant MaxBorrowConfigHandler__AddressZero = 100021;\n\n /// @notice thrown when an unauthorized `msg.sender` calls a protected method\n uint256 internal constant MaxBorrowConfigHandler__Unauthorized = 100022;\n\n /// @notice thrown when invalid params are passed into a method\n uint256 internal constant MaxBorrowConfigHandler__InvalidParams = 100023;\n\n /// @notice thrown when no update is currently needed\n uint256 internal constant MaxBorrowConfigHandler__NoUpdate = 100024;\n\n /***********************************|\n | BufferRateConfigHandler | \n |__________________________________*/\n\n /// @notice thrown when an input address is zero\n uint256 internal constant BufferRateConfigHandler__AddressZero = 100031;\n\n /// @notice thrown when an unauthorized `msg.sender` calls a protected method\n uint256 internal constant BufferRateConfigHandler__Unauthorized = 100032;\n\n /// @notice thrown when invalid params are passed into a method\n uint256 internal constant BufferRateConfigHandler__InvalidParams = 100033;\n\n /// @notice thrown when no update is currently needed\n uint256 internal constant BufferRateConfigHandler__NoUpdate = 100034;\n\n /// @notice thrown when rate data version is not supported\n uint256 internal constant BufferRateConfigHandler__RateVersionUnsupported = 100035;\n}\n"
},
"contracts/config/ethenaRateHandler/events.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nabstract contract Events {\n /// @notice emitted when borrow magnifier is updated at vault\n event LogUpdateBorrowRateMagnifier(uint256 oldMagnifier, uint256 newMagnifier);\n}\n"
},
"contracts/config/ethenaRateHandler/interfaces/iStakedUSDe.sol": {
"content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.21;\n\nimport { IERC4626 } from \"@openzeppelin/contracts/interfaces/IERC4626.sol\";\n\ninterface IStakedUSDe is IERC4626 {\n /// @notice The amount of the last asset distribution from the controller contract into this\n /// contract + any unvested remainder at that time\n function vestingAmount() external view returns (uint256);\n\n /// @notice The timestamp of the last asset distribution from the controller contract into this contract\n function lastDistributionTimestamp() external view returns (uint256);\n\n /// @notice Returns the amount of USDe tokens that are vested in the contract.\n function totalAssets() external view returns (uint256);\n}\n"
},
"contracts/config/ethenaRateHandler/main.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IFluidLiquidity } from \"../../liquidity/interfaces/iLiquidity.sol\";\nimport { IFluidReserveContract } from \"../../reserve/interfaces/iReserveContract.sol\";\nimport { IFluidVaultT1 } from \"../../protocols/vault/interfaces/iVaultT1.sol\";\nimport { LiquiditySlotsLink } from \"../../libraries/liquiditySlotsLink.sol\";\nimport { FluidVaultT1Admin } from \"../../protocols/vault/vaultT1/adminModule/main.sol\";\nimport { IStakedUSDe } from \"./interfaces/iStakedUSDe.sol\";\nimport { Variables } from \"./variables.sol\";\nimport { Events } from \"./events.sol\";\nimport { Error } from \"../error.sol\";\nimport { ErrorTypes } from \"../errorTypes.sol\";\n\n/// @notice Sets borrow rate for sUSDe/debtToken vaults based on sUSDe yield rate, by adjusting the borrowRateMagnifier\ncontract FluidEthenaRateConfigHandler is Variables, Error, Events {\n /// @dev Validates that an address is not the zero address\n modifier validAddress(address value_) {\n if (value_ == address(0)) {\n revert FluidConfigError(ErrorTypes.EthenaRateConfigHandler__AddressZero);\n }\n _;\n }\n\n /// @dev Validates that an address is a rebalancer (taken from reserve contract)\n modifier onlyRebalancer() {\n if (!RESERVE_CONTRACT.isRebalancer(msg.sender)) {\n revert FluidConfigError(ErrorTypes.EthenaRateConfigHandler__Unauthorized);\n }\n _;\n }\n\n constructor(\n IFluidReserveContract reserveContract_,\n IFluidLiquidity liquidity_,\n IFluidVaultT1 vault_,\n IStakedUSDe stakedUSDe_,\n address borrowToken_,\n uint256 ratePercentMargin_,\n uint256 maxRewardsDelay_,\n uint256 utilizationPenaltyStart_,\n uint256 utilization100PenaltyPercent_\n )\n validAddress(address(reserveContract_))\n validAddress(address(liquidity_))\n validAddress(address(vault_))\n validAddress(address(stakedUSDe_))\n validAddress(borrowToken_)\n {\n if (\n ratePercentMargin_ == 0 ||\n ratePercentMargin_ >= 1e4 ||\n maxRewardsDelay_ == 0 ||\n utilizationPenaltyStart_ >= 1e4 ||\n utilization100PenaltyPercent_ == 0\n ) {\n revert FluidConfigError(ErrorTypes.EthenaRateConfigHandler__InvalidParams);\n }\n\n RESERVE_CONTRACT = reserveContract_;\n LIQUIDITY = liquidity_;\n SUSDE = stakedUSDe_;\n VAULT = vault_;\n BORROW_TOKEN = borrowToken_;\n\n _LIQUDITY_BORROW_TOKEN_EXCHANGE_PRICES_SLOT = LiquiditySlotsLink.calculateMappingStorageSlot(\n LiquiditySlotsLink.LIQUIDITY_EXCHANGE_PRICES_MAPPING_SLOT,\n borrowToken_\n );\n\n RATE_PERCENT_MARGIN = ratePercentMargin_;\n MAX_REWARDS_DELAY = maxRewardsDelay_;\n\n UTILIZATION_PENALTY_START = utilizationPenaltyStart_;\n UTILIZATION100_PENALTY_PERCENT = utilization100PenaltyPercent_;\n }\n\n /// @notice Rebalances the borrow rate magnifier for `VAULT` based on borrow rate at Liquidity in relation to\n /// sUSDe yield rate (`getSUSDEYieldRate()`).\n /// Emits `LogUpdateBorrowRateMagnifier` in case of update. Reverts if no update is needed.\n /// Can only be called by an authorized rebalancer.\n function rebalance() external onlyRebalancer {\n uint256 targetMagnifier_ = calculateMagnifier();\n uint256 currentMagnifier_ = currentMagnifier();\n\n // execute update on vault if necessary\n if (targetMagnifier_ == currentMagnifier_) {\n revert FluidConfigError(ErrorTypes.EthenaRateConfigHandler__NoUpdate);\n }\n\n FluidVaultT1Admin(address(VAULT)).updateBorrowRateMagnifier(targetMagnifier_);\n\n emit LogUpdateBorrowRateMagnifier(currentMagnifier_, targetMagnifier_);\n }\n\n /// @notice Calculates the new borrow rate magnifier based on sUSDe yield rate and utilization\n /// @return magnifier_ the calculated magnifier va
},
"contracts/config/ethenaRateHandler/variables.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IFluidLiquidity } from \"../../liquidity/interfaces/iLiquidity.sol\";\nimport { IFluidReserveContract } from \"../../reserve/interfaces/iReserveContract.sol\";\nimport { IFluidVaultT1 } from \"../../protocols/vault/interfaces/iVaultT1.sol\";\nimport { IStakedUSDe } from \"./interfaces/iStakedUSDe.sol\";\n\nabstract contract Constants {\n IFluidReserveContract public immutable RESERVE_CONTRACT;\n IFluidLiquidity public immutable LIQUIDITY;\n IFluidVaultT1 public immutable VAULT;\n IStakedUSDe public immutable SUSDE;\n address public immutable BORROW_TOKEN;\n\n /// @notice sUSDe vesting yield reward rate percent margin that goes to lenders\n /// e.g. RATE_PERCENT_MARGIN = 10% then borrow rate for debt token ends up as 90% of the sUSDe yield.\n /// (in 1e2: 100% = 10_000; 1% = 100)\n uint256 public immutable RATE_PERCENT_MARGIN;\n\n /// @notice max delay in seconds for rewards update after vesting period ended, after which we assume rate is 0.\n /// e.g. 15 min\n uint256 public immutable MAX_REWARDS_DELAY;\n\n /// @notice utilization penalty start point (in 1e2: 100% = 10_000; 1% = 100). above this, a penalty percent\n /// is applied, to incentivize deleveraging.\n uint256 public immutable UTILIZATION_PENALTY_START;\n /// @notice penalty percent target at 100%, on top of sUSDe yield rate if utilization is above UTILIZATION_PENALTY_START\n /// (in 1e2: 100% = 10_000; 1% = 100)\n uint256 public immutable UTILIZATION100_PENALTY_PERCENT;\n\n bytes32 internal immutable _LIQUDITY_BORROW_TOKEN_EXCHANGE_PRICES_SLOT;\n\n /// @dev vesting period defined as private constant on StakedUSDe contract\n uint256 internal constant _SUSDE_VESTING_PERIOD = 8 hours;\n\n uint256 internal constant X14 = 0x3fff;\n uint256 internal constant X16 = 0xffff;\n uint256 internal constant _MIN_MAGNIFIER = 1e4; // min magnifier is always at least 1x (10000)\n uint256 internal constant _MAX_MAGNIFIER = 65535; // max magnifier to fit in storage slot is 65535 (16 bits)\n}\n\nabstract contract Variables is Constants {}\n"
},
"contracts/config/expandPercentHandler/main.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IFluidLiquidity } from \"../../liquidity/interfaces/iLiquidity.sol\";\nimport { LiquiditySlotsLink } from \"../../libraries/liquiditySlotsLink.sol\";\nimport { BigMathMinified } from \"../../libraries/bigMathMinified.sol\";\nimport { IFluidReserveContract } from \"../../reserve/interfaces/iReserveContract.sol\";\nimport { Structs as AdminModuleStructs } from \"../../liquidity/adminModule/structs.sol\";\nimport { Error } from \"../error.sol\";\nimport { ErrorTypes } from \"../errorTypes.sol\";\n\nabstract contract Constants {\n IFluidReserveContract public immutable RESERVE_CONTRACT;\n IFluidLiquidity public immutable LIQUIDITY;\n address public immutable PROTOCOL;\n address public immutable WITHDRAW_TOKEN;\n address public immutable BORROW_TOKEN;\n\n uint256 public immutable BORROW_CHECKPOINT1;\n uint256 public immutable BORROW_CHECKPOINT2;\n uint256 public immutable BORROW_CHECKPOINT3;\n uint256 public immutable BORROW_EXPAND_UNTIL_CHECKPOINT1;\n uint256 public immutable BORROW_EXPAND_UNTIL_CHECKPOINT2;\n uint256 public immutable BORROW_EXPAND_UNTIL_CHECKPOINT3;\n uint256 public immutable BORROW_EXPAND_ABOVE_CHECKPOINT3;\n\n uint256 public immutable WITHDRAW_CHECKPOINT1;\n uint256 public immutable WITHDRAW_CHECKPOINT2;\n uint256 public immutable WITHDRAW_CHECKPOINT3;\n uint256 public immutable WITHDRAW_EXPAND_UNTIL_CHECKPOINT1;\n uint256 public immutable WITHDRAW_EXPAND_UNTIL_CHECKPOINT2;\n uint256 public immutable WITHDRAW_EXPAND_UNTIL_CHECKPOINT3;\n uint256 public immutable WITHDRAW_EXPAND_ABOVE_CHECKPOINT3;\n\n bytes32 internal immutable _LIQUDITY_WITHDRAW_TOKEN_EXCHANGE_PRICES_SLOT;\n bytes32 internal immutable _LIQUDITY_BORROW_TOKEN_EXCHANGE_PRICES_SLOT;\n\n bytes32 internal immutable _LIQUDITY_PROTOCOL_SUPPLY_SLOT;\n bytes32 internal immutable _LIQUDITY_PROTOCOL_BORROW_SLOT;\n\n uint256 internal constant DEFAULT_EXPONENT_SIZE = 8;\n uint256 internal constant DEFAULT_EXPONENT_MASK = 0xff;\n\n uint256 internal constant X14 = 0x3fff;\n uint256 internal constant X18 = 0x3ffff;\n uint256 internal constant X24 = 0xffffff;\n uint256 internal constant X64 = 0xffffffffffffffff;\n}\n\nabstract contract Events {\n /// @notice emitted when withdraw limit expand percent is updated\n event LogUpdateWithdrawLimitExpansion(uint256 supply, uint256 oldExpandPercent, uint256 newExpandPercent);\n\n /// @notice emitted when borrow limit expand percent is updated\n event LogUpdateBorrowLimitExpansion(uint256 borrow, uint256 oldExpandPercent, uint256 newExpandPercent);\n}\n\nabstract contract Structs {\n struct LimitCheckPoints {\n uint256 tvlCheckPoint1; // e.g. 20M\n uint256 expandPercentUntilCheckPoint1; // e.g. 25%\n uint256 tvlCheckPoint2; // e.g. 30M\n uint256 expandPercentUntilCheckPoint2; // e.g. 20%\n uint256 tvlCheckPoint3; // e.g. 40M\n uint256 expandPercentUntilCheckPoint3; // e.g. 15%\n uint256 expandPercentAboveCheckPoint3; // e.g. 10%\n }\n}\n\n/// @notice Sets limits on Liquidity for a protocol based on TVL checkpoints.\ncontract FluidExpandPercentConfigHandler is Constants, Error, Events, Structs {\n /// @dev Validates that an address is not the zero address\n modifier validAddress(address value_) {\n if (value_ == address(0)) {\n revert FluidConfigError(ErrorTypes.ExpandPercentConfigHandler__AddressZero);\n }\n _;\n }\n\n /// @dev Validates that an address is a rebalancer (taken from reserve contract)\n modifier onlyRebalancer() {\n if (!RESERVE_CONTRACT.isRebalancer(msg.sender)) {\n revert FluidConfigError(ErrorTypes.ExpandPercentConfigHandler__Unauthorized);\n }\n _;\n }\n\n constructor(\n IFluidReserveContract reserveContract_,\n IFluidLiquidity liquidity_,\n address protocol_,\n address withdrawToken_, // can be unused in some cases (e.g. StETH)\n address
},
"contracts/config/fluidConfigHandler.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IFluidConfigHandler } from \"./interfaces/iFluidConfigHandler.sol\";\n\n/// @title FluidConfigHandler\n/// @notice Base contract that any Fluid Config Handler must implement\nabstract contract FluidConfigHandler is IFluidConfigHandler {\n /// @inheritdoc IFluidConfigHandler\n function configPercentDiff() public view virtual returns (uint256 configPercentDiff_);\n\n /// @inheritdoc IFluidConfigHandler\n function rebalance() external virtual;\n}\n"
},
"contracts/config/interfaces/iFluidConfigHandler.sol": {
"content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.21;\n\ninterface IFluidConfigHandler {\n /// @notice returns how much the new config would be different from current config in percent (100 = 1%, 1 = 0.01%).\n function configPercentDiff() external view returns (uint256 configPercentDiff_);\n\n /// @notice Rebalances the configs at Fluid Liquidity based on config handler target.\n /// Reverts if no update is needed.\n /// Can only be called by an authorized rebalancer.\n function rebalance() external;\n}\n"
},
"contracts/config/maxBorrowHandler/main.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IFluidLiquidity } from \"../../liquidity/interfaces/iLiquidity.sol\";\nimport { IFluidLiquidityResolver } from \"../../periphery/resolvers/liquidity/iLiquidityResolver.sol\";\nimport { LiquiditySlotsLink } from \"../../libraries/liquiditySlotsLink.sol\";\nimport { BigMathMinified } from \"../../libraries/bigMathMinified.sol\";\nimport { LiquidityCalcs } from \"../../libraries/liquidityCalcs.sol\";\nimport { IFluidReserveContract } from \"../../reserve/interfaces/iReserveContract.sol\";\nimport { Structs as AdminModuleStructs } from \"../../liquidity/adminModule/structs.sol\";\nimport { Error } from \"../error.sol\";\nimport { ErrorTypes } from \"../errorTypes.sol\";\n\nabstract contract Constants {\n IFluidReserveContract public immutable RESERVE_CONTRACT;\n IFluidLiquidity public immutable LIQUIDITY;\n IFluidLiquidityResolver public immutable LIQUIDITY_RESOLVER;\n address public immutable PROTOCOL;\n address public immutable BORROW_TOKEN;\n\n /// @dev max utilization of total supply that will be set as max borrow limit. In percent (100 = 1%, 1 = 0.01%)\n uint256 public immutable MAX_UTILIZATION;\n\n /// @dev minimum percent difference to trigger an update. In percent (100 = 1%, 1 = 0.01%)\n uint256 public immutable MIN_UPDATE_DIFF;\n\n bytes32 internal immutable _LIQUDITY_PROTOCOL_BORROW_SLOT;\n\n uint256 internal constant MAX_UTILIZATION_PRECISION = 1e4;\n uint256 internal constant DEFAULT_EXPONENT_SIZE = 8;\n uint256 internal constant DEFAULT_EXPONENT_MASK = 0xff;\n\n uint256 internal constant EXCHANGE_PRICES_PRECISION = 1e12;\n\n uint256 internal constant X14 = 0x3fff;\n uint256 internal constant X18 = 0x3ffff;\n uint256 internal constant X24 = 0xffffff;\n}\n\nabstract contract Events {\n /// @notice emitted when borrow max limit is updated\n event LogUpdateBorrowMaxDebtCeiling(\n uint256 totalSupplyNormal,\n uint256 oldMaxDebtCeilingRaw,\n uint256 maxDebtCeilingRaw,\n uint256 borrowExchangePrice\n );\n}\n\n/// @notice Sets max borrow limit for a protocol on Liquidity based on utilization of total supply of the same borrow token\ncontract FluidMaxBorrowConfigHandler is Constants, Error, Events {\n /// @dev Validates that an address is not the zero address\n modifier validAddress(address value_) {\n if (value_ == address(0)) {\n revert FluidConfigError(ErrorTypes.MaxBorrowConfigHandler__AddressZero);\n }\n _;\n }\n\n /// @dev Validates that an address is a rebalancer (taken from reserve contract)\n modifier onlyRebalancer() {\n if (!RESERVE_CONTRACT.isRebalancer(msg.sender)) {\n revert FluidConfigError(ErrorTypes.MaxBorrowConfigHandler__Unauthorized);\n }\n _;\n }\n\n constructor(\n IFluidReserveContract reserveContract_,\n IFluidLiquidity liquidity_,\n IFluidLiquidityResolver liquidityResolver_,\n address protocol_,\n address borrowToken_,\n uint256 maxUtilization_,\n uint256 minUpdateDiff_\n )\n validAddress(address(reserveContract_))\n validAddress(address(liquidity_))\n validAddress(address(liquidityResolver_))\n validAddress(protocol_)\n validAddress(borrowToken_)\n {\n RESERVE_CONTRACT = reserveContract_;\n LIQUIDITY = liquidity_;\n LIQUIDITY_RESOLVER = liquidityResolver_;\n PROTOCOL = protocol_;\n BORROW_TOKEN = borrowToken_;\n\n if (maxUtilization_ > MAX_UTILIZATION_PRECISION || minUpdateDiff_ == 0) {\n revert FluidConfigError(ErrorTypes.MaxBorrowConfigHandler__InvalidParams);\n }\n\n _LIQUDITY_PROTOCOL_BORROW_SLOT = LiquiditySlotsLink.calculateDoubleMappingStorageSlot(\n LiquiditySlotsLink.LIQUIDITY_USER_BORROW_DOUBLE_MAPPING_SLOT,\n protocol_,\n borrowToken_\n );\n\n MAX_UTILIZATION = maxUtilization_;\n MIN_UPDATE_DIFF = minUpdateDiff_;\n
},
"contracts/infiniteProxy/interfaces/iProxy.sol": {
"content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.21;\n\ninterface IProxy {\n function setAdmin(address newAdmin_) external;\n\n function setDummyImplementation(address newDummyImplementation_) external;\n\n function addImplementation(address implementation_, bytes4[] calldata sigs_) external;\n\n function removeImplementation(address implementation_) external;\n\n function getAdmin() external view returns (address);\n\n function getDummyImplementation() external view returns (address);\n\n function getImplementationSigs(address impl_) external view returns (bytes4[] memory);\n\n function getSigsImplementation(bytes4 sig_) external view returns (address);\n\n function readFromStorage(bytes32 slot_) external view returns (uint256 result_);\n}\n"
},
"contracts/libraries/bigMathMinified.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\n/// @title library that represents a number in BigNumber(coefficient and exponent) format to store in smaller bits.\n/// @notice the number is divided into two parts: a coefficient and an exponent. This comes at a cost of losing some precision\n/// at the end of the number because the exponent simply fills it with zeroes. This precision is oftentimes negligible and can\n/// result in significant gas cost reduction due to storage space reduction.\n/// Also note, a valid big number is as follows: if the exponent is > 0, then coefficient last bits should be occupied to have max precision.\n/// @dev roundUp is more like a increase 1, which happens everytime for the same number.\n/// roundDown simply sets trailing digits after coefficientSize to zero (floor), only once for the same number.\nlibrary BigMathMinified {\n /// @dev constants to use for `roundUp` input param to increase readability\n bool internal constant ROUND_DOWN = false;\n bool internal constant ROUND_UP = true;\n\n /// @dev converts `normal` number to BigNumber with `exponent` and `coefficient` (or precision).\n /// e.g.:\n /// 5035703444687813576399599 (normal) = (coefficient[32bits], exponent[8bits])[40bits]\n /// 5035703444687813576399599 (decimal) => 10000101010010110100000011111011110010100110100000000011100101001101001101011101111 (binary)\n /// => 10000101010010110100000011111011000000000000000000000000000000000000000000000000000\n /// ^-------------------- 51(exponent) -------------- ^\n /// coefficient = 1000,0101,0100,1011,0100,0000,1111,1011 (2236301563)\n /// exponent = 0011,0011 (51)\n /// bigNumber = 1000,0101,0100,1011,0100,0000,1111,1011,0011,0011 (572493200179)\n ///\n /// @param normal number which needs to be converted into Big Number\n /// @param coefficientSize at max how many bits of precision there should be (64 = uint64 (64 bits precision))\n /// @param exponentSize at max how many bits of exponent there should be (8 = uint8 (8 bits exponent))\n /// @param roundUp signals if result should be rounded down or up\n /// @return bigNumber converted bigNumber (coefficient << exponent)\n function toBigNumber(\n uint256 normal,\n uint256 coefficientSize,\n uint256 exponentSize,\n bool roundUp\n ) internal pure returns (uint256 bigNumber) {\n assembly {\n let lastBit_\n let number_ := normal\n if gt(number_, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) {\n number_ := shr(0x80, number_)\n lastBit_ := 0x80\n }\n if gt(number_, 0xFFFFFFFFFFFFFFFF) {\n number_ := shr(0x40, number_)\n lastBit_ := add(lastBit_, 0x40)\n }\n if gt(number_, 0xFFFFFFFF) {\n number_ := shr(0x20, number_)\n lastBit_ := add(lastBit_, 0x20)\n }\n if gt(number_, 0xFFFF) {\n number_ := shr(0x10, number_)\n lastBit_ := add(lastBit_, 0x10)\n }\n if gt(number_, 0xFF) {\n number_ := shr(0x8, number_)\n lastBit_ := add(lastBit_, 0x8)\n }\n if gt(number_, 0xF) {\n number_ := shr(0x4, number_)\n lastBit_ := add(lastBit_, 0x4)\n }\n if gt(number_, 0x3) {\n number_ := shr(0x2, number_)\n lastBit_ := add(lastBit_, 0x2)\n }\n if gt(number_, 0x1) {\n lastBit_ := add(lastBit_, 1)\n }\n if gt(number_, 0) {\n lastBit_ := add(lastBit_, 1)\n }\n if lt(lastBit_, coefficientSize) {\n // for throw exception\n lastBit_ := coefficientSize\n }\n let
},
"contracts/libraries/bigMathVault.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { BigMathMinified } from \"./bigMathMinified.sol\";\n\n/// @title Extended version of BigMathMinified. Implements functions for normal operators (*, /, etc) modified to interact with big numbers.\n/// @notice this is an optimized version mainly created by taking Fluid vault's codebase into consideration so it's use is limited for other cases.\n// \n// @dev IMPORTANT: for any change here, make sure to uncomment and run the fuzz tests in bigMathVault.t.sol\nlibrary BigMathVault {\n uint private constant COEFFICIENT_SIZE_DEBT_FACTOR = 35;\n uint private constant EXPONENT_SIZE_DEBT_FACTOR = 15;\n uint private constant COEFFICIENT_MAX_DEBT_FACTOR = (1 << COEFFICIENT_SIZE_DEBT_FACTOR) - 1;\n uint private constant EXPONENT_MAX_DEBT_FACTOR = (1 << EXPONENT_SIZE_DEBT_FACTOR) - 1;\n uint private constant DECIMALS_DEBT_FACTOR = 16384;\n uint internal constant MAX_MASK_DEBT_FACTOR = (1 << (COEFFICIENT_SIZE_DEBT_FACTOR + EXPONENT_SIZE_DEBT_FACTOR)) - 1;\n\n // Having precision as 2**64 on vault\n uint internal constant PRECISION = 64;\n uint internal constant TWO_POWER_64 = 1 << PRECISION;\n // Max bit for 35 bits * 35 bits number will be 70\n // why do we use 69 then here instead of 70\n uint internal constant TWO_POWER_69_MINUS_1 = (1 << 69) - 1;\n\n uint private constant COEFFICIENT_PLUS_PRECISION = COEFFICIENT_SIZE_DEBT_FACTOR + PRECISION; // 99\n uint private constant COEFFICIENT_PLUS_PRECISION_MINUS_1 = COEFFICIENT_PLUS_PRECISION - 1; // 98\n uint private constant TWO_POWER_COEFFICIENT_PLUS_PRECISION_MINUS_1 = (1 << COEFFICIENT_PLUS_PRECISION_MINUS_1) - 1; // (1 << 98) - 1;\n uint private constant TWO_POWER_COEFFICIENT_PLUS_PRECISION_MINUS_1_MINUS_1 =\n (1 << (COEFFICIENT_PLUS_PRECISION_MINUS_1 - 1)) - 1; // (1 << 97) - 1;\n\n /// @dev multiplies a `normal` number with a `bigNumber1` and then divides by `bigNumber2`.\n /// @dev For vault's use case MUST always:\n /// - bigNumbers have exponent size 15 bits\n /// - bigNumbers have coefficient size 35 bits and have 35th bit always 1 (when exponent > 0 BigMath numbers have max precision)\n /// so coefficients must always be in range 17179869184 <= coefficient <= 34359738367.\n /// - bigNumber1 (debt factor) always have exponent >= 1 & <= 16384\n /// - bigNumber2 (connection factor) always have exponent >= 1 & <= 32767 (15 bits)\n /// - bigNumber2 always >= bigNumber1 (connection factor can never be < base branch debt factor)\n /// - as a result of previous points, numbers must never be 0\n /// - normal is positionRawDebt and is always within 10000 and type(int128).max\n /// @return normal * bigNumber1 / bigNumber2\n function mulDivNormal(uint256 normal, uint256 bigNumber1, uint256 bigNumber2) internal pure returns (uint256) {\n unchecked {\n // exponent2_ - exponent1_\n uint netExponent_ = (bigNumber2 & EXPONENT_MAX_DEBT_FACTOR) - (bigNumber1 & EXPONENT_MAX_DEBT_FACTOR);\n if (netExponent_ < 129) {\n // (normal * coefficient1_) / (coefficient2_ << netExponent_);\n return ((normal * (bigNumber1 >> EXPONENT_SIZE_DEBT_FACTOR)) /\n ((bigNumber2 >> EXPONENT_SIZE_DEBT_FACTOR) << netExponent_));\n }\n // else:\n // biggest possible nominator: type(int128).max * 35bits max = 5846006549323611672814739330865132078589370433536\n // smallest possible denominator: 17179869184 << 129 (= 1 << 163) = 11692013098647223345629478661730264157247460343808\n // -> can only ever be 0\n return 0;\n }\n }\n\n /// @dev multiplies a `bigNumber` with normal `number1` and then divides by `TWO_POWER_64`.\n /// @dev For vault's use case (calculating new branch debt factor after liquidation):\n /// - number1 is debtFactor, intialized as TWO_POWER_64 and reduced from there, hence it's always <= TWO_POWER_64 and
},
"contracts/libraries/errorTypes.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nlibrary LibsErrorTypes {\n /***********************************|\n | LiquidityCalcs | \n |__________________________________*/\n\n /// @notice thrown when supply or borrow exchange price is zero at calc token data (token not configured yet)\n uint256 internal constant LiquidityCalcs__ExchangePriceZero = 70001;\n\n /// @notice thrown when rate data is set to a version that is not implemented\n uint256 internal constant LiquidityCalcs__UnsupportedRateVersion = 70002;\n\n /// @notice thrown when the calculated borrow rate turns negative. This should never happen.\n uint256 internal constant LiquidityCalcs__BorrowRateNegative = 70003;\n\n /***********************************|\n | SafeTransfer | \n |__________________________________*/\n\n /// @notice thrown when safe transfer from for an ERC20 fails\n uint256 internal constant SafeTransfer__TransferFromFailed = 71001;\n\n /// @notice thrown when safe transfer for an ERC20 fails\n uint256 internal constant SafeTransfer__TransferFailed = 71002;\n}\n"
},
"contracts/libraries/liquidityCalcs.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { LibsErrorTypes as ErrorTypes } from \"./errorTypes.sol\";\nimport { LiquiditySlotsLink } from \"./liquiditySlotsLink.sol\";\nimport { BigMathMinified } from \"./bigMathMinified.sol\";\n\n/// @notice implements calculation methods used for Fluid liquidity such as updated exchange prices,\n/// borrow rate, withdrawal / borrow limits, revenue amount.\nlibrary LiquidityCalcs {\n error FluidLiquidityCalcsError(uint256 errorId_);\n\n /// @notice emitted if the calculated borrow rate surpassed max borrow rate (16 bits) and was capped at maximum value 65535\n event BorrowRateMaxCap();\n\n /// @dev constants as from Liquidity variables.sol\n uint256 internal constant EXCHANGE_PRICES_PRECISION = 1e12;\n\n /// @dev Ignoring leap years\n uint256 internal constant SECONDS_PER_YEAR = 365 days;\n // constants used for BigMath conversion from and to storage\n uint256 internal constant DEFAULT_EXPONENT_SIZE = 8;\n uint256 internal constant DEFAULT_EXPONENT_MASK = 0xFF;\n\n uint256 internal constant FOUR_DECIMALS = 1e4;\n uint256 internal constant TWELVE_DECIMALS = 1e12;\n uint256 internal constant X14 = 0x3fff;\n uint256 internal constant X15 = 0x7fff;\n uint256 internal constant X16 = 0xffff;\n uint256 internal constant X18 = 0x3ffff;\n uint256 internal constant X24 = 0xffffff;\n uint256 internal constant X33 = 0x1ffffffff;\n uint256 internal constant X64 = 0xffffffffffffffff;\n\n ///////////////////////////////////////////////////////////////////////////\n ////////// CALC EXCHANGE PRICES /////////\n ///////////////////////////////////////////////////////////////////////////\n\n /// @dev calculates interest (exchange prices) for a token given its' exchangePricesAndConfig from storage.\n /// @param exchangePricesAndConfig_ exchange prices and config packed uint256 read from storage\n /// @return supplyExchangePrice_ updated supplyExchangePrice\n /// @return borrowExchangePrice_ updated borrowExchangePrice\n function calcExchangePrices(\n uint256 exchangePricesAndConfig_\n ) internal view returns (uint256 supplyExchangePrice_, uint256 borrowExchangePrice_) {\n // Extracting exchange prices\n supplyExchangePrice_ =\n (exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_SUPPLY_EXCHANGE_PRICE) &\n X64;\n borrowExchangePrice_ =\n (exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_BORROW_EXCHANGE_PRICE) &\n X64;\n\n if (supplyExchangePrice_ == 0 || borrowExchangePrice_ == 0) {\n revert FluidLiquidityCalcsError(ErrorTypes.LiquidityCalcs__ExchangePriceZero);\n }\n\n uint256 temp_ = exchangePricesAndConfig_ & X16; // temp_ = borrowRate\n\n unchecked {\n // last timestamp can not be > current timestamp\n uint256 secondsSinceLastUpdate_ = block.timestamp -\n ((exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_LAST_TIMESTAMP) & X33);\n\n uint256 borrowRatio_ = (exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_BORROW_RATIO) &\n X15;\n if (secondsSinceLastUpdate_ == 0 || temp_ == 0 || borrowRatio_ == 1) {\n // if no time passed, borrow rate is 0, or no raw borrowings: no exchange price update needed\n // (if borrowRatio_ == 1 means there is only borrowInterestFree, as first bit is 1 and rest is 0)\n return (supplyExchangePrice_, borrowExchangePrice_);\n }\n\n // calculate new borrow exchange price.\n // formula borrowExchangePriceIncrease: previous price * borrow rate * secondsSinceLastUpdate_.\n // nominator is max uint112 (uint64 * uint16 * uint32). Divisor can not be 0.\n borrowExchangePrice_ +=\n (borrowExchangePrice_ * temp_ * secondsSinceLastUpdate_) /\n (SECO
},
"contracts/libraries/liquiditySlotsLink.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\n/// @notice library that helps in reading / working with storage slot data of Fluid Liquidity.\n/// @dev as all data for Fluid Liquidity is internal, any data must be fetched directly through manual\n/// slot reading through this library or, if gas usage is less important, through the FluidLiquidityResolver.\nlibrary LiquiditySlotsLink {\n /// @dev storage slot for status at Liquidity\n uint256 internal constant LIQUIDITY_STATUS_SLOT = 1;\n /// @dev storage slot for auths mapping at Liquidity\n uint256 internal constant LIQUIDITY_AUTHS_MAPPING_SLOT = 2;\n /// @dev storage slot for guardians mapping at Liquidity\n uint256 internal constant LIQUIDITY_GUARDIANS_MAPPING_SLOT = 3;\n /// @dev storage slot for user class mapping at Liquidity\n uint256 internal constant LIQUIDITY_USER_CLASS_MAPPING_SLOT = 4;\n /// @dev storage slot for exchangePricesAndConfig mapping at Liquidity\n uint256 internal constant LIQUIDITY_EXCHANGE_PRICES_MAPPING_SLOT = 5;\n /// @dev storage slot for rateData mapping at Liquidity\n uint256 internal constant LIQUIDITY_RATE_DATA_MAPPING_SLOT = 6;\n /// @dev storage slot for totalAmounts mapping at Liquidity\n uint256 internal constant LIQUIDITY_TOTAL_AMOUNTS_MAPPING_SLOT = 7;\n /// @dev storage slot for user supply double mapping at Liquidity\n uint256 internal constant LIQUIDITY_USER_SUPPLY_DOUBLE_MAPPING_SLOT = 8;\n /// @dev storage slot for user borrow double mapping at Liquidity\n uint256 internal constant LIQUIDITY_USER_BORROW_DOUBLE_MAPPING_SLOT = 9;\n /// @dev storage slot for listed tokens array at Liquidity\n uint256 internal constant LIQUIDITY_LISTED_TOKENS_ARRAY_SLOT = 10;\n\n // --------------------------------\n // @dev stacked uint256 storage slots bits position data for each:\n\n // ExchangePricesAndConfig\n uint256 internal constant BITS_EXCHANGE_PRICES_BORROW_RATE = 0;\n uint256 internal constant BITS_EXCHANGE_PRICES_FEE = 16;\n uint256 internal constant BITS_EXCHANGE_PRICES_UTILIZATION = 30;\n uint256 internal constant BITS_EXCHANGE_PRICES_UPDATE_THRESHOLD = 44;\n uint256 internal constant BITS_EXCHANGE_PRICES_LAST_TIMESTAMP = 58;\n uint256 internal constant BITS_EXCHANGE_PRICES_SUPPLY_EXCHANGE_PRICE = 91;\n uint256 internal constant BITS_EXCHANGE_PRICES_BORROW_EXCHANGE_PRICE = 155;\n uint256 internal constant BITS_EXCHANGE_PRICES_SUPPLY_RATIO = 219;\n uint256 internal constant BITS_EXCHANGE_PRICES_BORROW_RATIO = 234;\n\n // RateData:\n uint256 internal constant BITS_RATE_DATA_VERSION = 0;\n // RateData: V1\n uint256 internal constant BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_ZERO = 4;\n uint256 internal constant BITS_RATE_DATA_V1_UTILIZATION_AT_KINK = 20;\n uint256 internal constant BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_KINK = 36;\n uint256 internal constant BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_MAX = 52;\n // RateData: V2\n uint256 internal constant BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_ZERO = 4;\n uint256 internal constant BITS_RATE_DATA_V2_UTILIZATION_AT_KINK1 = 20;\n uint256 internal constant BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_KINK1 = 36;\n uint256 internal constant BITS_RATE_DATA_V2_UTILIZATION_AT_KINK2 = 52;\n uint256 internal constant BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_KINK2 = 68;\n uint256 internal constant BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_MAX = 84;\n\n // TotalAmounts\n uint256 internal constant BITS_TOTAL_AMOUNTS_SUPPLY_WITH_INTEREST = 0;\n uint256 internal constant BITS_TOTAL_AMOUNTS_SUPPLY_INTEREST_FREE = 64;\n uint256 internal constant BITS_TOTAL_AMOUNTS_BORROW_WITH_INTEREST = 128;\n uint256 internal constant BITS_TOTAL_AMOUNTS_BORROW_INTEREST_FREE = 192;\n\n // UserSupplyData\n uint256 internal constant BITS_USER_SUPPLY_MODE = 0;\n uint256 internal constant BITS_USER_SUPPLY_AMOUNT = 1;\n uint256 internal constant BITS_USER_SUPPLY_PREVIOUS_WITHDRAWAL_LIMIT = 65;\n uint256 internal constant BITS_USER_SUPPLY_LAST_UPDATE
},
"contracts/libraries/safeTransfer.sol": {
"content": "// SPDX-License-Identifier: MIT OR Apache-2.0\npragma solidity 0.8.21;\n\nimport { LibsErrorTypes as ErrorTypes } from \"./errorTypes.sol\";\n\n/// @notice provides minimalistic methods for safe transfers, e.g. ERC20 safeTransferFrom\nlibrary SafeTransfer {\n error FluidSafeTransferError(uint256 errorId_);\n\n /// @dev Transfer `amount_` of `token_` from `from_` to `to_`, spending the approval given by `from_` to the\n /// calling contract. If `token_` returns no value, non-reverting calls are assumed to be successful.\n /// Minimally modified from Solmate SafeTransferLib (address as input param for token, Custom Error):\n /// https://github.com/transmissions11/solmate/blob/50e15bb566f98b7174da9b0066126a4c3e75e0fd/src/utils/SafeTransferLib.sol#L31-L63\n function safeTransferFrom(address token_, address from_, address to_, uint256 amount_) internal {\n bool success_;\n\n /// @solidity memory-safe-assembly\n assembly {\n // Get a pointer to some free memory.\n let freeMemoryPointer := mload(0x40)\n\n // Write the abi-encoded calldata into memory, beginning with the function selector.\n mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)\n mstore(add(freeMemoryPointer, 4), and(from_, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the \"from_\" argument.\n mstore(add(freeMemoryPointer, 36), and(to_, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the \"to_\" argument.\n mstore(add(freeMemoryPointer, 68), amount_) // Append the \"amount_\" argument. Masking not required as it's a full 32 byte type.\n\n success_ := and(\n // Set success to whether the call reverted, if not we check it either\n // returned exactly 1 (can't just be non-zero data), or had no return data.\n or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\n // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3.\n // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\n // Counterintuitively, this call must be positioned second to the or() call in the\n // surrounding and() call or else returndatasize() will be zero during the computation.\n call(gas(), token_, 0, freeMemoryPointer, 100, 0, 32)\n )\n }\n\n if (!success_) {\n revert FluidSafeTransferError(ErrorTypes.SafeTransfer__TransferFromFailed);\n }\n }\n\n /// @dev Transfer `amount_` of `token_` to `to_`.\n /// If `token_` returns no value, non-reverting calls are assumed to be successful.\n /// Minimally modified from Solmate SafeTransferLib (address as input param for token, Custom Error):\n /// https://github.com/transmissions11/solmate/blob/50e15bb566f98b7174da9b0066126a4c3e75e0fd/src/utils/SafeTransferLib.sol#L65-L95\n function safeTransfer(address token_, address to_, uint256 amount_) internal {\n bool success_;\n\n /// @solidity memory-safe-assembly\n assembly {\n // Get a pointer to some free memory.\n let freeMemoryPointer := mload(0x40)\n\n // Write the abi-encoded calldata into memory, beginning with the function selector.\n mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)\n mstore(add(freeMemoryPointer, 4), and(to_, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the \"to_\" argument.\n mstore(add(freeMemoryPointer, 36), amount_) // Append the \"amount_\" argument. Masking not required as it's a full 32 byte type.\n\n success_ := and(\n // Set success to whether the call reverted, if not we check it either\n // returned exactly 1 (can't just be non-zero data), or had no return data.\n or(and(eq(mload(0), 1), gt(returndatasize
},
"contracts/libraries/storageRead.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\n/// @notice implements a method to read uint256 data from storage at a bytes32 storage slot key.\ncontract StorageRead {\n function readFromStorage(bytes32 slot_) public view returns (uint256 result_) {\n assembly {\n result_ := sload(slot_) // read value from the storage slot\n }\n }\n}\n"
},
"contracts/libraries/tickMath.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\n/// @title library that calculates number \"tick\" and \"ratioX96\" from this: ratioX96 = (1.0015^tick) * 2^96\n/// @notice this library is used in Fluid Vault protocol for optimiziation.\n/// @dev \"tick\" supports between -32767 and 32767. \"ratioX96\" supports between 37075072 and 169307877264527972847801929085841449095838922544595\nlibrary TickMath {\n /// The minimum tick that can be passed in getRatioAtTick. 1.0015**-32767\n int24 internal constant MIN_TICK = -32767;\n /// The maximum tick that can be passed in getRatioAtTick. 1.0015**32767\n int24 internal constant MAX_TICK = 32767;\n\n uint256 internal constant FACTOR00 = 0x100000000000000000000000000000000;\n uint256 internal constant FACTOR01 = 0xff9dd7de423466c20352b1246ce4856f; // 2^128/1.0015**1 = 339772707859149738855091969477551883631\n uint256 internal constant FACTOR02 = 0xff3bd55f4488ad277531fa1c725a66d0; // 2^128/1.0015**2 = 339263812140938331358054887146831636176\n uint256 internal constant FACTOR03 = 0xfe78410fd6498b73cb96a6917f853259; // 2^128/1.0015**4 = 338248306163758188337119769319392490073\n uint256 internal constant FACTOR04 = 0xfcf2d9987c9be178ad5bfeffaa123273; // 2^128/1.0015**8 = 336226404141693512316971918999264834163\n uint256 internal constant FACTOR05 = 0xf9ef02c4529258b057769680fc6601b3; // 2^128/1.0015**16 = 332218786018727629051611634067491389875\n uint256 internal constant FACTOR06 = 0xf402d288133a85a17784a411f7aba082; // 2^128/1.0015**32 = 324346285652234375371948336458280706178\n uint256 internal constant FACTOR07 = 0xe895615b5beb6386553757b0352bda90; // 2^128/1.0015**64 = 309156521885964218294057947947195947664\n uint256 internal constant FACTOR08 = 0xd34f17a00ffa00a8309940a15930391a; // 2^128/1.0015**128 = 280877777739312896540849703637713172762 \n uint256 internal constant FACTOR09 = 0xae6b7961714e20548d88ea5123f9a0ff; // 2^128/1.0015**256 = 231843708922198649176471782639349113087\n uint256 internal constant FACTOR10 = 0x76d6461f27082d74e0feed3b388c0ca1; // 2^128/1.0015**512 = 157961477267171621126394973980180876449\n uint256 internal constant FACTOR11 = 0x372a3bfe0745d8b6b19d985d9a8b85bb; // 2^128/1.0015**1024 = 73326833024599564193373530205717235131\n uint256 internal constant FACTOR12 = 0x0be32cbee48979763cf7247dd7bb539d; // 2^128/1.0015**2048 = 15801066890623697521348224657638773661\n uint256 internal constant FACTOR13 = 0x8d4f70c9ff4924dac37612d1e2921e; // 2^128/1.0015**4096 = 733725103481409245883800626999235102\n uint256 internal constant FACTOR14 = 0x4e009ae5519380809a02ca7aec77; // 2^128/1.0015**8192 = 1582075887005588088019997442108535\n uint256 internal constant FACTOR15 = 0x17c45e641b6e95dee056ff10; // 2^128/1.0015**16384 = 7355550435635883087458926352\n\n /// The minimum value that can be returned from getRatioAtTick. Equivalent to getRatioAtTick(MIN_TICK). ~ Equivalent to `(1 << 96) * (1.0015**-32767)`\n uint256 internal constant MIN_RATIOX96 = 37075072;\n /// The maximum value that can be returned from getRatioAtTick. Equivalent to getRatioAtTick(MAX_TICK).\n /// ~ Equivalent to `(1 << 96) * (1.0015**32767)`, rounding etc. leading to minor difference\n uint256 internal constant MAX_RATIOX96 = 169307877264527972847801929085841449095838922544595;\n\n uint256 internal constant ZERO_TICK_SCALED_RATIO = 0x1000000000000000000000000; // 1 << 96 // 79228162514264337593543950336\n uint256 internal constant _1E26 = 1e26;\n\n /// @notice ratioX96 = (1.0015^tick) * 2^96\n /// @dev Throws if |tick| > max tick\n /// @param tick The input tick for the above formula\n /// @return ratioX96 ratio = (debt amount/collateral amount)\n function getRatioAtTick(int tick) internal pure returns (uint256 ratioX96) {\n assembly {\n let absTick_ := sub(xor(tick, sar(255, tick)), sar(255, tick))\n\n if gt(absTick_, MAX_TICK) {\n revert(0, 0)\n }\n let factor_ := FACTOR00\n if
},
"contracts/liquidity/adminModule/events.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { Structs } from \"./structs.sol\";\n\ncontract Events is Structs {\n /// @notice emitted when allowed auths are updated\n event LogUpdateAuths(AddressBool[] authsStatus);\n\n /// @notice emitted when allowed guardians are updated\n event LogUpdateGuardians(AddressBool[] guardiansStatus);\n\n /// @notice emitted when revenue collector address is updated\n event LogUpdateRevenueCollector(address indexed revenueCollector);\n\n /// @notice emitted when status is changed (paused / unpaused)\n event LogChangeStatus(uint256 indexed newStatus);\n\n /// @notice emitted when user classes are updated\n event LogUpdateUserClasses(AddressUint256[] userClasses);\n\n /// @notice emitted when token configs are updated\n event LogUpdateTokenConfigs(TokenConfig[] tokenConfigs);\n\n /// @notice emitted when user supply configs are updated\n event LogUpdateUserSupplyConfigs(UserSupplyConfig[] userSupplyConfigs);\n\n /// @notice emitted when user borrow configs are updated\n event LogUpdateUserBorrowConfigs(UserBorrowConfig[] userBorrowConfigs);\n\n /// @notice emitted when a user gets certain tokens paused\n event LogPauseUser(address user, address[] supplyTokens, address[] borrowTokens);\n\n /// @notice emitted when a user gets certain tokens unpaused\n event LogUnpauseUser(address user, address[] supplyTokens, address[] borrowTokens);\n\n /// @notice emitted when token rate data is updated with rate data v1\n event LogUpdateRateDataV1s(RateDataV1Params[] tokenRateDatas);\n\n /// @notice emitted when token rate data is updated with rate data v2\n event LogUpdateRateDataV2s(RateDataV2Params[] tokenRateDatas);\n\n /// @notice emitted when revenue is collected\n event LogCollectRevenue(address indexed token, uint256 indexed amount);\n\n /// @notice emitted when exchange prices and borrow rate are updated\n event LogUpdateExchangePrices(\n address indexed token,\n uint256 indexed supplyExchangePrice,\n uint256 indexed borrowExchangePrice,\n uint256 borrowRate,\n uint256 utilization\n );\n}\n"
},
"contracts/liquidity/adminModule/main.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\nimport { FixedPointMathLib } from \"solmate/src/utils/FixedPointMathLib.sol\";\n\nimport { BigMathMinified } from \"../../libraries/bigMathMinified.sol\";\nimport { LiquidityCalcs } from \"../../libraries/liquidityCalcs.sol\";\nimport { LiquiditySlotsLink } from \"../../libraries/liquiditySlotsLink.sol\";\nimport { Events } from \"./events.sol\";\nimport { Structs } from \"./structs.sol\";\nimport { CommonHelpers } from \"../common/helpers.sol\";\nimport { IFluidLiquidityAdmin } from \"../interfaces/iLiquidity.sol\";\nimport { ErrorTypes } from \"../errorTypes.sol\";\nimport { Error } from \"../error.sol\";\n\nabstract contract AdminModuleConstants is Error {\n /// @dev hard cap value for max borrow limit, used as sanity check. Usually 10x of total supply.\n uint256 public immutable NATIVE_TOKEN_MAX_BORROW_LIMIT_CAP;\n\n constructor(uint256 nativeTokenMaxBorrowLimitCap_) {\n if (nativeTokenMaxBorrowLimitCap_ == 0) {\n revert FluidLiquidityError(ErrorTypes.AdminModule__InvalidParams);\n }\n\n NATIVE_TOKEN_MAX_BORROW_LIMIT_CAP = nativeTokenMaxBorrowLimitCap_;\n }\n}\n\n/// @notice Fluid Liquidity Governance only related methods\nabstract contract GovernanceModule is IFluidLiquidityAdmin, CommonHelpers, Events, AdminModuleConstants {\n /// @notice only governance guard\n modifier onlyGovernance() {\n if (_getGovernanceAddr() != msg.sender) {\n revert FluidLiquidityError(ErrorTypes.AdminModule__OnlyGovernance);\n }\n _;\n }\n\n /// @dev checks that `value_` is a valid address (not zero address)\n function _checkValidAddress(address value_) internal pure {\n if (value_ == address(0)) {\n revert FluidLiquidityError(ErrorTypes.AdminModule__AddressZero);\n }\n }\n\n /// @dev checks that `value_` address is a contract (which includes address zero check)\n function _checkIsContractOrNativeAddress(address value_) internal view {\n if (value_.code.length == 0 && value_ != NATIVE_TOKEN_ADDRESS) {\n revert FluidLiquidityError(ErrorTypes.AdminModule__AddressNotAContract);\n }\n }\n\n /// @inheritdoc IFluidLiquidityAdmin\n function updateAuths(AddressBool[] calldata authsStatus_) external onlyGovernance {\n uint256 length_ = authsStatus_.length;\n for (uint256 i; i < length_; ) {\n _checkValidAddress(authsStatus_[i].addr);\n\n _isAuth[authsStatus_[i].addr] = authsStatus_[i].value ? 1 : 0;\n\n unchecked {\n ++i;\n }\n }\n\n emit LogUpdateAuths(authsStatus_);\n }\n\n /// @inheritdoc IFluidLiquidityAdmin\n function updateGuardians(AddressBool[] calldata guardiansStatus_) external onlyGovernance {\n uint256 length_ = guardiansStatus_.length;\n for (uint256 i; i < length_; ) {\n _checkValidAddress(guardiansStatus_[i].addr);\n\n _isGuardian[guardiansStatus_[i].addr] = guardiansStatus_[i].value ? 1 : 0;\n\n unchecked {\n ++i;\n }\n }\n\n emit LogUpdateGuardians(guardiansStatus_);\n }\n\n /// @inheritdoc IFluidLiquidityAdmin\n function updateRevenueCollector(address revenueCollector_) external onlyGovernance {\n _checkValidAddress(revenueCollector_);\n\n _revenueCollector = revenueCollector_;\n\n emit LogUpdateRevenueCollector(revenueCollector_);\n }\n}\n\nabstract contract AuthInternals is Error, CommonHelpers, Events {\n /// @dev computes rata data packed uint256 for version 1 rate input params telling desired values\n /// at different uzilitation points (0%, kink, 100%)\n /// @param rataDataV1Params_ rata data params for a given token\n /// @return
},
"contracts/liquidity/adminModule/structs.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nabstract contract Structs {\n struct AddressBool {\n address addr;\n bool value;\n }\n\n struct AddressUint256 {\n address addr;\n uint256 value;\n }\n\n /// @notice struct to set borrow rate data for version 1\n struct RateDataV1Params {\n ///\n /// @param token for rate data\n address token;\n ///\n /// @param kink in borrow rate. in 1e2: 100% = 10_000; 1% = 100\n /// utilization below kink usually means slow increase in rate, once utilization is above kink borrow rate increases fast\n uint256 kink;\n ///\n /// @param rateAtUtilizationZero desired borrow rate when utilization is zero. in 1e2: 100% = 10_000; 1% = 100\n /// i.e. constant minimum borrow rate\n /// e.g. at utilization = 0.01% rate could still be at least 4% (rateAtUtilizationZero would be 400 then)\n uint256 rateAtUtilizationZero;\n ///\n /// @param rateAtUtilizationKink borrow rate when utilization is at kink. in 1e2: 100% = 10_000; 1% = 100\n /// e.g. when rate should be 7% at kink then rateAtUtilizationKink would be 700\n uint256 rateAtUtilizationKink;\n ///\n /// @param rateAtUtilizationMax borrow rate when utilization is maximum at 100%. in 1e2: 100% = 10_000; 1% = 100\n /// e.g. when rate should be 125% at 100% then rateAtUtilizationMax would be 12_500\n uint256 rateAtUtilizationMax;\n }\n\n /// @notice struct to set borrow rate data for version 2\n struct RateDataV2Params {\n ///\n /// @param token for rate data\n address token;\n ///\n /// @param kink1 first kink in borrow rate. in 1e2: 100% = 10_000; 1% = 100\n /// utilization below kink 1 usually means slow increase in rate, once utilization is above kink 1 borrow rate increases faster\n uint256 kink1;\n ///\n /// @param kink2 second kink in borrow rate. in 1e2: 100% = 10_000; 1% = 100\n /// utilization below kink 2 usually means slow / medium increase in rate, once utilization is above kink 2 borrow rate increases fast\n uint256 kink2;\n ///\n /// @param rateAtUtilizationZero desired borrow rate when utilization is zero. in 1e2: 100% = 10_000; 1% = 100\n /// i.e. constant minimum borrow rate\n /// e.g. at utilization = 0.01% rate could still be at least 4% (rateAtUtilizationZero would be 400 then)\n uint256 rateAtUtilizationZero;\n ///\n /// @param rateAtUtilizationKink1 desired borrow rate when utilization is at first kink. in 1e2: 100% = 10_000; 1% = 100\n /// e.g. when rate should be 7% at first kink then rateAtUtilizationKink would be 700\n uint256 rateAtUtilizationKink1;\n ///\n /// @param rateAtUtilizationKink2 desired borrow rate when utilization is at second kink. in 1e2: 100% = 10_000; 1% = 100\n /// e.g. when rate should be 7% at second kink then rateAtUtilizationKink would be 1_200\n uint256 rateAtUtilizationKink2;\n ///\n /// @param rateAtUtilizationMax desired borrow rate when utilization is maximum at 100%. in 1e2: 100% = 10_000; 1% = 100\n /// e.g. when rate should be 125% at 100% then rateAtUtilizationMax would be 12_500\n uint256 rateAtUtilizationMax;\n }\n\n /// @notice struct to set token config\n struct TokenConfig {\n ///\n /// @param token address\n address token;\n ///\n /// @param fee charges on borrower's interest. in 1e2: 100% = 10_000; 1% = 100\n uint256 fee;\n ///\n /// @param threshold on when to update the storage slot. in 1e2: 100% = 10_000; 1% = 100\n uint256 threshold;\n }\n\n /// @notice struct to set user supply & withdrawal config\n struct UserSupplyConfig {\n ///\n /// @param user address\n address user;\n ///\n /// @param token address\n address token;\n ///\n
},
"contracts/liquidity/common/helpers.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { Variables } from \"./variables.sol\";\nimport { ErrorTypes } from \"../errorTypes.sol\";\nimport { Error } from \"../error.sol\";\n\n/// @dev ReentrancyGuard based on OpenZeppelin implementation.\n/// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v4.8/contracts/security/ReentrancyGuard.sol\nabstract contract ReentrancyGuard is Variables, Error {\n uint8 internal constant REENTRANCY_NOT_ENTERED = 1;\n uint8 internal constant REENTRANCY_ENTERED = 2;\n\n constructor() {\n // on logic contracts, switch reentrancy to entered so no call is possible (forces delegatecall)\n _status = REENTRANCY_ENTERED; \n }\n\n /// @dev Prevents a contract from calling itself, directly or indirectly.\n /// See OpenZeppelin implementation for more info\n modifier reentrancy() {\n // On the first call to nonReentrant, _status will be NOT_ENTERED\n if (_status == REENTRANCY_ENTERED) {\n revert FluidLiquidityError(ErrorTypes.LiquidityHelpers__Reentrancy);\n }\n\n // Any calls to nonReentrant after this point will fail\n _status = REENTRANCY_ENTERED;\n\n _;\n\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = REENTRANCY_NOT_ENTERED;\n }\n}\n\nabstract contract CommonHelpers is ReentrancyGuard {\n /// @dev Returns the current admin (governance).\n function _getGovernanceAddr() internal view returns (address governance_) {\n assembly {\n governance_ := sload(GOVERNANCE_SLOT)\n }\n }\n}\n"
},
"contracts/liquidity/common/variables.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\ncontract ConstantVariables {\n /// @dev Storage slot with the admin of the contract. Logic from \"proxy.sol\".\n /// This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1, and is validated in the constructor.\n bytes32 internal constant GOVERNANCE_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n uint256 internal constant EXCHANGE_PRICES_PRECISION = 1e12;\n\n /// @dev address that is mapped to the chain native token\n address internal constant NATIVE_TOKEN_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n /// @dev limit for triggering a revert if sent along excess `msg.value` is bigger than this amount\n uint256 internal constant NATIVE_AMOUNT_EXCESS_LIMIT = 1e9;\n\n /// @dev Ignoring leap years\n uint256 internal constant SECONDS_PER_YEAR = 365 days;\n\n /// @dev limit any total amount to be half of type(uint128).max (~3.4e38) at type(int128).max (~1.7e38) as safety\n /// measure for any potential overflows / unexpected outcomes. This is checked for total borrow / supply.\n uint256 internal constant MAX_TOKEN_AMOUNT_CAP = uint256(uint128(type(int128).max));\n\n /// @dev time after which a write to storage of exchangePricesAndConfig will happen always.\n uint256 internal constant FORCE_STORAGE_WRITE_AFTER_TIME = 1 days;\n\n /// @dev constants used for BigMath conversion from and to storage\n uint256 internal constant SMALL_COEFFICIENT_SIZE = 10;\n uint256 internal constant DEFAULT_COEFFICIENT_SIZE = 56;\n uint256 internal constant DEFAULT_EXPONENT_SIZE = 8;\n uint256 internal constant DEFAULT_EXPONENT_MASK = 0xFF;\n\n /// @dev constants to increase readability for using bit masks\n uint256 internal constant FOUR_DECIMALS = 1e4;\n uint256 internal constant TWELVE_DECIMALS = 1e12;\n uint256 internal constant X8 = 0xff;\n uint256 internal constant X14 = 0x3fff;\n uint256 internal constant X15 = 0x7fff;\n uint256 internal constant X16 = 0xffff;\n uint256 internal constant X18 = 0x3ffff;\n uint256 internal constant X24 = 0xffffff;\n uint256 internal constant X33 = 0x1ffffffff;\n uint256 internal constant X64 = 0xffffffffffffffff;\n}\n\ncontract Variables is ConstantVariables {\n /// @dev address of contract that gets sent the revenue. Configurable by governance\n address internal _revenueCollector;\n\n // 12 bytes empty\n\n // ----- storage slot 1 ------\n\n /// @dev paused status: status = 1 -> normal. status = 2 -> paused.\n /// not tightly packed with revenueCollector address to allow for potential changes later that improve gas more\n /// (revenueCollector is only rarely used by admin methods, where optimization is not as important).\n /// to be replaced with transient storage once EIP-1153 Transient storage becomes available with dencun upgrade.\n uint256 internal _status;\n\n // ----- storage slot 2 ------\n\n /// @dev Auths can set most config values. E.g. contracts that automate certain flows like e.g. adding a new fToken.\n /// Governance can add/remove auths.\n /// Governance is auth by default\n mapping(address => uint256) internal _isAuth;\n\n // ----- storage slot 3 ------\n\n /// @dev Guardians can pause lower class users\n /// Governance can add/remove guardians\n /// Governance is guardian by default\n mapping(address => uint256) internal _isGuardian;\n\n // ----- storage slot 4 ------\n\n /// @dev class defines which protocols can be paused by guardians\n /// Currently there are 2 classes: 0 can be paused by guardians. 1 cannot be paused by guardians.\n /// New protocols are added as class 0 and will be upgraded to 1 over time.\n mapping(address => uint256) internal _userClass;\n\n // ----- storage slot 5 ------\n\n /// @dev exchange prices and token config per token: token -> exchange prices & config\n /// First 16 bits => 0- 15 => borrow rate (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\n /
},
"contracts/liquidity/dummyImpl.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IFluidLiquidityLogic, IFluidLiquidityAdmin } from \"./interfaces/iLiquidity.sol\";\nimport { Structs as AdminModuleStructs } from \"./adminModule/structs.sol\";\n\n/// @notice Liquidity dummy implementation used for Fluid Liquidity infinite proxy.\n/// @dev see https://github.com/Instadapp/infinite-proxy?tab=readme-ov-file#dummy-implementation\ncontract FluidLiquidityDummyImpl is IFluidLiquidityLogic {\n /// @inheritdoc IFluidLiquidityAdmin\n function updateAuths(AdminModuleStructs.AddressBool[] calldata authsStatus_) external {}\n\n /// @inheritdoc IFluidLiquidityAdmin\n function updateGuardians(AdminModuleStructs.AddressBool[] calldata guardiansStatus_) external {}\n\n /// @inheritdoc IFluidLiquidityAdmin\n function updateRevenueCollector(address revenueCollector_) external {}\n\n /// @inheritdoc IFluidLiquidityAdmin\n function changeStatus(uint256 newStatus_) external {}\n\n /// @inheritdoc IFluidLiquidityAdmin\n function updateRateDataV1s(AdminModuleStructs.RateDataV1Params[] calldata tokensRateData_) external {}\n\n /// @inheritdoc IFluidLiquidityAdmin\n function updateRateDataV2s(AdminModuleStructs.RateDataV2Params[] calldata tokensRateData_) external {}\n\n /// @inheritdoc IFluidLiquidityAdmin\n function updateTokenConfigs(AdminModuleStructs.TokenConfig[] calldata tokenConfigs_) external {}\n\n /// @inheritdoc IFluidLiquidityAdmin\n function updateUserClasses(AdminModuleStructs.AddressUint256[] calldata userClasses_) external {}\n\n /// @inheritdoc IFluidLiquidityAdmin\n function updateUserSupplyConfigs(AdminModuleStructs.UserSupplyConfig[] memory userSupplyConfigs_) external {}\n\n /// @inheritdoc IFluidLiquidityAdmin\n function updateUserBorrowConfigs(AdminModuleStructs.UserBorrowConfig[] memory userBorrowConfigs_) external {}\n\n /// @inheritdoc IFluidLiquidityAdmin\n function pauseUser(address user_, address[] calldata supplyTokens_, address[] calldata borrowTokens_) external {}\n\n /// @inheritdoc IFluidLiquidityAdmin\n function unpauseUser(address user_, address[] calldata supplyTokens_, address[] calldata borrowTokens_) external {}\n\n /// @inheritdoc IFluidLiquidityAdmin\n function collectRevenue(address[] calldata tokens_) external {}\n\n /// @inheritdoc IFluidLiquidityAdmin\n function updateExchangePrices(\n address[] calldata tokens_\n ) external returns (uint256[] memory supplyExchangePrices_, uint256[] memory borrowExchangePrices_) {}\n\n /// @inheritdoc IFluidLiquidityLogic\n function operate(\n address token_,\n int256 supplyAmount_,\n int256 borrowAmount_,\n address withdrawTo_,\n address borrowTo_,\n bytes calldata callbackData_\n ) external payable returns (uint256 memVar3_, uint256 memVar4_) {}\n}\n"
},
"contracts/liquidity/error.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\ncontract Error {\n error FluidLiquidityError(uint256 errorId_);\n}\n"
},
"contracts/liquidity/errorTypes.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nlibrary ErrorTypes {\n /***********************************|\n | Admin Module | \n |__________________________________*/\n\n /// @notice thrown when an input address is zero\n uint256 internal constant AdminModule__AddressZero = 10001;\n\n /// @notice thrown when msg.sender is not governance\n uint256 internal constant AdminModule__OnlyGovernance = 10002;\n\n /// @notice thrown when msg.sender is not auth\n uint256 internal constant AdminModule__OnlyAuths = 10003;\n\n /// @notice thrown when msg.sender is not guardian\n uint256 internal constant AdminModule__OnlyGuardians = 10004;\n\n /// @notice thrown when base withdrawal limit, base debt limit or max withdrawal limit is sent as 0\n uint256 internal constant AdminModule__LimitZero = 10005;\n\n /// @notice thrown whenever an invalid input param is given\n uint256 internal constant AdminModule__InvalidParams = 10006;\n\n /// @notice thrown if user class 1 is paused (can not be paused)\n uint256 internal constant AdminModule__UserNotPausable = 10007;\n\n /// @notice thrown if user is tried to be unpaused but is not paused in the first place\n uint256 internal constant AdminModule__UserNotPaused = 10008;\n\n /// @notice thrown if user is not defined yet: Governance didn't yet set any config for this user on a particular token\n uint256 internal constant AdminModule__UserNotDefined = 10009;\n\n /// @notice thrown if a token is configured in an invalid order: 1. Set rate config for token 2. Set token config 3. allow any user.\n uint256 internal constant AdminModule__InvalidConfigOrder = 10010;\n\n /// @notice thrown if revenue is collected when revenue collector address is not set\n uint256 internal constant AdminModule__RevenueCollectorNotSet = 10011;\n\n /// @notice all ValueOverflow errors below are thrown if a certain input param overflows the allowed storage size\n uint256 internal constant AdminModule__ValueOverflow__RATE_AT_UTIL_ZERO = 10012;\n uint256 internal constant AdminModule__ValueOverflow__RATE_AT_UTIL_KINK = 10013;\n uint256 internal constant AdminModule__ValueOverflow__RATE_AT_UTIL_MAX = 10014;\n uint256 internal constant AdminModule__ValueOverflow__RATE_AT_UTIL_KINK1 = 10015;\n uint256 internal constant AdminModule__ValueOverflow__RATE_AT_UTIL_KINK2 = 10016;\n uint256 internal constant AdminModule__ValueOverflow__RATE_AT_UTIL_MAX_V2 = 10017;\n uint256 internal constant AdminModule__ValueOverflow__FEE = 10018;\n uint256 internal constant AdminModule__ValueOverflow__THRESHOLD = 10019;\n uint256 internal constant AdminModule__ValueOverflow__EXPAND_PERCENT = 10020;\n uint256 internal constant AdminModule__ValueOverflow__EXPAND_DURATION = 10021;\n uint256 internal constant AdminModule__ValueOverflow__EXPAND_PERCENT_BORROW = 10022;\n uint256 internal constant AdminModule__ValueOverflow__EXPAND_DURATION_BORROW = 10023;\n uint256 internal constant AdminModule__ValueOverflow__EXCHANGE_PRICES = 10024;\n uint256 internal constant AdminModule__ValueOverflow__UTILIZATION = 10025;\n\n /// @notice thrown when an address is not a contract\n uint256 internal constant AdminModule__AddressNotAContract = 10026;\n\n /***********************************|\n | User Module | \n |__________________________________*/\n\n /// @notice thrown when user operations are paused for an interacted token\n uint256 internal constant UserModule__UserNotDefined = 11001;\n\n /// @notice thrown when user operations are paused for an interacted token\n uint256 internal constant UserModule__UserPaused = 11002;\n\n /// @notice thrown when user's try to withdraw below withdrawal limit\n uint256 internal constant UserModule__WithdrawalLimitReached = 11003;\n\n /// @notice thrown when user's try to borrow above borrow limit\n uint256 internal constant UserModule__BorrowLimitReached = 11004;\n\n /// @notice thrown when u
},
"contracts/liquidity/interfaces/iLiquidity.sol": {
"content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.21;\n\nimport { IProxy } from \"../../infiniteProxy/interfaces/iProxy.sol\";\nimport { Structs as AdminModuleStructs } from \"../adminModule/structs.sol\";\n\ninterface IFluidLiquidityAdmin {\n /// @notice adds/removes auths. Auths generally could be contracts which can have restricted actions defined on contract.\n /// auths can be helpful in reducing governance overhead where it's not needed.\n /// @param authsStatus_ array of structs setting allowed status for an address.\n /// status true => add auth, false => remove auth\n function updateAuths(AdminModuleStructs.AddressBool[] calldata authsStatus_) external;\n\n /// @notice adds/removes guardians. Only callable by Governance.\n /// @param guardiansStatus_ array of structs setting allowed status for an address.\n /// status true => add guardian, false => remove guardian\n function updateGuardians(AdminModuleStructs.AddressBool[] calldata guardiansStatus_) external;\n\n /// @notice changes the revenue collector address (contract that is sent revenue). Only callable by Governance.\n /// @param revenueCollector_ new revenue collector address\n function updateRevenueCollector(address revenueCollector_) external;\n\n /// @notice changes current status, e.g. for pausing or unpausing all user operations. Only callable by Auths.\n /// @param newStatus_ new status\n /// status = 2 -> pause, status = 1 -> resume.\n function changeStatus(uint256 newStatus_) external;\n\n /// @notice update tokens rate data version 1. Only callable by Auths.\n /// @param tokensRateData_ array of RateDataV1Params with rate data to set for each token\n function updateRateDataV1s(AdminModuleStructs.RateDataV1Params[] calldata tokensRateData_) external;\n\n /// @notice update tokens rate data version 2. Only callable by Auths.\n /// @param tokensRateData_ array of RateDataV2Params with rate data to set for each token\n function updateRateDataV2s(AdminModuleStructs.RateDataV2Params[] calldata tokensRateData_) external;\n\n /// @notice updates token configs: fee charge on borrowers interest & storage update utilization threshold.\n /// Only callable by Auths.\n /// @param tokenConfigs_ contains token address, fee & utilization threshold\n function updateTokenConfigs(AdminModuleStructs.TokenConfig[] calldata tokenConfigs_) external;\n\n /// @notice updates user classes: 0 is for new protocols, 1 is for established protocols.\n /// Only callable by Auths.\n /// @param userClasses_ struct array of uint256 value to assign for each user address\n function updateUserClasses(AdminModuleStructs.AddressUint256[] calldata userClasses_) external;\n\n /// @notice sets user supply configs per token basis. Eg: with interest or interest-free and automated limits.\n /// Only callable by Auths.\n /// @param userSupplyConfigs_ struct array containing user supply config, see `UserSupplyConfig` struct for more info\n function updateUserSupplyConfigs(AdminModuleStructs.UserSupplyConfig[] memory userSupplyConfigs_) external;\n\n /// @notice setting user borrow configs per token basis. Eg: with interest or interest-free and automated limits.\n /// Only callable by Auths.\n /// @param userBorrowConfigs_ struct array containing user borrow config, see `UserBorrowConfig` struct for more info\n function updateUserBorrowConfigs(AdminModuleStructs.UserBorrowConfig[] memory userBorrowConfigs_) external;\n\n /// @notice pause operations for a particular user in class 0 (class 1 users can't be paused by guardians).\n /// Only callable by Guardians.\n /// @param user_ address of user to pause operations for\n /// @param supplyTokens_ token addresses to pause withdrawals for\n /// @param borrowTokens_ token addresses to pause borrowings for\n function pauseUser(address user_, address[] calldata su
},
"contracts/liquidity/userModule/events.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\ncontract Events {\n /// @notice emitted on any `operate()` execution: deposit / supply / withdraw / borrow.\n /// includes info related to the executed operation, new total amounts (packed uint256 of BigMath numbers as in storage)\n /// and exchange prices (packed uint256 as in storage).\n /// @param user protocol that triggered this operation (e.g. via an fToken or via Vault protocol)\n /// @param token token address for which this operation was executed\n /// @param supplyAmount supply amount for the operation. if >0 then a deposit happened, if <0 then a withdrawal happened.\n /// if 0 then nothing.\n /// @param borrowAmount borrow amount for the operation. if >0 then a borrow happened, if <0 then a payback happened.\n /// if 0 then nothing.\n /// @param withdrawTo address that funds where withdrawn to (if supplyAmount <0)\n /// @param borrowTo address that funds where borrowed to (if borrowAmount >0)\n /// @param totalAmounts updated total amounts, stacked uint256 as written to storage:\n /// First 64 bits => 0- 63 => total supply with interest in raw (totalSupply = totalSupplyRaw * supplyExchangePrice); BigMath: 56 | 8\n /// Next 64 bits => 64-127 => total interest free supply in normal token amount (totalSupply = totalSupply); BigMath: 56 | 8\n /// Next 64 bits => 128-191 => total borrow with interest in raw (totalBorrow = totalBorrowRaw * borrowExchangePrice); BigMath: 56 | 8\n /// Next 64 bits => 192-255 => total interest free borrow in normal token amount (totalBorrow = totalBorrow); BigMath: 56 | 8\n /// @param exchangePricesAndConfig updated exchange prices and configs storage slot. Contains updated supply & borrow exchange price:\n /// First 16 bits => 0- 15 => borrow rate (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\n /// Next 14 bits => 16- 29 => fee on interest from borrowers to lenders (in 1e2: 100% = 10_000; 1% = 100 -> max value 16_383). configurable.\n /// Next 14 bits => 30- 43 => last stored utilization (in 1e2: 100% = 10_000; 1% = 100 -> max value 16_383)\n /// Next 14 bits => 44- 57 => update on storage threshold (in 1e2: 100% = 10_000; 1% = 100 -> max value 16_383). configurable.\n /// Next 33 bits => 58- 90 => last update timestamp (enough until 16 March 2242 -> max value 8589934591)\n /// Next 64 bits => 91-154 => supply exchange price (1e12 -> max value 18_446_744,073709551615)\n /// Next 64 bits => 155-218 => borrow exchange price (1e12 -> max value 18_446_744,073709551615)\n /// Next 1 bit => 219-219 => if 0 then ratio is supplyInterestFree / supplyWithInterest else ratio is supplyWithInterest / supplyInterestFree\n /// Next 14 bits => 220-233 => supplyRatio: supplyInterestFree / supplyWithInterest (in 1e2: 100% = 10_000; 1% = 100 -> max value 16_383)\n /// Next 1 bit => 234-234 => if 0 then ratio is borrowInterestFree / borrowWithInterest else ratio is borrowWithInterest / borrowInterestFree\n /// Next 14 bits => 235-248 => borrowRatio: borrowInterestFree / borrowWithInterest (in 1e2: 100% = 10_000; 1% = 100 -> max value 16_383)\n event LogOperate(\n address indexed user,\n address indexed token,\n int256 supplyAmount,\n int256 borrowAmount,\n address withdrawTo,\n address borrowTo,\n uint256 totalAmounts,\n uint256 exchangePricesAndConfig\n );\n}\n"
},
"contracts/liquidity/userModule/main.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IERC20 } from \"@openzeppelin/contracts/interfaces/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { FixedPointMathLib } from \"solmate/src/utils/FixedPointMathLib.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\n\nimport { BigMathMinified } from \"../../libraries/bigMathMinified.sol\";\nimport { LiquidityCalcs } from \"../../libraries/liquidityCalcs.sol\";\nimport { LiquiditySlotsLink } from \"../../libraries/liquiditySlotsLink.sol\";\nimport { CommonHelpers } from \"../common/helpers.sol\";\nimport { Events } from \"./events.sol\";\nimport { ErrorTypes } from \"../errorTypes.sol\";\nimport { Error } from \"../error.sol\";\n\ninterface IProtocol {\n function liquidityCallback(address token_, uint256 amount_, bytes calldata data_) external;\n}\n\nabstract contract CoreInternals is Error, CommonHelpers, Events {\n using BigMathMinified for uint256;\n\n /// @dev supply or withdraw for both with interest & interest free.\n /// positive `amount_` is deposit, negative `amount_` is withdraw.\n function _supplyOrWithdraw(\n address token_,\n int256 amount_,\n uint256 supplyExchangePrice_\n ) internal returns (int256 newSupplyInterestRaw_, int256 newSupplyInterestFree_) {\n uint256 userSupplyData_ = _userSupplyData[msg.sender][token_];\n\n if (userSupplyData_ == 0) {\n revert FluidLiquidityError(ErrorTypes.UserModule__UserNotDefined);\n }\n if ((userSupplyData_ >> LiquiditySlotsLink.BITS_USER_SUPPLY_IS_PAUSED) & 1 == 1) {\n revert FluidLiquidityError(ErrorTypes.UserModule__UserPaused);\n }\n\n // extract user supply amount\n uint256 userSupply_ = (userSupplyData_ >> LiquiditySlotsLink.BITS_USER_SUPPLY_AMOUNT) & X64;\n userSupply_ = (userSupply_ >> DEFAULT_EXPONENT_SIZE) << (userSupply_ & DEFAULT_EXPONENT_MASK);\n\n // calculate current, updated (expanded etc.) withdrawal limit\n uint256 newWithdrawalLimit_ = LiquidityCalcs.calcWithdrawalLimitBeforeOperate(userSupplyData_, userSupply_);\n\n // calculate updated user supply amount\n if (userSupplyData_ & 1 == 1) {\n // mode: with interest\n if (amount_ > 0) {\n // convert amount from normal to raw (divide by exchange price) -> round down for deposit\n newSupplyInterestRaw_ = (amount_ * int256(EXCHANGE_PRICES_PRECISION)) / int256(supplyExchangePrice_);\n userSupply_ = userSupply_ + uint256(newSupplyInterestRaw_);\n } else {\n // convert amount from normal to raw (divide by exchange price) -> round up for withdraw\n newSupplyInterestRaw_ = -int256(\n FixedPointMathLib.mulDivUp(uint256(-amount_), EXCHANGE_PRICES_PRECISION, supplyExchangePrice_)\n );\n // if withdrawal is more than user's supply then solidity will throw here\n userSupply_ = userSupply_ - uint256(-newSupplyInterestRaw_);\n }\n } else {\n // mode: without interest\n newSupplyInterestFree_ = amount_;\n if (newSupplyInterestFree_ > 0) {\n userSupply_ = userSupply_ + uint256(newSupplyInterestFree_);\n } else {\n // if withdrawal is more than user's supply then solidity will throw here\n userSupply_ = userSupply_ - uint256(-newSupplyInterestFree_);\n }\n }\n\n if (amount_ < 0 && userSupply_ < newWithdrawalLimit_) {\n // if withdraw, then check the user supply after withdrawal is above withdrawal limit\n revert FluidLiquidityError(ErrorTypes.UserModule__WithdrawalLimitReached);\n }\n\n // calculate withdrawal limit to store as previous withdrawal limit in storage\n newWithdrawalLimit_ = LiquidityCalcs.calcWithdrawalLimitAfterOperate(\n userSupplyDat
},
"contracts/mocks/mockProtocol.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\nimport { FluidLiquidityUserModule } from \"../liquidity/userModule/main.sol\";\nimport { IFluidLiquidity } from \"../liquidity/interfaces/iLiquidity.sol\";\n\n/// @title Mock Protocol\n/// @notice Mock protocol for testing, implements:\n/// function liquidityCallback(address token_, uint256 amount_, bytes calldata data_) external;\n/// This callback method MUST transferFrom data_ decoded from address to the liquidity contract\ncontract MockProtocol {\n using SafeERC20 for IERC20;\n\n /// @dev address that is mapped to the chain native token\n address internal constant NATIVE_TOKEN_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n address public immutable liquidityContract;\n\n /// @notice thrown when liquidity callback is called for a native token operation\n error MockProtocol__UnexpectedLiquidityCallback();\n\n bool transferInsufficientMode = false;\n bool transferExcessMode = false;\n bool reentrancyFromCallback = false;\n address transferFromAddress;\n\n /// @notice Construct a new MockProtocol\n /// @param liquidityContract_ The address of the liquidity contract\n constructor(address liquidityContract_) {\n liquidityContract = liquidityContract_;\n }\n\n receive() external payable {}\n\n function setTransferInsufficientMode(bool transferInsufficientMode_) public {\n transferInsufficientMode = transferInsufficientMode_;\n }\n\n function setTransferExcessMode(bool transferExcessMode_) public {\n transferExcessMode = transferExcessMode_;\n }\n\n function setReentrancyFromCallback(bool reentrancyFromCallback_) public {\n reentrancyFromCallback = reentrancyFromCallback_;\n }\n\n function setTransferFromAddress(address transferFromAddress_) public {\n transferFromAddress = transferFromAddress_;\n }\n\n /// @notice Mock liquidity callback\n /// @param token_ The token being transferred\n /// @param amount_ The amount being transferred\n function liquidityCallback(address token_, uint256 amount_, bytes memory data_) external {\n if (reentrancyFromCallback) {\n // call operate with some random values (should not matter as it reverts anyway)\n IFluidLiquidity(liquidityContract).operate(token_, 10, 0, address(0), address(0), abi.encode(address(this)));\n }\n\n if (token_ == NATIVE_TOKEN_ADDRESS) {\n revert MockProtocol__UnexpectedLiquidityCallback();\n }\n\n address from_;\n if (transferFromAddress == address(0)) {\n // take the last 20 bytes of data_ and decode them to address. Gives more flexibility in type of\n // data that can be passed in to Liquidity at mock calls while ensuring mock Protocol can do what it\n // is supposed to do: transfer amount of token to liquidity.\n assembly {\n from_ := mload(\n add(\n // add padding for length as present for dynamic arrays in memory\n add(data_, 32),\n // assembly expects address with leading zeros / left padded so need to use 32 as length here\n sub(mload(data_), 32)\n )\n )\n }\n } else {\n from_ = transferFromAddress;\n }\n\n if (amount_ > 0) {\n if (transferExcessMode) {\n amount_ += 1e6;\n } else if (transferInsufficientMode) {\n amount_ -= 1;\n }\n }\n\n if (from_ == address(this)) {\n // use approve and transferFrom for more consistent testing of methods called\n // (always transferFrom instead of transfer)\n IERC20(token_).safeApprove(address(th
},
"contracts/oracle/fluidOracle.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IFluidOracle } from \"./interfaces/iFluidOracle.sol\";\n\n/// @title FluidOracle\n/// @notice Base contract that any Fluid Oracle must implement\nabstract contract FluidOracle is IFluidOracle {\n /// @inheritdoc IFluidOracle\n function getExchangeRate() external view virtual returns (uint256 exchangeRate_);\n}\n"
},
"contracts/oracle/interfaces/iFluidOracle.sol": {
"content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.21;\n\ninterface IFluidOracle {\n /// @notice Get the `exchangeRate_` between the underlying asset and the peg asset in 1e27\n function getExchangeRate() external view returns (uint256 exchangeRate_);\n}\n"
},
"contracts/periphery/merkleDistributor/errors.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nabstract contract Errors {\n error Unauthorized();\n error InvalidParams();\n\n // claim related errors:\n error InvalidCycle();\n error InvalidProof();\n error NothingToClaim();\n}\n"
},
"contracts/periphery/merkleDistributor/events.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nabstract contract Events {\n /// @notice Emitted when an address is added or removed from the allowed proposers\n event LogUpdateProposer(address proposer, bool isProposer);\n\n /// @notice Emitted when a new cycle root hash is proposed\n event LogRootProposed(uint256 cycle, bytes32 root, bytes32 contentHash, uint256 timestamp, uint256 blockNumber);\n\n /// @notice Emitted when a new cycle root hash is approved by the owner and becomes the new active root\n event LogRootUpdated(uint256 cycle, bytes32 root, bytes32 contentHash, uint256 timestamp, uint256 blockNumber);\n\n /// @notice Emitted when a `user` claims `amount` via a valid merkle proof\n event LogClaimed(\n address user,\n uint256 amount,\n uint256 cycle,\n address fToken,\n uint256 timestamp,\n uint256 blockNumber\n );\n}\n"
},
"contracts/periphery/merkleDistributor/main.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { MerkleProof } from \"@openzeppelin/contracts/utils/cryptography/MerkleProof.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\n\nimport { Structs } from \"./structs.sol\";\nimport { Variables } from \"./variables.sol\";\nimport { Events } from \"./events.sol\";\nimport { Errors } from \"./errors.sol\";\n\n// ---------------------------------------------------------------------------------------------\n//\n// @dev WARNING: DO NOT USE `multiProof` related methods of `MerkleProof`.\n// This repo uses OpenZeppelin 4.8.2 which has a vulnerability for multi proofs. See:\n// https://github.com/OpenZeppelin/openzeppelin-contracts/security/advisories/GHSA-wprv-93r4-jj2p\n//\n// ---------------------------------------------------------------------------------------------\n\nabstract contract FluidMerkleDistributorCore is Structs, Variables, Events, Errors {\n /// @dev validates that an address is not the zero address\n modifier validAddress(address value_) {\n if (value_ == address(0)) {\n revert InvalidParams();\n }\n _;\n }\n}\n\nabstract contract FluidMerkleDistributorAdmin is FluidMerkleDistributorCore {\n /// @notice Updates an address status as a root proposer\n /// @param proposer_ The address to update\n /// @param isProposer_ Whether or not the address should be an allowed proposer\n function updateProposer(address proposer_, bool isProposer_) public onlyOwner validAddress(proposer_) {\n _proposers[proposer_] = isProposer_;\n emit LogUpdateProposer(proposer_, isProposer_);\n }\n\n /// @notice Approve the current pending root and content hash\n function approveRoot(\n bytes32 root_,\n bytes32 contentHash_,\n uint40 cycle_,\n uint40 startBlock_,\n uint40 endBlock_\n ) external onlyOwner {\n MerkleCycle memory merkleCycle_ = _pendingMerkleCycle;\n\n if (\n root_ != merkleCycle_.merkleRoot ||\n contentHash_ != merkleCycle_.merkleContentHash ||\n cycle_ != merkleCycle_.cycle ||\n startBlock_ != merkleCycle_.startBlock ||\n endBlock_ != merkleCycle_.endBlock\n ) {\n revert InvalidParams();\n }\n\n previousMerkleRoot = _currentMerkleCycle.merkleRoot;\n\n merkleCycle_.timestamp = uint40(block.timestamp);\n merkleCycle_.publishBlock = uint40(block.number);\n\n _currentMerkleCycle = merkleCycle_;\n\n emit LogRootUpdated(cycle_, root_, contentHash_, block.timestamp, block.number);\n }\n\n /// @dev open payload method for admin to resolve emergency cases\n function spell(address[] memory targets_, bytes[] memory calldatas_) public onlyOwner {\n for (uint256 i = 0; i < targets_.length; i++) {\n Address.functionDelegateCall(targets_[i], calldatas_[i]);\n }\n }\n\n /// @notice Pause contract functionality of new roots and claiming\n function pause() external onlyOwner {\n _pause();\n }\n\n /// @notice Unpause contract functionality of new roots and claiming\n function unpause() external onlyOwner {\n _unpause();\n }\n}\n\nabstract contract FluidMerkleDistributorProposer is FluidMerkleDistributorCore {\n /// @dev Checks that the sender is a proposer\n modifier onlyProposer() {\n if (!isProposer(msg.sender)) {\n revert Unauthorized();\n }\n _;\n }\n\n /// @notice checks if the `proposer_` is an allowed root proposer\n function isProposer(address proposer_) public view returns (bool) {\n return (_proposers[proposer_] || owner == proposer_);\n }\n\n /// @notice Propose a new root and content hash, which will be stored as pending until approved\n function proposeRoot(\n bytes32 root_,\n bytes32 contentHash_,\n uint40
},
"contracts/periphery/merkleDistributor/structs.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nabstract contract Structs {\n struct MerkleCycle {\n // slot 1\n bytes32 merkleRoot;\n // slot 2\n bytes32 merkleContentHash;\n // slot 3\n uint40 cycle;\n uint40 timestamp;\n uint40 publishBlock;\n uint40 startBlock;\n uint40 endBlock;\n }\n}\n"
},
"contracts/periphery/merkleDistributor/variables.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { Owned } from \"solmate/src/auth/Owned.sol\";\nimport { Pausable } from \"@openzeppelin/contracts/security/Pausable.sol\";\n\nimport { Structs } from \"./structs.sol\";\n\nabstract contract Constants {\n IERC20 public constant TOKEN = IERC20(0x6f40d4A6237C257fff2dB00FA0510DeEECd303eb); // INST\n}\n\nabstract contract Variables is Owned, Pausable, Constants, Structs {\n // ------------ storage variables from inherited contracts (Owned, Pausable) come before vars here --------\n\n // ----------------------- slot 0 ---------------------------\n // address public owner; -> from Owned\n\n // bool private _paused; -> from Pausable\n\n // 11 bytes empty\n\n // ----------------------- slot 1 ---------------------------\n\n /// @dev allow list for allowed root proposer addresses\n mapping(address => bool) internal _proposers;\n\n // ----------------------- slot 2-4 ---------------------------\n\n /// @dev merkle root data related to current cycle (proposed and approved).\n /// @dev timestamp & publishBlock = data from last publish.\n // with custom getter to return whole struct at once instead of default solidity getter splitting it into tuple\n MerkleCycle internal _currentMerkleCycle;\n\n // ----------------------- slot 5-7 ---------------------------\n\n /// @dev merkle root data related to pending cycle (proposed but not yet approved).\n /// @dev timestamp & publishBlock = data from last propose.\n // with custom getter to return whole struct at once instead of default solidity getter splitting it into tuple\n MerkleCycle internal _pendingMerkleCycle;\n\n // ----------------------- slot 8 ---------------------------\n\n /// @notice merkle root of the previous cycle\n bytes32 public previousMerkleRoot;\n\n // ----------------------- slot 9 ---------------------------\n\n /// @notice total claimed amount per user address\n mapping(address => uint256) public claimed;\n\n constructor(address owner_) Owned(owner_) {}\n}\n"
},
"contracts/periphery/resolvers/lending/iLendingResolver.sol": {
"content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.21;\n\nimport { IFluidLiquidity } from \"../../../liquidity/interfaces/iLiquidity.sol\";\nimport { IAllowanceTransfer } from \"../../../protocols/lending/interfaces/permit2/iAllowanceTransfer.sol\";\nimport { IFluidLendingFactory } from \"../../../protocols/lending/interfaces/iLendingFactory.sol\";\nimport { IFluidLendingRewardsRateModel } from \"../../../protocols/lending/interfaces/iLendingRewardsRateModel.sol\";\nimport { IFToken } from \"../../../protocols/lending/interfaces/iFToken.sol\";\nimport { Structs } from \"./structs.sol\";\nimport { IFluidLiquidityResolver } from \"../../../periphery/resolvers/liquidity/iLiquidityResolver.sol\";\n\ninterface IFluidLendingResolver {\n /// @notice returns the lending factory address\n function LENDING_FACTORY() external view returns (IFluidLendingFactory);\n\n /// @notice returns the liquidity resolver address\n function LIQUIDITY_RESOLVER() external view returns (IFluidLiquidityResolver);\n\n /// @notice returns all fToken types at the `LENDING_FACTORY`\n function getAllFTokenTypes() external view returns (string[] memory);\n\n /// @notice returns all created fTokens at the `LENDING_FACTORY`\n function getAllFTokens() external view returns (address[] memory);\n\n /// @notice reads if a certain `auth_` address is an allowed auth or not. Owner is auth by default.\n function isLendingFactoryAuth(address auth_) external view returns (bool);\n\n /// @notice reads if a certain `deployer_` address is an allowed deployer or not. Owner is deployer by default.\n function isLendingFactoryDeployer(address deployer_) external view returns (bool);\n\n /// @notice computes deterministic token address for `asset_` for a lending protocol\n /// @param asset_ address of the asset\n /// @param fTokenType_ type of fToken:\n /// - if underlying asset supports EIP-2612, the fToken should be type `EIP2612Deposits`\n /// - otherwise it should use `Permit2Deposits`\n /// - if it's the native token, it should use `NativeUnderlying`\n /// - could be more types available, check `fTokenTypes()`\n /// @return token_ detemrinistic address of the computed token\n function computeFToken(address asset_, string calldata fTokenType_) external view returns (address);\n\n /// @notice gets all public details for a certain `fToken_`, such as\n /// fToken type, name, symbol, decimals, underlying asset, total amounts, convertTo values, rewards.\n /// Note it also returns whether the fToken supports deposits / mints via EIP-2612, but it is not a 100% guarantee!\n /// To make sure, check for the underlying if it supports EIP-2612 manually.\n /// @param fToken_ the fToken to get the details for\n /// @return fTokenDetails_ retrieved FTokenDetails struct\n function getFTokenDetails(IFToken fToken_) external view returns (Structs.FTokenDetails memory fTokenDetails_);\n\n /// @notice returns config, rewards and exchange prices data of an fToken.\n /// @param fToken_ the fToken to get the data for\n /// @return liquidity_ address of the Liquidity contract.\n /// @return lendingFactory_ address of the Lending factory contract.\n /// @return lendingRewardsRateModel_ address of the rewards rate model contract. changeable by LendingFactory auths.\n /// @return permit2_ address of the Permit2 contract used for deposits / mint with signature\n /// @return rebalancer_ address of the rebalancer allowed to execute `rebalance()`\n /// @return rewardsActive_ true if rewards are currently active\n /// @return liquidityBalance_ current Liquidity supply balance of `address(this)` for the underyling asset\n /// @return liquidityExchangePrice_ (updated) exchange price for the underlying assset in the liquidity protocol (without rewards)\n /// @return tokenExchangePrice_ (updated) exchange price between fToken and the underlying assset (with rewards)\n function getFTokenInternalData(\n IFToken fToken_\n )\n ex
},
"contracts/periphery/resolvers/lending/main.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IERC20Permit } from \"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport { LiquidityCalcs } from \"../../../libraries/liquidityCalcs.sol\";\nimport { IFluidLendingFactory } from \"../../../protocols/lending/interfaces/iLendingFactory.sol\";\nimport { IFluidLendingRewardsRateModel } from \"../../../protocols/lending/interfaces/iLendingRewardsRateModel.sol\";\nimport { IFluidLiquidity } from \"../../../liquidity/interfaces/iLiquidity.sol\";\nimport { IAllowanceTransfer } from \"../../../protocols/lending/interfaces/permit2/iAllowanceTransfer.sol\";\nimport { IFToken, IFTokenNativeUnderlying } from \"../../../protocols/lending/interfaces/iFToken.sol\";\nimport { IFluidLiquidityResolver } from \"../../../periphery/resolvers/liquidity/iLiquidityResolver.sol\";\nimport { Structs as LiquidityStructs } from \"../../../periphery/resolvers/liquidity/structs.sol\";\nimport { IFluidLendingResolver } from \"./iLendingResolver.sol\";\nimport { Structs } from \"./structs.sol\";\n\n/// @notice Fluid Lending protocol (fTokens) resolver\n/// Implements various view-only methods to give easy access to Lending protocol data.\ncontract FluidLendingResolver is IFluidLendingResolver, Structs {\n /// @dev address that is mapped to the chain native token\n address internal constant _NATIVE_TOKEN_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @inheritdoc IFluidLendingResolver\n IFluidLendingFactory public immutable LENDING_FACTORY;\n\n /// @inheritdoc IFluidLendingResolver\n IFluidLiquidityResolver public immutable LIQUIDITY_RESOLVER;\n\n /// @notice thrown if an input param address is zero\n error FluidLendingResolver__AddressZero();\n\n /// @notice constructor sets the immutable `LENDING_FACTORY` and `LIQUIDITY_RESOLVER` address\n constructor(IFluidLendingFactory lendingFactory_, IFluidLiquidityResolver liquidityResolver_) {\n if (address(lendingFactory_) == address(0) || address(liquidityResolver_) == address(0)) {\n revert FluidLendingResolver__AddressZero();\n }\n LENDING_FACTORY = lendingFactory_;\n LIQUIDITY_RESOLVER = liquidityResolver_;\n }\n\n /// @inheritdoc IFluidLendingResolver\n function isLendingFactoryAuth(address auth_) external view returns (bool) {\n return LENDING_FACTORY.isAuth(auth_);\n }\n\n /// @inheritdoc IFluidLendingResolver\n function isLendingFactoryDeployer(address deployer_) external view returns (bool) {\n return LENDING_FACTORY.isDeployer(deployer_);\n }\n\n /// @inheritdoc IFluidLendingResolver\n function getAllFTokenTypes() public view returns (string[] memory) {\n return LENDING_FACTORY.fTokenTypes();\n }\n\n /// @inheritdoc IFluidLendingResolver\n function getAllFTokens() public view returns (address[] memory) {\n return LENDING_FACTORY.allTokens();\n }\n\n /// @inheritdoc IFluidLendingResolver\n function computeFToken(address asset_, string calldata fTokenType_) external view returns (address) {\n return LENDING_FACTORY.computeToken(asset_, fTokenType_);\n }\n\n /// @inheritdoc IFluidLendingResolver\n function getFTokenDetails(IFToken fToken_) public view returns (FTokenDetails memory fTokenDetails_) {\n address underlying_ = fToken_.asset();\n\n bool isNativeUnderlying_ = false;\n try IFTokenNativeUnderlying(address(fToken_)).NATIVE_TOKEN_ADDRESS() {\n // if NATIVE_TOKEN_ADDRESS is defined, fTokenType must be NativeUnderlying.\n isNativeUnderlying_ = true;\n } catch {}\n\n bool supportsEIP2612Deposits_ = false;\n try IERC20Permit(underlying_).DOMAIN_SEPARATOR() {\n // if DOMAIN_SEPARATOR is defined, we assume underlying supports EIP2612. Not a 100% guarantee\n supportsEIP2612Deposits_ = true;\n } catch {}\n\n (, uint256 rewardsRate_) = getFTok
},
"contracts/periphery/resolvers/lending/structs.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IFluidLendingFactory } from \"../../../protocols/lending/interfaces/iLendingFactory.sol\";\nimport { Structs as FluidLiquidityResolverStructs } from \"../liquidity/structs.sol\";\n\nabstract contract Structs {\n struct FTokenDetails {\n address tokenAddress;\n bool eip2612Deposits;\n bool isNativeUnderlying;\n string name;\n string symbol;\n uint256 decimals;\n address asset;\n uint256 totalAssets;\n uint256 totalSupply;\n uint256 convertToShares;\n uint256 convertToAssets;\n // additional yield from rewards, if active\n uint256 rewardsRate;\n // yield at Liquidity\n uint256 supplyRate;\n // difference between fToken assets & actual deposit at Liquidity. (supplyAtLiquidity - totalAssets).\n // if negative, rewards must be funded to guarantee withdrawal is possible for all users. This happens\n // by executing rebalance().\n int256 rebalanceDifference;\n // liquidity related data such as supply amount, limits, expansion etc.\n FluidLiquidityResolverStructs.UserSupplyData liquidityUserSupplyData;\n }\n\n struct UserPosition {\n uint256 fTokenShares;\n uint256 underlyingAssets;\n uint256 underlyingBalance;\n uint256 allowance;\n }\n\n struct FTokenDetailsUserPosition {\n FTokenDetails fTokenDetails;\n UserPosition userPosition;\n }\n}\n"
},
"contracts/periphery/resolvers/liquidity/iLiquidityResolver.sol": {
"content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.21;\n\nimport { Structs as LiquidityStructs } from \"../../../periphery/resolvers/liquidity/structs.sol\";\n\ninterface IFluidLiquidityResolver {\n /// @notice gets the `revenueAmount_` for a `token_`.\n function getRevenue(address token_) external view returns (uint256 revenueAmount_);\n\n /// @notice address of contract that gets sent the revenue. Configurable by governance\n function getRevenueCollector() external view returns (address);\n\n /// @notice Liquidity contract paused status: status = 1 -> normal. status = 2 -> paused.\n function getStatus() external view returns (uint256);\n\n /// @notice checks if `auth_` is an allowed auth on Liquidity.\n /// Auths can set most config values. E.g. contracts that automate certain flows like e.g. adding a new fToken.\n /// Governance can add/remove auths. Governance is auth by default.\n function isAuth(address auth_) external view returns (uint256);\n\n /// @notice checks if `guardian_` is an allowed Guardian on Liquidity.\n /// Guardians can pause lower class users.\n /// Governance can add/remove guardians. Governance is guardian by default.\n function isGuardian(address guardian_) external view returns (uint256);\n\n /// @notice gets user class for `user_`. Class defines which protocols can be paused by guardians.\n /// Currently there are 2 classes: 0 can be paused by guardians. 1 cannot be paused by guardians.\n /// New protocols are added as class 0 and will be upgraded to 1 over time.\n function getUserClass(address user_) external view returns (uint256);\n\n /// @notice gets exchangePricesAndConfig packed uint256 storage slot for `token_`.\n function getExchangePricesAndConfig(address token_) external view returns (uint256);\n\n /// @notice gets rateConfig packed uint256 storage slot for `token_`.\n function getRateConfig(address token_) external view returns (uint256);\n\n /// @notice gets totalAmounts packed uint256 storage slot for `token_`.\n function getTotalAmounts(address token_) external view returns (uint256);\n\n /// @notice gets userSupply data packed uint256 storage slot for `user_` and `token_`.\n function getUserSupply(address user_, address token_) external view returns (uint256);\n\n /// @notice gets userBorrow data packed uint256 storage slot for `user_` and `token_`.\n function getUserBorrow(address user_, address token_) external view returns (uint256);\n\n /// @notice returns all `listedTokens_` at the Liquidity contract. Once configured, a token can never be removed.\n function listedTokens() external view returns (address[] memory listedTokens_);\n\n /// @notice get the Rate config data `rateData_` for a `token_` compiled from the packed uint256 rateConfig storage slot\n function getTokenRateData(address token_) external view returns (LiquidityStructs.RateData memory rateData_);\n\n /// @notice get the Rate config datas `rateDatas_` for multiple `tokens_` compiled from the packed uint256 rateConfig storage slot\n function getTokensRateData(\n address[] calldata tokens_\n ) external view returns (LiquidityStructs.RateData[] memory rateDatas_);\n\n /// @notice returns general data for `token_` such as rates, exchange prices, utilization, fee, total amounts etc.\n function getOverallTokenData(\n address token_\n ) external view returns (LiquidityStructs.OverallTokenData memory overallTokenData_);\n\n /// @notice returns general data for multiple `tokens_` such as rates, exchange prices, utilization, fee, total amounts etc.\n function getOverallTokensData(\n address[] calldata tokens_\n ) external view returns (LiquidityStructs.OverallTokenData[] memory overallTokensData_);\n\n /// @notice returns `user_` supply data and general data (such as rates, exchange prices, utilization, fee, total amounts etc.) for `token_`\n function getUserSupplyData(\n address user_,\n address token_\n )\n external\n vie
},
"contracts/periphery/resolvers/liquidity/main.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport { LiquidityCalcs } from \"../../../libraries/liquidityCalcs.sol\";\nimport { BigMathMinified } from \"../../../libraries/bigMathMinified.sol\";\nimport { LiquiditySlotsLink } from \"../../../libraries/liquiditySlotsLink.sol\";\nimport { IFluidLiquidity } from \"../../../liquidity/interfaces/iLiquidity.sol\";\nimport { IFluidLiquidityResolver } from \"./iLiquidityResolver.sol\";\nimport { Structs } from \"./structs.sol\";\nimport { Variables } from \"./variables.sol\";\n\ninterface TokenInterface {\n function balanceOf(address) external view returns (uint);\n}\n\n/// @notice Fluid Liquidity resolver\n/// Implements various view-only methods to give easy access to Liquidity data.\ncontract FluidLiquidityResolver is IFluidLiquidityResolver, Variables, Structs {\n /// @dev address that is mapped to the chain native token\n address internal constant _NATIVE_TOKEN_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice thrown if an input param address is zero\n error FluidLiquidityResolver__AddressZero();\n\n constructor(IFluidLiquidity liquidity_) Variables(liquidity_) {\n if (address(liquidity_) == address(0)) {\n revert FluidLiquidityResolver__AddressZero();\n }\n }\n\n /// @inheritdoc IFluidLiquidityResolver\n function getRevenueCollector() public view returns (address) {\n return address(uint160(LIQUIDITY.readFromStorage(bytes32(0))));\n }\n\n /// @inheritdoc IFluidLiquidityResolver\n function getRevenue(address token_) public view returns (uint256 revenueAmount_) {\n uint256 liquidityTokenBalance_ = token_ == _NATIVE_TOKEN_ADDRESS\n ? address(LIQUIDITY).balance\n : IERC20(token_).balanceOf(address(LIQUIDITY));\n\n return\n LiquidityCalcs.calcRevenue(\n getTotalAmounts(token_),\n getExchangePricesAndConfig(token_),\n liquidityTokenBalance_\n );\n }\n\n /// @inheritdoc IFluidLiquidityResolver\n function getStatus() public view returns (uint256) {\n return LIQUIDITY.readFromStorage(bytes32(LiquiditySlotsLink.LIQUIDITY_STATUS_SLOT));\n }\n\n /// @inheritdoc IFluidLiquidityResolver\n function isAuth(address auth_) public view returns (uint256) {\n return\n LIQUIDITY.readFromStorage(\n LiquiditySlotsLink.calculateMappingStorageSlot(LiquiditySlotsLink.LIQUIDITY_AUTHS_MAPPING_SLOT, auth_)\n );\n }\n\n /// @inheritdoc IFluidLiquidityResolver\n function isGuardian(address guardian_) public view returns (uint256) {\n return\n LIQUIDITY.readFromStorage(\n LiquiditySlotsLink.calculateMappingStorageSlot(\n LiquiditySlotsLink.LIQUIDITY_GUARDIANS_MAPPING_SLOT,\n guardian_\n )\n );\n }\n\n /// @inheritdoc IFluidLiquidityResolver\n function getUserClass(address user_) public view returns (uint256) {\n return\n LIQUIDITY.readFromStorage(\n LiquiditySlotsLink.calculateMappingStorageSlot(\n LiquiditySlotsLink.LIQUIDITY_USER_CLASS_MAPPING_SLOT,\n user_\n )\n );\n }\n\n /// @inheritdoc IFluidLiquidityResolver\n function getExchangePricesAndConfig(address token_) public view returns (uint256) {\n return\n LIQUIDITY.readFromStorage(\n LiquiditySlotsLink.calculateMappingStorageSlot(\n LiquiditySlotsLink.LIQUIDITY_EXCHANGE_PRICES_MAPPING_SLOT,\n token_\n )\n );\n }\n\n /// @inheritdoc IFluidLiquidityResolver\n function getRateConfig(address token_) public view returns (uint256) {\n return\n LIQUIDITY.readFromStorage(\n LiquiditySlotsLink.calculateMappingStorageSlot(\n
},
"contracts/periphery/resolvers/liquidity/structs.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { Structs as AdminModuleStructs } from \"../../../liquidity/adminModule/structs.sol\";\n\nabstract contract Structs {\n struct RateData {\n uint256 version;\n AdminModuleStructs.RateDataV1Params rateDataV1;\n AdminModuleStructs.RateDataV2Params rateDataV2;\n }\n\n struct OverallTokenData {\n uint256 borrowRate;\n uint256 supplyRate;\n uint256 fee; // revenue fee\n uint256 lastStoredUtilization;\n uint256 storageUpdateThreshold;\n uint256 lastUpdateTimestamp;\n uint256 supplyExchangePrice;\n uint256 borrowExchangePrice;\n uint256 supplyRawInterest;\n uint256 supplyInterestFree;\n uint256 borrowRawInterest;\n uint256 borrowInterestFree;\n uint256 totalSupply;\n uint256 totalBorrow;\n uint256 revenue;\n RateData rateData;\n }\n\n // amounts are always in normal (for withInterest already multiplied with exchange price)\n struct UserSupplyData {\n bool modeWithInterest; // true if mode = with interest, false = without interest\n uint256 supply; // user supply amount\n // the withdrawal limit (e.g. if 10% is the limit, and 100M is supplied, it would be 90M)\n uint256 withdrawalLimit;\n uint256 lastUpdateTimestamp;\n uint256 expandPercent; // withdrawal limit expand percent in 1e2\n uint256 expandDuration; // withdrawal limit expand duration in seconds\n uint256 baseWithdrawalLimit;\n // the current actual max withdrawable amount (e.g. if 10% is the limit, and 100M is supplied, it would be 10M)\n uint256 withdrawableUntilLimit;\n uint256 withdrawable; // actual currently withdrawable amount (supply - withdrawal Limit) & considering balance\n }\n\n // amounts are always in normal (for withInterest already multiplied with exchange price)\n struct UserBorrowData {\n bool modeWithInterest; // true if mode = with interest, false = without interest\n uint256 borrow; // user borrow amount\n uint256 borrowLimit;\n uint256 lastUpdateTimestamp;\n uint256 expandPercent;\n uint256 expandDuration;\n uint256 baseBorrowLimit;\n uint256 maxBorrowLimit;\n uint256 borrowableUntilLimit;\n uint256 borrowable; // actual currently borrowable amount (borrow limit - already borrowed) & considering balance\n }\n}\n"
},
"contracts/periphery/resolvers/liquidity/variables.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IFluidLiquidity } from \"../../../liquidity/interfaces/iLiquidity.sol\";\n\ncontract Variables {\n /// @dev Storage slot with the admin of the contract. Logic from \"proxy.sol\".\n /// This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1, and is\n /// validated in the constructor.\n bytes32 internal constant GOVERNANCE_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n uint256 internal constant EXCHANGE_PRICES_PRECISION = 1e12;\n\n /// @dev Ignoring leap years\n uint256 internal constant SECONDS_PER_YEAR = 365 days;\n // constants used for BigMath conversion from and to storage\n uint256 internal constant SMALL_COEFFICIENT_SIZE = 10;\n uint256 internal constant DEFAULT_COEFFICIENT_SIZE = 56;\n uint256 internal constant DEFAULT_EXPONENT_SIZE = 8;\n uint256 internal constant DEFAULT_EXPONENT_MASK = 0xFF;\n\n uint256 internal constant FOUR_DECIMALS = 10000;\n uint256 internal constant X8 = 0xff;\n uint256 internal constant X14 = 0x3fff;\n uint256 internal constant X16 = 0xffff;\n uint256 internal constant X18 = 0x3ffff;\n uint256 internal constant X24 = 0xffffff;\n uint256 internal constant X33 = 0x1ffffffff;\n uint256 internal constant X64 = 0xffffffffffffffff;\n\n /// @notice address of the liquidity contract\n IFluidLiquidity public immutable LIQUIDITY;\n\n constructor(IFluidLiquidity liquidity_) {\n LIQUIDITY = IFluidLiquidity(liquidity_);\n }\n}\n"
},
"contracts/periphery/resolvers/revenue/calcRevenueSimulatedTime.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { LibsErrorTypes as ErrorTypes } from \"../../../libraries/errorTypes.sol\";\nimport { LiquiditySlotsLink } from \"../../../libraries/liquiditySlotsLink.sol\";\nimport { BigMathMinified } from \"../../../libraries/bigMathMinified.sol\";\n\n/// @dev this is the exact same code as `LiquidityCalcs` library, just that it supports a simulated\n/// block.timestamp to expose historical revenue calculations.\nlibrary CalcRevenueSimulatedTime {\n error FluidLiquidityCalcsError(uint256 errorId_);\n error FluidCalcRevenueSimulatedTimeInvalidTimestamp();\n\n /// @dev constants as from Liquidity variables.sol\n uint256 internal constant EXCHANGE_PRICES_PRECISION = 1e12;\n\n /// @dev Ignoring leap years\n uint256 internal constant SECONDS_PER_YEAR = 365 days;\n // constants used for BigMath conversion from and to storage\n uint256 internal constant DEFAULT_EXPONENT_SIZE = 8;\n uint256 internal constant DEFAULT_EXPONENT_MASK = 0xFF;\n\n uint256 internal constant FOUR_DECIMALS = 1e4;\n uint256 internal constant TWELVE_DECIMALS = 1e12;\n uint256 internal constant X14 = 0x3fff;\n uint256 internal constant X15 = 0x7fff;\n uint256 internal constant X16 = 0xffff;\n uint256 internal constant X18 = 0x3ffff;\n uint256 internal constant X24 = 0xffffff;\n uint256 internal constant X33 = 0x1ffffffff;\n uint256 internal constant X64 = 0xffffffffffffffff;\n\n ///////////////////////////////////////////////////////////////////////////\n ////////// CALC EXCHANGE PRICES /////////\n ///////////////////////////////////////////////////////////////////////////\n\n /// @dev calculates interest (exchange prices) for a token given its' exchangePricesAndConfig from storage.\n /// @param exchangePricesAndConfig_ exchange prices and config packed uint256 read from storage\n /// @param blockTimestamp_ simulated block.timestamp\n /// @return supplyExchangePrice_ updated supplyExchangePrice\n /// @return borrowExchangePrice_ updated borrowExchangePrice\n function calcExchangePrices(\n uint256 exchangePricesAndConfig_,\n uint256 blockTimestamp_\n ) internal pure returns (uint256 supplyExchangePrice_, uint256 borrowExchangePrice_) {\n // Extracting exchange prices\n supplyExchangePrice_ =\n (exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_SUPPLY_EXCHANGE_PRICE) &\n X64;\n borrowExchangePrice_ =\n (exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_BORROW_EXCHANGE_PRICE) &\n X64;\n\n if (supplyExchangePrice_ == 0 || borrowExchangePrice_ == 0) {\n revert FluidLiquidityCalcsError(ErrorTypes.LiquidityCalcs__ExchangePriceZero);\n }\n\n uint256 temp_ = exchangePricesAndConfig_ & X16; // temp_ = borrowRate\n\n // @dev HERE CUSTOM: added check for simulated timestamp\n if (\n blockTimestamp_ <\n ((exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_LAST_TIMESTAMP) & X33)\n ) {\n revert FluidCalcRevenueSimulatedTimeInvalidTimestamp();\n }\n\n unchecked {\n // last timestamp can not be > current timestamp\n uint256 secondsSinceLastUpdate_ = blockTimestamp_ -\n ((exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_LAST_TIMESTAMP) & X33);\n\n uint256 borrowRatio_ = (exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_BORROW_RATIO) &\n X15;\n if (secondsSinceLastUpdate_ == 0 || temp_ == 0 || borrowRatio_ == 1) {\n // if no time passed, borrow rate is 0, or no raw borrowings: no exchange price update needed\n // (if borrowRatio_ == 1 means there is only borrowInterestFree, as first bit is 1 and rest is 0)\n return (supplyExchangePrice_, borrowExchangePrice_);\n }\n\n // calculat
},
"contracts/periphery/resolvers/revenue/main.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport { IFluidLiquidity } from \"../../../liquidity/interfaces/iLiquidity.sol\";\nimport { LiquidityCalcs } from \"../../../libraries/liquidityCalcs.sol\";\nimport { LiquiditySlotsLink } from \"../../../libraries/liquiditySlotsLink.sol\";\nimport { CalcRevenueSimulatedTime } from \"./calcRevenueSimulatedTime.sol\";\n\n/// @notice Fluid Revenue resolver\ncontract FluidRevenueResolver {\n /// @notice address of the liquidity contract\n IFluidLiquidity public immutable LIQUIDITY;\n\n /// @dev address that is mapped to the chain native token\n address internal constant _NATIVE_TOKEN_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n struct TokenRevenue {\n address token;\n uint256 revenueAmount;\n }\n\n constructor(IFluidLiquidity liquidity_) {\n LIQUIDITY = IFluidLiquidity(liquidity_);\n }\n\n /// @notice address of contract that gets sent the revenue. Configurable by governance\n function getRevenueCollector() public view returns (address) {\n return address(uint160(LIQUIDITY.readFromStorage(bytes32(0))));\n }\n\n /// @notice gets the currently uncollected `revenueAmount_` for a `token_`.\n function getRevenue(address token_) public view returns (uint256 revenueAmount_) {\n uint256 liquidityTokenBalance_ = token_ == _NATIVE_TOKEN_ADDRESS\n ? address(LIQUIDITY).balance\n : IERC20(token_).balanceOf(address(LIQUIDITY));\n\n uint256 totalAmounts_ = LIQUIDITY.readFromStorage(\n LiquiditySlotsLink.calculateMappingStorageSlot(\n LiquiditySlotsLink.LIQUIDITY_TOTAL_AMOUNTS_MAPPING_SLOT,\n token_\n )\n );\n\n uint256 exchangePricesAndConfig_ = LIQUIDITY.readFromStorage(\n LiquiditySlotsLink.calculateMappingStorageSlot(\n LiquiditySlotsLink.LIQUIDITY_EXCHANGE_PRICES_MAPPING_SLOT,\n token_\n )\n );\n\n return LiquidityCalcs.calcRevenue(totalAmounts_, exchangePricesAndConfig_, liquidityTokenBalance_);\n }\n\n /// @notice gets the currently uncollected revenues for all listed tokens at Liquidity\n function getRevenues() public view returns (TokenRevenue[] memory tokenRevenues_) {\n uint256 length_ = LIQUIDITY.readFromStorage(bytes32(LiquiditySlotsLink.LIQUIDITY_LISTED_TOKENS_ARRAY_SLOT));\n\n tokenRevenues_ = new TokenRevenue[](length_);\n\n uint256 startingSlotForArrayElements_ = uint256(\n keccak256(abi.encode(LiquiditySlotsLink.LIQUIDITY_LISTED_TOKENS_ARRAY_SLOT))\n );\n\n for (uint256 i; i < length_; i++) {\n tokenRevenues_[i].token = address(\n uint160(LIQUIDITY.readFromStorage(bytes32(startingSlotForArrayElements_ + i)))\n );\n tokenRevenues_[i].revenueAmount = getRevenue(tokenRevenues_[i].token);\n }\n }\n\n /// @notice gets the `revenueAmount_` for a token given its' totalAmounts and exchangePricesAndConfig from stacked\n /// uint256 storage slots and the balance of the Fluid liquidity contract for the token.\n /// @dev exposed for advanced revenue calculations\n /// @param totalAmounts_ total amounts packed uint256 read from storage\n /// @param exchangePricesAndConfig_ exchange prices and config packed uint256 read from storage\n /// @param liquidityTokenBalance_ current balance of Liquidity contract (IERC20(token_).balanceOf(address(this)))\n /// @return revenueAmount_ collectable revenue amount\n function calcRevenue(\n uint256 totalAmounts_,\n uint256 exchangePricesAndConfig_,\n uint256 liquidityTokenBalance_\n ) public view returns (uint256 revenueAmount_) {\n return LiquidityCalcs.calcRevenue(totalAmounts_, exchangePricesAndConfig_, liquidityTokenBalance_);\n }\n\n /// @notice same as `calcRevenue`, but for a simulated `block.timestamp` set via `simula
},
"contracts/periphery/resolvers/stakingMerkle/main.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IFToken } from \"../../../protocols/lending/interfaces/iFToken.sol\";\nimport { IFluidLendingStakingRewards } from \"../../../protocols/lending/interfaces/iStakingRewards.sol\";\n\n/// @notice Fluid Lending protocol Merkle Staking Rewards resolver\ncontract FluidStakingMerkleResolver {\n IFToken public constant FUSDC = IFToken(0x9Fb7b4477576Fe5B32be4C1843aFB1e55F251B33);\n IFToken public constant FUSDT = IFToken(0x5C20B550819128074FD538Edf79791733ccEdd18);\n\n IFluidLendingStakingRewards public constant FUSDC_STAKING =\n IFluidLendingStakingRewards(0x2fA6c95B69c10f9F52b8990b6C03171F13C46225);\n IFluidLendingStakingRewards public constant FUSDT_STAKING =\n IFluidLendingStakingRewards(0x490681095ed277B45377d28cA15Ac41d64583048);\n\n struct UserPosition {\n address user;\n uint256 shares; // normalShares + stakeShares\n uint256 normalShares;\n uint256 stakeShares;\n }\n\n function getUsersPosition(\n address[] calldata users_,\n IFToken fToken_,\n IFluidLendingStakingRewards stakingContract_\n ) public view returns (UserPosition[] memory positions_) {\n positions_ = new UserPosition[](users_.length);\n\n for (uint256 i; i < users_.length; ++i) {\n positions_[i].user = users_[i];\n positions_[i].normalShares = fToken_.balanceOf(users_[i]);\n positions_[i].stakeShares = stakingContract_.balanceOf(users_[i]);\n positions_[i].shares = positions_[i].normalShares + positions_[i].stakeShares;\n }\n }\n\n function getUsersPositionFUSDC(address[] calldata users_) public view returns (UserPosition[] memory positions_) {\n return getUsersPosition(users_, FUSDC, FUSDC_STAKING);\n }\n\n function getUsersPositionFUSDT(address[] calldata users_) public view returns (UserPosition[] memory positions_) {\n return getUsersPosition(users_, FUSDT, FUSDT_STAKING);\n }\n}\n"
},
"contracts/periphery/resolvers/stakingRewards/main.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IERC20Permit } from \"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport { IFluidLendingResolver } from \"../lending/iLendingResolver.sol\";\nimport { Structs as FluidLendingResolverStructs } from \"../lending/structs.sol\";\nimport { IFluidLendingStakingRewards } from \"../../../protocols/lending/interfaces/iStakingRewards.sol\";\nimport { Structs } from \"./structs.sol\";\n\n\n/// @notice Fluid Lending protocol Staking Rewards (for fTokens) resolver\n/// Implements various view-only methods to give easy access to Lending protocol staked fToken rewards data.\ncontract FluidStakingRewardsResolver is Structs {\n IFluidLendingResolver immutable public LENDING_RESOLVER;\n\n /// @notice thrown if an input param address is zero\n error FluidStakingRewardsResolver__AddressZero();\n\n constructor(address lendingResolver_) {\n if(lendingResolver_ == address(0)){\n revert FluidStakingRewardsResolver__AddressZero();\n }\n LENDING_RESOLVER = IFluidLendingResolver(lendingResolver_);\n }\n\n function getFTokenStakingRewardsEntireData(address reward_) public view returns (FTokenStakingRewardsDetails memory r_) {\n // if address is 0 then data will be returned as 0\n if (reward_ != address(0)) {\n IFluidLendingStakingRewards rewardContract_ = IFluidLendingStakingRewards(reward_);\n \n r_.rewardPerToken = rewardContract_.rewardPerToken();\n r_.getRewardForDuration = rewardContract_.getRewardForDuration();\n r_.totalSupply = rewardContract_.totalSupply();\n r_.periodFinish = rewardContract_.periodFinish();\n r_.rewardRate = rewardContract_.rewardRate();\n r_.rewardsDuration = rewardContract_.rewardsDuration();\n r_.rewardsToken = address(rewardContract_.rewardsToken());\n r_.fToken = address(rewardContract_.stakingToken());\n }\n }\n\n function getFTokensStakingRewardsEntireData(address[] memory rewards_) public view returns (FTokenStakingRewardsDetails[] memory r_) {\n r_ = new FTokenStakingRewardsDetails[](rewards_.length);\n for (uint i = 0; i < rewards_.length; i++) {\n r_[i] = getFTokenStakingRewardsEntireData(rewards_[i]);\n }\n }\n\n function getUserRewardsData(\n address user_,\n address reward_,\n FluidLendingResolverStructs.FTokenDetails memory fTokenDetails_\n ) public view returns (UserRewardDetails memory u_) {\n if (reward_ != address(0)) {\n IFluidLendingStakingRewards rewardContract_ = IFluidLendingStakingRewards(reward_);\n \n u_.earned = rewardContract_.earned(user_);\n u_.fTokenShares = rewardContract_.balanceOf(user_);\n u_.underlyingAssets = (u_.fTokenShares * fTokenDetails_.convertToAssets) / (10**fTokenDetails_.decimals);\n u_.ftokenAllowance = IERC20(fTokenDetails_.tokenAddress).allowance(user_, reward_);\n }\n }\n\n function getUserAllRewardsData(\n address user_,\n address[] memory rewards_,\n FluidLendingResolverStructs.FTokenDetails[] memory fTokensDetails_\n ) public view returns (UserRewardDetails[] memory u_) {\n u_ = new UserRewardDetails[](rewards_.length);\n for (uint i = 0; i < rewards_.length; i++) {\n u_[i] = getUserRewardsData(user_, rewards_[i], fTokensDetails_[i]);\n }\n }\n\n struct underlyingTokenToRewardsMap {\n address underlyingToken;\n address rewardContract;\n }\n\n function getUserPositions(\n address user_,\n underlyingTokenToRewardsMap[] memory rewardsMap_\n ) public view returns (UserFTokenRewardsEntireData[] memory u_) {\n FluidLendingResolverStructs.FTokenDetailsUserPosition[] memory e_ = LENDING_RESOLVER.getUserPositions(user_);\n uint length_ = e
},
"contracts/periphery/resolvers/stakingRewards/structs.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { Structs as FluidLendingResolverStructs } from \"../lending/structs.sol\";\n\nabstract contract Structs {\n struct FTokenStakingRewardsDetails {\n uint rewardPerToken; // how much rewards have distributed per token since start\n uint getRewardForDuration; // total rewards being distributed\n uint totalSupply; // total fToken deposited\n uint periodFinish; // when rewards will get over\n uint rewardRate; // total rewards / duration\n uint rewardsDuration; // how long rewards are for since start to end\n address rewardsToken; // which token are we distributing as rewards\n address fToken; // which token are we distributing as rewards\n }\n\n struct UserRewardDetails {\n uint earned;\n uint fTokenShares; // user fToken balance deposited\n uint underlyingAssets; // user fToken balance converted into underlying token\n uint ftokenAllowance; // allowance of fToken to rewards contract\n }\n\n struct UserFTokenRewardsEntireData {\n FluidLendingResolverStructs.FTokenDetails fTokenDetails;\n FluidLendingResolverStructs.UserPosition userPosition;\n FTokenStakingRewardsDetails fTokenRewardsDetails;\n UserRewardDetails userRewardsDetails;\n }\n}\n"
},
"contracts/periphery/resolvers/steth/iStETHResolver.sol": {
"content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.21;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport { IFluidLiquidityResolver } from \"../liquidity/iLiquidityResolver.sol\";\nimport { IFluidStETHQueue } from \"../../../protocols/steth/interfaces/iStETHQueue.sol\";\nimport { ILidoWithdrawalQueue } from \"../../../protocols/steth/interfaces/external/iLidoWithdrawalQueue.sol\";\nimport { IFluidLiquidity } from \"../../../liquidity/interfaces/iLiquidity.sol\";\nimport { Structs as StETHQueueStructs } from \"../../../protocols/steth/structs.sol\";\nimport { Structs as LiquidityStructs } from \"../liquidity/structs.sol\";\n\ninterface IFluidStETHResolver {\n /// @notice address of the stETHQueue contract\n function STETH_QUEUE() external view returns (IFluidStETHQueue);\n\n /// @notice address of the Lido Withdrawal Queue contract (0x889edC2eDab5f40e902b864aD4d7AdE8E412F9B1)\n function LIDO_WITHDRAWAL_QUEUE() external view returns (ILidoWithdrawalQueue);\n\n /// @notice address of the LiquidityResolver\n function LIQUIDITY_RESOLVER() external view returns (IFluidLiquidityResolver);\n\n /// @notice returns all constants and config values\n function config()\n external\n view\n returns (\n IFluidLiquidity liquidity_,\n ILidoWithdrawalQueue lidoWithdrawalQueue_,\n IERC20 stETH_,\n address owner_,\n uint16 maxLTV_,\n bool allowListActive_,\n bool isPaused_,\n LiquidityStructs.UserBorrowData memory userBorrowData_,\n LiquidityStructs.OverallTokenData memory overallTokenData_\n );\n\n /// @notice checks if a linked claim for `claimTo_` and `claimTo_` is ready to be processed at Lido Withdrawal Queue\n /// @param claimTo_ claimTo receiver to process the claim for\n /// @param requestIdFrom_ Lido requestId from (start), as emitted at time of queuing via `LogQueue`\n function isClaimable(address claimTo_, uint256 requestIdFrom_) external view returns (bool);\n\n /// @notice reads if a certain `auth_` address is an allowed auth or not\n function isAuth(address auth_) external view returns (bool);\n\n /// @notice reads if a certain `guardian_` address is an allowed guardian or not\n function isGuardian(address guardian_) external view returns (bool);\n\n /// @notice reads if a certain `user_` address is an allowed user or not\n function isUserAllowed(address user_) external view returns (bool);\n\n /// @notice reads if the protocol is paused or not\n function isPaused() external view returns (bool);\n\n /// @notice reads a Claim struct containing necessary information for executing the claim process from the mapping\n /// claimTo and requestIdFrom -> claims and the claimable status.\n function claim(\n address claimTo_,\n uint256 requestIdFrom_\n ) external view returns (StETHQueueStructs.Claim memory claim_, bool isClaimable_);\n\n /// @notice returns borrow data and general data (such as rates, exchange prices, utilization, fee, total amounts etc.) for native token\n function getUserBorrowData()\n external\n view\n returns (\n LiquidityStructs.UserBorrowData memory userBorrowData_,\n LiquidityStructs.OverallTokenData memory overallTokenData_\n );\n}\n"
},
"contracts/periphery/resolvers/steth/main.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport { IFluidLiquidityResolver } from \"../liquidity/iLiquidityResolver.sol\";\nimport { IFluidStETHResolver } from \"./iStETHResolver.sol\";\nimport { IFluidStETHQueue } from \"../../../protocols/steth/interfaces/iStETHQueue.sol\";\nimport { Structs as StETHQueueStructs } from \"../../../protocols/steth/structs.sol\";\nimport { ILidoWithdrawalQueue } from \"../../../protocols/steth/interfaces/external/iLidoWithdrawalQueue.sol\";\nimport { IFluidLiquidity } from \"../../../liquidity/interfaces/iLiquidity.sol\";\nimport { Structs as LiquidityStructs } from \"../liquidity/structs.sol\";\n\n/// @notice Fluid StETH protocol resolver\n/// Implements various view-only methods to give easy access to StETH protocol data.\ncontract FluidStETHResolver is IFluidStETHResolver {\n /// @inheritdoc IFluidStETHResolver\n IFluidStETHQueue public immutable STETH_QUEUE;\n\n /// @inheritdoc IFluidStETHResolver\n ILidoWithdrawalQueue public immutable LIDO_WITHDRAWAL_QUEUE;\n\n /// @inheritdoc IFluidStETHResolver\n IFluidLiquidityResolver public immutable LIQUIDITY_RESOLVER;\n\n /// @dev address that is mapped to the chain native token at Liquidity\n address internal constant NATIVE_TOKEN_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice thrown if an input param address is zero\n error FluidStETHResolver__AddressZero();\n /// @notice thrown if there is no Claim queued for the given input data\n error FluidStETHResolver__NoClaimQueued();\n\n constructor(IFluidStETHQueue stEthQueue_, IFluidLiquidityResolver liquidityResolver_, ILidoWithdrawalQueue lidoWithdrawalQueue_) {\n if (address(stEthQueue_) == address(0) || address(liquidityResolver_) == address(0) || address(lidoWithdrawalQueue_) == address(0)) {\n revert FluidStETHResolver__AddressZero();\n }\n\n STETH_QUEUE = stEthQueue_;\n LIQUIDITY_RESOLVER = liquidityResolver_;\n LIDO_WITHDRAWAL_QUEUE = lidoWithdrawalQueue_;\n }\n\n /// @inheritdoc IFluidStETHResolver\n function isClaimable(address claimTo_, uint256 requestIdFrom_) public view returns (bool) {\n StETHQueueStructs.Claim memory claim_ = STETH_QUEUE.claims(claimTo_, requestIdFrom_);\n\n if (claim_.checkpoint == 0) {\n revert FluidStETHResolver__NoClaimQueued();\n }\n\n uint256 requestsLength_ = claim_.requestIdTo - requestIdFrom_ + 1;\n uint256[] memory requestIds_;\n if (requestsLength_ == 1) {\n // only one request id\n requestIds_ = new uint256[](1);\n requestIds_[0] = requestIdFrom_;\n return LIDO_WITHDRAWAL_QUEUE.getWithdrawalStatus(requestIds_)[0].isFinalized;\n }\n\n // build requestIds array from `requestIdFrom` to `requestIdTo`\n uint256 curRequest_ = requestIdFrom_;\n for (uint256 i; i < requestsLength_; ) {\n requestIds_[i] = curRequest_;\n\n unchecked {\n ++i;\n ++curRequest_;\n }\n }\n\n // get requests statuses\n ILidoWithdrawalQueue.WithdrawalRequestStatus[] memory statuses_ = LIDO_WITHDRAWAL_QUEUE.getWithdrawalStatus(\n requestIds_\n );\n\n // check for each status that it is finalized\n for (uint256 i; i < requestsLength_; ) {\n if (!statuses_[i].isFinalized) {\n return false;\n }\n\n unchecked {\n ++i;\n }\n }\n\n return true;\n }\n\n /// @inheritdoc IFluidStETHResolver\n function config()\n public\n view\n returns (\n IFluidLiquidity liquidity_,\n ILidoWithdrawalQueue lidoWithdrawalQueue_,\n IERC20 stETH_,\n address owner_,\n uint16 maxLTV_,\n bool allowListActive_,\n bool isPaused_,\n LiquidityStructs.Us
},
"contracts/periphery/resolvers/vault/helpers.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { Variables } from \"./variables.sol\";\nimport { Structs } from \"./structs.sol\";\n\ncontract Helpers is Variables, Structs {\n function normalSlot(uint256 slot_) public pure returns (bytes32) {\n return bytes32(slot_);\n }\n\n /// @notice Calculating the slot ID for Liquidity contract for single mapping\n function calculateStorageSlotUintMapping(uint256 slot_, uint key_) public pure returns (bytes32) {\n return keccak256(abi.encode(key_, slot_));\n }\n\n /// @notice Calculating the slot ID for Liquidity contract for single mapping\n function calculateStorageSlotIntMapping(uint256 slot_, int key_) public pure returns (bytes32) {\n return keccak256(abi.encode(key_, slot_));\n }\n\n /// @notice Calculating the slot ID for Liquidity contract for double mapping\n function calculateDoubleIntUintMapping(uint256 slot_, int key1_, uint key2_) public pure returns (bytes32) {\n bytes32 intermediateSlot_ = keccak256(abi.encode(key1_, slot_));\n return keccak256(abi.encode(key2_, intermediateSlot_));\n }\n\n function tickHelper(uint tickRaw_) public pure returns (int tick) {\n require(tickRaw_ < X20, \"invalid-number\");\n if (tickRaw_ > 0) {\n tick = tickRaw_ & 1 == 1 ? int((tickRaw_ >> 1) & X19) : -int((tickRaw_ >> 1) & X19);\n } else {\n tick = type(int).min;\n }\n }\n\n constructor(\n address factory_,\n address liquidity_,\n address liquidityResolver_\n ) Variables(factory_, liquidity_, liquidityResolver_) {}\n}\n"
},
"contracts/periphery/resolvers/vault/iVaultResolver.sol": {
"content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.21;\n\nimport { Structs } from \"./structs.sol\";\n\ninterface IFluidVaultResolver {\n function vaultByNftId(uint nftId_) external view returns (address vault_);\n\n function positionByNftId(\n uint nftId_\n ) external view returns (Structs.UserPosition memory userPosition_, Structs.VaultEntireData memory vaultData_);\n\n function getVaultVariablesRaw(address vault_) external view returns (uint);\n\n function getAllVaultsAddresses() external view returns (address[] memory vaults_);\n\n function getVaultLiquidation(\n address vault_,\n uint tokenInAmt_\n ) external returns (Structs.LiquidationStruct memory liquidationData_);\n\n function getVaultEntireData(address vault_) external view returns (Structs.VaultEntireData memory vaultData_);\n}\n"
},
"contracts/periphery/resolvers/vault/main.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { Helpers } from \"./helpers.sol\";\nimport { TickMath } from \"../../../libraries/tickMath.sol\";\nimport { BigMathMinified } from \"../../../libraries/bigMathMinified.sol\";\nimport { IFluidOracle } from \"../../../oracle/fluidOracle.sol\";\nimport { IFluidVaultT1 } from \"../../../protocols/vault/interfaces/iVaultT1.sol\";\nimport { Structs as LiquidityStructs } from \"../liquidity/structs.sol\";\nimport { LiquiditySlotsLink } from \"../../../libraries/liquiditySlotsLink.sol\";\nimport { LiquidityCalcs } from \"../../../libraries/liquidityCalcs.sol\";\n\ninterface TokenInterface {\n function balanceOf(address) external view returns (uint);\n}\n\n/// @notice Fluid Vault protocol resolver\n/// Implements various view-only methods to give easy access to Vault protocol data.\ncontract FluidVaultResolver is Helpers {\n function getVaultAddress(uint256 vaultId_) public view returns (address vault_) {\n // @dev based on https://ethereum.stackexchange.com/a/61413\n bytes memory data;\n if (vaultId_ == 0x00) {\n // nonce of smart contract always starts with 1. so, with nonce 0 there won't be any deployment\n return address(0);\n } else if (vaultId_ <= 0x7f) {\n data = abi.encodePacked(bytes1(0xd6), bytes1(0x94), address(FACTORY), uint8(vaultId_));\n } else if (vaultId_ <= 0xff) {\n data = abi.encodePacked(bytes1(0xd7), bytes1(0x94), address(FACTORY), bytes1(0x81), uint8(vaultId_));\n } else if (vaultId_ <= 0xffff) {\n data = abi.encodePacked(bytes1(0xd8), bytes1(0x94), address(FACTORY), bytes1(0x82), uint16(vaultId_));\n } else if (vaultId_ <= 0xffffff) {\n data = abi.encodePacked(bytes1(0xd9), bytes1(0x94), address(FACTORY), bytes1(0x83), uint24(vaultId_));\n } else {\n data = abi.encodePacked(bytes1(0xda), bytes1(0x94), address(FACTORY), bytes1(0x84), uint32(vaultId_));\n }\n\n return address(uint160(uint256(keccak256(data))));\n }\n\n function getVaultId(address vault_) public view returns (uint id_) {\n id_ = IFluidVaultT1(vault_).VAULT_ID();\n }\n\n function getTokenConfig(uint nftId_) public view returns (uint) {\n return FACTORY.readFromStorage(calculateStorageSlotUintMapping(3, nftId_));\n }\n\n function getVaultVariablesRaw(address vault_) public view returns (uint) {\n return IFluidVaultT1(vault_).readFromStorage(normalSlot(0));\n }\n\n function getVaultVariables2Raw(address vault_) public view returns (uint) {\n return IFluidVaultT1(vault_).readFromStorage(normalSlot(1));\n }\n\n function getAbsorbedLiquidityRaw(address vault_) public view returns (uint) {\n return IFluidVaultT1(vault_).readFromStorage(normalSlot(2));\n }\n\n function getPositionDataRaw(address vault_, uint positionId_) public view returns (uint) {\n return IFluidVaultT1(vault_).readFromStorage(calculateStorageSlotUintMapping(3, positionId_));\n }\n\n // if tick > 0 then key_ = tick / 256\n // if tick < 0 then key_ = (tick / 256) - 1\n function getTickHasDebtRaw(address vault_, int key_) public view returns (uint) {\n return IFluidVaultT1(vault_).readFromStorage(calculateStorageSlotIntMapping(4, key_));\n }\n\n function getTickDataRaw(address vault_, int tick_) public view returns (uint) {\n return IFluidVaultT1(vault_).readFromStorage(calculateStorageSlotIntMapping(5, tick_));\n }\n\n // TODO: Verify below\n // id_ = (realId_ / 3) + 1\n function getTickIdDataRaw(address vault_, int tick_, uint id_) public view returns (uint) {\n return IFluidVaultT1(vault_).readFromStorage(calculateDoubleIntUintMapping(6, tick_, id_));\n }\n\n function getBranchDataRaw(address vault_, uint branch_) public view returns (uint) {\n return IFluidVaultT1(vault_).readFromStorage(calculateStorageSlotUintMapping(7, branch_));\n }\n\n function getRateRaw(address vault_) public view returns
},
"contracts/periphery/resolvers/vault/structs.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IFluidVaultT1 } from \"../../../protocols/vault/interfaces/iVaultT1.sol\";\nimport { Structs as FluidLiquidityResolverStructs } from \"../liquidity/structs.sol\";\n\ncontract Structs {\n struct Configs {\n uint16 supplyRateMagnifier;\n uint16 borrowRateMagnifier;\n uint16 collateralFactor;\n uint16 liquidationThreshold;\n uint16 liquidationMaxLimit;\n uint16 withdrawalGap;\n uint16 liquidationPenalty;\n uint16 borrowFee;\n address oracle;\n uint oraclePrice;\n address rebalancer;\n }\n\n struct ExchangePricesAndRates {\n uint lastStoredLiquiditySupplyExchangePrice;\n uint lastStoredLiquidityBorrowExchangePrice;\n uint lastStoredVaultSupplyExchangePrice;\n uint lastStoredVaultBorrowExchangePrice;\n uint liquiditySupplyExchangePrice;\n uint liquidityBorrowExchangePrice;\n uint vaultSupplyExchangePrice;\n uint vaultBorrowExchangePrice;\n uint supplyRateVault;\n uint borrowRateVault;\n uint supplyRateLiquidity;\n uint borrowRateLiquidity;\n uint rewardsRate; // rewards rate in percent 1e2 precision (1% = 100, 100% = 10000)\n }\n\n struct TotalSupplyAndBorrow {\n uint totalSupplyVault;\n uint totalBorrowVault;\n uint totalSupplyLiquidity;\n uint totalBorrowLiquidity;\n uint absorbedSupply;\n uint absorbedBorrow;\n }\n\n struct LimitsAndAvailability {\n uint withdrawLimit;\n uint withdrawableUntilLimit;\n uint withdrawable;\n uint borrowLimit;\n uint borrowableUntilLimit;\n uint borrowable;\n uint minimumBorrowing;\n }\n\n struct CurrentBranchState {\n uint status; // if 0 then not liquidated, if 1 then liquidated, if 2 then merged, if 3 then closed\n int minimaTick;\n uint debtFactor;\n uint partials;\n uint debtLiquidity;\n uint baseBranchId;\n int baseBranchMinima;\n }\n\n struct VaultState {\n uint totalPositions;\n int topTick;\n uint currentBranch;\n uint totalBranch;\n uint totalBorrow;\n uint totalSupply;\n CurrentBranchState currentBranchState;\n }\n\n struct VaultEntireData {\n address vault;\n IFluidVaultT1.ConstantViews constantVariables;\n Configs configs;\n ExchangePricesAndRates exchangePricesAndRates;\n TotalSupplyAndBorrow totalSupplyAndBorrow;\n LimitsAndAvailability limitsAndAvailability;\n VaultState vaultState;\n // liquidity related data such as supply amount, limits, expansion etc.\n FluidLiquidityResolverStructs.UserSupplyData liquidityUserSupplyData;\n // liquidity related data such as borrow amount, limits, expansion etc.\n FluidLiquidityResolverStructs.UserBorrowData liquidityUserBorrowData;\n }\n\n struct UserPosition {\n uint nftId;\n address owner;\n bool isLiquidated;\n bool isSupplyPosition; // if true that means borrowing is 0\n int tick;\n uint tickId;\n uint beforeSupply;\n uint beforeBorrow;\n uint beforeDustBorrow;\n uint supply;\n uint borrow;\n uint dustBorrow;\n }\n\n /// @dev liquidation related data\n /// @param vault address of vault\n /// @param tokenIn_ address of token in\n /// @param tokenOut_ address of token out\n /// @param tokenInAmtOne_ (without absorb liquidity) minimum of available liquidation & tokenInAmt_\n /// @param tokenOutAmtOne_ (without absorb liquidity) expected token out, collateral to withdraw\n /// @param tokenInAmtTwo_ (absorb liquidity included) minimum of available liquidation & tokenInAmt_. In most cases it'll be same as tokenInAmtOne_ but sometimes can be bigger.\n /// @param tokenOutAmtTwo_ (absorb liquidity included) expected token out, collateral to withdraw. In most cases it'll be sa
},
"contracts/periphery/resolvers/vault/variables.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IFluidLiquidityResolver } from \"../liquidity/iLiquidityResolver.sol\";\nimport { IFluidVaultFactory } from \"../../../protocols/vault/interfaces/iVaultFactory.sol\";\n\ninterface IFluidLiquidity {\n function readFromStorage(bytes32 slot_) external view returns (uint256 result_);\n}\n\ncontract Variables {\n IFluidVaultFactory public immutable FACTORY;\n IFluidLiquidity public immutable LIQUIDITY;\n IFluidLiquidityResolver public immutable LIQUIDITY_RESOLVER;\n\n // 30 bits (used for partials mainly)\n uint internal constant X8 = 0xff;\n uint internal constant X10 = 0x3ff;\n uint internal constant X14 = 0x3fff;\n uint internal constant X15 = 0x7fff;\n uint internal constant X16 = 0xffff;\n uint internal constant X19 = 0x7ffff;\n uint internal constant X20 = 0xfffff;\n uint internal constant X24 = 0xffffff;\n uint internal constant X25 = 0x1ffffff;\n uint internal constant X30 = 0x3fffffff;\n uint internal constant X32 = 0xffffffff;\n uint internal constant X35 = 0x7ffffffff;\n uint internal constant X40 = 0xffffffffff;\n uint internal constant X50 = 0x3ffffffffffff;\n uint internal constant X64 = 0xffffffffffffffff;\n uint internal constant X96 = 0xffffffffffffffffffffffff;\n uint internal constant X128 = 0xffffffffffffffffffffffffffffffff;\n /// @dev address that is mapped to the chain native token\n address internal constant NATIVE_TOKEN_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n constructor(address factory_, address liquidity_, address liquidityResolver_) {\n FACTORY = IFluidVaultFactory(factory_);\n LIQUIDITY = IFluidLiquidity(liquidity_);\n LIQUIDITY_RESOLVER = IFluidLiquidityResolver(liquidityResolver_);\n }\n}\n"
},
"contracts/periphery/resolvers/vaultLiquidation/main.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { Variables } from \"./variables.sol\";\nimport { Structs } from \"./structs.sol\";\nimport { Structs as VaultResolverStructs } from \"../vault/structs.sol\";\nimport { IFluidVaultResolver } from \"../vault/iVaultResolver.sol\";\nimport { IFluidVaultT1 } from \"../../../protocols/vault/interfaces/iVaultT1.sol\";\n\n/// @notice Resolver contract that helps in finding available token swaps through Fluid Vault liquidations.\ncontract FluidVaultLiquidationResolver is Variables, Structs {\n /// @notice thrown if an input param address is zero\n error FluidVaultLiquidationsResolver__AddressZero();\n /// @notice thrown if an invalid param is given to a method\n error FluidVaultLiquidationsResolver__InvalidParams();\n\n /// @notice constructor sets the immutable vault resolver address\n constructor(IFluidVaultResolver vaultResolver_) Variables(vaultResolver_) {\n if (address(vaultResolver_) == address(0)) {\n revert FluidVaultLiquidationsResolver__AddressZero();\n }\n }\n\n /// @notice returns all token swap pairs available through Fluid Vault Liquidations\n function getAllSwapPairs() public view returns (VaultData[] memory vaultDatas_) {\n address[] memory vaultAddresses_ = VAULT_RESOLVER.getAllVaultsAddresses();\n vaultDatas_ = new VaultData[](vaultAddresses_.length);\n\n IFluidVaultT1.ConstantViews memory constants_;\n for (uint256 i; i < vaultAddresses_.length; ++i) {\n constants_ = IFluidVaultT1(vaultAddresses_[i]).constantsView();\n vaultDatas_[i] = VaultData({\n vault: vaultAddresses_[i],\n tokenIn: constants_.borrowToken,\n tokenOut: constants_.supplyToken\n });\n }\n }\n\n /// @notice returns the vault address for a certain `tokenIn_` swapped to a `tokenOut_`.\n /// returns zero address if no vault is available for a given pair.\n /// @dev for native token, send 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE.\n function getVaultForSwap(address tokenIn_, address tokenOut_) public view returns (address vault_) {\n address[] memory vaults_ = VAULT_RESOLVER.getAllVaultsAddresses();\n\n IFluidVaultT1.ConstantViews memory constants_;\n for (uint256 i; i < vaults_.length; ++i) {\n constants_ = IFluidVaultT1(vaults_[i]).constantsView();\n\n if (constants_.borrowToken == tokenIn_ && constants_.supplyToken == tokenOut_) {\n return vaults_[i];\n }\n }\n }\n\n /// @notice returns all available token pair swaps for any `tokensIn_` to any `tokensOut_` with the vault address.\n /// @dev for native token, send 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE.\n function getVaultsForSwap(\n address[] calldata tokensIn_,\n address[] calldata tokensOut_\n ) public view returns (VaultData[] memory vaultDatas_) {\n uint256 maxCombinations_ = tokensIn_.length * tokensOut_.length;\n\n VaultData[] memory allVaults_ = new VaultData[](maxCombinations_);\n\n address[] memory vaultAddresses_ = VAULT_RESOLVER.getAllVaultsAddresses();\n\n uint256 matches_;\n uint256 index_;\n\n IFluidVaultT1.ConstantViews memory constants_;\n for (uint256 vi; vi < vaultAddresses_.length; ++vi) {\n constants_ = IFluidVaultT1(vaultAddresses_[vi]).constantsView();\n\n index_ = 0;\n // for each vault, iterate over all possible input params token combinations\n for (uint256 i; i < tokensIn_.length; ++i) {\n for (uint256 j; j < tokensOut_.length; ++j) {\n if (constants_.borrowToken == tokensIn_[i] && constants_.supplyToken == tokensOut_[j]) {\n allVaults_[index_] = VaultData({\n vault: vaultAddresses_[vi],\n tokenIn: tokensIn_[i],\n tokenOut: tokensOut_[j]\n
},
"contracts/periphery/resolvers/vaultLiquidation/structs.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\ncontract Structs {\n struct VaultData{\n ///\n /// @param vault vault address at which the token pair is available\n address vault;\n ///\n /// @param tokenIn input token, borrow token at the vault\n address tokenIn;\n ///\n /// @param tokenOut output token, collateral token at the vault\n address tokenOut;\n }\n\n struct SwapData {\n ///\n /// @param vault vault address at which the token pair is available\n address vault;\n ///\n /// @param inAmt total input token available amount (without absorb)\n uint256 inAmt;\n ///\n /// @param outAmt total output token amount received for `inAmt` (without absorb)\n uint256 outAmt;\n ///\n /// @param inAmtWithAbsorb total input token available amount (with absorb)\n uint256 inAmtWithAbsorb;\n ///\n /// @param outAmtWithAbsorb total output token amount received for `inAmtWithAbsorb` (with absorb)\n uint256 outAmtWithAbsorb;\n }\n}\n"
},
"contracts/periphery/resolvers/vaultLiquidation/variables.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IFluidVaultResolver } from \"../vault/iVaultResolver.sol\";\n\ncontract Variables {\n IFluidVaultResolver public immutable VAULT_RESOLVER;\n\n constructor(IFluidVaultResolver vaultResolver_) {\n VAULT_RESOLVER = vaultResolver_;\n }\n}\n"
},
"contracts/periphery/resolvers/vaultPositions/main.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { Variables } from \"./variables.sol\";\nimport { Structs } from \"./structs.sol\";\nimport { IFluidVaultFactory } from \"../../../protocols/vault/interfaces/iVaultFactory.sol\";\nimport { Structs as VaultResolverStructs } from \"../vault/structs.sol\";\nimport { IFluidVaultResolver } from \"../vault/iVaultResolver.sol\";\n\ncontract FluidVaultPositionsResolver is Variables, Structs {\n /// @notice thrown if an input param address is zero\n error FluidVaultPositionsResolver__AddressZero();\n\n /// @notice constructor sets the immutable vault resolver and vault factory address\n constructor(\n IFluidVaultResolver vaultResolver_,\n IFluidVaultFactory vaultFactory_\n ) Variables(vaultResolver_, vaultFactory_) {\n if (address(vaultResolver_) == address(0) || address(vaultFactory_) == address(0)) {\n revert FluidVaultPositionsResolver__AddressZero();\n }\n }\n\n function getAllVaultNftIds(address vault_) public view returns (uint256[] memory nftIds_) {\n uint256 totalPositions_ = FACTORY.totalSupply();\n\n /// get total positions for vault: Next 32 bits => 210-241 => Total positions\n uint256 totalVaultPositions_ = (VAULT_RESOLVER.getVaultVariablesRaw(vault_) >> 210) & 0xFFFFFFFF;\n nftIds_ = new uint256[](totalVaultPositions_);\n\n // get nft Ids belonging to the vault_\n uint256 nftId_;\n uint256 j;\n for (uint256 i; i < totalPositions_; ++i) {\n nftId_ = FACTORY.tokenByIndex(i);\n if (VAULT_RESOLVER.vaultByNftId(nftId_) != vault_) {\n continue;\n }\n nftIds_[j] = nftId_;\n ++j;\n }\n }\n\n function getPositionsForNftIds(uint256[] memory nftIds_) public view returns (UserPosition[] memory positions_) {\n positions_ = new UserPosition[](nftIds_.length);\n\n VaultResolverStructs.UserPosition memory userPosition_;\n for (uint256 i; i < nftIds_.length; ++i) {\n (userPosition_, ) = VAULT_RESOLVER.positionByNftId(nftIds_[i]);\n\n positions_[i].nftId = nftIds_[i];\n positions_[i].owner = userPosition_.owner;\n positions_[i].supply = userPosition_.supply;\n positions_[i].borrow = userPosition_.borrow;\n }\n }\n\n function getAllVaultPositions(address vault_) public view returns (UserPosition[] memory positions_) {\n return getPositionsForNftIds(getAllVaultNftIds(vault_));\n }\n}\n"
},
"contracts/periphery/resolvers/vaultPositions/structs.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\ncontract Structs {\n struct UserPosition {\n uint nftId;\n address owner;\n uint supply;\n uint borrow;\n }\n}\n"
},
"contracts/periphery/resolvers/vaultPositions/variables.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IFluidVaultResolver } from \"../vault/iVaultResolver.sol\";\nimport { IFluidVaultFactory } from \"../../../protocols/vault/interfaces/iVaultFactory.sol\";\n\ncontract Variables {\n IFluidVaultResolver public immutable VAULT_RESOLVER;\n IFluidVaultFactory public immutable FACTORY;\n\n constructor(IFluidVaultResolver vaultResolver_, IFluidVaultFactory vaultFactory_) {\n VAULT_RESOLVER = vaultResolver_;\n FACTORY = vaultFactory_;\n }\n}\n"
},
"contracts/protocols/flashloan/error.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nabstract contract Error {\n error FluidFlashLenderError(uint256 errorId_);\n}\n"
},
"contracts/protocols/flashloan/errorTypes.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nlibrary ErrorTypes {\n /***********************************|\n | FlashLender | \n |__________________________________*/\n\n /// @notice Thrown when a function encounters or is provided with an address set to the zero address.\n uint256 internal constant FlashLender__ZeroAddress = 80001;\n\n /// @notice Thrown when the requested flash loan amount exceeds the allowed maximum.\n uint256 internal constant FlashLender__MaxFlashLoanAmountExceeded = 80002;\n\n /// @notice Thrown when a function returns an unexpected value.\n uint256 internal constant FlashLender__InvalidReturnValue = 80003;\n\n /// @notice Thrown when an unauthorized action is attempted.\n uint256 internal constant FlashLender__Unauthorized = 80004;\n\n /// @notice Thrown when an operation involves a token that isn't supported.\n uint256 internal constant FlashLender__TokenNotSupported = 80005;\n\n /// @notice Thrown when a token is already being borrowed by flashloan protocol.\n uint256 internal constant FlashLender__DuplicateBorrow = 80006;\n}\n"
},
"contracts/protocols/flashloan/helpers.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { LiquiditySlotsLink } from \"../../libraries/liquiditySlotsLink.sol\";\nimport { IFluidLiquidity } from \"../../liquidity/interfaces/iLiquidity.sol\";\n\nimport { ErrorTypes } from \"./errorTypes.sol\";\nimport { Error } from \"./error.sol\";\nimport { Variables } from \"./variables.sol\";\n\n/// @dev Flashloan protocol helper methods\nabstract contract Helpers is Variables, Error {\n constructor(IFluidLiquidity liquidity_) Variables(liquidity_) {}\n\n /// @notice Reads user borrow data of currency to be lent.\n /// @param token_ The loan currency.\n /// @return user borrow data for `token`.\n function _readUserBorrowData(address token_) internal view returns (uint256) {\n bytes32 slot_ = LiquiditySlotsLink.calculateDoubleMappingStorageSlot(\n LiquiditySlotsLink.LIQUIDITY_USER_BORROW_DOUBLE_MAPPING_SLOT,\n address(this),\n token_\n );\n return LIQUIDITY.readFromStorage(slot_);\n }\n\n /// @notice Checks if the given address is valid (not equal to address(0)).\n /// @param value_ The address to check..\n function _checkValidAddress(address value_) internal pure {\n if (value_ == address(0)) {\n revert FluidFlashLenderError(ErrorTypes.FlashLender__ZeroAddress);\n }\n }\n\n /// @notice Ensures that the provided address is valid (not equal to address(0)).\n /// @param value_ The address to check.\n modifier validAddress(address value_) {\n _checkValidAddress(value_);\n _;\n }\n}\n"
},
"contracts/protocols/flashloan/interfaces/IERC3156FlashBorrower.sol": {
"content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.21;\n\ninterface IERC3156FlashBorrower {\n function onFlashLoan(\n address initiator,\n address token,\n uint256 amount,\n uint256 fee,\n bytes calldata data\n ) external returns (bytes32);\n}\n"
},
"contracts/protocols/flashloan/interfaces/IERC3156FlashLender.sol": {
"content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.21;\n\nimport \"./IERC3156FlashBorrower.sol\";\n\ninterface IERC3156FlashLender {\n /// @dev The amount of currency available to be lent.\n /// @param token The loan currency.\n /// @return The amount of `token` that can be borrowed.\n function maxFlashLoan(address token) external view returns (uint256);\n\n /// @dev The fee to be charged for a given loan.\n /// @param token The loan currency.\n /// @param amount The amount of tokens lent.\n /// @return The amount of `token` to be charged for the loan, on top of the returned principal.\n function flashFee(address token, uint256 amount) external view returns (uint256);\n\n /// @dev Initiate a flash loan.\n /// @param receiver The receiver of the tokens in the loan, and the receiver of the callback.\n /// @param token The loan currency.\n /// @param amount The amount of tokens lent.\n /// @param data Arbitrary data structure, intended to contain user-defined parameters.\n function flashLoan(\n IERC3156FlashBorrower receiver,\n address token,\n uint256 amount,\n bytes calldata data\n ) external returns (bool);\n}\n"
},
"contracts/protocols/flashloan/interfaces/iFlashBorrower.sol": {
"content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.21;\n\nimport \"./IERC3156FlashBorrower.sol\";\nimport { Structs } from \"../structs.sol\";\n\ninterface IFlashBorrower is IERC3156FlashBorrower {\n function onFlashLoanMultiple(\n address initiator,\n Structs.AddressUint256[] calldata tokensWithValues,\n uint256 fee,\n bytes calldata data\n ) external returns (bytes32);\n}\n"
},
"contracts/protocols/flashloan/interfaces/iFlashLender.sol": {
"content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.21;\n\nimport { IFlashBorrower } from \"./iFlashBorrower.sol\";\nimport { IERC3156FlashLender } from \"./IERC3156FlashLender.sol\";\nimport { IERC3156FlashBorrower } from \"./IERC3156FlashBorrower.sol\";\nimport { Structs } from \"../structs.sol\";\n\ninterface IFluidFlashLender is IERC3156FlashLender {\n /// @notice Initiate a flash loan with multiple tokens.\n /// @param receiver_ The receiver of the tokens in the loan, and the receiver of the callback.\n /// @param tokensWithAmounts_ An array of token addresses and loan amounts.\n /// @param data_ Arbitrary data structure, intended to contain user-defined parameters.\n /// @return 'true' if the flash loan are successful\n function flashLoanMultiple(\n IFlashBorrower receiver_,\n Structs.AddressUint256[] calldata tokensWithAmounts_,\n bytes calldata data_\n ) external returns (bool);\n}\n"
},
"contracts/protocols/flashloan/main.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\nimport { SafeCast } from \"@openzeppelin/contracts/utils/math/SafeCast.sol\";\n\nimport { Helpers } from \"./helpers.sol\";\nimport { Structs } from \"./structs.sol\";\nimport { ErrorTypes } from \"./errorTypes.sol\";\nimport { IFluidFlashLender } from \"./interfaces/iFlashLender.sol\";\nimport { IERC3156FlashBorrower } from \"./interfaces/IERC3156FlashBorrower.sol\";\nimport { IFlashBorrower } from \"./interfaces/iFlashBorrower.sol\";\n\nimport { IFluidLiquidity } from \"../../liquidity/interfaces/iLiquidity.sol\";\nimport { IProtocol } from \"../../liquidity/userModule/main.sol\";\n\nimport { LiquidityCalcs } from \"../../libraries/liquidityCalcs.sol\";\nimport { LiquiditySlotsLink } from \"../../libraries/liquiditySlotsLink.sol\";\n\n/// @notice contract that provides Flashloans via Fluid. ERC-3156 compatible.\n/// In addition also implements a `flashLoanMultiple()` method which can be used to flash loan multiple tokens at once.\n/// @dev Fee is a constant 0. This contract is not upgradeable.\n//\n// @dev Fee is not really implemented, just the parts that are needed to ensure compatibility with ERC-3156.\n// @dev user borrow amount for this contract at Liquidity will slowly grow but that is not an issue as the amount\n// being repaid is still the exact original amount always.\ncontract FluidFlashLender is Structs, IFluidFlashLender, IProtocol, Helpers {\n using SafeERC20 for IERC20;\n\n /// @notice emitted whenever funds for a certain `token` are rescued to Liquidity\n event LogRescueFunds(address indexed token);\n\n /// @notice emitted when a flashloan has been taken and repaid\n event LogFlashLoan(address indexed token, uint256 indexed amount, address indexed receiver);\n\n constructor(IFluidLiquidity liquidity_) Helpers(liquidity_) {}\n\n /// @notice The amount of currency available to be lent.\n /// @param token_ The loan currency.\n /// @return The amount of `token` that can be borrowed.\n function maxFlashLoan(address token_) public view returns (uint256) {\n // maximum flashloan is either:\n // a) the borrow limit of Flashloan protocol at Liquidity or\n // b) the total available amount of token at Liquidity (if lower than borrow limit)\n\n // get current exchange rates\n (uint256 supplyExchangePrice_, uint256 borrowExchangePrice_) = LiquidityCalcs.calcExchangePrices(\n LIQUIDITY.readFromStorage(\n LiquiditySlotsLink.calculateMappingStorageSlot(\n LiquiditySlotsLink.LIQUIDITY_EXCHANGE_PRICES_MAPPING_SLOT,\n token_\n )\n )\n );\n\n // a) get the borrow limit\n uint256 userBorrowData_ = _readUserBorrowData(token_);\n uint256 userBorrow_ = (userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_AMOUNT) & LiquidityCalcs.X64;\n // get borrow limit\n uint256 borrowLimit_ = LiquidityCalcs.calcBorrowLimitBeforeOperate(userBorrowData_, userBorrow_);\n // revert if Flashloan protocol has already borrowed more than 0.0001% of borrow limit for the `token_`. This\n // catches any duplicate token borrows. We can not just check for user borrow == 0 because of rounding.\n if (userBorrow_ > (borrowLimit_ / 100_000)) {\n revert FluidFlashLenderError(ErrorTypes.FlashLender__DuplicateBorrow);\n }\n // subtract any already borrowed amount\n borrowLimit_ -= userBorrow_;\n\n if (userBorrowData_ & 1 == 1) {\n // convert raw borrow limit amount to normal for withInterest mode\n borrowLimit_ = (borrowLimit_ * borrowExchangePrice_) / LiquidityCalcs.EXCHANGE_PRICES_PRECISION;\n }\n\n // b) get the total available amount at Liquidity (tota
},
"contracts/protocols/flashloan/structs.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nabstract contract Structs {\n struct AddressUint256 {\n address addr;\n uint256 value;\n }\n}\n"
},
"contracts/protocols/flashloan/variables.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IFluidLiquidity } from \"../../liquidity/interfaces/iLiquidity.sol\";\n\nabstract contract Variables {\n /// @dev address that is mapped to the chain native token\n address internal constant _NATIVE_TOKEN_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n bytes32 internal constant _RETURN_VALUE_FOR_FLASHLOAN_SINGLE = keccak256(\"ERC3156FlashBorrower.onFlashLoan\");\n bytes32 internal constant _RETURN_VALUE_FOR_FLASHLOAN_MULTIPLE = keccak256(\"FlashBorrower.onFlashLoanMultiple\");\n\n /// @dev Storage slot with the admin of the contract at Liquidity. Logic from \"proxy.sol\".\n /// This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1.\n bytes32 internal constant _GOVERNANCE_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n /// @dev fee for flashloan set globally for all tokens\n //\n // @dev can't just change this to a value != 0 as that case is not fully implemented. Ensure necessary changes are\n // made if _FLASH_FEE must be set to value != 0.\n uint256 internal constant _FLASH_FEE = 0;\n\n /// @notice address of the Fluid Liquidity contract\n IFluidLiquidity public immutable LIQUIDITY;\n\n constructor(IFluidLiquidity liquidity_) {\n LIQUIDITY = liquidity_;\n }\n}\n"
},
"contracts/protocols/lending/error.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nabstract contract Error {\n error FluidLendingError(uint256 errorId_);\n}\n"
},
"contracts/protocols/lending/errorTypes.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nlibrary ErrorTypes {\n /***********************************|\n | fToken | \n |__________________________________*/\n\n /// @notice thrown when a deposit amount is too small to increase BigMath stored balance in Liquidity.\n /// precision of BigMath is 1e12, so if token holds 120_000_000_000 USDC, min amount to make a difference would be 0.1 USDC.\n /// i.e. user would send a very small deposit which mints no shares -> revert\n uint256 internal constant fToken__DepositInsignificant = 20001;\n\n /// @notice thrown when minimum output amount is not reached, e.g. for minimum shares minted (deposit) or\n /// minimum assets received (redeem)\n uint256 internal constant fToken__MinAmountOut = 20002;\n\n /// @notice thrown when maximum amount is surpassed, e.g. for maximum shares burned (withdraw) or\n /// maximum assets input (mint)\n uint256 internal constant fToken__MaxAmount = 20003;\n\n /// @notice thrown when invalid params are sent to a method, e.g. zero address\n uint256 internal constant fToken__InvalidParams = 20004;\n\n /// @notice thrown when an unauthorized caller is trying to execute an auth-protected method\n uint256 internal constant fToken__Unauthorized = 20005;\n\n /// @notice thrown when a with permit / signature method is called from msg.sender that is the owner.\n /// Should call the method without permit instead if msg.sender is the owner.\n uint256 internal constant fToken__PermitFromOwnerCall = 20006;\n\n /// @notice thrown when a reentrancy is detected.\n uint256 internal constant fToken__Reentrancy = 20007;\n\n /// @notice thrown when _tokenExchangePrice overflows type(uint64).max\n uint256 internal constant fToken__ExchangePriceOverflow = 20008;\n\n /// @notice thrown when msg.sender is not rebalancer\n uint256 internal constant fToken__NotRebalancer = 20009;\n\n /// @notice thrown when rebalance is called with msg.value > 0 for non NativeUnderlying fToken\n uint256 internal constant fToken__NotNativeUnderlying = 20010;\n\n /// @notice thrown when the received new liquidity exchange price is of unexpected value (< than the old one)\n uint256 internal constant fToken__LiquidityExchangePriceUnexpected = 20011;\n\n /***********************************|\n | fToken Native Underlying | \n |__________________________________*/\n\n /// @notice thrown when native deposit is called but sent along `msg.value` does not cover the deposit amount\n uint256 internal constant fTokenNativeUnderlying__TransferInsufficient = 21001;\n\n /// @notice thrown when a liquidity callback is called for a native token operation\n uint256 internal constant fTokenNativeUnderlying__UnexpectedLiquidityCallback = 21002;\n\n /***********************************|\n | Lending Factory | \n |__________________________________*/\n\n /// @notice thrown when a method is called with invalid params\n uint256 internal constant LendingFactory__InvalidParams = 22001;\n\n /// @notice thrown when the provided input param address is zero\n uint256 internal constant LendingFactory__ZeroAddress = 22002;\n\n /// @notice thrown when the token already exists\n uint256 internal constant LendingFactory__TokenExists = 22003;\n\n /// @notice thrown when the fToken has not yet been configured at Liquidity\n uint256 internal constant LendingFactory__LiquidityNotConfigured = 22004;\n\n /// @notice thrown when an unauthorized caller is trying to execute an auth-protected method\n uint256 internal constant LendingFactory__Unauthorized = 22005;\n\n /***********************************|\n | Lending Rewards Rate Model | \n |__________________________________*/\n\n /// @notice thrown when invalid params are given as input\n uint256 internal constant LendingRewardsRateModel__InvalidParams = 23001;\n\n /// @notice thrown when calculated rewards rate i
},
"contracts/protocols/lending/fToken/events.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IFluidLendingRewardsRateModel } from \"../interfaces/iLendingRewardsRateModel.sol\";\n\nabstract contract Events {\n /// @notice emitted whenever admin updates rewards rate model\n event LogUpdateRewards(IFluidLendingRewardsRateModel indexed rewardsRateModel);\n\n /// @notice emitted whenever rebalance is executed to fund difference between Liquidity deposit and totalAssets()\n /// as rewards through the rebalancer.\n event LogRebalance(uint256 assets);\n\n /// @notice emitted whenever exchange rates are updated\n event LogUpdateRates(uint256 tokenExchangePrice, uint256 liquidityExchangePrice);\n\n /// @notice emitted whenever funds for a certain `token` are rescued to Liquidity\n event LogRescueFunds(address indexed token);\n\n /// @notice emitted whenever rebalancer address is updated\n event LogUpdateRebalancer(address indexed rebalancer);\n}\n"
},
"contracts/protocols/lending/fToken/main.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { ERC20, IERC20Metadata } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { IERC4626 } from \"@openzeppelin/contracts/interfaces/IERC4626.sol\";\nimport { FixedPointMathLib } from \"solmate/src/utils/FixedPointMathLib.sol\";\nimport { IERC20Permit } from \"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\";\nimport { SafeCast } from \"@openzeppelin/contracts/utils/math/SafeCast.sol\";\n\nimport { IAllowanceTransfer } from \"../interfaces/permit2/iAllowanceTransfer.sol\";\nimport { IFluidLendingRewardsRateModel } from \"../interfaces/iLendingRewardsRateModel.sol\";\nimport { IFluidLendingFactory } from \"../interfaces/iLendingFactory.sol\";\nimport { IFToken, IFTokenAdmin } from \"../interfaces/iFToken.sol\";\nimport { LiquidityCalcs } from \"../../../libraries/liquidityCalcs.sol\";\nimport { BigMathMinified } from \"../../../libraries/bigMathMinified.sol\";\nimport { LiquiditySlotsLink } from \"../../../libraries/liquiditySlotsLink.sol\";\nimport { SafeTransfer } from \"../../../libraries/safeTransfer.sol\";\nimport { IFluidLiquidity } from \"../../../liquidity/interfaces/iLiquidity.sol\";\nimport { Variables } from \"./variables.sol\";\nimport { Events } from \"./events.sol\";\nimport { ErrorTypes } from \"../errorTypes.sol\";\nimport { Error } from \"../error.sol\";\n\n/// @dev ReentrancyGuard based on OpenZeppelin implementation.\n/// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v4.8/contracts/security/ReentrancyGuard.sol\nabstract contract ReentrancyGuard is Error, Variables {\n uint8 internal constant REENTRANCY_NOT_ENTERED = 1;\n uint8 internal constant REENTRANCY_ENTERED = 2;\n\n constructor() {\n _status = REENTRANCY_NOT_ENTERED;\n }\n\n /// @dev checks that no reentrancy occurs, reverts if so. Calling the method in the modifier reduces\n /// bytecode size as modifiers are inlined into bytecode\n function _checkReentrancy() internal {\n // On the first call to nonReentrant, _status will be NOT_ENTERED\n if (_status != REENTRANCY_NOT_ENTERED) {\n revert FluidLendingError(ErrorTypes.fToken__Reentrancy);\n }\n\n // Any calls to nonReentrant after this point will fail\n _status = REENTRANCY_ENTERED;\n }\n\n /// @dev Prevents a contract from calling itself, directly or indirectly.\n /// See OpenZeppelin implementation for more info\n modifier nonReentrant() {\n _checkReentrancy();\n\n _;\n\n // storing original value triggers a refund (see https://eips.ethereum.org/EIPS/eip-2200)\n _status = REENTRANCY_NOT_ENTERED;\n }\n}\n\n/// @dev internal methods for fToken contracts\nabstract contract fTokenCore is Error, IERC4626, IFToken, Variables, Events, ReentrancyGuard {\n using FixedPointMathLib for uint256;\n\n /// @dev Gets current (updated) Liquidity supply exchange price for the underyling asset\n function _getLiquidityExchangePrice() internal view returns (uint256 supplyExchangePrice_) {\n (supplyExchangePrice_, ) = LiquidityCalcs.calcExchangePrices(\n LIQUIDITY.readFromStorage(LIQUIDITY_EXCHANGE_PRICES_SLOT)\n );\n }\n\n /// @dev Gets current Liquidity supply balance of `address(this)` for the underyling asset\n function _getLiquidityBalance() internal view returns (uint256 balance_) {\n // extract user supply amount\n uint256 userSupplyRaw_ = BigMathMinified.fromBigNumber(\n (LIQUIDITY.readFromStorage(LIQUIDITY_USER_SUPPLY_SLOT) >> LiquiditySlotsLink.BITS_USER_SUPPLY_AMOUNT) &\n LiquidityCalcs.X64,\n LiquidityCalcs.DEFAULT_EXPONENT_SIZE,\n LiquidityCalcs.DEFAULT_EXPONENT_MASK\n );\n\n unchecked {\n // can not overflow as userSupplyRaw_ can be maximally type(int128).max, liquidity exchange price type(uint64).max\n return (userSupplyRaw_ * _g
},
"contracts/protocols/lending/fToken/nativeUnderlying/fTokenNativeUnderlying.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { IERC4626 } from \"@openzeppelin/contracts/interfaces/IERC4626.sol\";\nimport { FixedPointMathLib } from \"solmate/src/utils/FixedPointMathLib.sol\";\nimport { SafeCast } from \"@openzeppelin/contracts/utils/math/SafeCast.sol\";\n\nimport { SafeTransfer } from \"../../../../libraries/safeTransfer.sol\";\nimport { LiquiditySlotsLink } from \"../../../../libraries/liquiditySlotsLink.sol\";\nimport { ErrorTypes } from \"../../errorTypes.sol\";\nimport { fTokenCore, fTokenAdmin, fToken } from \"../main.sol\";\n\nimport { IWETH9 } from \"../../interfaces/external/iWETH9.sol\";\nimport { IFluidLendingFactory } from \"../../interfaces/iLendingFactory.sol\";\nimport { IFTokenAdmin, IFTokenNativeUnderlying, IFToken } from \"../../interfaces/iFToken.sol\";\nimport { IFluidLiquidity } from \"../../../../liquidity/interfaces/iLiquidity.sol\";\n\n/// @dev overrides certain methods from the inherited fToken used as base contract to make them compatible with\n/// the native token being used as underlying.\nabstract contract fTokenNativeUnderlyingOverrides is fToken, IFTokenNativeUnderlying {\n using FixedPointMathLib for uint256;\n\n /// @inheritdoc IFTokenNativeUnderlying\n address public constant NATIVE_TOKEN_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @dev gets asset address for liquidity slot links, overridden to set native token address\n function _getLiquiditySlotLinksAsset() internal view virtual override returns (address) {\n return NATIVE_TOKEN_ADDRESS;\n }\n\n /// @dev Gets current Liquidity underlying token balance\n function _getLiquidityUnderlyingBalance() internal view virtual override returns (uint256) {\n return address(LIQUIDITY).balance;\n }\n\n /// @inheritdoc IFTokenAdmin\n function rescueFunds(address token_) external virtual override(IFTokenAdmin, fTokenAdmin) nonReentrant {\n _checkIsLendingFactoryAuth();\n\n if (token_ == NATIVE_TOKEN_ADDRESS) {\n Address.sendValue(payable(address(LIQUIDITY)), address(this).balance);\n } else {\n SafeTransfer.safeTransfer(address(token_), address(LIQUIDITY), IERC20(token_).balanceOf(address(this)));\n }\n\n emit LogRescueFunds(token_);\n }\n\n /*//////////////////////////////////////////////////////////////\n REWARDS\n //////////////////////////////////////////////////////////////*/\n\n /// @inheritdoc fTokenAdmin\n function rebalance()\n external\n payable\n virtual\n override(IFTokenAdmin, fTokenAdmin)\n nonReentrant\n returns (uint256 assets_)\n {\n if (msg.sender != _rebalancer) {\n revert FluidLendingError(ErrorTypes.fToken__NotRebalancer);\n }\n // calculating difference in assets. if liquidity balance is bigger it'll throw which is an expected behaviour\n assets_ = totalAssets() - _getLiquidityBalance();\n\n if (msg.value < assets_) {\n assets_ = msg.value;\n } else if (msg.value > assets_) {\n // send back overfunded msg.value amount\n Address.sendValue(payable(msg.sender), msg.value - assets_);\n }\n\n // send funds to Liquidity protocol to generate yield\n uint256 liquidityExchangePrice_ = _depositToLiquidity(assets_, new bytes(0));\n\n // update the exchange prices, always updating on storage\n _updateRates(liquidityExchangePrice_, true);\n\n // no shares are minted when funding fToken contract for rewards\n\n emit LogRebalance(assets_);\n }\n\n /*//////////////////////////////////////////////////////////////\n DEPOSIT\n //////////////////////////////////////////////////////////////*/\n\n /// @inheritdoc fTokenCore\n function _depositToLiquidity(
},
"contracts/protocols/lending/fToken/variables.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { ERC20, IERC20Metadata } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { ERC20Permit } from \"@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol\";\n\nimport { IAllowanceTransfer } from \"../interfaces/permit2/iAllowanceTransfer.sol\";\nimport { LiquiditySlotsLink } from \"../../../libraries/liquiditySlotsLink.sol\";\nimport { IFToken } from \"../interfaces/iFToken.sol\";\nimport { IAllowanceTransfer } from \"../interfaces/permit2/iAllowanceTransfer.sol\";\nimport { IFluidLendingRewardsRateModel } from \"../interfaces/iLendingRewardsRateModel.sol\";\nimport { IFluidLendingFactory } from \"../interfaces/iLendingFactory.sol\";\nimport { IFluidLiquidity } from \"../../../liquidity/interfaces/iLiquidity.sol\";\nimport { ErrorTypes } from \"../errorTypes.sol\";\nimport { Error } from \"../error.sol\";\n\nabstract contract Constants {\n /// @dev permit2 contract, deployed to same address on EVM networks, see https://github.com/Uniswap/permit2\n IAllowanceTransfer internal constant PERMIT2 = IAllowanceTransfer(0x000000000022D473030F116dDEE9F6B43aC78BA3);\n\n /// @dev precision for exchange prices\n uint256 internal constant EXCHANGE_PRICES_PRECISION = 1e12;\n\n /// @dev Ignoring leap years\n uint256 internal constant SECONDS_PER_YEAR = 365 days;\n\n /// @dev max allowed reward rate is 50%\n uint256 internal constant MAX_REWARDS_RATE = 50 * 1e12; // 50%;\n\n /// @dev address of the Liquidity contract.\n IFluidLiquidity internal immutable LIQUIDITY;\n\n /// @dev address of the Lending factory contract.\n IFluidLendingFactory internal immutable LENDING_FACTORY;\n\n /// @dev address of the underlying asset contract.\n IERC20 internal immutable ASSET;\n\n /// @dev number of decimals for the fToken, same as ASSET\n uint8 internal immutable DECIMALS;\n\n /// @dev slot ids in Liquidity contract for underlying token.\n /// Helps in low gas fetch from liquidity contract by skipping delegate call with `readFromStorage`\n bytes32 internal immutable LIQUIDITY_EXCHANGE_PRICES_SLOT;\n bytes32 internal immutable LIQUIDITY_TOTAL_AMOUNTS_SLOT;\n bytes32 internal immutable LIQUIDITY_USER_SUPPLY_SLOT;\n\n /// @param liquidity_ liquidity contract address\n /// @param lendingFactory_ lending factory contract address\n /// @param asset_ underlying token address\n constructor(IFluidLiquidity liquidity_, IFluidLendingFactory lendingFactory_, IERC20 asset_) {\n DECIMALS = IERC20Metadata(address(asset_)).decimals();\n ASSET = asset_;\n LIQUIDITY = liquidity_;\n LENDING_FACTORY = lendingFactory_;\n\n LIQUIDITY_EXCHANGE_PRICES_SLOT = LiquiditySlotsLink.calculateMappingStorageSlot(\n LiquiditySlotsLink.LIQUIDITY_EXCHANGE_PRICES_MAPPING_SLOT,\n _getLiquiditySlotLinksAsset()\n );\n LIQUIDITY_TOTAL_AMOUNTS_SLOT = LiquiditySlotsLink.calculateMappingStorageSlot(\n LiquiditySlotsLink.LIQUIDITY_TOTAL_AMOUNTS_MAPPING_SLOT,\n _getLiquiditySlotLinksAsset()\n );\n LIQUIDITY_USER_SUPPLY_SLOT = LiquiditySlotsLink.calculateDoubleMappingStorageSlot(\n LiquiditySlotsLink.LIQUIDITY_USER_SUPPLY_DOUBLE_MAPPING_SLOT,\n address(this),\n _getLiquiditySlotLinksAsset()\n );\n }\n\n /// @dev gets asset address for liquidity slot links, extracted to separate method so it can be overridden if needed\n function _getLiquiditySlotLinksAsset() internal view virtual returns (address) {\n return address(ASSET);\n }\n}\n\nabstract contract Variables is ERC20, ERC20Permit, Error, Constants, IFToken {\n /// @dev prefix for token name. fToken will append the underlying asset name\n string private constant TOKEN_NAME_PREFIX = \"Fluid \";\n /// @dev prefix for token symbol. fToken will append the underlying asset symbol\n string private constant
},
"contracts/protocols/lending/interfaces/external/iWETH9.sol": {
"content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.21;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface IWETH9 is IERC20 {\n function deposit() external payable;\n\n function withdraw(uint256 wad) external;\n}\n"
},
"contracts/protocols/lending/interfaces/iFToken.sol": {
"content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.21;\n\nimport { IERC4626 } from \"@openzeppelin/contracts/interfaces/IERC4626.sol\";\n\nimport { IAllowanceTransfer } from \"./permit2/iAllowanceTransfer.sol\";\nimport { IFluidLendingRewardsRateModel } from \"./iLendingRewardsRateModel.sol\";\nimport { IFluidLendingFactory } from \"./iLendingFactory.sol\";\nimport { IFluidLiquidity } from \"../../../liquidity/interfaces/iLiquidity.sol\";\n\ninterface IFTokenAdmin {\n /// @notice updates the rewards rate model contract.\n /// Only callable by LendingFactory auths.\n /// @param rewardsRateModel_ the new rewards rate model contract address.\n /// can be set to address(0) to set no rewards (to save gas)\n function updateRewards(IFluidLendingRewardsRateModel rewardsRateModel_) external;\n\n /// @notice Balances out the difference between fToken supply at Liquidity vs totalAssets().\n /// Deposits underlying from rebalancer address into Liquidity but doesn't mint any shares\n /// -> thus making deposit available as rewards.\n /// Only callable by rebalancer.\n /// @return assets_ amount deposited to Liquidity\n function rebalance() external payable returns (uint256 assets_);\n\n /// @notice gets the liquidity exchange price of the underlying asset, calculates the updated exchange price (with reward rates)\n /// and writes those values to storage.\n /// Callable by anyone.\n /// @return tokenExchangePrice_ exchange price of fToken share to underlying asset\n /// @return liquidityExchangePrice_ exchange price at Liquidity for the underlying asset\n function updateRates() external returns (uint256 tokenExchangePrice_, uint256 liquidityExchangePrice_);\n\n /// @notice sends any potentially stuck funds to Liquidity contract. Only callable by LendingFactory auths.\n function rescueFunds(address token_) external;\n\n /// @notice Updates the rebalancer address (ReserveContract). Only callable by LendingFactory auths.\n function updateRebalancer(address rebalancer_) external;\n}\n\ninterface IFToken is IERC4626, IFTokenAdmin {\n /// @notice returns minimum amount required for deposit (rounded up)\n function minDeposit() external view returns (uint256);\n\n /// @notice returns config, rewards and exchange prices data in a single view method.\n /// @return liquidity_ address of the Liquidity contract.\n /// @return lendingFactory_ address of the Lending factory contract.\n /// @return lendingRewardsRateModel_ address of the rewards rate model contract. changeable by LendingFactory auths.\n /// @return permit2_ address of the Permit2 contract used for deposits / mint with signature\n /// @return rebalancer_ address of the rebalancer allowed to execute `rebalance()`\n /// @return rewardsActive_ true if rewards are currently active\n /// @return liquidityBalance_ current Liquidity supply balance of `address(this)` for the underyling asset\n /// @return liquidityExchangePrice_ (updated) exchange price for the underlying assset in the liquidity protocol (without rewards)\n /// @return tokenExchangePrice_ (updated) exchange price between fToken and the underlying assset (with rewards)\n function getData()\n external\n view\n returns (\n IFluidLiquidity liquidity_,\n IFluidLendingFactory lendingFactory_,\n IFluidLendingRewardsRateModel lendingRewardsRateModel_,\n IAllowanceTransfer permit2_,\n address rebalancer_,\n bool rewardsActive_,\n uint256 liquidityBalance_,\n uint256 liquidityExchangePrice_,\n uint256 tokenExchangePrice_\n );\n\n /// @notice transfers `amount_` of `token_` to liquidity. Only callable by liquidity contract.\n /// @dev this callback is used to optimize gas consumption (reducing necessary token transfers).\n function liquidityCallback(address token_, uint256 amount_, bytes calldata data_) extern
},
"contracts/protocols/lending/interfaces/iLendingFactory.sol": {
"content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.21;\n\nimport { IFluidLiquidity } from \"../../../liquidity/interfaces/iLiquidity.sol\";\n\ninterface IFluidLendingFactoryAdmin {\n /// @notice reads if a certain `auth_` address is an allowed auth or not. Owner is auth by default.\n function isAuth(address auth_) external view returns (bool);\n\n /// @notice Sets an address as allowed auth or not. Only callable by owner.\n /// @param auth_ address to set auth value for\n /// @param allowed_ bool flag for whether address is allowed as auth or not\n function setAuth(address auth_, bool allowed_) external;\n\n /// @notice reads if a certain `deployer_` address is an allowed deployer or not. Owner is deployer by default.\n function isDeployer(address deployer_) external view returns (bool);\n\n /// @notice Sets an address as allowed deployer or not. Only callable by owner.\n /// @param deployer_ address to set deployer value for\n /// @param allowed_ bool flag for whether address is allowed as deployer or not\n function setDeployer(address deployer_, bool allowed_) external;\n\n /// @notice Sets the `creationCode_` bytecode for a certain `fTokenType_`. Only callable by auths.\n /// @param fTokenType_ the fToken Type used to refer the creation code\n /// @param creationCode_ contract creation code. can be set to bytes(0) to remove a previously available `fTokenType_`\n function setFTokenCreationCode(string memory fTokenType_, bytes calldata creationCode_) external;\n\n /// @notice creates token for `asset_` for a lending protocol with interest. Only callable by deployers.\n /// @param asset_ address of the asset\n /// @param fTokenType_ type of fToken:\n /// - if it's the native token, it should use `NativeUnderlying`\n /// - otherwise it should use `fToken`\n /// - could be more types available, check `fTokenTypes()`\n /// @param isNativeUnderlying_ flag to signal fToken type that uses native underlying at Liquidity\n /// @return token_ address of the created token\n function createToken(\n address asset_,\n string calldata fTokenType_,\n bool isNativeUnderlying_\n ) external returns (address token_);\n}\n\ninterface IFluidLendingFactory is IFluidLendingFactoryAdmin {\n /// @notice list of all created tokens\n function allTokens() external view returns (address[] memory);\n\n /// @notice list of all fToken types that can be deployed\n function fTokenTypes() external view returns (string[] memory);\n\n /// @notice returns the creation code for a certain `fTokenType_`\n function fTokenCreationCode(string memory fTokenType_) external view returns (bytes memory);\n\n /// @notice address of the Liquidity contract.\n function LIQUIDITY() external view returns (IFluidLiquidity);\n\n /// @notice computes deterministic token address for `asset_` for a lending protocol\n /// @param asset_ address of the asset\n /// @param fTokenType_ type of fToken:\n /// - if it's the native token, it should use `NativeUnderlying`\n /// - otherwise it should use `fToken`\n /// - could be more types available, check `fTokenTypes()`\n /// @return token_ detemrinistic address of the computed token\n function computeToken(address asset_, string calldata fTokenType_) external view returns (address token_);\n}\n"
},
"contracts/protocols/lending/interfaces/iLendingRewardsRateModel.sol": {
"content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.21;\n\ninterface IFluidLendingRewardsRateModel {\n /// @notice Calculates the current rewards rate (APR)\n /// @param totalAssets_ amount of assets in the lending\n /// @return rate_ rewards rate percentage per year with 1e12 RATE_PRECISION, e.g. 1e12 = 1%, 1e14 = 100%\n /// @return ended_ flag to signal that rewards have ended (always 0 going forward)\n /// @return startTime_ start time of rewards to compare against last update timestamp\n function getRate(uint256 totalAssets_) external view returns (uint256 rate_, bool ended_, uint256 startTime_);\n\n /// @notice Returns config constants for rewards rate model\n function getConfig()\n external\n view\n returns (\n uint256 duration_,\n uint256 startTime_,\n uint256 endTime_,\n uint256 startTvl_,\n uint256 maxRate_,\n uint256 rewardAmount_,\n address initiator_\n );\n}\n"
},
"contracts/protocols/lending/interfaces/iStakingRewards.sol": {
"content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.21;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface IFluidLendingStakingRewards {\n // Views\n function lastTimeRewardApplicable() external view returns (uint256);\n\n function rewardPerToken() external view returns (uint256);\n\n function earned(address account) external view returns (uint256);\n\n function getRewardForDuration() external view returns (uint256);\n\n function totalSupply() external view returns (uint256);\n\n function balanceOf(address account) external view returns (uint256);\n\n function periodFinish() external view returns (uint256);\n\n function rewardRate() external view returns (uint256);\n\n function lastUpdateTime() external view returns (uint256);\n\n function rewardPerTokenStored() external view returns (uint256);\n\n function rewardsDuration() external view returns (uint256);\n\n function rewardsToken() external view returns (IERC20);\n\n function stakingToken() external view returns (IERC20);\n\n // Mutative\n\n function stake(uint256 amount) external;\n\n function withdraw(uint256 amount) external;\n\n function getReward() external;\n\n function exit() external;\n}\n"
},
"contracts/protocols/lending/interfaces/permit2/iAllowanceTransfer.sol": {
"content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.21;\n\n/// @title AllowanceTransfer\n/// @notice Handles ERC20 token permissions through signature based allowance setting and ERC20 token transfers by checking allowed amounts\n/// @dev Requires user's token approval on the Permit2 contract\n/// from https://github.com/Uniswap/permit2/blob/main/src/interfaces/ISignatureTransfer.sol.\n/// Copyright (c) 2022 Uniswap Labs\ninterface IAllowanceTransfer {\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n\n /// @notice Thrown when an allowance on a token has expired.\n /// @param deadline The timestamp at which the allowed amount is no longer valid\n error AllowanceExpired(uint256 deadline);\n\n /// @notice Thrown when an allowance on a token has been depleted.\n /// @param amount The maximum amount allowed\n error InsufficientAllowance(uint256 amount);\n\n /// @notice Thrown when too many nonces are invalidated.\n error ExcessiveInvalidation();\n\n /// @notice Emits an event when the owner successfully invalidates an ordered nonce.\n event NonceInvalidation(\n address indexed owner,\n address indexed token,\n address indexed spender,\n uint48 newNonce,\n uint48 oldNonce\n );\n\n /// @notice Emits an event when the owner successfully sets permissions on a token for the spender.\n event Approval(\n address indexed owner,\n address indexed token,\n address indexed spender,\n uint160 amount,\n uint48 expiration\n );\n\n /// @notice Emits an event when the owner successfully sets permissions using a permit signature on a token for the spender.\n event Permit(\n address indexed owner,\n address indexed token,\n address indexed spender,\n uint160 amount,\n uint48 expiration,\n uint48 nonce\n );\n\n /// @notice Emits an event when the owner sets the allowance back to 0 with the lockdown function.\n event Lockdown(address indexed owner, address token, address spender);\n\n /// @notice The permit data for a token\n struct PermitDetails {\n // ERC20 token address\n address token;\n // the maximum amount allowed to spend\n uint160 amount;\n // timestamp at which a spender's token allowances become invalid\n uint48 expiration;\n // an incrementing value indexed per owner,token,and spender for each signature\n uint48 nonce;\n }\n\n /// @notice The permit message signed for a single token allownce\n struct PermitSingle {\n // the permit data for a single token alownce\n PermitDetails details;\n // address permissioned on the allowed tokens\n address spender;\n // deadline on the permit signature\n uint256 sigDeadline;\n }\n\n /// @notice The permit message signed for multiple token allowances\n struct PermitBatch {\n // the permit data for multiple token allowances\n PermitDetails[] details;\n // address permissioned on the allowed tokens\n address spender;\n // deadline on the permit signature\n uint256 sigDeadline;\n }\n\n /// @notice The saved permissions\n /// @dev This info is saved per owner, per token, per spender and all signed over in the permit message\n /// @dev Setting amount to type(uint160).max sets an unlimited approval\n struct PackedAllowance {\n // amount allowed\n uint160 amount;\n // permission expiry\n uint48 expiration;\n // an incrementing value indexed per owner,token,and spender for each signature\n uint48 nonce;\n }\n\n /// @notice A token spender pair.\n struct TokenSpenderPair {\n // the token the spender is approved\n address token;\n // the spender address\n address spender;\n }\n\n /// @notice Details for a token transfer.\n struct AllowanceTransferDetails {\n // the owner of the token\n address from;\n // the recipient of
},
"contracts/protocols/lending/lendingFactory/events.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IFluidLendingFactory } from \"../interfaces/iLendingFactory.sol\";\n\nabstract contract Events {\n /// @notice emitted when a new fToken is created\n event LogTokenCreated(address indexed token, address indexed asset, uint256 indexed count, string fTokenType);\n\n /// @notice emitted when an auth is modified by owner\n event LogSetAuth(address indexed auth, bool indexed allowed);\n\n /// @notice emitted when a deployer is modified by owner\n event LogSetDeployer(address indexed deployer, bool indexed allowed);\n\n /// @notice emitted when the creation code for an fTokenType is set\n event LogSetFTokenCreationCode(string indexed fTokenType, address indexed creationCodePointer);\n}\n"
},
"contracts/protocols/lending/lendingFactory/main.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { CREATE3 } from \"solmate/src/utils/CREATE3.sol\";\nimport { SSTORE2 } from \"solmate/src/utils/SSTORE2.sol\";\nimport { Owned } from \"solmate/src/auth/Owned.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\n\nimport { IFluidLiquidity } from \"../../../liquidity/interfaces/iLiquidity.sol\";\nimport { IFluidLendingFactory, IFluidLendingFactoryAdmin } from \"../interfaces/iLendingFactory.sol\";\nimport { LiquiditySlotsLink } from \"../../../libraries/liquiditySlotsLink.sol\";\nimport { ErrorTypes } from \"../errorTypes.sol\";\nimport { Error } from \"../error.sol\";\nimport { Events } from \"./events.sol\";\n\nabstract contract LendingFactoryVariables is Owned, Error, IFluidLendingFactory {\n /*//////////////////////////////////////////////////////////////\n CONSTANTS / IMMUTABLES\n //////////////////////////////////////////////////////////////*/\n\n /// @inheritdoc IFluidLendingFactory\n IFluidLiquidity public immutable LIQUIDITY;\n\n /// @dev address that is mapped to the chain native token\n address internal constant _NATIVE_TOKEN_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /*//////////////////////////////////////////////////////////////\n STORAGE VARIABLES\n //////////////////////////////////////////////////////////////*/\n\n // ------------ storage variables from inherited contracts (Owned) come before vars here --------\n\n // ----------------------- slot 0 ---------------------------\n // address public owner;\n\n // 12 bytes empty\n\n // ----------------------- slot 1 ---------------------------\n /// @dev auths can update rewards related config at created fToken contracts.\n /// owner can add/remove auths.\n /// Owner is auth by default.\n mapping(address => uint256) internal _auths;\n\n // ----------------------- slot 2 ---------------------------\n /// @dev deployers can deploy new fTokens.\n /// owner can add/remove deployers.\n /// Owner is deployer by default.\n mapping(address => uint256) internal _deployers;\n\n // ----------------------- slot 3 ---------------------------\n /// @dev list of all created tokens.\n /// Solidity creates an automatic getter only to fetch at a certain position, so explicitly define a getter that returns all.\n address[] internal _allTokens;\n\n // ----------------------- slot 4 ---------------------------\n\n /// @dev available fTokenTypes for deployment. At least EIP2612Deposits, Permit2Deposits, NativeUnderlying.\n /// Solidity creates an automatic getter only to fetch at a certain position, so explicitly define a getter that returns all.\n string[] internal _fTokenTypes;\n\n // ----------------------- slot 5 ---------------------------\n\n /// @dev fToken creation code for each fTokenType, accessed via SSTORE2.\n /// maps keccak256(abi.encode(fTokenType)) -> SSTORE2 written creation code for the fToken contract\n mapping(bytes32 => address) internal _fTokenCreationCodePointers;\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n constructor(IFluidLiquidity liquidity_, address owner_) Owned(owner_) {\n if (owner_ == address(0)) {\n // Owned does not have a zero check for owner_\n revert FluidLendingError(ErrorTypes.LendingFactory__ZeroAddress);\n }\n\n LIQUIDITY = liquidity_;\n }\n\n /// @inheritdoc IFluidLendingFactory\n function allTokens() public view returns (address[] memory) {\n return _allTokens;\n }\n\n /// @inheritdoc IFluidLendingFactory\n function fTokenTypes() public view returns (string[] memory) {\n return _fTokenTypes;\n }\n\n /// @inheritdoc IFluidLendingFactory\n function fTokenCreationCode(string memory fTokenType_) public view returns (bytes memory) {\n
},
"contracts/protocols/steth/error.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\ncontract Error {\n /// @notice general Custom error used for all contract specific errors with the `errorId_` param as error code.\n /// Look up the specific error code in the source code to find a better explanation of what went wrong (errors.sol).\n error StETHQueueError(uint256 errorId_);\n}\n"
},
"contracts/protocols/steth/errorTypes.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nlibrary ErrorTypes {\n /***********************************|\n | StETH | \n |__________________________________*/\n\n /// @notice thrown when maxLTV precent amount is set to 0\n uint256 internal constant StETH__MaxLTVZero = 40001;\n\n /// @notice thrown when the borrow ETH amount to StETH collateral ratio is bigger than the configured `maxLTV`\n uint256 internal constant StETH__MaxLTV = 40002;\n\n /// @notice thrown when an ERC721 other than a Lido Withdrawal NFT is transferred to this contract\n uint256 internal constant StETH__InvalidERC721Transfer = 40003;\n\n /// @notice thrown when an input amount (ethBorrowAmount or stETHAmount) is zero\n uint256 internal constant StETH__InputAmountZero = 40004;\n\n /// @notice thrown when `liquidityCallback` is called, as this protocol only uses native token as borrow asset\n uint256 internal constant StETH__UnexpectedLiquidityCallback = 40005;\n\n /// @notice thrown when there is no claim queued for a claim owner\n uint256 internal constant StETH__NoClaimQueued = 40006;\n\n /// @notice thrown when an unauthorized `msg.sender` calls a protected method\n uint256 internal constant StETH__Unauthorized = 40007;\n\n /// @notice thrown when the borrowAmountRaw is rounded to zero because of the exchange price\n uint256 internal constant StETH__BorrowAmountRawRoundingZero = 40008;\n\n /// @notice thrown when an input address is zero\n uint256 internal constant StETH__AddressZero = 40009;\n\n /// @notice thrown when a reentrancy happens\n uint256 internal constant StETH__Reentrancy = 40010;\n\n /// @notice thrown when maxLTV precent amount is set to >= 100%\n uint256 internal constant StETH__MaxLTVAboveCap = 40011;\n\n /// @notice thrown when renounceOwnership is called\n uint256 internal constant StETH__RenounceOwnershipUnsupported = 40012;\n}\n"
},
"contracts/protocols/steth/events.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nabstract contract Events {\n /// @notice emitted whenever `maxLTV` is updated\n event LogSetMaxLTV(uint256 maxLTV);\n\n /// @notice emitted when a queue() process is executed\n event LogQueue(\n address indexed claimTo,\n uint256 requestIdFrom,\n uint256 borrowETHAmount,\n uint256 queueStETHAmount,\n address borrowTo\n );\n\n /// @notice emitted when a claim() process is executed\n event LogClaim(address indexed claimTo, uint256 requestIdFrom, uint256 claimedAmount, uint256 repayAmount);\n\n /// @notice emitted when an auth is modified by owner\n event LogSetAuth(address indexed auth, bool allowed);\n\n /// @notice emitted when a guardian is modified by owner\n event LogSetGuardian(address indexed guardian, bool allowed);\n\n /// @notice emitted when an allowed user is modified by auths\n event LogSetAllowed(address indexed user, bool allowed);\n\n /// @notice emitted when `allowListActive` status is updated\n event LogSetAllowListActive(bool active);\n\n /// @notice emitted when protocol is paused by guardian\n event LogPaused();\n\n /// @notice emitted when protocol is unpaused by owner\n event LogUnpaused();\n}\n"
},
"contracts/protocols/steth/interfaces/external/iLidoWithdrawalQueue.sol": {
"content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.21;\n\ninterface ILidoWithdrawalQueue {\n function balanceOf(address) external view returns (uint);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n // code below based on Lido WithdrawalQueueBase.sol\n // see https://github.com/lidofinance/lido-dao/blob/v2.0.0/contracts/0.8.9/WithdrawalQueueBase.sol\n\n /// @notice output format struct for `_getWithdrawalStatus()` method\n struct WithdrawalRequestStatus {\n /// @notice stETH token amount that was locked on withdrawal queue for this request\n uint256 amountOfStETH;\n /// @notice amount of stETH shares locked on withdrawal queue for this request\n uint256 amountOfShares;\n /// @notice address that can claim or transfer this request\n address owner;\n /// @notice timestamp of when the request was created, in seconds\n uint256 timestamp;\n /// @notice true, if request is finalized\n bool isFinalized;\n /// @notice true, if request is claimed. Request is claimable if (isFinalized && !isClaimed)\n bool isClaimed;\n }\n\n /// @notice length of the checkpoint array. Last possible value for the hint.\n /// NB! checkpoints are indexed from 1, so it returns 0 if there is no checkpoints\n function getLastCheckpointIndex() external view returns (uint256);\n\n // code below based on Lido WithdrawalQueue.sol\n // see https://github.com/lidofinance/lido-dao/blob/v2.0.0/contracts/0.8.9/WithdrawalQueue.sol\n\n /// @notice Request the batch of stETH for withdrawal. Approvals for the passed amounts should be done before.\n /// @param _amounts an array of stETH amount values.\n /// The standalone withdrawal request will be created for each item in the passed list.\n /// @param _owner address that will be able to manage the created requests.\n /// If `address(0)` is passed, `msg.sender` will be used as owner.\n /// @return requestIds an array of the created withdrawal request ids\n function requestWithdrawals(\n uint256[] calldata _amounts,\n address _owner\n ) external returns (uint256[] memory requestIds);\n\n /// @notice Claim one`_requestId` request once finalized sending locked ether to the owner\n /// @param _requestId request id to claim\n /// @dev use unbounded loop to find a hint, which can lead to OOG\n /// @dev\n /// Reverts if requestId or hint are not valid\n /// Reverts if request is not finalized or already claimed\n /// Reverts if msg sender is not an owner of request\n function claimWithdrawal(uint256 _requestId) external;\n\n /// @notice Claim a batch of withdrawal requests if they are finalized sending locked ether to the owner\n /// @param _requestIds array of request ids to claim\n /// @param _hints checkpoint hint for each id. Can be obtained with `findCheckpointHints()`\n /// @dev\n /// Reverts if requestIds and hints arrays length differs\n /// Reverts if any requestId or hint in arguments are not valid\n /// Reverts if any request is not finalized or already claimed\n /// Reverts if msg sender is not an owner of the requests\n function claimWithdrawals(uint256[] calldata _requestIds, uint256[] calldata _hints) external;\n\n //// @notice Returns all withdrawal requests that belongs to the `_owner` address\n ///\n /// WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n /// to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n /// this function has an unbounded cost, and using it as part of a state-changing function may render the function\n /// uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n function getWithdrawalRequ
},
"contracts/protocols/steth/interfaces/iStETHQueue.sol": {
"content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.21;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport { Structs } from \"../structs.sol\";\nimport { IFluidLiquidity } from \"../../../liquidity/interfaces/iLiquidity.sol\";\nimport { ILidoWithdrawalQueue } from \"../interfaces/external/iLidoWithdrawalQueue.sol\";\n\ninterface IFluidStETHQueue {\n /// @notice returns the constant values for LIQUIDITY, LIDO_WITHDRAWAL_QUEUE, STETH\n function constantsView() external view returns (IFluidLiquidity, ILidoWithdrawalQueue, IERC20);\n\n /// @notice gets an open Claim for `claimTo_` and `requestIdFrom_`\n function claims(address claimTo_, uint256 requestIdFrom_) external view returns (Structs.Claim memory);\n\n /// @notice reads if a certain `auth_` address is an allowed auth or not\n function isAuth(address auth_) external view returns (bool);\n\n /// @notice reads if a certain `guardian_` address is an allowed guardian or not\n function isGuardian(address guardian_) external view returns (bool);\n\n /// @notice reads if a certain `user_` address is an allowed user or not\n function isUserAllowed(address user_) external view returns (bool);\n\n /// @notice maximum allowed percentage of LTV (loan-to-value). E.g. 90% -> max. 90 ETH can be borrowed with 100 stETH\n /// as collateral in withdrawal queue. ETH will be received at time of claim to cover the paid borrowed ETH amount.\n /// In 1e2 (1% = 100, 90% = 9_000, 100% = 10_000).\n /// Configurable by auths.\n function maxLTV() external view returns (uint16);\n\n /// @notice flag whether allow list behavior is enabled or not.\n function allowListActive() external view returns (bool);\n\n /// @notice reads if the protocol is paused or not\n function isPaused() external view returns (bool);\n\n /// @notice reads owner address\n function owner() external view returns (address);\n}\n"
},
"contracts/protocols/steth/main.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\nimport { UUPSUpgradeable } from \"@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol\";\n\nimport { LiquiditySlotsLink } from \"../../libraries/liquiditySlotsLink.sol\";\nimport { ILidoWithdrawalQueue } from \"./interfaces/external/iLidoWithdrawalQueue.sol\";\nimport { IFluidLiquidity } from \"../../liquidity/interfaces/iLiquidity.sol\";\nimport { ErrorTypes } from \"./errorTypes.sol\";\nimport { Error } from \"./error.sol\";\nimport { Events } from \"./events.sol\";\nimport { Variables } from \"./variables.sol\";\nimport { LiquidityCalcs } from \"../../libraries/liquidityCalcs.sol\";\n\nabstract contract StETHQueueCore is Variables, Events, Error {\n /// @dev validates that an address is not the zero address\n modifier validAddress(address value_) {\n if (value_ == address(0)) {\n revert StETHQueueError(ErrorTypes.StETH__AddressZero);\n }\n _;\n }\n\n /// @dev reads the current, updated borrow exchange price for Native ETH at Liquidity\n function _getLiquidityExchangePrice() internal view returns (uint256 borrowExchangePrice_) {\n (, borrowExchangePrice_) = LiquidityCalcs.calcExchangePrices(\n LIQUIDITY.readFromStorage(LIQUIDITY_EXCHANGE_PRICES_SLOT)\n );\n }\n}\n\n/// @dev ReentrancyGuard based on OpenZeppelin implementation.\n/// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v4.8/contracts/security/ReentrancyGuard.sol\nabstract contract ReentrancyGuard is StETHQueueCore {\n uint8 internal constant REENTRANCY_NOT_ENTERED = 1;\n uint8 internal constant REENTRANCY_ENTERED = 2;\n\n constructor() {\n _status = REENTRANCY_ENTERED; // set status to entered on logic contract so only delegateCalls are possible\n }\n\n /// @dev Prevents a contract from calling itself, directly or indirectly.\n /// See OpenZeppelin implementation for more info\n modifier nonReentrant() {\n // On the first call to nonReentrant, _status will be NOT_ENTERED\n if (_status != REENTRANCY_NOT_ENTERED) {\n revert StETHQueueError(ErrorTypes.StETH__Reentrancy);\n }\n\n // Any calls to nonReentrant after this point will fail\n _status = REENTRANCY_ENTERED;\n\n _;\n\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = REENTRANCY_NOT_ENTERED;\n }\n}\n\n/// @dev FluidStETHQueue admin related methods\nabstract contract StETHQueueAdmin is Variables, ReentrancyGuard {\n /// @dev only auths guard\n modifier onlyAuths() {\n if (!isAuth(msg.sender)) {\n revert StETHQueueError(ErrorTypes.StETH__Unauthorized);\n }\n _;\n }\n\n /// @notice reads if a certain `auth_` address is an allowed auth or not\n function isAuth(address auth_) public view returns (bool) {\n return auth_ == owner() || _auths[auth_] == 1;\n }\n\n /// @notice reads if a certain `guardian_` address is an allowed guardian or not\n function isGuardian(address guardian_) public view returns (bool) {\n return guardian_ == owner() || _guardians[guardian_] == 1;\n }\n\n /// @notice reads if a certain `user_` address is an allowed user or not\n function isUserAllowed(address user_) public view returns (bool) {\n return _allowed[user_] == 1;\n }\n\n /// @notice reads if the protocol is paused or not\n function isPaused() public view returns (bool){\n return _status == REENTRANCY_ENTERED;\n }\n\n /// @notice Sets an address as allowed auth or not. Only callable by owner.\n /// @param auth_ address to set auth value for\n /// @param allowed_ bool flag for whether
},
"contracts/protocols/steth/structs.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nabstract contract Structs {\n /// @notice Claim data struct for storage link to owner address\n struct Claim {\n /// @param borrowAmountRaw raw borrow amount at Liquidity. Multiply with borrowExchangePrice to get normal borrow amount\n uint128 borrowAmountRaw;\n /// @param checkpoint checkpoint at time of queue. optimizes finding checkpoint hints range at claim time.\n uint48 checkpoint;\n /// @param requestIdTo last request Id linked to the claim\n uint40 requestIdTo;\n // 5 bytes empty\n }\n}\n"
},
"contracts/protocols/steth/variables.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { Initializable } from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport { OwnableUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\n\nimport { LiquiditySlotsLink } from \"../../libraries/liquiditySlotsLink.sol\";\nimport { IFluidLiquidity } from \"../../liquidity/interfaces/iLiquidity.sol\";\nimport { ILidoWithdrawalQueue } from \"./interfaces/external/iLidoWithdrawalQueue.sol\";\nimport { Structs } from \"./structs.sol\";\n\nabstract contract Constants {\n /// @dev hundred percent at 1e2 precision\n uint256 internal constant HUNDRED_PERCENT = 1e4;\n\n /// @dev precision for exchange prices in Liquidity\n uint256 internal constant EXCHANGE_PRICES_PRECISION = 1e12;\n\n /// @dev address that is mapped to the chain native token at Liquidity\n address internal constant NATIVE_TOKEN_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @dev dust amount to borrow from Liquidity at initialize()\n uint256 internal constant DUST_BORROW_AMOUNT = 1e12;\n\n /// @notice address of the Liquidity contract.\n IFluidLiquidity internal immutable LIQUIDITY;\n\n /// @notice address of the Lido Withdrawal Queue contract (0x889edC2eDab5f40e902b864aD4d7AdE8E412F9B1)\n ILidoWithdrawalQueue internal immutable LIDO_WITHDRAWAL_QUEUE;\n\n /// @notice address of the StETH contract.\n IERC20 internal immutable STETH;\n\n /// @dev slot id in Liquidity contract for exchange prices storage slot for NATIVE_TOKEN_ADDRESS.\n bytes32 internal immutable LIQUIDITY_EXCHANGE_PRICES_SLOT;\n\n constructor(IFluidLiquidity liquidity_, ILidoWithdrawalQueue lidoWithdrawalQueue_, IERC20 stETH_) {\n LIQUIDITY = liquidity_;\n\n LIDO_WITHDRAWAL_QUEUE = lidoWithdrawalQueue_;\n\n STETH = stETH_;\n\n LIQUIDITY_EXCHANGE_PRICES_SLOT = LiquiditySlotsLink.calculateMappingStorageSlot(\n LiquiditySlotsLink.LIQUIDITY_EXCHANGE_PRICES_MAPPING_SLOT,\n NATIVE_TOKEN_ADDRESS\n );\n }\n\n /// @notice returns the constant values for LIQUIDITY, LIDO_WITHDRAWAL_QUEUE, STETH\n function constantsView() external view returns (IFluidLiquidity, ILidoWithdrawalQueue, IERC20) {\n return (LIQUIDITY, LIDO_WITHDRAWAL_QUEUE, STETH);\n }\n}\n\nabstract contract Variables is Initializable, OwnableUpgradeable, Constants, Structs {\n // ------------ storage variables from inherited contracts (Initializable, OwnableUpgradeable) come before vars here --------\n // @dev variables here start at storage slot 101, before is:\n // - Initializable with storage slot 0:\n // uint8 private _initialized;\n // bool private _initializing;\n // - OwnableUpgradeable with slots 1 to 100:\n // uint256[50] private __gap; (from ContextUpgradeable, slot 1 until slot 50)\n // address private _owner; (at slot 51)\n // uint256[49] private __gap; (slot 52 until slot 100)\n\n // ----------------------- slot 101 ---------------------------\n\n /// @notice maps claimTo address and requestIdFrom to the Claim struct containing necessary information for executing the claim process.\n mapping(address => mapping(uint256 => Claim)) public claims;\n\n // ----------------------- slot 102 ---------------------------\n\n /// @dev status for reentrancy guard\n uint8 internal _status;\n\n /// @notice maximum allowed percentage of LTV (loan-to-value). E.g. 90% -> max. 90 ETH can be borrowed with 100 stETH\n /// as collateral in withdrawal queue. ETH will be received at time of claim to cover the paid borrowed ETH amount.\n /// In 1e2 (1% = 100, 90% = 9_000, 100% = 10_000).\n /// Configurable by auths.\n uint16 public maxLTV;\n\n /// @notice flag whether allow list behavior is enabled or not.\n bool public allowListActive;\n\n // 28 bytes free\n\n // ----------------------- slot 103 ---------------------------\
},
"contracts/protocols/vault/error.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\ncontract Error {\n error FluidVaultError(uint256 errorId_);\n\n /// @notice used to simulate liquidation to find the maximum liquidatable amounts\n error FluidLiquidateResult(uint256 colLiquidated, uint256 debtLiquidated);\n}\n"
},
"contracts/protocols/vault/errorTypes.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nlibrary ErrorTypes {\n /***********************************|\n | Vault Factory | \n |__________________________________*/\n\n uint256 internal constant VaultFactory__InvalidOperation = 30001;\n uint256 internal constant VaultFactory__Unauthorized = 30002;\n uint256 internal constant VaultFactory__SameTokenNotAllowed = 30003;\n uint256 internal constant VaultFactory__InvalidParams = 30004;\n uint256 internal constant VaultFactory__InvalidVault = 30005;\n uint256 internal constant VaultFactory__InvalidVaultAddress = 30006;\n uint256 internal constant VaultFactory__OnlyDelegateCallAllowed = 30007;\n\n /***********************************|\n | VaultT1 | \n |__________________________________*/\n\n /// @notice thrown at reentrancy\n uint256 internal constant VaultT1__AlreadyEntered = 31001;\n\n /// @notice thrown when user sends deposit & borrow amount as 0\n uint256 internal constant VaultT1__InvalidOperateAmount = 31002;\n\n /// @notice thrown when msg.value is not in sync with native token deposit or payback\n uint256 internal constant VaultT1__InvalidMsgValueOperate = 31003;\n\n /// @notice thrown when msg.sender is not the owner of the vault\n uint256 internal constant VaultT1__NotAnOwner = 31004;\n\n /// @notice thrown when user's position does not exist. Sending the wrong index from the frontend\n uint256 internal constant VaultT1__TickIsEmpty = 31005;\n\n /// @notice thrown when the user's position is above CF and the user tries to make it more risky by trying to withdraw or borrow\n uint256 internal constant VaultT1__PositionAboveCF = 31006;\n\n /// @notice thrown when the top tick is not initialized. Happens if the vault is totally new or all the user's left\n uint256 internal constant VaultT1__TopTickDoesNotExist = 31007;\n\n /// @notice thrown when msg.value in liquidate is not in sync payback\n uint256 internal constant VaultT1__InvalidMsgValueLiquidate = 31008;\n\n /// @notice thrown when slippage is more on liquidation than what the liquidator sent\n uint256 internal constant VaultT1__ExcessSlippageLiquidation = 31009;\n\n /// @notice thrown when msg.sender is not the rebalancer/reserve contract\n uint256 internal constant VaultT1__NotRebalancer = 31010;\n\n /// @notice thrown when NFT of one vault interacts with the NFT of other vault\n uint256 internal constant VaultT1__NftNotOfThisVault = 31011;\n\n /// @notice thrown when the token is not initialized on the liquidity contract\n uint256 internal constant VaultT1__TokenNotInitialized = 31012;\n\n /// @notice thrown when admin updates fallback if a non-auth calls vault\n uint256 internal constant VaultT1__NotAnAuth = 31013;\n\n /// @notice thrown in operate when user tries to witdhraw more collateral than deposited\n uint256 internal constant VaultT1__ExcessCollateralWithdrawal = 31014;\n\n /// @notice thrown in operate when user tries to payback more debt than borrowed\n uint256 internal constant VaultT1__ExcessDebtPayback = 31015;\n\n /// @notice thrown when user try to withdrawal more than operate's withdrawal limit\n uint256 internal constant VaultT1__WithdrawMoreThanOperateLimit = 31016;\n\n /// @notice thrown when caller of liquidityCallback is not Liquidity\n uint256 internal constant VaultT1__InvalidLiquidityCallbackAddress = 31017;\n\n /// @notice thrown when reentrancy is not already on\n uint256 internal constant VaultT1__NotEntered = 31018;\n\n /// @notice thrown when someone directly calls secondary implementation contract\n uint256 internal constant VaultT1__OnlyDelegateCallAllowed = 31019;\n\n /// @notice thrown when the safeTransferFrom for a token amount failed\n uint256 internal constant VaultT1__TransferFromFailed = 31020;\n\n /// @notice thrown when exchange price overflows while updating on storage\n uint256 internal constant VaultT1__ExchangePriceOv
},
"contracts/protocols/vault/factory/deploymentLogics/vaultT1Logic.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { SSTORE2 } from \"solmate/src/utils/SSTORE2.sol\";\n\nimport { ErrorTypes } from \"../../errorTypes.sol\";\nimport { Error } from \"../../error.sol\";\nimport { IFluidVaultFactory } from \"../../interfaces/iVaultFactory.sol\";\n\nimport { LiquiditySlotsLink } from \"../../../../libraries/liquiditySlotsLink.sol\";\n\nimport { IFluidVaultT1 } from \"../../interfaces/iVaultT1.sol\";\nimport { FluidVaultT1 } from \"../../vaultT1/coreModule/main.sol\";\n\ninterface IERC20 {\n function decimals() external view returns (uint8);\n}\n\ncontract FluidVaultT1DeploymentLogic is Error {\n address internal constant NATIVE_TOKEN = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @dev SSTORE2 pointer for the VaultT1 creation code. Stored externally to reduce factory bytecode (in 2 parts)\n address internal immutable VAULT_T1_CREATIONCODE_ADDRESS_1;\n address internal immutable VAULT_T1_CREATIONCODE_ADDRESS_2;\n\n /// @notice address of liquidity contract\n address public immutable LIQUIDITY;\n\n /// @notice address of Admin implementation\n address public immutable ADMIN_IMPLEMENTATION;\n\n /// @notice address of Secondary implementation\n address public immutable SECONDARY_IMPLEMENTATION;\n\n /// @notice address of this contract\n address public immutable ADDRESS_THIS;\n\n /// @notice Emitted when a new vaultT1 is deployed.\n /// @param vault The address of the newly deployed vault.\n /// @param vaultId The id of the newly deployed vault.\n /// @param supplyToken The address of the supply token.\n /// @param borrowToken The address of the borrow token.\n event VaultT1Deployed(\n address indexed vault,\n uint256 vaultId,\n address indexed supplyToken,\n address indexed borrowToken\n );\n\n constructor(address liquidity_, address vaultAdminImplementation_, address vaultSecondaryImplementation_) {\n LIQUIDITY = liquidity_;\n ADMIN_IMPLEMENTATION = vaultAdminImplementation_;\n SECONDARY_IMPLEMENTATION = vaultSecondaryImplementation_;\n\n // split storing creation code into two SSTORE2 pointers, because:\n // due to contract code limits 24576 bytes is the maximum amount of data that can be written in a single pointer / key.\n // Attempting to write more will result in failure.\n // So by splitting in two parts we can make sure that the contract bytecode size can use up the full limit of 24576 bytes.\n uint256 creationCodeLength_ = type(FluidVaultT1).creationCode.length;\n VAULT_T1_CREATIONCODE_ADDRESS_1 = SSTORE2.write(\n _bytesSlice(type(FluidVaultT1).creationCode, 0, creationCodeLength_ / 2)\n );\n // slice lengths:\n // when even length, e.g. 250:\n // part 1 = 0 -> 250 / 2, so 0 until 125 length, so 0 -> 125\n // part 2 = 250 / 2 -> 250 - 250 / 2, so 125 until 125 length, so 125 -> 250\n // when odd length: e.g. 251:\n // part 1 = 0 -> 251 / 2, so 0 until 125 length, so 0 -> 125\n // part 2 = 251 / 2 -> 251 - 251 / 2, so 125 until 126 length, so 125 -> 251\n VAULT_T1_CREATIONCODE_ADDRESS_2 = SSTORE2.write(\n _bytesSlice(\n type(FluidVaultT1).creationCode,\n creationCodeLength_ / 2,\n creationCodeLength_ - creationCodeLength_ / 2\n )\n );\n\n ADDRESS_THIS = address(this);\n }\n\n /// @notice Computes vaultT1 bytecode for the given supply token (`supplyToken_`) and borrow token (`borrowToken_`).\n /// This will be called by the VaultFactory via .delegateCall\n /// @param supplyToken_ The address of the supply token.\n /// @param borrowToken_ The address of the borrow token.\n /// @return vaultCreationBytecode_ Returns the bytecode of the new vault to deploy.\n function vaultT1(\n address supplyToken_,\n addre
},
"contracts/protocols/vault/interfaces/iVaultFactory.sol": {
"content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.21;\n\nimport { IERC721Enumerable } from \"@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol\";\n\ninterface IFluidVaultFactory is IERC721Enumerable {\n /// @notice Minting an NFT Vault for the user\n function mint(uint256 vaultId_, address user_) external returns (uint256 tokenId_);\n\n /// @notice returns owner of Vault which is also an NFT\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /// @notice Global auth is auth for all vaults\n function isGlobalAuth(address auth_) external view returns (bool);\n\n /// @notice Vault auth is auth for a specific vault\n function isVaultAuth(address vault_, address auth_) external view returns (bool);\n\n /// @notice Total vaults deployed.\n function totalVaults() external view returns (uint256);\n\n /// @notice Compute vaultAddress\n function getVaultAddress(uint256 vaultId) external view returns (address);\n\n /// @notice read uint256 `result_` for a storage `slot_` key\n function readFromStorage(bytes32 slot_) external view returns (uint256 result_);\n}\n"
},
"contracts/protocols/vault/interfaces/iVaultT1.sol": {
"content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.21;\n\ninterface IFluidVaultT1 {\n /// @notice returns the vault id\n function VAULT_ID() external view returns (uint256);\n\n /// @notice reads uint256 data `result_` from storage at a bytes32 storage `slot_` key.\n function readFromStorage(bytes32 slot_) external view returns (uint256 result_);\n\n struct ConstantViews {\n address liquidity;\n address factory;\n address adminImplementation;\n address secondaryImplementation;\n address supplyToken;\n address borrowToken;\n uint8 supplyDecimals;\n uint8 borrowDecimals;\n uint vaultId;\n bytes32 liquiditySupplyExchangePriceSlot;\n bytes32 liquidityBorrowExchangePriceSlot;\n bytes32 liquidityUserSupplySlot;\n bytes32 liquidityUserBorrowSlot;\n }\n\n /// @notice returns all Vault constants\n function constantsView() external view returns (ConstantViews memory constantsView_);\n\n /// @notice fetches the latest user position after a liquidation\n function fetchLatestPosition(\n int256 positionTick_,\n uint256 positionTickId_,\n uint256 positionRawDebt_,\n uint256 tickData_\n )\n external\n view\n returns (\n int256, // tick\n uint256, // raw debt\n uint256, // raw collateral\n uint256, // branchID_\n uint256 // branchData_\n );\n\n /// @notice calculates the updated vault exchange prices\n function updateExchangePrices(\n uint256 vaultVariables2_\n )\n external\n view\n returns (\n uint256 liqSupplyExPrice_,\n uint256 liqBorrowExPrice_,\n uint256 vaultSupplyExPrice_,\n uint256 vaultBorrowExPrice_\n );\n\n /// @notice calculates the updated vault exchange prices and writes them to storage\n function updateExchangePricesOnStorage()\n external\n returns (\n uint256 liqSupplyExPrice_,\n uint256 liqBorrowExPrice_,\n uint256 vaultSupplyExPrice_,\n uint256 vaultBorrowExPrice_\n );\n\n /// @notice returns the liquidity contract address\n function LIQUIDITY() external view returns (address);\n\n function operate(\n uint256 nftId_, // if 0 then new position\n int256 newCol_, // if negative then withdraw\n int256 newDebt_, // if negative then payback\n address to_ // address at which the borrow & withdraw amount should go to. If address(0) then it'll go to msg.sender\n )\n external\n payable\n returns (\n uint256, // nftId_\n int256, // final supply amount. if - then withdraw\n int256 // final borrow amount. if - then payback\n );\n \n function liquidate(\n uint256 debtAmt_,\n uint256 colPerUnitDebt_, // min collateral needed per unit of debt in 1e18\n address to_,\n bool absorb_\n ) external payable returns (uint actualDebtAmt_, uint actualColAmt_);\n\n function absorb() external;\n\n function rebalance() external payable returns (int supplyAmt_, int borrowAmt_);\n\n error FluidLiquidateResult(uint256 colLiquidated, uint256 debtLiquidated);\n}\n"
},
"contracts/protocols/vault/rewards/events.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nabstract contract Events {\n /// @notice Emitted when magnifier is updated\n event LogUpdateMagnifier(address indexed vault, uint256 newMagnifier);\n\n /// @notice Emitted when rewards are started\n event LogRewardsStarted(uint256 startTime, uint256 endTime);\n}\n"
},
"contracts/protocols/vault/rewards/main.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { FluidVaultT1Admin } from \"../vaultT1/adminModule/main.sol\";\nimport { IFluidVaultT1 } from \"../interfaces/iVaultT1.sol\";\nimport { IFluidReserveContract } from \"../../../reserve/interfaces/iReserveContract.sol\";\nimport { LiquiditySlotsLink } from \"../../../libraries/liquiditySlotsLink.sol\";\nimport { Events } from \"./events.sol\";\nimport { Variables } from \"./variables.sol\";\nimport { ErrorTypes } from \"../errorTypes.sol\";\nimport { Error } from \"../error.sol\";\nimport { IFluidLiquidity } from \"../../../liquidity/interfaces/iLiquidity.sol\";\n\n/// @title VaultRewards\n/// @notice This contract is designed to adjust the supply rate magnifier for a vault based on the current collateral supply & supply rate.\n/// The adjustment aims to dynamically scale the rewards given to lenders as the TVL in the vault changes.\n///\n/// The magnifier is adjusted based on a regular most used reward type where rewardRate = totalRewardsAnnually / totalSupply.\n/// Reward rate is applied by adjusting the supply magnifier on vault.\n/// Adjustments are made via the rebalance function, which is restricted to be called by designated rebalancers only.\ncontract FluidVaultRewards is Variables, Events, Error {\n /// @dev Validates that an address is not the zero address\n modifier validAddress(address value_) {\n if (value_ == address(0)) {\n revert FluidVaultError(ErrorTypes.VaultRewards__AddressZero);\n }\n _;\n }\n\n /// @dev Validates that an address is a rebalancer (taken from reserve contract)\n modifier onlyRebalancer() {\n if (!RESERVE_CONTRACT.isRebalancer(msg.sender)) {\n revert FluidVaultError(ErrorTypes.VaultRewards__Unauthorized);\n }\n _;\n }\n\n /// @notice Constructs the FluidVaultRewards contract.\n /// @param reserveContract_ The address of the reserve contract where rebalancers are defined.\n /// @param vault_ The vault to which this contract will apply new magnifier parameter.\n /// @param liquidity_ Fluid liquidity address\n /// @param rewardsAmt_ Amounts of rewards to distribute\n /// @param duration_ rewards duration\n /// @param initiator_ address that can start rewards with `start()`\n /// @param collateralToken_ vault collateral token address\n constructor(\n IFluidReserveContract reserveContract_,\n IFluidVaultT1 vault_,\n IFluidLiquidity liquidity_,\n uint256 rewardsAmt_,\n uint256 duration_,\n address initiator_,\n address collateralToken_\n ) validAddress(address(reserveContract_)) validAddress(address(liquidity_)) validAddress(address(vault_)) validAddress(initiator_) validAddress(address(collateralToken_)){\n if (rewardsAmt_ == 0 || duration_ == 0) {\n revert FluidVaultError(ErrorTypes.VaultRewards__InvalidParams);\n }\n RESERVE_CONTRACT = reserveContract_;\n VAULT = vault_;\n REWARDS_AMOUNT = rewardsAmt_;\n REWARDS_AMOUNT_PER_YEAR = rewardsAmt_ * SECONDS_PER_YEAR / duration_;\n DURATION = duration_;\n INITIATOR = initiator_;\n LIQUIDITY = liquidity_;\n VAULT_COLLATERAL_TOKEN = collateralToken_;\n\n LIQUIDITY_TOTAL_AMOUNTS_COLLATERAL_TOKEN_SLOT = LiquiditySlotsLink.calculateMappingStorageSlot(\n LiquiditySlotsLink.LIQUIDITY_TOTAL_AMOUNTS_MAPPING_SLOT,\n collateralToken_\n );\n LIQUIDITY_EXCHANGE_PRICE_COLLATERAL_TOKEN_SLOT = LiquiditySlotsLink.calculateMappingStorageSlot(\n LiquiditySlotsLink.LIQUIDITY_EXCHANGE_PRICES_MAPPING_SLOT,\n collateralToken_\n );\n }\n\n /// @notice Rebalances the supply rate magnifier based on the current collateral supply.\n /// Can only be called by an authorized rebalancer.\n function rebalance() external onlyRebalancer {\n (uint256 newMagnifier_, bool ended_) = calculateMagnifier();\n if (ended_) {\n ended = true;\n }\n
},
"contracts/protocols/vault/rewards/variables.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IFluidReserveContract } from \"../../../reserve/interfaces/iReserveContract.sol\";\nimport { IFluidVaultT1 } from \"../interfaces/iVaultT1.sol\";\nimport { IFluidLiquidity } from \"../../../liquidity/interfaces/iLiquidity.sol\";\n\nabstract contract Constants {\n IFluidLiquidity public immutable LIQUIDITY;\n IFluidReserveContract public immutable RESERVE_CONTRACT;\n IFluidVaultT1 public immutable VAULT;\n uint256 public immutable REWARDS_AMOUNT;\n uint256 public immutable REWARDS_AMOUNT_PER_YEAR;\n uint256 public immutable DURATION;\n address public immutable INITIATOR;\n address public immutable VAULT_COLLATERAL_TOKEN;\n\n bytes32 internal immutable LIQUIDITY_TOTAL_AMOUNTS_COLLATERAL_TOKEN_SLOT;\n bytes32 internal immutable LIQUIDITY_EXCHANGE_PRICE_COLLATERAL_TOKEN_SLOT;\n uint256 internal constant FOUR_DECIMALS = 10000;\n uint256 internal constant SECONDS_PER_YEAR = 365 days;\n uint256 internal constant DEFAULT_EXPONENT_SIZE = 8;\n uint256 internal constant DEFAULT_EXPONENT_MASK = 0xff;\n uint256 internal constant EXCHANGE_PRICES_PRECISION = 1e12;\n uint256 internal constant X14 = 0x3fff;\n uint256 internal constant X16 = 0xffff;\n uint256 internal constant X64 = 0xffffffffffffffff;\n}\n\nabstract contract Variables is Constants {\n bool public ended; // when rewards are ended\n uint96 public startTime;\n uint96 public endTime;\n}\n"
},
"contracts/protocols/vault/vaultT1/adminModule/events.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\ncontract Events {\n /// @notice emitted when the supply rate magnifier config is updated\n event LogUpdateSupplyRateMagnifier(uint supplyRateMagnifier_);\n\n /// @notice emitted when the borrow rate magnifier config is updated\n event LogUpdateBorrowRateMagnifier(uint borrowRateMagnifier_);\n\n /// @notice emitted when the collateral factor config is updated\n event LogUpdateCollateralFactor(uint collateralFactor_);\n\n /// @notice emitted when the liquidation threshold config is updated\n event LogUpdateLiquidationThreshold(uint liquidationThreshold_);\n\n /// @notice emitted when the liquidation max limit config is updated\n event LogUpdateLiquidationMaxLimit(uint liquidationMaxLimit_);\n\n /// @notice emitted when the withdrawal gap config is updated\n event LogUpdateWithdrawGap(uint withdrawGap_);\n\n /// @notice emitted when the liquidation penalty config is updated\n event LogUpdateLiquidationPenalty(uint liquidationPenalty_);\n\n /// @notice emitted when the borrow fee config is updated\n event LogUpdateBorrowFee(uint borrowFee_);\n\n /// @notice emitted when the core setting configs are updated\n event LogUpdateCoreSettings(\n uint supplyRateMagnifier_,\n uint borrowRateMagnifier_,\n uint collateralFactor_,\n uint liquidationThreshold_,\n uint liquidationMaxLimit_,\n uint withdrawGap_,\n uint liquidationPenalty_,\n uint borrowFee_\n );\n\n /// @notice emitted when the oracle is updated\n event LogUpdateOracle(address indexed newOracle_);\n\n /// @notice emitted when the allowed rebalancer is updated\n event LogUpdateRebalancer(address indexed newRebalancer_);\n\n /// @notice emitted when funds are rescued\n event LogRescueFunds(address indexed token_);\n\n /// @notice emitted when dust debt is absorbed for `nftIds_`\n event LogAbsorbDustDebt(uint256[] nftIds_, uint256 absorbedDustDebt_);\n}\n"
},
"contracts/protocols/vault/vaultT1/adminModule/main.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\n\nimport { Variables } from \"../common/variables.sol\";\nimport { Events } from \"./events.sol\";\nimport { ErrorTypes } from \"../../errorTypes.sol\";\nimport { Error } from \"../../error.sol\";\nimport { IFluidVaultT1 } from \"../../interfaces/iVaultT1.sol\";\nimport { BigMathMinified } from \"../../../../libraries/bigMathMinified.sol\";\nimport { TickMath } from \"../../../../libraries/tickMath.sol\";\n\n/// @notice Fluid Vault protocol Admin Module contract.\n/// Implements admin related methods to set configs such as liquidation params, rates\n/// oracle address etc.\n/// Methods are limited to be called via delegateCall only. Vault CoreModule (\"VaultT1\" contract)\n/// is expected to call the methods implemented here after checking the msg.sender is authorized.\n/// All methods update the exchange prices in storage before changing configs.\ncontract FluidVaultT1Admin is Variables, Events, Error {\n uint private constant X8 = 0xff;\n uint private constant X10 = 0x3ff;\n uint private constant X16 = 0xffff;\n uint private constant X19 = 0x7ffff;\n uint private constant X24 = 0xffffff;\n uint internal constant X64 = 0xffffffffffffffff;\n uint private constant X96 = 0xffffffffffffffffffffffff;\n address private constant NATIVE_TOKEN = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n address private immutable addressThis;\n\n constructor() {\n addressThis = address(this);\n }\n\n modifier _verifyCaller() {\n if (address(this) == addressThis) {\n revert FluidVaultError(ErrorTypes.VaultT1Admin__OnlyDelegateCallAllowed);\n }\n _;\n }\n\n /// @dev updates exchange price on storage, called on all admin methods in combination with _verifyCaller modifier so\n /// only called by authorized delegatecall\n modifier _updateExchangePrice() {\n IFluidVaultT1(address(this)).updateExchangePricesOnStorage();\n _;\n }\n\n function _checkLiquidationMaxLimitAndPenalty(uint liquidationMaxLimit_, uint liquidationPenalty_) private pure {\n // liquidation max limit with penalty should not go above 99.7%\n // As liquidation with penalty can happen from liquidation Threshold to max limit\n // If it goes above 100% than that means liquidator is getting more collateral than user's available\n if ((liquidationMaxLimit_ + liquidationPenalty_) > 9970) {\n revert FluidVaultError(ErrorTypes.VaultT1Admin__ValueAboveLimit);\n }\n }\n\n /// @notice updates the supply rate magnifier to `supplyRateMagnifier_`. Input in 1e2 (1% = 100, 100% = 10_000).\n function updateSupplyRateMagnifier(uint supplyRateMagnifier_) public _updateExchangePrice _verifyCaller {\n emit LogUpdateSupplyRateMagnifier(supplyRateMagnifier_);\n\n if (supplyRateMagnifier_ > X16) revert FluidVaultError(ErrorTypes.VaultT1Admin__ValueAboveLimit);\n\n vaultVariables2 =\n (vaultVariables2 & 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000) |\n supplyRateMagnifier_;\n }\n\n /// @notice updates the borrow rate magnifier to `borrowRateMagnifier_`. Input in 1e2 (1% = 100, 100% = 10_000).\n function updateBorrowRateMagnifier(uint borrowRateMagnifier_) public _updateExchangePrice _verifyCaller {\n emit LogUpdateBorrowRateMagnifier(borrowRateMagnifier_);\n\n if (borrowRateMagnifier_ > X16) revert FluidVaultError(ErrorTypes.VaultT1Admin__ValueAboveLimit);\n\n vaultVariables2 =\n (vaultVariables2 & 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffff) |\n (borrowRateMagnifier_ << 16);\n }\n\n /// @notice updates the collateral factor to `collateralFactor_`.
},
"contracts/protocols/vault/vaultT1/common/variables.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\ncontract Variables {\n /***********************************|\n | Storage Variables |\n |__________________________________*/\n\n /// note: in all variables. For tick >= 0 are represented with bit as 1, tick < 0 are represented with bit as 0\n /// note: read all the variables through storageRead.sol\n\n /// note: vaultVariables contains vault variables which need regular updates through transactions\n /// First 1 bit => 0 => re-entrancy. If 0 then allow transaction to go, else throw.\n /// Next 1 bit => 1 => Is the current active branch liquidated? If true then check the branch's minima tick before creating a new position\n /// If the new tick is greater than minima tick then initialize a new branch, make that as current branch & do proper linking\n /// Next 1 bit => 2 => sign of topmost tick (0 -> negative; 1 -> positive)\n /// Next 19 bits => 3-21 => absolute value of topmost tick\n /// Next 30 bits => 22-51 => current branch ID\n /// Next 30 bits => 52-81 => total branch ID\n /// Next 64 bits => 82-145 => Total supply\n /// Next 64 bits => 146-209 => Total borrow\n /// Next 32 bits => 210-241 => Total positions\n uint256 internal vaultVariables;\n\n /// note: vaultVariables2 contains variables which do not update on every transaction. So mainly admin/auth set amount\n /// First 16 bits => 0-15 => supply rate magnifier; 10000 = 1x (Here 16 bits should be more than enough)\n /// Next 16 bits => 16-31 => borrow rate magnifier; 10000 = 1x (Here 16 bits should be more than enough)\n /// Next 10 bits => 32-41 => collateral factor. 800 = 0.8 = 80% (max precision of 0.1%)\n /// Next 10 bits => 42-51 => liquidation Threshold. 900 = 0.9 = 90% (max precision of 0.1%)\n /// Next 10 bits => 52-61 => liquidation Max Limit. 950 = 0.95 = 95% (max precision of 0.1%) (above this 100% liquidation can happen)\n /// Next 10 bits => 62-71 => withdraw gap. 100 = 0.1 = 10%. (max precision of 0.1%) (max 7 bits can also suffice for the requirement here of 0.1% to 10%). Needed to save some limits on withdrawals so liquidate can work seamlessly.\n /// Next 10 bits => 72-81 => liquidation penalty. 100 = 0.01 = 1%. (max precision of 0.01%) (max liquidation penantly can be 10.23%). Applies when tick is in between liquidation Threshold & liquidation Max Limit.\n /// Next 10 bits => 82-91 => borrow fee. 100 = 0.01 = 1%. (max precision of 0.01%) (max borrow fee can be 10.23%). Fees on borrow.\n /// Next 4 bits => 92-95 => empty\n /// Next 160 bits => 96-255 => Oracle address\n uint256 internal vaultVariables2;\n\n /// note: stores absorbed liquidity\n /// First 128 bits raw debt amount\n /// last 128 bits raw col amount\n uint256 internal absorbedLiquidity;\n\n /// position index => position data uint\n /// if the entire variable is 0 (meaning not initialized) at the start that means no position at all\n /// First 1 bit => 0 => position type (0 => borrow position; 1 => supply position)\n /// Next 1 bit => 1 => sign of user's tick (0 => negative; 1 => positive)\n /// Next 19 bits => 2-20 => absolute value of user's tick\n /// Next 24 bits => 21-44 => user's tick's id\n /// Below we are storing user's collateral & not debt, because the position can also be only collateral with no tick but it can never be only debt\n /// Next 64 bits => 45-108 => user's supply amount. Debt will be calculated through supply & ratio.\n /// Next 64 bits => 109-172 => user's dust debt amount. User's net debt = total debt - dust amount. Total debt is calculated through supply & ratio\n /// User won't pay any extra interest on dust debt & hence we will not show it as a debt on UI. For user's there's no dust.\n mapping(uint256 => uint256) internal positionData;\n\n /// Tick has debt only keeps data of non liquidated positions. liquidated tick's data stays in branch itself\n /// tick parent => uint (represents bool for 256 children)\n /// par
},
"contracts/protocols/vault/vaultT1/coreModule/constantVariables.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IFluidVaultFactory } from \"../../interfaces/iVaultFactory.sol\";\nimport { IFluidLiquidity } from \"../../../../liquidity/interfaces/iLiquidity.sol\";\nimport { StorageRead } from \"../../../../libraries/storageRead.sol\";\n\nimport { Structs } from \"./structs.sol\";\n\ninterface TokenInterface {\n function decimals() external view returns (uint8);\n}\n\ncontract ConstantVariables is StorageRead, Structs {\n /***********************************|\n | Constant Variables |\n |__________________________________*/\n\n address internal constant NATIVE_TOKEN = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n /// @dev collateral token address\n address internal immutable SUPPLY_TOKEN;\n /// @dev borrow token address\n address internal immutable BORROW_TOKEN;\n\n /// @dev Token decimals. For example wETH is 18 decimals\n uint8 internal immutable SUPPLY_DECIMALS;\n /// @dev Token decimals. For example USDC is 6 decimals\n uint8 internal immutable BORROW_DECIMALS;\n\n /// @dev VaultT1 AdminModule implemenation address\n address internal immutable ADMIN_IMPLEMENTATION;\n\n /// @dev VaultT1 Secondary implemenation (main2.sol) address\n address internal immutable SECONDARY_IMPLEMENTATION;\n\n /// @dev liquidity proxy contract address\n IFluidLiquidity public immutable LIQUIDITY;\n\n /// @dev vault factory contract address\n IFluidVaultFactory public immutable VAULT_FACTORY;\n\n uint public immutable VAULT_ID;\n\n uint internal constant X8 = 0xff;\n uint internal constant X10 = 0x3ff;\n uint internal constant X16 = 0xffff;\n uint internal constant X19 = 0x7ffff;\n uint internal constant X20 = 0xfffff;\n uint internal constant X24 = 0xffffff;\n uint internal constant X25 = 0x1ffffff;\n uint internal constant X30 = 0x3fffffff;\n uint internal constant X35 = 0x7ffffffff;\n uint internal constant X50 = 0x3ffffffffffff;\n uint internal constant X64 = 0xffffffffffffffff;\n uint internal constant X96 = 0xffffffffffffffffffffffff;\n uint internal constant X128 = 0xffffffffffffffffffffffffffffffff;\n\n uint256 internal constant EXCHANGE_PRICES_PRECISION = 1e12;\n\n /// @dev slot ids in Liquidity contract. Helps in low gas fetch from liquidity contract by skipping delegate call\n bytes32 internal immutable LIQUIDITY_SUPPLY_EXCHANGE_PRICE_SLOT;\n bytes32 internal immutable LIQUIDITY_BORROW_EXCHANGE_PRICE_SLOT;\n bytes32 internal immutable LIQUIDITY_USER_SUPPLY_SLOT;\n bytes32 internal immutable LIQUIDITY_USER_BORROW_SLOT;\n\n /// @notice returns all Vault constants\n function constantsView() external view returns (ConstantViews memory constantsView_) {\n constantsView_.liquidity = address(LIQUIDITY);\n constantsView_.factory = address(VAULT_FACTORY);\n constantsView_.adminImplementation = ADMIN_IMPLEMENTATION;\n constantsView_.secondaryImplementation = SECONDARY_IMPLEMENTATION;\n constantsView_.supplyToken = SUPPLY_TOKEN;\n constantsView_.borrowToken = BORROW_TOKEN;\n constantsView_.supplyDecimals = SUPPLY_DECIMALS;\n constantsView_.borrowDecimals = BORROW_DECIMALS;\n constantsView_.vaultId = VAULT_ID;\n constantsView_.liquiditySupplyExchangePriceSlot = LIQUIDITY_SUPPLY_EXCHANGE_PRICE_SLOT;\n constantsView_.liquidityBorrowExchangePriceSlot = LIQUIDITY_BORROW_EXCHANGE_PRICE_SLOT;\n constantsView_.liquidityUserSupplySlot = LIQUIDITY_USER_SUPPLY_SLOT;\n constantsView_.liquidityUserBorrowSlot = LIQUIDITY_USER_BORROW_SLOT;\n }\n\n constructor(ConstantViews memory constants_) {\n LIQUIDITY = IFluidLiquidity(constants_.liquidity);\n VAULT_FACTORY = IFluidVaultFactory(constants_.factory);\n VAULT_ID = constants_.vaultId;\n\n SUPPLY_TOKEN = constants_.supplyToken;\n BORROW_TOKEN = constants_.borrowToken;\n SUPPLY_DECIMALS = constants_.supplyDecimals;\n BORROW_DECIMALS = constants_
},
"contracts/protocols/vault/vaultT1/coreModule/events.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\ncontract Events {\n /// @notice emitted when an operate() method is executed that changes collateral (`colAmt_`) / debt (debtAmt_`)\n /// amount for a `user_` position with `nftId_`. Receiver of any funds is the address `to_`.\n event LogOperate(address user_, uint256 nftId_, int256 colAmt_, int256 debtAmt_, address to_);\n\n /// @notice emitted when the exchange prices are updated in storage.\n event LogUpdateExchangePrice(uint256 supplyExPrice_, uint256 borrowExPrice_);\n\n /// @notice emitted when a liquidation has been executed.\n event LogLiquidate(address liquidator_, uint256 colAmt_, uint256 debtAmt_, address to_);\n\n /// @notice emitted when `absorb()` was executed to absorb bad debt.\n event LogAbsorb(uint colAbsorbedRaw_, uint debtAbsorbedRaw_);\n\n /// @notice emitted when a `rebalance()` has been executed, balancing out total supply / borrow between Vault\n /// and Fluid Liquidity pools.\n /// if `colAmt_` is positive then profit, meaning withdrawn from vault and sent to rebalancer address.\n /// if `colAmt_` is negative then loss, meaning transfer from rebalancer address to vault and deposit.\n /// if `debtAmt_` is positive then profit, meaning borrow from vault and sent to rebalancer address.\n /// if `debtAmt_` is negative then loss, meaning transfer from rebalancer address to vault and payback.\n event LogRebalance(int colAmt_, int debtAmt_);\n}\n"
},
"contracts/protocols/vault/vaultT1/coreModule/helpers.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { Variables } from \"../common/variables.sol\";\nimport { ConstantVariables } from \"./constantVariables.sol\";\nimport { Events } from \"./events.sol\";\nimport { TickMath } from \"../../../../libraries/tickMath.sol\";\nimport { BigMathMinified } from \"../../../../libraries/bigMathMinified.sol\";\nimport { BigMathVault } from \"../../../../libraries/bigMathVault.sol\";\nimport { LiquidityCalcs } from \"../../../../libraries/liquidityCalcs.sol\";\n\nimport { ErrorTypes } from \"../../errorTypes.sol\";\nimport { Error } from \"../../error.sol\";\n\n/// @dev Fluid vault protocol helper methods. Mostly used for `operate()` and `liquidate()` methods of CoreModule.\nabstract contract Helpers is Variables, ConstantVariables, Events, Error {\n using BigMathMinified for uint256;\n using BigMathVault for uint256;\n\n /// @notice Calculates new vault exchange prices. Does not update values in storage.\n /// @param vaultVariables2_ exactly same as vaultVariables2 from storage\n /// @return liqSupplyExPrice_ latest liquidity's supply token supply exchange price\n /// @return liqBorrowExPrice_ latest liquidity's borrow token borrow exchange price\n /// @return vaultSupplyExPrice_ latest vault's supply token exchange price\n /// @return vaultBorrowExPrice_ latest vault's borrow token exchange price\n function updateExchangePrices(\n uint256 vaultVariables2_\n )\n public\n view\n returns (\n uint256 liqSupplyExPrice_,\n uint256 liqBorrowExPrice_,\n uint256 vaultSupplyExPrice_,\n uint256 vaultBorrowExPrice_\n )\n {\n // Fetching last stored rates\n uint rates_ = rates;\n\n (liqSupplyExPrice_, ) = LiquidityCalcs.calcExchangePrices(\n LIQUIDITY.readFromStorage(LIQUIDITY_SUPPLY_EXCHANGE_PRICE_SLOT)\n );\n (, liqBorrowExPrice_) = LiquidityCalcs.calcExchangePrices(\n LIQUIDITY.readFromStorage(LIQUIDITY_BORROW_EXCHANGE_PRICE_SLOT)\n );\n\n uint256 oldLiqSupplyExPrice_ = (rates_ & X64);\n uint256 oldLiqBorrowExPrice_ = ((rates_ >> 64) & X64);\n if (liqSupplyExPrice_ < oldLiqSupplyExPrice_ || liqBorrowExPrice_ < oldLiqBorrowExPrice_) {\n // new liquidity exchange price is < than the old one. liquidity exchange price should only ever increase.\n // If not, something went wrong and avoid proceeding with unknown outcome.\n revert FluidVaultError(ErrorTypes.VaultT1__LiquidityExchangePriceUnexpected);\n }\n\n // liquidity Exchange Prices always increases in next block. Hence substraction with old will never be negative\n // uint64 * 1e18 is the max the number that could be\n unchecked {\n // Calculating increase in supply exchange price w.r.t last stored liquidity's exchange price\n // vaultSupplyExPrice_ => supplyIncreaseInPercent_\n vaultSupplyExPrice_ = ((((liqSupplyExPrice_ * 1e18) / oldLiqSupplyExPrice_) - 1e18) *\n (vaultVariables2_ & X16)) / 10000; // supply rate magnifier\n\n // Calculating increase in borrow exchange price w.r.t last stored liquidity's exchange price\n // vaultBorrowExPrice_ => borrowIncreaseInPercent_\n vaultBorrowExPrice_ = ((((liqBorrowExPrice_ * 1e18) / oldLiqBorrowExPrice_) - 1e18) *\n ((vaultVariables2_ >> 16) & X16)) / 10000; // borrow rate magnifier\n\n // It's extremely hard the exchange prices to overflow even in 100 years but if it does it's not an\n // issue here as we are not updating on storage\n // (rates_ >> 128) & X64) -> last stored vault's supply token exchange price\n vaultSupplyExPrice_ = (((rates_ >> 128) & X64) * (1e18 + vaultSupplyExPrice_)) / 1e18;\n // (rates_ >> 192) -> last stored vault's borrow token exchange price (no need to mask with & X64 as it is anyway max 64 bits)\n vaultBorrowExPrice_
},
"contracts/protocols/vault/vaultT1/coreModule/main.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IFluidOracle } from \"../../../../oracle/fluidOracle.sol\";\n\nimport { TickMath } from \"../../../../libraries/tickMath.sol\";\nimport { BigMathMinified } from \"../../../../libraries/bigMathMinified.sol\";\nimport { BigMathVault } from \"../../../../libraries/bigMathVault.sol\";\nimport { LiquidityCalcs } from \"../../../../libraries/liquidityCalcs.sol\";\nimport { SafeTransfer } from \"../../../../libraries/safeTransfer.sol\";\n\nimport { Helpers } from \"./helpers.sol\";\nimport { LiquiditySlotsLink } from \"../../../../libraries/liquiditySlotsLink.sol\";\n\nimport { ErrorTypes } from \"../../errorTypes.sol\";\n\n/// @notice Fluid \"VaultT1\" (Vault Type 1). Fluid vault protocol main contract.\n/// Fluid Vault protocol is a borrow / lending protocol, allowing users to create collateral / borrow positions.\n/// All funds are deposited into / borrowed from Fluid Liquidity layer.\n/// Positions are represented through NFTs minted by the VaultFactory.\n/// Deployed by \"VaultFactory\" and linked together with VaultT1 AdminModule `ADMIN_IMPLEMENTATION` and\n/// FluidVaultT1Secondary (main2.sol) `SECONDARY_IMPLEMENTATION`.\n/// AdminModule & FluidVaultT1Secondary methods are delegateCalled, if the msg.sender has the required authorization.\n/// This contract links to an Oracle, which is used to assess collateral / debt value. Oracles implement the\n/// \"FluidOracle\" base contract and return the price in 1e27 precision.\n/// @dev For view methods / accessing data, use the \"VaultResolver\" periphery contract.\ncontract FluidVaultT1 is Helpers {\n using BigMathMinified for uint256;\n using BigMathVault for uint256;\n\n /// @dev Single function which handles supply, withdraw, borrow & payback\n /// @param nftId_ NFT ID for interaction. If 0 then create new NFT/position.\n /// @param newCol_ new collateral. If positive then deposit, if negative then withdraw, if 0 then do nohing\n /// @param newDebt_ new debt. If positive then borrow, if negative then payback, if 0 then do nohing\n /// @param to_ address where withdraw or borrow should go. If address(0) then msg.sender\n /// @return nftId_ if 0 then this returns the newly created NFT Id else returns the same NFT ID\n /// @return newCol_ final supply amount. Mainly if max withdraw using type(int).min then this is useful to get perfect amount else remain same as newCol_\n /// @return newDebt_ final borrow amount. Mainly if max payback using type(int).min then this is useful to get perfect amount else remain same as newDebt_\n function operate(\n uint256 nftId_, // if 0 then new position\n int256 newCol_, // if negative then withdraw\n int256 newDebt_, // if negative then payback\n address to_ // address at which the borrow & withdraw amount should go to. If address(0) then it'll go to msg.sender\n )\n public\n payable\n returns (\n uint256, // nftId_\n int256, // final supply amount. if - then withdraw\n int256 // final borrow amount. if - then payback\n )\n {\n uint256 vaultVariables_ = vaultVariables;\n // re-entrancy check\n if (vaultVariables_ & 1 == 0) {\n // Updating on storage\n vaultVariables = vaultVariables_ | 1;\n } else {\n revert FluidVaultError(ErrorTypes.VaultT1__AlreadyEntered);\n }\n\n if (\n (newCol_ == 0 && newDebt_ == 0) ||\n // withdrawal or deposit cannot be too small\n ((newCol_ != 0) && (newCol_ > -10000 && newCol_ < 10000)) ||\n // borrow or payback cannot be too small\n ((newDebt_ != 0) && (newDebt_ > -10000 && newDebt_ < 10000))\n ) {\n revert FluidVaultError(ErrorTypes.VaultT1__InvalidOperateAmount);\n }\n\n // Check msg.value aligns with input amounts if supply or borrow token is native token.\n // N
},
"contracts/protocols/vault/vaultT1/coreModule/main2.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { Variables } from \"../common/variables.sol\";\nimport { IFluidOracle } from \"../../../../oracle/fluidOracle.sol\";\nimport { TickMath } from \"../../../../libraries/tickMath.sol\";\nimport { BigMathMinified } from \"../../../../libraries/bigMathMinified.sol\";\nimport { Error } from \"../../error.sol\";\nimport { ErrorTypes } from \"../../errorTypes.sol\";\nimport { IFluidVaultT1 } from \"../../interfaces/iVaultT1.sol\";\nimport { Structs } from \"./structs.sol\";\nimport { Events } from \"./events.sol\";\nimport { LiquiditySlotsLink } from \"../../../../libraries/liquiditySlotsLink.sol\";\nimport { LiquidityCalcs } from \"../../../../libraries/liquidityCalcs.sol\";\nimport { IFluidLiquidity } from \"../../../../liquidity/interfaces/iLiquidity.sol\";\nimport { SafeTransfer } from \"../../../../libraries/safeTransfer.sol\";\n\n/// @notice Fluid Vault protocol secondary methods contract.\n/// Implements `absorb()` and `rebalance()` methods, extracted from main contract due to contract size limits.\n/// Methods are limited to be called via delegateCall only (as done by Vault CoreModule \"VaultT1\" contract).\ncontract FluidVaultT1Secondary is Variables, Error, Structs, Events {\n using BigMathMinified for uint;\n\n address internal constant NATIVE_TOKEN = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n // 30 bits (used for partials mainly)\n uint internal constant X8 = 0xff;\n uint internal constant X10 = 0x3ff;\n uint internal constant X16 = 0xffff;\n uint internal constant X19 = 0x7ffff;\n uint internal constant X20 = 0xfffff;\n uint internal constant X24 = 0xffffff;\n uint internal constant X25 = 0x1ffffff;\n uint internal constant X30 = 0x3fffffff;\n uint internal constant X35 = 0x7ffffffff;\n uint internal constant X50 = 0x3ffffffffffff;\n uint internal constant X64 = 0xffffffffffffffff;\n uint internal constant X96 = 0xffffffffffffffffffffffff;\n uint internal constant X128 = 0xffffffffffffffffffffffffffffffff;\n\n address private immutable addressThis;\n\n constructor() {\n addressThis = address(this);\n }\n\n modifier _verifyCaller() {\n if (address(this) == addressThis) {\n revert FluidVaultError(ErrorTypes.VaultT1__OnlyDelegateCallAllowed);\n }\n _;\n }\n\n /// @dev absorb function absorbs the bad debt if the bad debt is above max limit. The main use of it is\n /// if the bad debt didn't got liquidated in time maybe due to sudden price drop or bad debt was extremely small to liquidate\n /// and the bad debt goes above 100% ratio then there's no incentive for anyone to liquidate now\n /// hence absorb functions absorbs that bad debt to allow newer bad debt to liquidate seamlessly.\n /// if absorbing were to happen after this it's on governance on how to deal with it\n /// although it can still be removed through liquidate via liquidator if the price goes back up and liquidation becomes beneficial\n /// upon absorbed user position gets 100% liquidated.\n function absorb() public _verifyCaller {\n uint256 vaultVariables_ = vaultVariables;\n\n // ############# turning re-entrancy bit on #############\n if (vaultVariables_ & 1 == 0) {\n // Updating on storage\n vaultVariables = vaultVariables_ | 1;\n } else {\n revert FluidVaultError(ErrorTypes.VaultT1__AlreadyEntered);\n }\n\n AbsorbMemoryVariables memory a_;\n\n // Temporary holder variables, used many times for different small few liner things\n uint temp_;\n uint temp2_;\n\n int maxTick_;\n\n {\n a_.vaultVariables2 = vaultVariables2;\n\n // temp_ -> top tick\n temp_ = ((vaultVariables_ >> 2) & X20);\n if (temp_ == 0) {\n revert FluidVaultError(ErrorTypes.VaultT1__TopTickDoesNotExist);\n }\n\n // Below are exchange prices of vaults\n (,
},
"contracts/protocols/vault/vaultT1/coreModule/structs.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\ncontract Structs {\n // structs are used to mitigate Stack too deep errors\n\n struct OperateMemoryVars {\n // ## User's position before update ##\n uint oldColRaw;\n uint oldNetDebtRaw; // total debt - dust debt\n int oldTick;\n // ## User's position after update ##\n uint colRaw;\n uint debtRaw; // total debt - dust debt\n uint dustDebtRaw;\n int tick;\n uint tickId;\n // others\n uint256 vaultVariables2;\n uint256 branchId;\n int256 topTick;\n uint liquidityExPrice;\n uint supplyExPrice;\n uint borrowExPrice;\n uint branchData;\n // user's supply slot data in liquidity\n uint userSupplyLiquidityData;\n }\n\n struct BranchData {\n uint id;\n uint data;\n uint ratio;\n uint debtFactor;\n int minimaTick;\n uint baseBranchData;\n }\n\n struct TickData {\n int tick;\n uint data;\n uint ratio;\n uint ratioOneLess;\n uint length;\n uint currentRatio; // current tick is ratio with partials.\n uint partials;\n }\n\n // note: All the below token amounts are in raw form.\n struct CurrentLiquidity {\n uint256 debtRemaining; // Debt remaining to liquidate\n uint256 debt; // Current liquidatable debt before reaching next check point\n uint256 col; // Calculate using debt & ratioCurrent\n uint256 colPerDebt; // How much collateral to liquidate per unit of Debt\n uint256 totalDebtLiq; // Total debt liquidated till now\n uint256 totalColLiq; // Total collateral liquidated till now\n int tick; // Current tick to liquidate\n uint ratio; // Current ratio to liquidate\n uint tickStatus; // if 1 then it's a perfect tick, if 2 that means it's a liquidated tick\n int refTick; // ref tick to liquidate\n uint refRatio; // ratio at ref tick\n uint refTickStatus; // if 1 then it's a perfect tick, if 2 that means it's a liquidated tick, if 3 that means it's a liquidation threshold\n }\n\n struct TickHasDebt {\n int tick; // current tick\n int nextTick; // next tick with liquidity\n int mapId; // mapping ID of tickHasDebt\n uint bitsToRemove; // liquidity to remove till tick_ so we can search for next tick\n uint tickHasDebt; // getting tickHasDebt_ from tickHasDebt[mapId_]\n uint mostSigBit; // most significant bit in tickHasDebt_ to get the next tick\n }\n\n struct LiquidateMemoryVars {\n uint256 vaultVariables2;\n int liquidationTick;\n int maxTick;\n uint256 supplyExPrice;\n uint256 borrowExPrice;\n }\n\n struct AbsorbMemoryVariables {\n uint256 supplyExPrice;\n uint256 borrowExPrice;\n uint256 debtAbsorbed;\n uint256 colAbsorbed;\n uint256 vaultVariables2;\n int256 startingTick;\n uint256 mostSigBit;\n }\n\n struct ConstantViews {\n address liquidity;\n address factory;\n address adminImplementation;\n address secondaryImplementation;\n address supplyToken;\n address borrowToken;\n uint8 supplyDecimals;\n uint8 borrowDecimals;\n uint vaultId;\n bytes32 liquiditySupplyExchangePriceSlot;\n bytes32 liquidityBorrowExchangePriceSlot;\n bytes32 liquidityUserSupplySlot;\n bytes32 liquidityUserBorrowSlot;\n }\n\n struct RebalanceMemoryVariables {\n uint256 liqSupplyExPrice;\n uint256 liqBorrowExPrice;\n uint256 vaultSupplyExPrice;\n uint256 vaultBorrowExPrice;\n }\n}\n"
},
"contracts/reserve/error.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nabstract contract Error {\n error FluidReserveContractError(uint256 errorId_);\n}\n"
},
"contracts/reserve/errorTypes.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nlibrary ErrorTypes {\n /***********************************|\n | Reserve | \n |__________________________________*/\n\n /// @notice thrown when an unauthorized caller is trying to execute an auth-protected method\n uint256 internal constant ReserveContract__Unauthorized = 90001;\n\n /// @notice thrown when an input address is zero\n uint256 internal constant ReserveContract__AddressZero = 90002;\n\n /// @notice thrown when input arrays has different lenghts\n uint256 internal constant ReserveContract__InvalidInputLenghts = 90003;\n\n /// @notice thrown when renounceOwnership is called\n uint256 internal constant ReserveContract__RenounceOwnershipUnsupported = 90004;\n\n /// @notice thrown when wrong msg.value is at time of rebalancing\n uint256 internal constant ReserveContract__WrongValueSent = 90005;\n}\n"
},
"contracts/reserve/events.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nabstract contract Events {\n /// @notice Emitted when an address is added or removed from the auths\n event LogUpdateAuth(address indexed auth, bool isAuth);\n\n /// @notice Emitted when an address is added or removed from the rebalancers\n event LogUpdateRebalancer(address indexed rebalancer, bool isRebalancer);\n\n /// @notice Emitted when a token is approved for use by a protocol\n event LogAllow(address indexed protocol, address indexed token, uint256 newAllowance, uint existingAllowance);\n\n /// @notice Emitted when a token is revoked for use by a protocol\n event LogRevoke(address indexed protocol, address indexed token);\n\n /// @notice Emitted when fToken is rebalanced\n event LogRebalanceFToken(address indexed protocol, uint amount);\n\n /// @notice Emitted when vault is rebalanced\n event LogRebalanceVault(address indexed protocol, int colAmount, int debtAmount);\n\n /// @notice Emitted whenever funds for a certain `token` are transfered to Liquidity\n event LogTransferFunds(address indexed token);\n}\n"
},
"contracts/reserve/interfaces/iReserveContract.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IFluidLiquidity } from \"../../liquidity/interfaces/iLiquidity.sol\";\n\ninterface IFluidReserveContract {\n function isRebalancer(address user) external returns (bool);\n\n function initialize(\n address[] memory _auths,\n address[] memory _rebalancers,\n IFluidLiquidity liquidity_,\n address owner_\n ) external;\n\n function rebalanceFToken(address protocol_) external;\n\n function rebalanceVault(address protocol_) external;\n\n function transferFunds(address token_) external;\n\n function getProtocolTokens(address protocol_) external;\n\n function updateAuth(address auth_, bool isAuth_) external;\n\n function updateRebalancer(address rebalancer_, bool isRebalancer_) external;\n\n function approve(address[] memory protocols_, address[] memory tokens_, uint256[] memory amounts_) external;\n\n function revoke(address[] memory protocols_, address[] memory tokens_) external;\n}\n"
},
"contracts/reserve/main.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { UUPSUpgradeable } from \"@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { EnumerableSet } from \"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\";\n\nimport { IFluidLiquidity } from \"../liquidity/interfaces/iLiquidity.sol\";\nimport { IFluidLendingFactory } from \"../protocols/lending/interfaces/iLendingFactory.sol\";\nimport { IFTokenAdmin } from \"../protocols/lending/interfaces/iFToken.sol\";\nimport { IFluidVaultT1 } from \"../protocols/vault/interfaces/iVaultT1.sol\";\nimport { SafeTransfer } from \"../libraries/safeTransfer.sol\";\n\nimport { Variables } from \"./variables.sol\";\nimport { Events } from \"./events.sol\";\nimport { ErrorTypes } from \"./errorTypes.sol\";\nimport { Error } from \"./error.sol\";\n\nabstract contract ReserveContractAuth is Variables, Error, Events {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n /// @dev validates that an address is not the zero address\n modifier validAddress(address value_) {\n if (value_ == address(0)) {\n revert FluidReserveContractError(ErrorTypes.ReserveContract__AddressZero);\n }\n _;\n }\n\n /// @notice Checks that the sender is an auth\n modifier onlyAuth() {\n if (!isAuth[msg.sender] && owner() != msg.sender)\n revert FluidReserveContractError(ErrorTypes.ReserveContract__Unauthorized);\n _;\n }\n\n /// @notice Updates an auth's status as an auth\n /// @param auth_ The address to update\n /// @param isAuth_ Whether or not the address should be an auth\n function updateAuth(address auth_, bool isAuth_) external onlyOwner validAddress(auth_) {\n isAuth[auth_] = isAuth_;\n emit LogUpdateAuth(auth_, isAuth_);\n }\n\n /// @notice Updates a rebalancer's status as a rebalancer\n /// @param rebalancer_ The address to update\n /// @param isRebalancer_ Whether or not the address should be a rebalancer\n function updateRebalancer(address rebalancer_, bool isRebalancer_) external onlyAuth validAddress(rebalancer_) {\n isRebalancer[rebalancer_] = isRebalancer_;\n emit LogUpdateRebalancer(rebalancer_, isRebalancer_);\n }\n\n /// @notice Approves protocols to spend the reserves tokens\n /// @dev The parameters are parallel arrays\n /// @param protocols_ The protocols that will be spending reserve tokens\n /// @param tokens_ The tokens to approve\n /// @param amounts_ The amounts to approve\n function approve(\n address[] memory protocols_,\n address[] memory tokens_,\n uint256[] memory amounts_\n ) external onlyAuth {\n if (protocols_.length != tokens_.length || tokens_.length != amounts_.length) {\n revert FluidReserveContractError(ErrorTypes.ReserveContract__InvalidInputLenghts);\n }\n\n for (uint256 i = 0; i < protocols_.length; i++) {\n address protocol_ = protocols_[i];\n address token_ = tokens_[i];\n uint256 amount_ = amounts_[i];\n uint256 existingAllowance_ = IERC20(token_).allowance(address(this), protocol_);\n\n // making approval 0 first and then re-approving with a new amount.\n SafeERC20.safeApprove(IERC20(address(token_)), protocol_, 0);\n SafeERC20.safeApprove(IERC20(address(token_)), protocol_, amount_);\n _protocolTokens[protocol_].add(token_);\n emit LogAllow(protocol_, token_, amount_, existingAllowance_);\n }\n }\n\n /// @notice Revokes protocols' ability to spend the reserves tokens\n /// @dev The parameters are parallel arrays\n /// @param protocols_ The protocols that will no longer be spending reserve tokens\n /
},
"contracts/reserve/variables.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { Initializable } from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport { OwnableUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport { EnumerableSet } from \"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\";\nimport { IFluidLiquidity } from \"../liquidity/interfaces/iLiquidity.sol\";\nimport { IFluidLendingFactory } from \"../protocols/lending/interfaces/iLendingFactory.sol\";\n\nabstract contract Constants {\n /// @notice address of the liquidity contract\n IFluidLiquidity public immutable LIQUIDITY;\n\n /// @dev address that is mapped to the chain native token\n address internal constant NATIVE_TOKEN_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n constructor(IFluidLiquidity liquidity_) {\n LIQUIDITY = liquidity_;\n }\n}\n\nabstract contract Variables is Constants, Initializable, OwnableUpgradeable {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n // ------------ storage variables from inherited contracts (Initializable, OwnableUpgradeable) come before vars here --------\n // @dev variables here start at storage slot 101, before is:\n // - Initializable with storage slot 0:\n // uint8 private _initialized;\n // bool private _initializing;\n // - OwnableUpgradeable with slots 1 to 100:\n // uint256[50] private __gap; (from ContextUpgradeable, slot 1 until slot 50)\n // address private _owner; (at slot 51)\n // uint256[49] private __gap; (slot 52 until slot 100)\n\n // ----------------------- slot 101 ---------------------------\n /// @notice Maps address to there status as an Auth\n mapping(address => bool) public isAuth;\n\n /// @notice Maps address to there status as a Rebalancer\n mapping(address => bool) public isRebalancer;\n\n /// @notice Mapping of protocol addresses to the tokens that are allowed to be used by that protocol\n mapping(address => EnumerableSet.AddressSet) internal _protocolTokens;\n\n constructor(IFluidLiquidity liquidity_) Constants(liquidity_) {}\n}\n"
},
"solmate/src/auth/Owned.sol": {
"content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\n/// @notice Simple single owner authorization mixin.\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Owned.sol)\nabstract contract Owned {\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event OwnershipTransferred(address indexed user, address indexed newOwner);\n\n /*//////////////////////////////////////////////////////////////\n OWNERSHIP STORAGE\n //////////////////////////////////////////////////////////////*/\n\n address public owner;\n\n modifier onlyOwner() virtual {\n require(msg.sender == owner, \"UNAUTHORIZED\");\n\n _;\n }\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n constructor(address _owner) {\n owner = _owner;\n\n emit OwnershipTransferred(address(0), _owner);\n }\n\n /*//////////////////////////////////////////////////////////////\n OWNERSHIP LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function transferOwnership(address newOwner) public virtual onlyOwner {\n owner = newOwner;\n\n emit OwnershipTransferred(msg.sender, newOwner);\n }\n}\n"
},
"solmate/src/utils/Bytes32AddressLib.sol": {
"content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\n/// @notice Library for converting between addresses and bytes32 values.\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/Bytes32AddressLib.sol)\nlibrary Bytes32AddressLib {\n function fromLast20Bytes(bytes32 bytesValue) internal pure returns (address) {\n return address(uint160(uint256(bytesValue)));\n }\n\n function fillLast12Bytes(address addressValue) internal pure returns (bytes32) {\n return bytes32(bytes20(addressValue));\n }\n}\n"
},
"solmate/src/utils/CREATE3.sol": {
"content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\nimport {Bytes32AddressLib} from \"./Bytes32AddressLib.sol\";\n\n/// @notice Deploy to deterministic addresses without an initcode factor.\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/CREATE3.sol)\n/// @author Modified from 0xSequence (https://github.com/0xSequence/create3/blob/master/contracts/Create3.sol)\nlibrary CREATE3 {\n using Bytes32AddressLib for bytes32;\n\n //--------------------------------------------------------------------------------//\n // Opcode | Opcode + Arguments | Description | Stack View //\n //--------------------------------------------------------------------------------//\n // 0x36 | 0x36 | CALLDATASIZE | size //\n // 0x3d | 0x3d | RETURNDATASIZE | 0 size //\n // 0x3d | 0x3d | RETURNDATASIZE | 0 0 size //\n // 0x37 | 0x37 | CALLDATACOPY | //\n // 0x36 | 0x36 | CALLDATASIZE | size //\n // 0x3d | 0x3d | RETURNDATASIZE | 0 size //\n // 0x34 | 0x34 | CALLVALUE | value 0 size //\n // 0xf0 | 0xf0 | CREATE | newContract //\n //--------------------------------------------------------------------------------//\n // Opcode | Opcode + Arguments | Description | Stack View //\n //--------------------------------------------------------------------------------//\n // 0x67 | 0x67XXXXXXXXXXXXXXXX | PUSH8 bytecode | bytecode //\n // 0x3d | 0x3d | RETURNDATASIZE | 0 bytecode //\n // 0x52 | 0x52 | MSTORE | //\n // 0x60 | 0x6008 | PUSH1 08 | 8 //\n // 0x60 | 0x6018 | PUSH1 18 | 24 8 //\n // 0xf3 | 0xf3 | RETURN | //\n //--------------------------------------------------------------------------------//\n bytes internal constant PROXY_BYTECODE = hex\"67_36_3d_3d_37_36_3d_34_f0_3d_52_60_08_60_18_f3\";\n\n bytes32 internal constant PROXY_BYTECODE_HASH = keccak256(PROXY_BYTECODE);\n\n function deploy(\n bytes32 salt,\n bytes memory creationCode,\n uint256 value\n ) internal returns (address deployed) {\n bytes memory proxyChildBytecode = PROXY_BYTECODE;\n\n address proxy;\n /// @solidity memory-safe-assembly\n assembly {\n // Deploy a new contract with our pre-made bytecode via CREATE2.\n // We start 32 bytes into the code to avoid copying the byte length.\n proxy := create2(0, add(proxyChildBytecode, 32), mload(proxyChildBytecode), salt)\n }\n require(proxy != address(0), \"DEPLOYMENT_FAILED\");\n\n deployed = getDeployed(salt);\n (bool success, ) = proxy.call{value: value}(creationCode);\n require(success && deployed.code.length != 0, \"INITIALIZATION_FAILED\");\n }\n\n function getDeployed(bytes32 salt) internal view returns (address) {\n address proxy = keccak256(\n abi.encodePacked(\n // Prefix:\n bytes1(0xFF),\n // Creator:\n address(this),\n // Salt:\n salt,\n // Bytecode hash:\n PROXY_BYTECODE_HASH\n )\n ).fromLast20Bytes();\n\n return\n keccak256(\n abi.encodePacked(\n // 0xd6 = 0xc0 (short RLP prefix) + 0x16 (length of: 0x94 ++ proxy ++ 0x01)\n // 0x94 = 0x80 + 0x14 (0x14 = the length of an address, 20 bytes, in h
},
"solmate/src/utils/FixedPointMathLib.sol": {
"content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\n/// @notice Arithmetic library with operations for fixed-point numbers.\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol)\n/// @author Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol)\nlibrary FixedPointMathLib {\n /*//////////////////////////////////////////////////////////////\n SIMPLIFIED FIXED POINT OPERATIONS\n //////////////////////////////////////////////////////////////*/\n\n uint256 internal constant MAX_UINT256 = 2**256 - 1;\n\n uint256 internal constant WAD = 1e18; // The scalar of ETH and most ERC20s.\n\n function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) {\n return mulDivDown(x, y, WAD); // Equivalent to (x * y) / WAD rounded down.\n }\n\n function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) {\n return mulDivUp(x, y, WAD); // Equivalent to (x * y) / WAD rounded up.\n }\n\n function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) {\n return mulDivDown(x, WAD, y); // Equivalent to (x * WAD) / y rounded down.\n }\n\n function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) {\n return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up.\n }\n\n /*//////////////////////////////////////////////////////////////\n LOW LEVEL FIXED POINT OPERATIONS\n //////////////////////////////////////////////////////////////*/\n\n function mulDivDown(\n uint256 x,\n uint256 y,\n uint256 denominator\n ) internal pure returns (uint256 z) {\n /// @solidity memory-safe-assembly\n assembly {\n // Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y))\n if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) {\n revert(0, 0)\n }\n\n // Divide x * y by the denominator.\n z := div(mul(x, y), denominator)\n }\n }\n\n function mulDivUp(\n uint256 x,\n uint256 y,\n uint256 denominator\n ) internal pure returns (uint256 z) {\n /// @solidity memory-safe-assembly\n assembly {\n // Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y))\n if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) {\n revert(0, 0)\n }\n\n // If x * y modulo the denominator is strictly greater than 0,\n // 1 is added to round up the division of x * y by the denominator.\n z := add(gt(mod(mul(x, y), denominator), 0), div(mul(x, y), denominator))\n }\n }\n\n function rpow(\n uint256 x,\n uint256 n,\n uint256 scalar\n ) internal pure returns (uint256 z) {\n /// @solidity memory-safe-assembly\n assembly {\n switch x\n case 0 {\n switch n\n case 0 {\n // 0 ** 0 = 1\n z := scalar\n }\n default {\n // 0 ** n = 0\n z := 0\n }\n }\n default {\n switch mod(n, 2)\n case 0 {\n // If n is even, store scalar in z for now.\n z := scalar\n }\n default {\n // If n is odd, store x in z for now.\n z := x\n }\n\n // Shifting right by 1 is like dividing by 2.\n let half := shr(1, scalar)\n\n for {\n // Shift n right by 1 before looping to halve it.\n n := shr(1, n)\n } n {\n // Shift n right by 1 each iteration to halve it.\n n := shr(1, n)\n } {\n
},
"solmate/src/utils/SSTORE2.sol": {
"content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\n/// @notice Read and write to persistent storage at a fraction of the cost.\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SSTORE2.sol)\n/// @author Modified from 0xSequence (https://github.com/0xSequence/sstore2/blob/master/contracts/SSTORE2.sol)\nlibrary SSTORE2 {\n uint256 internal constant DATA_OFFSET = 1; // We skip the first byte as it's a STOP opcode to ensure the contract can't be called.\n\n /*//////////////////////////////////////////////////////////////\n WRITE LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function write(bytes memory data) internal returns (address pointer) {\n // Prefix the bytecode with a STOP opcode to ensure it cannot be called.\n bytes memory runtimeCode = abi.encodePacked(hex\"00\", data);\n\n bytes memory creationCode = abi.encodePacked(\n //---------------------------------------------------------------------------------------------------------------//\n // Opcode | Opcode + Arguments | Description | Stack View //\n //---------------------------------------------------------------------------------------------------------------//\n // 0x60 | 0x600B | PUSH1 11 | codeOffset //\n // 0x59 | 0x59 | MSIZE | 0 codeOffset //\n // 0x81 | 0x81 | DUP2 | codeOffset 0 codeOffset //\n // 0x38 | 0x38 | CODESIZE | codeSize codeOffset 0 codeOffset //\n // 0x03 | 0x03 | SUB | (codeSize - codeOffset) 0 codeOffset //\n // 0x80 | 0x80 | DUP | (codeSize - codeOffset) (codeSize - codeOffset) 0 codeOffset //\n // 0x92 | 0x92 | SWAP3 | codeOffset (codeSize - codeOffset) 0 (codeSize - codeOffset) //\n // 0x59 | 0x59 | MSIZE | 0 codeOffset (codeSize - codeOffset) 0 (codeSize - codeOffset) //\n // 0x39 | 0x39 | CODECOPY | 0 (codeSize - codeOffset) //\n // 0xf3 | 0xf3 | RETURN | //\n //---------------------------------------------------------------------------------------------------------------//\n hex\"60_0B_59_81_38_03_80_92_59_39_F3\", // Returns all code in the contract except for the first 11 (0B in hex) bytes.\n runtimeCode // The bytecode we want the contract to have after deployment. Capped at 1 byte less than the code size limit.\n );\n\n /// @solidity memory-safe-assembly\n assembly {\n // Deploy a new contract with the generated creation code.\n // We start 32 bytes into the code to avoid copying the byte length.\n pointer := create(0, add(creationCode, 32), mload(creationCode))\n }\n\n require(pointer != address(0), \"DEPLOYMENT_FAILED\");\n }\n\n /*//////////////////////////////////////////////////////////////\n READ LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function read(address pointer) internal view returns (bytes memory) {\n return readBytecode(pointer, DATA_OFFSET, pointer.code.length - DATA_OFFSET);\n }\n\n function read(address pointer, uint256 start) internal view returns (bytes memory) {\n start += DATA_OFFSET;\n\n return readBytecode(pointer, start, pointer.code.length - start);\n }\n\n function read(\n address pointer,\n ui
}
},
"settings": {
"optimizer": {
"enabled": true,
"runs": 10000000
},
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"abi",
"evm.bytecode",
"evm.deployedBytecode",
"evm.methodIdentifiers",
"metadata",
"devdoc",
"userdoc",
"storageLayout",
"evm.gasEstimates"
],
"": [
"ast"
]
}
},
"metadata": {
"useLiteralContent": true
}
}
}