fluid-contracts-public/deployments/mainnet/dump/0x4Fc6D37FE897D6a7FfF0093D3B8418194ce1B1Bb.json
2024-07-11 13:05:09 +00:00

322 lines
220 KiB
JSON

{
"address": "0x4Fc6D37FE897D6a7FfF0093D3B8418194ce1B1Bb",
"abi": [
{
"inputs": [
{
"internalType": "uint256",
"name": "errorId_",
"type": "uint256"
}
],
"name": "FluidLiquidityCalcsError",
"type": "error"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "errorId_",
"type": "uint256"
}
],
"name": "FluidLiquidityError",
"type": "error"
},
{
"anonymous": false,
"inputs": [],
"name": "BorrowRateMaxCap",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "user",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "token",
"type": "address"
},
{
"indexed": false,
"internalType": "int256",
"name": "supplyAmount",
"type": "int256"
},
{
"indexed": false,
"internalType": "int256",
"name": "borrowAmount",
"type": "int256"
},
{
"indexed": false,
"internalType": "address",
"name": "withdrawTo",
"type": "address"
},
{
"indexed": false,
"internalType": "address",
"name": "borrowTo",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "totalAmounts",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "exchangePricesAndConfig",
"type": "uint256"
}
],
"name": "LogOperate",
"type": "event"
},
{
"inputs": [
{
"internalType": "address",
"name": "token_",
"type": "address"
},
{
"internalType": "int256",
"name": "supplyAmount_",
"type": "int256"
},
{
"internalType": "int256",
"name": "borrowAmount_",
"type": "int256"
},
{
"internalType": "address",
"name": "withdrawTo_",
"type": "address"
},
{
"internalType": "address",
"name": "borrowTo_",
"type": "address"
},
{
"internalType": "bytes",
"name": "callbackData_",
"type": "bytes"
}
],
"name": "operate",
"outputs": [
{
"internalType": "uint256",
"name": "memVar3_",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "memVar4_",
"type": "uint256"
}
],
"stateMutability": "payable",
"type": "function"
}
],
"transactionHash": "0xeb0d76267f646e50f00f03ffc89b8702441c67aa0fbbcd7d9f75206096dcc926",
"receipt": {
"to": "0x4e59b44847b379578588920cA78FbF26c0B4956C",
"from": "0x0Ed35B1609Ec45c7079E80d11149a52717e4859A",
"contractAddress": null,
"transactionIndex": 145,
"gasUsed": "2493013",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"blockHash": "0x021149f818fa115f38b755daed583e1345e39ff7e4106fe6a58f4aed029bfd84",
"transactionHash": "0xeb0d76267f646e50f00f03ffc89b8702441c67aa0fbbcd7d9f75206096dcc926",
"logs": [],
"blockNumber": 19848240,
"cumulativeGasUsed": "10984256",
"status": 1,
"byzantium": true
},
"args": [],
"numDeployments": 2,
"solcInputHash": "3dc18f2b4b793011cda88c7a3b5a6ec8",
"metadata": "{\"compiler\":{\"version\":\"0.8.21+commit.d9974bed\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"errorId_\",\"type\":\"uint256\"}],\"name\":\"FluidLiquidityCalcsError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"errorId_\",\"type\":\"uint256\"}],\"name\":\"FluidLiquidityError\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"BorrowRateMaxCap\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"int256\",\"name\":\"supplyAmount\",\"type\":\"int256\"},{\"indexed\":false,\"internalType\":\"int256\",\"name\":\"borrowAmount\",\"type\":\"int256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"withdrawTo\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"borrowTo\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalAmounts\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"exchangePricesAndConfig\",\"type\":\"uint256\"}],\"name\":\"LogOperate\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token_\",\"type\":\"address\"},{\"internalType\":\"int256\",\"name\":\"supplyAmount_\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"borrowAmount_\",\"type\":\"int256\"},{\"internalType\":\"address\",\"name\":\"withdrawTo_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrowTo_\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"callbackData_\",\"type\":\"bytes\"}],\"name\":\"operate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"memVar3_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"memVar4_\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"For view methods / accessing data, use the \\\"LiquidityResolver\\\" periphery contract.\",\"events\":{\"LogOperate(address,address,int256,int256,address,address,uint256,uint256)\":{\"params\":{\"borrowAmount\":\"borrow amount for the operation. if >0 then a borrow happened, if <0 then a payback happened. if 0 then nothing.\",\"borrowTo\":\"address that funds where borrowed to (if borrowAmount >0)\",\"exchangePricesAndConfig\":\"updated exchange prices and configs storage slot. Contains updated supply & borrow exchange price: First 16 bits => 0- 15 => borrow rate (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535) Next 14 bits => 16- 29 => fee on interest from borrowers to lenders (in 1e2: 100% = 10_000; 1% = 100 -> max value 16_383). configurable. Next 14 bits => 30- 43 => last stored utilization (in 1e2: 100% = 10_000; 1% = 100 -> max value 16_383) Next 14 bits => 44- 57 => update on storage threshold (in 1e2: 100% = 10_000; 1% = 100 -> max value 16_383). configurable. Next 33 bits => 58- 90 => last update timestamp (enough until 16 March 2242 -> max value 8589934591) Next 64 bits => 91-154 => supply exchange price (1e12 -> max value 18_446_744,073709551615) Next 64 bits => 155-218 => borrow exchange price (1e12 -> max value 18_446_744,073709551615) Next 1 bit => 219-219 => if 0 then ratio is supplyInterestFree / supplyWithInterest else ratio is supplyWithInterest / supplyInterestFree Next 14 bits => 220-233 => supplyRatio: supplyInterestFree / supplyWithInterest (in 1e2: 100% = 10_000; 1% = 100 -> max value 16_383) Next 1 bit => 234-234 => if 0 then ratio is borrowInterestFree / borrowWithInterest else ratio is borrowWithInterest / borrowInterestFree Next 14 bits => 235-248 => borrowRatio: borrowInterestFree / borrowWithInterest (in 1e2: 100% = 10_000; 1% = 100 -> max value 16_383)\",\"supplyAmount\":\"supply amount for the operation. if >0 then a deposit happened, if <0 then a withdrawal happened. if 0 then nothing.\",\"token\":\"token address for which this operation was executed\",\"totalAmounts\":\"updated total amounts, stacked uint256 as written to storage: First 64 bits => 0- 63 => total supply with interest in raw (totalSupply = totalSupplyRaw * supplyExchangePrice); BigMath: 56 | 8 Next 64 bits => 64-127 => total interest free supply in normal token amount (totalSupply = totalSupply); BigMath: 56 | 8 Next 64 bits => 128-191 => total borrow with interest in raw (totalBorrow = totalBorrowRaw * borrowExchangePrice); BigMath: 56 | 8 Next 64 bits => 192-255 => total interest free borrow in normal token amount (totalBorrow = totalBorrow); BigMath: 56 | 8\",\"user\":\"protocol that triggered this operation (e.g. via an fToken or via Vault protocol)\",\"withdrawTo\":\"address that funds where withdrawn to (if supplyAmount <0)\"}}},\"kind\":\"dev\",\"methods\":{},\"title\":\"Fluid Liquidity UserModule\",\"version\":1},\"userdoc\":{\"events\":{\"BorrowRateMaxCap()\":{\"notice\":\"emitted if the calculated borrow rate surpassed max borrow rate (16 bits) and was capped at maximum value 65535\"},\"LogOperate(address,address,int256,int256,address,address,uint256,uint256)\":{\"notice\":\"emitted on any `operate()` execution: deposit / supply / withdraw / borrow. includes info related to the executed operation, new total amounts (packed uint256 of BigMath numbers as in storage) and exchange prices (packed uint256 as in storage).\"}},\"kind\":\"user\",\"methods\":{\"operate(address,int256,int256,address,address,bytes)\":{\"notice\":\"inheritdoc IFluidLiquidity\"}},\"notice\":\"Fluid Liquidity public facing endpoint logic contract that implements the `operate()` method. operate can be used to deposit, withdraw, borrow & payback funds, given that they have the necessary user config allowance. Interacting users must be allowed via the Fluid Liquidity AdminModule first. Intended users are thus allow-listed protocols, e.g. the Lending protocol (fTokens), Vault protocol etc.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/liquidity/userModule/main.sol\":\"FluidLiquidityUserModule\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000000},\"remappings\":[]},\"sources\":{\"@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\",\"keccak256\":\"0x6ebf1944ab804b8660eb6fc52f9fe84588cee01c2566a69023e59497e7d27f45\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@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 implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) {\\n // Return data is optional\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@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 errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"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 exponent := sub(lastBit_, coefficientSize)\\n let coefficient := shr(exponent, normal)\\n if and(roundUp, gt(exponent, 0)) {\\n // rounding up is only needed if exponent is > 0, as otherwise the coefficient fully holds the original number\\n coefficient := add(coefficient, 1)\\n if eq(shl(coefficientSize, 1), coefficient) {\\n // case were coefficient was e.g. 111, with adding 1 it became 1000 (in binary) and coefficientSize 3 bits\\n // final coefficient would exceed it's size. -> reduce coefficent to 100 and increase exponent by 1.\\n coefficient := shl(sub(coefficientSize, 1), 1)\\n exponent := add(exponent, 1)\\n }\\n }\\n if iszero(lt(exponent, shl(exponentSize, 1))) {\\n // if exponent is >= exponentSize, the normal number is too big to fit within\\n // BigNumber with too small sizes for coefficient and exponent\\n revert(0, 0)\\n }\\n bigNumber := shl(exponentSize, coefficient)\\n bigNumber := add(bigNumber, exponent)\\n }\\n }\\n\\n /// @dev get `normal` number from `bigNumber`, `exponentSize` and `exponentMask`\\n function fromBigNumber(\\n uint256 bigNumber,\\n uint256 exponentSize,\\n uint256 exponentMask\\n ) internal pure returns (uint256 normal) {\\n assembly {\\n let coefficient := shr(exponentSize, bigNumber)\\n let exponent := and(bigNumber, exponentMask)\\n normal := shl(exponent, coefficient)\\n }\\n }\\n\\n /// @dev gets the most significant bit `lastBit` of a `normal` number (length of given number of binary format).\\n /// e.g.\\n /// 5035703444687813576399599 = 10000101010010110100000011111011110010100110100000000011100101001101001101011101111\\n /// lastBit = ^--------------------------------- 83 ----------------------------------------^\\n function mostSignificantBit(uint256 normal) internal pure returns (uint lastBit) {\\n assembly {\\n let number_ := normal\\n if gt(normal, 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 }\\n }\\n}\\n\",\"keccak256\":\"0xf0be1002909edf30aec3dc6623c2bd2407ed94064b62674c01032b844dec206a\",\"license\":\"BUSL-1.1\"},\"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\",\"keccak256\":\"0xaf7732f30d00dd38082d37aa37887be485fc94b0c76ff302aff615d03381674f\",\"license\":\"BUSL-1.1\"},\"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 (SECONDS_PER_YEAR * FOUR_DECIMALS);\\n\\n // FOR SUPPLY EXCHANGE PRICE:\\n // all yield paid by borrowers (in mode with interest) goes to suppliers in mode with interest.\\n // formula: previous price * supply rate * secondsSinceLastUpdate_.\\n // where supply rate = (borrow rate - revenueFee%) * ratioSupplyYield. And\\n // ratioSupplyYield = utilization * supplyRatio * borrowRatio\\n //\\n // Example:\\n // supplyRawInterest is 80, supplyInterestFree is 20. totalSupply is 100. BorrowedRawInterest is 50.\\n // BorrowInterestFree is 10. TotalBorrow is 60. borrow rate 40%, revenueFee 10%.\\n // yield is 10 (so half a year must have passed).\\n // supplyRawInterest must become worth 89. totalSupply must become 109. BorrowedRawInterest must become 60.\\n // borrowInterestFree must still be 10. supplyInterestFree still 20. totalBorrow 70.\\n // supplyExchangePrice would have to go from 1 to 1,125 (+ 0.125). borrowExchangePrice from 1 to 1,2 (+0.2).\\n // utilization is 60%. supplyRatio = 20 / 80 = 25% (only 80% of lenders receiving yield).\\n // borrowRatio = 10 / 50 = 20% (only 83,333% of borrowers paying yield):\\n // x of borrowers paying yield = 100% - (20 / (100 + 20)) = 100% - 16.6666666% = 83,333%.\\n // ratioSupplyYield = 60% * 83,33333% * (100% + 20%) = 62,5%\\n // supplyRate = (40% * (100% - 10%)) * = 36% * 62,5% = 22.5%\\n // increase in supplyExchangePrice, assuming 100 as previous price.\\n // 100 * 22,5% * 1/2 (half a year) = 0,1125.\\n // cross-check supplyRawInterest worth = 80 * 1.1125 = 89. totalSupply worth = 89 + 20.\\n\\n // -------------- 1. calculate ratioSupplyYield --------------------------------\\n // step1: utilization * supplyRatio (or actually part of lenders receiving yield)\\n\\n // temp_ => supplyRatio (in 1e2: 100% = 10_000; 1% = 100 -> max value 16_383)\\n // if first bit 0 then ratio is supplyInterestFree / supplyWithInterest (supplyWithInterest is bigger)\\n // else ratio is supplyWithInterest / supplyInterestFree (supplyInterestFree is bigger)\\n temp_ = (exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_SUPPLY_RATIO) & X15;\\n\\n if (temp_ == 1) {\\n // if no raw supply: no exchange price update needed\\n // (if supplyRatio_ == 1 means there is only supplyInterestFree, as first bit is 1 and rest is 0)\\n return (supplyExchangePrice_, borrowExchangePrice_);\\n }\\n\\n // ratioSupplyYield precision is 1e27 as 100% for increased precision when supplyInterestFree > supplyWithInterest\\n if (temp_ & 1 == 1) {\\n // ratio is supplyWithInterest / supplyInterestFree (supplyInterestFree is bigger)\\n temp_ = temp_ >> 1;\\n\\n // Note: case where temp_ == 0 (only supplyInterestFree, no yield) already covered by early return\\n // in the if statement a little above.\\n\\n // based on above example but supplyRawInterest is 20, supplyInterestFree is 80. no fee.\\n // supplyRawInterest must become worth 30. totalSupply must become 110.\\n // supplyExchangePrice would have to go from 1 to 1,5. borrowExchangePrice from 1 to 1,2.\\n // so ratioSupplyYield must come out as 2.5 (250%).\\n // supplyRatio would be (20 * 10_000 / 80) = 2500. but must be inverted.\\n temp_ = (1e27 * FOUR_DECIMALS) / temp_; // e.g. 1e31 / 2500 = 4e27. (* 1e27 for precision)\\n // e.g. 5_000 * (1e27 + 4e27) / 1e27 = 25_000 (=250%).\\n temp_ =\\n // utilization * (100% + 100% / supplyRatio)\\n (((exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_UTILIZATION) & X14) *\\n (1e27 + temp_)) / // extract utilization (max 16_383 so there is no way this can overflow).\\n (FOUR_DECIMALS);\\n // max possible value of temp_ here is 16383 * (1e27 + 1e31) / 1e4 = ~1.64e31\\n } else {\\n // ratio is supplyInterestFree / supplyWithInterest (supplyWithInterest is bigger)\\n temp_ = temp_ >> 1;\\n // if temp_ == 0 then only supplyWithInterest => full yield. temp_ is already 0\\n\\n // e.g. 5_000 * 10_000 + (20 * 10_000 / 80) / 10_000 = 5000 * 12500 / 10000 = 6250 (=62.5%).\\n temp_ =\\n // 1e27 * utilization * (100% + supplyRatio) / 100%\\n (1e27 *\\n ((exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_UTILIZATION) & X14) * // extract utilization (max 16_383 so there is no way this can overflow).\\n (FOUR_DECIMALS + temp_)) /\\n (FOUR_DECIMALS * FOUR_DECIMALS);\\n // max possible temp_ value: 1e27 * 16383 * 2e4 / 1e8 = 3.2766e27\\n }\\n // from here temp_ => ratioSupplyYield (utilization * supplyRatio part) scaled by 1e27. max possible value ~1.64e31\\n\\n // step2 of ratioSupplyYield: add borrowRatio (only x% of borrowers paying yield)\\n if (borrowRatio_ & 1 == 1) {\\n // ratio is borrowWithInterest / borrowInterestFree (borrowInterestFree is bigger)\\n borrowRatio_ = borrowRatio_ >> 1;\\n // borrowRatio_ => x of total bororwers paying yield. scale to 1e27.\\n\\n // Note: case where borrowRatio_ == 0 (only borrowInterestFree, no yield) already covered\\n // at the beginning of the method by early return if `borrowRatio_ == 1`.\\n\\n // based on above example but borrowRawInterest is 10, borrowInterestFree is 50. no fee. borrowRatio = 20%.\\n // so only 16.66% of borrowers are paying yield. so the 100% - part of the formula is not needed.\\n // x of borrowers paying yield = (borrowRatio / (100 + borrowRatio)) = 16.6666666%\\n // borrowRatio_ => x of total bororwers paying yield. scale to 1e27.\\n borrowRatio_ = (borrowRatio_ * 1e27) / (FOUR_DECIMALS + borrowRatio_);\\n // max value here for borrowRatio_ is (1e31 / (1e4 + 1e4))= 5e26 (= 50% of borrowers paying yield).\\n } else {\\n // ratio is borrowInterestFree / borrowWithInterest (borrowWithInterest is bigger)\\n borrowRatio_ = borrowRatio_ >> 1;\\n\\n // borrowRatio_ => x of total bororwers paying yield. scale to 1e27.\\n // x of borrowers paying yield = 100% - (borrowRatio / (100 + borrowRatio)) = 100% - 16.6666666% = 83,333%.\\n borrowRatio_ = (1e27 - ((borrowRatio_ * 1e27) / (FOUR_DECIMALS + borrowRatio_)));\\n // borrowRatio can never be > 100%. so max subtraction can be 100% - 100% / 200%.\\n // or if borrowRatio_ is 0 -> 100% - 0. or if borrowRatio_ is 1 -> 100% - 1 / 101.\\n // max value here for borrowRatio_ is 1e27 - 0 = 1e27 (= 100% of borrowers paying yield).\\n }\\n\\n // temp_ => ratioSupplyYield. scaled down from 1e25 = 1% each to normal percent precision 1e2 = 1%.\\n // max nominator value is ~1.64e31 * 1e27 = 1.64e58. max result = 1.64e8\\n temp_ = (FOUR_DECIMALS * temp_ * borrowRatio_) / 1e54;\\n\\n // 2. calculate supply rate\\n // temp_ => supply rate (borrow rate - revenueFee%) * ratioSupplyYield.\\n // division part is done in next step to increase precision. (divided by 2x FOUR_DECIMALS, fee + borrowRate)\\n // Note that all calculation divisions for supplyExchangePrice are rounded down.\\n // Note supply rate can be bigger than the borrowRate, e.g. if there are only few lenders with interest\\n // but more suppliers not earning interest.\\n temp_ = ((exchangePricesAndConfig_ & X16) * // borrow rate\\n temp_ * // ratioSupplyYield\\n (FOUR_DECIMALS - ((exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_FEE) & X14))); // revenueFee\\n // fee can not be > 100%. max possible = 65535 * ~1.64e8 * 1e4 =~1.074774e17.\\n\\n // 3. calculate increase in supply exchange price\\n supplyExchangePrice_ += ((supplyExchangePrice_ * temp_ * secondsSinceLastUpdate_) /\\n (SECONDS_PER_YEAR * FOUR_DECIMALS * FOUR_DECIMALS * FOUR_DECIMALS));\\n // max possible nominator = max uint 64 * 1.074774e17 * max uint32 = ~8.52e45. Denominator can not be 0.\\n }\\n }\\n\\n ///////////////////////////////////////////////////////////////////////////\\n ////////// CALC REVENUE /////////\\n ///////////////////////////////////////////////////////////////////////////\\n\\n /// @dev gets the `revenueAmount_` for a token given its' totalAmounts and exchangePricesAndConfig from storage\\n /// and the current balance of the Fluid liquidity contract for the token.\\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 ) internal view returns (uint256 revenueAmount_) {\\n // @dev no need to super-optimize this method as it is only used by admin\\n\\n // calculate the new exchange prices based on earned interest\\n (uint256 supplyExchangePrice_, uint256 borrowExchangePrice_) = calcExchangePrices(exchangePricesAndConfig_);\\n\\n // total supply = interest free + with interest converted from raw\\n uint256 totalSupply_ = getTotalSupply(totalAmounts_, supplyExchangePrice_);\\n\\n if (totalSupply_ > 0) {\\n // available revenue: balanceOf(token) + totalBorrowings - totalLendings.\\n revenueAmount_ = liquidityTokenBalance_ + getTotalBorrow(totalAmounts_, borrowExchangePrice_);\\n // ensure there is no possible case because of rounding etc. where this would revert,\\n // explicitly check if >\\n revenueAmount_ = revenueAmount_ > totalSupply_ ? revenueAmount_ - totalSupply_ : 0;\\n // Note: if utilization > 100% (totalSupply < totalBorrow), then all the amount above 100% utilization\\n // can only be revenue.\\n } else {\\n // if supply is 0, then rest of balance can be withdrawn as revenue so that no amounts get stuck\\n revenueAmount_ = liquidityTokenBalance_;\\n }\\n }\\n\\n ///////////////////////////////////////////////////////////////////////////\\n ////////// CALC LIMITS /////////\\n ///////////////////////////////////////////////////////////////////////////\\n\\n /// @dev calculates withdrawal limit before an operate execution:\\n /// amount of user supply that must stay supplied (not amount that can be withdrawn).\\n /// i.e. if user has supplied 100m and can withdraw 5M, this method returns the 95M, not the withdrawable amount 5M\\n /// @param userSupplyData_ user supply data packed uint256 from storage\\n /// @param userSupply_ current user supply amount already extracted from `userSupplyData_` and converted from BigMath\\n /// @return currentWithdrawalLimit_ current withdrawal limit updated for expansion since last interaction.\\n /// returned value is in raw for with interest mode, normal amount for interest free mode!\\n function calcWithdrawalLimitBeforeOperate(\\n uint256 userSupplyData_,\\n uint256 userSupply_\\n ) internal view returns (uint256 currentWithdrawalLimit_) {\\n // @dev must support handling the case where timestamp is 0 (config is set but no interactions yet).\\n // first tx where timestamp is 0 will enter `if (lastWithdrawalLimit_ == 0)` because lastWithdrawalLimit_ is not set yet.\\n // returning max withdrawal allowed, which is not exactly right but doesn't matter because the first interaction must be\\n // a deposit anyway. Important is that it would not revert.\\n\\n // Note the first time a deposit brings the user supply amount to above the base withdrawal limit, the active limit\\n // is the fully expanded limit immediately.\\n\\n // extract last set withdrawal limit\\n uint256 lastWithdrawalLimit_ = (userSupplyData_ >>\\n LiquiditySlotsLink.BITS_USER_SUPPLY_PREVIOUS_WITHDRAWAL_LIMIT) & X64;\\n lastWithdrawalLimit_ =\\n (lastWithdrawalLimit_ >> DEFAULT_EXPONENT_SIZE) <<\\n (lastWithdrawalLimit_ & DEFAULT_EXPONENT_MASK);\\n if (lastWithdrawalLimit_ == 0) {\\n // withdrawal limit is not activated. Max withdrawal allowed\\n return 0;\\n }\\n\\n uint256 maxWithdrawableLimit_;\\n uint256 temp_;\\n unchecked {\\n // extract max withdrawable percent of user supply and\\n // calculate maximum withdrawable amount expandPercentage of user supply at full expansion duration elapsed\\n // e.g.: if 10% expandPercentage, meaning 10% is withdrawable after full expandDuration has elapsed.\\n\\n // userSupply_ needs to be atleast 1e73 to overflow max limit of ~1e77 in uint256 (no token in existence where this is possible).\\n maxWithdrawableLimit_ =\\n (((userSupplyData_ >> LiquiditySlotsLink.BITS_USER_SUPPLY_EXPAND_PERCENT) & X14) * userSupply_) /\\n FOUR_DECIMALS;\\n\\n // time elapsed since last withdrawal limit was set (in seconds)\\n // @dev last process timestamp is guaranteed to exist for withdrawal, as a supply must have happened before.\\n // last timestamp can not be > current timestamp\\n temp_ =\\n block.timestamp -\\n ((userSupplyData_ >> LiquiditySlotsLink.BITS_USER_SUPPLY_LAST_UPDATE_TIMESTAMP) & X33);\\n }\\n // calculate withdrawable amount of expandPercent that is elapsed of expandDuration.\\n // e.g. if 60% of expandDuration has elapsed, then user should be able to withdraw 6% of user supply, down to 94%.\\n // Note: no explicit check for this needed, it is covered by setting minWithdrawalLimit_ if needed.\\n temp_ =\\n (maxWithdrawableLimit_ * temp_) /\\n // extract expand duration: After this, decrement won't happen (user can withdraw 100% of withdraw limit)\\n ((userSupplyData_ >> LiquiditySlotsLink.BITS_USER_SUPPLY_EXPAND_DURATION) & X24); // expand duration can never be 0\\n // calculate expanded withdrawal limit: last withdrawal limit - withdrawable amount.\\n // Note: withdrawable amount here can grow bigger than userSupply if timeElapsed is a lot bigger than expandDuration,\\n // which would cause the subtraction `lastWithdrawalLimit_ - withdrawableAmount_` to revert. In that case, set 0\\n // which will cause minimum (fully expanded) withdrawal limit to be set in lines below.\\n unchecked {\\n // underflow explicitly checked & handled\\n currentWithdrawalLimit_ = lastWithdrawalLimit_ > temp_ ? lastWithdrawalLimit_ - temp_ : 0;\\n // calculate minimum withdrawal limit: minimum amount of user supply that must stay supplied at full expansion.\\n // subtraction can not underflow as maxWithdrawableLimit_ is a percentage amount (<=100%) of userSupply_\\n temp_ = userSupply_ - maxWithdrawableLimit_;\\n }\\n // if withdrawal limit is decreased below minimum then set minimum\\n // (e.g. when more than expandDuration time has elapsed)\\n if (temp_ > currentWithdrawalLimit_) {\\n currentWithdrawalLimit_ = temp_;\\n }\\n }\\n\\n /// @dev calculates withdrawal limit after an operate execution:\\n /// amount of user supply that must stay supplied (not amount that can be withdrawn).\\n /// i.e. if user has supplied 100m and can withdraw 5M, this method returns the 95M, not the withdrawable amount 5M\\n /// @param userSupplyData_ user supply data packed uint256 from storage\\n /// @param userSupply_ current user supply amount already extracted from `userSupplyData_` and added / subtracted with the executed operate amount\\n /// @param newWithdrawalLimit_ current withdrawal limit updated for expansion since last interaction, result from `calcWithdrawalLimitBeforeOperate`\\n /// @return withdrawalLimit_ updated withdrawal limit that should be written to storage. returned value is in\\n /// raw for with interest mode, normal amount for interest free mode!\\n function calcWithdrawalLimitAfterOperate(\\n uint256 userSupplyData_,\\n uint256 userSupply_,\\n uint256 newWithdrawalLimit_\\n ) internal pure returns (uint256) {\\n // temp_ => base withdrawal limit. below this, maximum withdrawals are allowed\\n uint256 temp_ = (userSupplyData_ >> LiquiditySlotsLink.BITS_USER_SUPPLY_BASE_WITHDRAWAL_LIMIT) & X18;\\n temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\\n\\n // if user supply is below base limit then max withdrawals are allowed\\n if (userSupply_ < temp_) {\\n return 0;\\n }\\n // temp_ => withdrawal limit expandPercent (is in 1e2 decimals)\\n temp_ = (userSupplyData_ >> LiquiditySlotsLink.BITS_USER_SUPPLY_EXPAND_PERCENT) & X14;\\n unchecked {\\n // temp_ => minimum withdrawal limit: userSupply - max withdrawable limit (userSupply * expandPercent))\\n // userSupply_ needs to be atleast 1e73 to overflow max limit of ~1e77 in uint256 (no token in existence where this is possible).\\n // subtraction can not underflow as maxWithdrawableLimit_ is a percentage amount (<=100%) of userSupply_\\n temp_ = userSupply_ - ((userSupply_ * temp_) / FOUR_DECIMALS);\\n }\\n // if new (before operation) withdrawal limit is less than minimum limit then set minimum limit.\\n // e.g. can happen on new deposits. withdrawal limit is instantly fully expanded in a scenario where\\n // increased deposit amount outpaces withrawals.\\n if (temp_ > newWithdrawalLimit_) {\\n return temp_;\\n }\\n return newWithdrawalLimit_;\\n }\\n\\n /// @dev calculates borrow limit before an operate execution:\\n /// total amount user borrow can reach (not borrowable amount in current operation).\\n /// i.e. if user has borrowed 50M and can still borrow 5M, this method returns the total 55M, not the borrowable amount 5M\\n /// @param userBorrowData_ user borrow data packed uint256 from storage\\n /// @param userBorrow_ current user borrow amount already extracted from `userBorrowData_`\\n /// @return currentBorrowLimit_ current borrow limit updated for expansion since last interaction. returned value is in\\n /// raw for with interest mode, normal amount for interest free mode!\\n function calcBorrowLimitBeforeOperate(\\n uint256 userBorrowData_,\\n uint256 userBorrow_\\n ) internal view returns (uint256 currentBorrowLimit_) {\\n // @dev must support handling the case where timestamp is 0 (config is set but no interactions yet) -> base limit.\\n // first tx where timestamp is 0 will enter `if (maxExpandedBorrowLimit_ < baseBorrowLimit_)` because `userBorrow_` and thus\\n // `maxExpansionLimit_` and thus `maxExpandedBorrowLimit_` is 0 and `baseBorrowLimit_` can not be 0.\\n\\n // temp_ = extract borrow expand percent (is in 1e2 decimals)\\n uint256 temp_ = (userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_EXPAND_PERCENT) & X14;\\n\\n uint256 maxExpansionLimit_;\\n uint256 maxExpandedBorrowLimit_;\\n unchecked {\\n // calculate max expansion limit: Max amount limit can expand to since last interaction\\n // userBorrow_ needs to be atleast 1e73 to overflow max limit of ~1e77 in uint256 (no token in existence where this is possible).\\n maxExpansionLimit_ = ((userBorrow_ * temp_) / FOUR_DECIMALS);\\n\\n // calculate max borrow limit: Max point limit can increase to since last interaction\\n maxExpandedBorrowLimit_ = userBorrow_ + maxExpansionLimit_;\\n }\\n\\n // currentBorrowLimit_ = extract base borrow limit\\n currentBorrowLimit_ = (userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_BASE_BORROW_LIMIT) & X18;\\n currentBorrowLimit_ =\\n (currentBorrowLimit_ >> DEFAULT_EXPONENT_SIZE) <<\\n (currentBorrowLimit_ & DEFAULT_EXPONENT_MASK);\\n\\n if (maxExpandedBorrowLimit_ < currentBorrowLimit_) {\\n return currentBorrowLimit_;\\n }\\n // time elapsed since last borrow limit was set (in seconds)\\n unchecked {\\n // temp_ = timeElapsed_ (last timestamp can not be > current timestamp)\\n temp_ =\\n block.timestamp -\\n ((userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_LAST_UPDATE_TIMESTAMP) & X33); // extract last update timestamp\\n }\\n\\n // currentBorrowLimit_ = expandedBorrowableAmount + extract last set borrow limit\\n currentBorrowLimit_ =\\n // calculate borrow limit expansion since last interaction for `expandPercent` that is elapsed of `expandDuration`.\\n // divisor is extract expand duration (after this, full expansion to expandPercentage happened).\\n ((maxExpansionLimit_ * temp_) /\\n ((userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_EXPAND_DURATION) & X24)) + // expand duration can never be 0\\n // extract last set borrow limit\\n BigMathMinified.fromBigNumber(\\n (userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_PREVIOUS_BORROW_LIMIT) & X64,\\n DEFAULT_EXPONENT_SIZE,\\n DEFAULT_EXPONENT_MASK\\n );\\n\\n // if timeElapsed is bigger than expandDuration, new borrow limit would be > max expansion,\\n // so set to `maxExpandedBorrowLimit_` in that case.\\n // also covers the case where last process timestamp = 0 (timeElapsed would simply be very big)\\n if (currentBorrowLimit_ > maxExpandedBorrowLimit_) {\\n currentBorrowLimit_ = maxExpandedBorrowLimit_;\\n }\\n // temp_ = extract hard max borrow limit. Above this user can never borrow (not expandable above)\\n temp_ = (userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_MAX_BORROW_LIMIT) & X18;\\n temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\\n\\n if (currentBorrowLimit_ > temp_) {\\n currentBorrowLimit_ = temp_;\\n }\\n }\\n\\n /// @dev calculates borrow limit after an operate execution:\\n /// total amount user borrow can reach (not borrowable amount in current operation).\\n /// i.e. if user has borrowed 50M and can still borrow 5M, this method returns the total 55M, not the borrowable amount 5M\\n /// @param userBorrowData_ user borrow data packed uint256 from storage\\n /// @param userBorrow_ current user borrow amount already extracted from `userBorrowData_` and added / subtracted with the executed operate amount\\n /// @param newBorrowLimit_ current borrow limit updated for expansion since last interaction, result from `calcBorrowLimitBeforeOperate`\\n /// @return borrowLimit_ updated borrow limit that should be written to storage.\\n /// returned value is in raw for with interest mode, normal amount for interest free mode!\\n function calcBorrowLimitAfterOperate(\\n uint256 userBorrowData_,\\n uint256 userBorrow_,\\n uint256 newBorrowLimit_\\n ) internal pure returns (uint256 borrowLimit_) {\\n // temp_ = extract borrow expand percent\\n uint256 temp_ = (userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_EXPAND_PERCENT) & X14; // (is in 1e2 decimals)\\n\\n unchecked {\\n // borrowLimit_ = calculate maximum borrow limit at full expansion.\\n // userBorrow_ needs to be at least 1e73 to overflow max limit of ~1e77 in uint256 (no token in existence where this is possible).\\n borrowLimit_ = userBorrow_ + ((userBorrow_ * temp_) / FOUR_DECIMALS);\\n }\\n\\n // temp_ = extract base borrow limit\\n temp_ = (userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_BASE_BORROW_LIMIT) & X18;\\n temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\\n\\n if (borrowLimit_ < temp_) {\\n // below base limit, borrow limit is always base limit\\n return temp_;\\n }\\n // temp_ = extract hard max borrow limit. Above this user can never borrow (not expandable above)\\n temp_ = (userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_MAX_BORROW_LIMIT) & X18;\\n temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\\n\\n // make sure fully expanded borrow limit is not above hard max borrow limit\\n if (borrowLimit_ > temp_) {\\n borrowLimit_ = temp_;\\n }\\n // if new borrow limit (from before operate) is > max borrow limit, set max borrow limit.\\n // (e.g. on a repay shrinking instantly to fully expanded borrow limit from new borrow amount. shrinking is instant)\\n if (newBorrowLimit_ > borrowLimit_) {\\n return borrowLimit_;\\n }\\n return newBorrowLimit_;\\n }\\n\\n ///////////////////////////////////////////////////////////////////////////\\n ////////// CALC RATES /////////\\n ///////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Calculates new borrow rate from utilization for a token\\n /// @param rateData_ rate data packed uint256 from storage for the token\\n /// @param utilization_ totalBorrow / totalSupply. 1e4 = 100% utilization\\n /// @return rate_ rate for that particular token in 1e2 precision (e.g. 5% rate = 500)\\n function calcBorrowRateFromUtilization(uint256 rateData_, uint256 utilization_) internal returns (uint256 rate_) {\\n // extract rate version: 4 bits (0xF) starting from bit 0\\n uint256 rateVersion_ = (rateData_ & 0xF);\\n\\n if (rateVersion_ == 1) {\\n rate_ = calcRateV1(rateData_, utilization_);\\n } else if (rateVersion_ == 2) {\\n rate_ = calcRateV2(rateData_, utilization_);\\n } else {\\n revert FluidLiquidityCalcsError(ErrorTypes.LiquidityCalcs__UnsupportedRateVersion);\\n }\\n\\n if (rate_ > X16) {\\n // hard cap for borrow rate at maximum value 16 bits (65535) to make sure it does not overflow storage space.\\n // this is unlikely to ever happen if configs stay within expected levels.\\n rate_ = X16;\\n // emit event to more easily become aware\\n emit BorrowRateMaxCap();\\n }\\n }\\n\\n /// @dev calculates the borrow rate based on utilization for rate data version 1 (with one kink) in 1e2 precision\\n /// @param rateData_ rate data packed uint256 from storage for the token\\n /// @param utilization_ in 1e2 (100% = 1e4)\\n /// @return rate_ rate in 1e2 precision\\n function calcRateV1(uint256 rateData_, uint256 utilization_) internal pure returns (uint256 rate_) {\\n /// For rate v1 (one kink) ------------------------------------------------------\\n /// Next 16 bits => 4 - 19 => Rate at utilization 0% (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\\n /// Next 16 bits => 20- 35 => Utilization at kink1 (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\\n /// Next 16 bits => 36- 51 => Rate at utilization kink1 (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\\n /// Next 16 bits => 52- 67 => Rate at utilization 100% (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\\n /// Last 188 bits => 68-255 => blank, might come in use in future\\n\\n // y = mx + c.\\n // y is borrow rate\\n // x is utilization\\n // m = slope (m can also be negative for declining rates)\\n // c is constant (c can be negative)\\n\\n uint256 y1_;\\n uint256 y2_;\\n uint256 x1_;\\n uint256 x2_;\\n\\n // extract kink1: 16 bits (0xFFFF) starting from bit 20\\n // kink is in 1e2, same as utilization, so no conversion needed for direct comparison of the two\\n uint256 kink1_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V1_UTILIZATION_AT_KINK) & X16;\\n if (utilization_ < kink1_) {\\n // if utilization is less than kink\\n y1_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_ZERO) & X16;\\n y2_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_KINK) & X16;\\n x1_ = 0; // 0%\\n x2_ = kink1_;\\n } else {\\n // else utilization is greater than kink\\n y1_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_KINK) & X16;\\n y2_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_MAX) & X16;\\n x1_ = kink1_;\\n x2_ = FOUR_DECIMALS; // 100%\\n }\\n\\n int256 constant_;\\n int256 slope_;\\n unchecked {\\n // calculating slope with twelve decimal precision. m = (y2 - y1) / (x2 - x1).\\n // utilization of x2 can not be <= utilization of x1 (so no underflow or 0 divisor)\\n // y is in 1e2 so can not overflow when multiplied with TWELVE_DECIMALS\\n slope_ = (int256(y2_ - y1_) * int256(TWELVE_DECIMALS)) / int256((x2_ - x1_));\\n\\n // calculating constant at 12 decimal precision. slope is already in 12 decimal hence only multiple with y1. c = y - mx.\\n // maximum y1_ value is 65535. 65535 * 1e12 can not overflow int256\\n // maximum slope is 65535 - 0 * TWELVE_DECIMALS / 1 = 65535 * 1e12;\\n // maximum x1_ is 100% (9_999 actually) => slope_ * x1_ can not overflow int256\\n // subtraction most extreme case would be 0 - max value slope_ * x1_ => can not underflow int256\\n constant_ = int256(y1_ * TWELVE_DECIMALS) - (slope_ * int256(x1_));\\n\\n // calculating new borrow rate\\n // - slope_ max value is 65535 * 1e12,\\n // - utilization max value is let's say 500% (extreme case where borrow rate increases borrow amount without new supply)\\n // - constant max value is 65535 * 1e12\\n // so max values are 65535 * 1e12 * 50_000 + 65535 * 1e12 -> 3.2768*10^21, which easily fits int256\\n // divisor TWELVE_DECIMALS can not be 0\\n slope_ = (slope_ * int256(utilization_)) + constant_; // reusing `slope_` as variable for gas savings\\n if (slope_ < 0) {\\n revert FluidLiquidityCalcsError(ErrorTypes.LiquidityCalcs__BorrowRateNegative);\\n }\\n rate_ = uint256(slope_) / TWELVE_DECIMALS;\\n }\\n }\\n\\n /// @dev calculates the borrow rate based on utilization for rate data version 2 (with two kinks) in 1e4 precision\\n /// @param rateData_ rate data packed uint256 from storage for the token\\n /// @param utilization_ in 1e2 (100% = 1e4)\\n /// @return rate_ rate in 1e4 precision\\n function calcRateV2(uint256 rateData_, uint256 utilization_) internal pure returns (uint256 rate_) {\\n /// For rate v2 (two kinks) -----------------------------------------------------\\n /// Next 16 bits => 4 - 19 => Rate at utilization 0% (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\\n /// Next 16 bits => 20- 35 => Utilization at kink1 (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\\n /// Next 16 bits => 36- 51 => Rate at utilization kink1 (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\\n /// Next 16 bits => 52- 67 => Utilization at kink2 (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\\n /// Next 16 bits => 68- 83 => Rate at utilization kink2 (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\\n /// Next 16 bits => 84- 99 => Rate at utilization 100% (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\\n /// Last 156 bits => 100-255 => blank, might come in use in future\\n\\n // y = mx + c.\\n // y is borrow rate\\n // x is utilization\\n // m = slope (m can also be negative for declining rates)\\n // c is constant (c can be negative)\\n\\n uint256 y1_;\\n uint256 y2_;\\n uint256 x1_;\\n uint256 x2_;\\n\\n // extract kink1: 16 bits (0xFFFF) starting from bit 20\\n // kink is in 1e2, same as utilization, so no conversion needed for direct comparison of the two\\n uint256 kink1_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_UTILIZATION_AT_KINK1) & X16;\\n if (utilization_ < kink1_) {\\n // if utilization is less than kink1\\n y1_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_ZERO) & X16;\\n y2_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_KINK1) & X16;\\n x1_ = 0; // 0%\\n x2_ = kink1_;\\n } else {\\n // extract kink2: 16 bits (0xFFFF) starting from bit 52\\n uint256 kink2_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_UTILIZATION_AT_KINK2) & X16;\\n if (utilization_ < kink2_) {\\n // if utilization is less than kink2\\n y1_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_KINK1) & X16;\\n y2_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_KINK2) & X16;\\n x1_ = kink1_;\\n x2_ = kink2_;\\n } else {\\n // else utilization is greater than kink2\\n y1_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_KINK2) & X16;\\n y2_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_MAX) & X16;\\n x1_ = kink2_;\\n x2_ = FOUR_DECIMALS;\\n }\\n }\\n\\n int256 constant_;\\n int256 slope_;\\n unchecked {\\n // calculating slope with twelve decimal precision. m = (y2 - y1) / (x2 - x1).\\n // utilization of x2 can not be <= utilization of x1 (so no underflow or 0 divisor)\\n // y is in 1e2 so can not overflow when multiplied with TWELVE_DECIMALS\\n slope_ = (int256(y2_ - y1_) * int256(TWELVE_DECIMALS)) / int256((x2_ - x1_));\\n\\n // calculating constant at 12 decimal precision. slope is already in 12 decimal hence only multiple with y1. c = y - mx.\\n // maximum y1_ value is 65535. 65535 * 1e12 can not overflow int256\\n // maximum slope is 65535 - 0 * TWELVE_DECIMALS / 1 = 65535 * 1e12;\\n // maximum x1_ is 100% (9_999 actually) => slope_ * x1_ can not overflow int256\\n // subtraction most extreme case would be 0 - max value slope_ * x1_ => can not underflow int256\\n constant_ = int256(y1_ * TWELVE_DECIMALS) - (slope_ * int256(x1_));\\n\\n // calculating new borrow rate\\n // - slope_ max value is 65535 * 1e12,\\n // - utilization max value is let's say 500% (extreme case where borrow rate increases borrow amount without new supply)\\n // - constant max value is 65535 * 1e12\\n // so max values are 65535 * 1e12 * 50_000 + 65535 * 1e12 -> 3.2768*10^21, which easily fits int256\\n // divisor TWELVE_DECIMALS can not be 0\\n slope_ = (slope_ * int256(utilization_)) + constant_; // reusing `slope_` as variable for gas savings\\n if (slope_ < 0) {\\n revert FluidLiquidityCalcsError(ErrorTypes.LiquidityCalcs__BorrowRateNegative);\\n }\\n rate_ = uint256(slope_) / TWELVE_DECIMALS;\\n }\\n }\\n\\n /// @dev reads the total supply out of Liquidity packed storage `totalAmounts_` for `supplyExchangePrice_`\\n function getTotalSupply(\\n uint256 totalAmounts_,\\n uint256 supplyExchangePrice_\\n ) internal pure returns (uint256 totalSupply_) {\\n // totalSupply_ => supplyInterestFree\\n totalSupply_ = (totalAmounts_ >> LiquiditySlotsLink.BITS_TOTAL_AMOUNTS_SUPPLY_INTEREST_FREE) & X64;\\n totalSupply_ = (totalSupply_ >> DEFAULT_EXPONENT_SIZE) << (totalSupply_ & DEFAULT_EXPONENT_MASK);\\n\\n uint256 totalSupplyRaw_ = totalAmounts_ & X64; // no shifting as supplyRaw is first 64 bits\\n totalSupplyRaw_ = (totalSupplyRaw_ >> DEFAULT_EXPONENT_SIZE) << (totalSupplyRaw_ & DEFAULT_EXPONENT_MASK);\\n\\n // totalSupply = supplyInterestFree + supplyRawInterest normalized from raw\\n totalSupply_ += ((totalSupplyRaw_ * supplyExchangePrice_) / EXCHANGE_PRICES_PRECISION);\\n }\\n\\n /// @dev reads the total borrow out of Liquidity packed storage `totalAmounts_` for `borrowExchangePrice_`\\n function getTotalBorrow(\\n uint256 totalAmounts_,\\n uint256 borrowExchangePrice_\\n ) internal pure returns (uint256 totalBorrow_) {\\n // totalBorrow_ => borrowInterestFree\\n // no & mask needed for borrow interest free as it occupies the last bits in the storage slot\\n totalBorrow_ = (totalAmounts_ >> LiquiditySlotsLink.BITS_TOTAL_AMOUNTS_BORROW_INTEREST_FREE);\\n totalBorrow_ = (totalBorrow_ >> DEFAULT_EXPONENT_SIZE) << (totalBorrow_ & DEFAULT_EXPONENT_MASK);\\n\\n uint256 totalBorrowRaw_ = (totalAmounts_ >> LiquiditySlotsLink.BITS_TOTAL_AMOUNTS_BORROW_WITH_INTEREST) & X64;\\n totalBorrowRaw_ = (totalBorrowRaw_ >> DEFAULT_EXPONENT_SIZE) << (totalBorrowRaw_ & DEFAULT_EXPONENT_MASK);\\n\\n // totalBorrow = borrowInterestFree + borrowRawInterest normalized from raw\\n totalBorrow_ += ((totalBorrowRaw_ * borrowExchangePrice_) / EXCHANGE_PRICES_PRECISION);\\n }\\n}\\n\",\"keccak256\":\"0xa65e2f84b2c33769ceb6b28fbd3221be29da2f8ac96e4d8b8cea91948d81a707\",\"license\":\"BUSL-1.1\"},\"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_TIMESTAMP = 129;\\n uint256 internal constant BITS_USER_SUPPLY_EXPAND_PERCENT = 162;\\n uint256 internal constant BITS_USER_SUPPLY_EXPAND_DURATION = 176;\\n uint256 internal constant BITS_USER_SUPPLY_BASE_WITHDRAWAL_LIMIT = 200;\\n uint256 internal constant BITS_USER_SUPPLY_IS_PAUSED = 255;\\n\\n // UserBorrowData\\n uint256 internal constant BITS_USER_BORROW_MODE = 0;\\n uint256 internal constant BITS_USER_BORROW_AMOUNT = 1;\\n uint256 internal constant BITS_USER_BORROW_PREVIOUS_BORROW_LIMIT = 65;\\n uint256 internal constant BITS_USER_BORROW_LAST_UPDATE_TIMESTAMP = 129;\\n uint256 internal constant BITS_USER_BORROW_EXPAND_PERCENT = 162;\\n uint256 internal constant BITS_USER_BORROW_EXPAND_DURATION = 176;\\n uint256 internal constant BITS_USER_BORROW_BASE_BORROW_LIMIT = 200;\\n uint256 internal constant BITS_USER_BORROW_MAX_BORROW_LIMIT = 218;\\n uint256 internal constant BITS_USER_BORROW_IS_PAUSED = 255;\\n\\n // --------------------------------\\n\\n /// @notice Calculating the slot ID for Liquidity contract for single mapping at `slot_` for `key_`\\n function calculateMappingStorageSlot(uint256 slot_, address key_) internal pure returns (bytes32) {\\n return keccak256(abi.encode(key_, slot_));\\n }\\n\\n /// @notice Calculating the slot ID for Liquidity contract for double mapping at `slot_` for `key1_` and `key2_`\\n function calculateDoubleMappingStorageSlot(\\n uint256 slot_,\\n address key1_,\\n address key2_\\n ) internal pure returns (bytes32) {\\n bytes32 intermediateSlot_ = keccak256(abi.encode(key1_, slot_));\\n return keccak256(abi.encode(key2_, intermediateSlot_));\\n }\\n}\\n\",\"keccak256\":\"0x85725ce90bbeb00541715fe58fb213b96706515e9eafdae357657995e9ac147d\",\"license\":\"BUSL-1.1\"},\"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\",\"keccak256\":\"0x0818447e79488c3da0fde292ae7219cf2a819951ad5d4456fb297082e5e83a9b\",\"license\":\"BUSL-1.1\"},\"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 /// 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 /// Last 7 bits => 249-255 => empty for future use\\n /// if more free bits are needed in the future, update on storage threshold bits could be reduced to 7 bits\\n /// (can plan to add `MAX_TOKEN_CONFIG_UPDATE_THRESHOLD` but need to adjust more bits)\\n /// if more bits absolutely needed then we can convert fee, utilization, update on storage threshold,\\n /// supplyRatio & borrowRatio from 14 bits to 10bits (1023 max number) where 1000 = 100% & 1 = 0.1%\\n mapping(address => uint256) internal _exchangePricesAndConfig;\\n\\n // ----- storage slot 6 ------\\n\\n /// @dev Rate related data per token: token -> rate data\\n /// READ (SLOAD): all actions; WRITE (SSTORE): only on set config admin actions\\n /// token => rate related data\\n /// First 4 bits => 0-3 => rate version\\n /// rest of the bits are rate dependent:\\n\\n /// For rate v1 (one kink) ------------------------------------------------------\\n /// Next 16 bits => 4 - 19 => Rate at utilization 0% (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\\n /// Next 16 bits => 20- 35 => Utilization at kink1 (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\\n /// Next 16 bits => 36- 51 => Rate at utilization kink1 (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\\n /// Next 16 bits => 52- 67 => Rate at utilization 100% (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\\n /// Last 188 bits => 68-255 => empty for future use\\n\\n /// For rate v2 (two kinks) -----------------------------------------------------\\n /// Next 16 bits => 4 - 19 => Rate at utilization 0% (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\\n /// Next 16 bits => 20- 35 => Utilization at kink1 (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\\n /// Next 16 bits => 36- 51 => Rate at utilization kink1 (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\\n /// Next 16 bits => 52- 67 => Utilization at kink2 (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\\n /// Next 16 bits => 68- 83 => Rate at utilization kink2 (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\\n /// Next 16 bits => 84- 99 => Rate at utilization 100% (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\\n /// Last 156 bits => 100-255 => empty for future use\\n mapping(address => uint256) internal _rateData;\\n\\n // ----- storage slot 7 ------\\n\\n /// @dev total supply / borrow amounts for with / without interest per token: token -> amounts\\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 mapping(address => uint256) internal _totalAmounts;\\n\\n // ----- storage slot 8 ------\\n\\n /// @dev user supply data per token: user -> token -> data\\n /// First 1 bit => 0 => mode: user supply with or without interest\\n /// 0 = without, amounts are in normal (i.e. no need to multiply with exchange price)\\n /// 1 = with interest, amounts are in raw (i.e. must multiply with exchange price to get actual token amounts)\\n /// Next 64 bits => 1- 64 => user supply amount (normal or raw depends on 1st bit); BigMath: 56 | 8\\n /// Next 64 bits => 65-128 => previous user withdrawal limit (normal or raw depends on 1st bit); BigMath: 56 | 8\\n /// Next 33 bits => 129-161 => last triggered process timestamp (enough until 16 March 2242 -> max value 8589934591)\\n /// Next 14 bits => 162-175 => expand withdrawal limit percentage (in 1e2: 100% = 10_000; 1% = 100 -> max value 16_383).\\n /// @dev shrinking is instant\\n /// Next 24 bits => 176-199 => withdrawal limit expand duration in seconds.(Max value 16_777_215; ~4_660 hours, ~194 days)\\n /// Next 18 bits => 200-217 => base withdrawal limit: below this, 100% withdrawals can be done (normal or raw depends on 1st bit); BigMath: 10 | 8\\n /// Next 37 bits => 218-254 => empty for future use\\n /// Last bit => 255-255 => is user paused (1 = paused, 0 = not paused)\\n mapping(address => mapping(address => uint256)) internal _userSupplyData;\\n\\n // ----- storage slot 9 ------\\n\\n /// @dev user borrow data per token: user -> token -> data\\n /// First 1 bit => 0 => mode: user borrow with or without interest\\n /// 0 = without, amounts are in normal (i.e. no need to multiply with exchange price)\\n /// 1 = with interest, amounts are in raw (i.e. must multiply with exchange price to get actual token amounts)\\n /// Next 64 bits => 1- 64 => user borrow amount (normal or raw depends on 1st bit); BigMath: 56 | 8\\n /// Next 64 bits => 65-128 => previous user debt ceiling (normal or raw depends on 1st bit); BigMath: 56 | 8\\n /// Next 33 bits => 129-161 => last triggered process timestamp (enough until 16 March 2242 -> max value 8589934591)\\n /// Next 14 bits => 162-175 => expand debt ceiling percentage (in 1e2: 100% = 10_000; 1% = 100 -> max value 16_383)\\n /// @dev shrinking is instant\\n /// Next 24 bits => 176-199 => debt ceiling expand duration in seconds (Max value 16_777_215; ~4_660 hours, ~194 days)\\n /// Next 18 bits => 200-217 => base debt ceiling: below this, there's no debt ceiling limits (normal or raw depends on 1st bit); BigMath: 10 | 8\\n /// Next 18 bits => 218-235 => max debt ceiling: absolute maximum debt ceiling can expand to (normal or raw depends on 1st bit); BigMath: 10 | 8\\n /// Next 19 bits => 236-254 => empty for future use\\n /// Last bit => 255-255 => is user paused (1 = paused, 0 = not paused)\\n mapping(address => mapping(address => uint256)) internal _userBorrowData;\\n\\n // ----- storage slot 10 ------\\n\\n /// @dev list of allowed tokens at Liquidity. tokens that are once configured can never be completely removed. so this\\n /// array is append-only.\\n address[] internal _listedTokens;\\n}\\n\",\"keccak256\":\"0x3a7af2c445534137db06ac311388e7d82546d4058c4dd0b804d5cbab11e574c5\",\"license\":\"BUSL-1.1\"},\"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\",\"keccak256\":\"0x6013ceb756cb1301b2a5ebac8aa0dfc39dc610012670462a70c13d99a2708302\",\"license\":\"BUSL-1.1\"},\"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 user sent supply/withdraw and borrow/payback both as 0\\n uint256 internal constant UserModule__OperateAmountsZero = 11005;\\n\\n /// @notice thrown when user sent supply/withdraw or borrow/payback both as bigger than 2**128\\n uint256 internal constant UserModule__OperateAmountOutOfBounds = 11006;\\n\\n /// @notice thrown when the operate amount for supply / withdraw / borrow / payback is below the minimum amount\\n /// that would cause a storage difference after BigMath & rounding imprecision. Extremely unlikely to ever happen\\n /// for all normal use-cases.\\n uint256 internal constant UserModule__OperateAmountInsufficient = 11007;\\n\\n /// @notice thrown when withdraw or borrow is executed but withdrawTo or borrowTo is the zero address\\n uint256 internal constant UserModule__ReceiverNotDefined = 11008;\\n\\n /// @notice thrown when user did send excess or insufficient amount (beyond rounding issues)\\n uint256 internal constant UserModule__TransferAmountOutOfBounds = 11009;\\n\\n /// @notice thrown when user sent msg.value along for an operation not for the native token\\n uint256 internal constant UserModule__MsgValueForNonNativeToken = 11010;\\n\\n /// @notice thrown when a borrow operation is done when utilization is above 100%\\n uint256 internal constant UserModule__MaxUtilizationReached = 11011;\\n\\n /// @notice all ValueOverflow errors below are thrown if a certain input param or calc result overflows the allowed storage size\\n uint256 internal constant UserModule__ValueOverflow__EXCHANGE_PRICES = 11012;\\n uint256 internal constant UserModule__ValueOverflow__UTILIZATION = 11013;\\n uint256 internal constant UserModule__ValueOverflow__TOTAL_SUPPLY = 11014;\\n uint256 internal constant UserModule__ValueOverflow__TOTAL_BORROW = 11015;\\n\\n /***********************************|\\n | LiquidityHelpers | \\n |__________________________________*/\\n\\n /// @notice thrown when a reentrancy happens\\n uint256 internal constant LiquidityHelpers__Reentrancy = 12001;\\n}\\n\",\"keccak256\":\"0xa0abd61991acadca901f9d0b1b137316f76586d89b76d1b466c069198b385926\",\"license\":\"BUSL-1.1\"},\"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\",\"keccak256\":\"0x34d00aa5b172195544bca0706b0168717fe1c002a6bd8fe538234e009cb219ac\",\"license\":\"BUSL-1.1\"},\"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 userSupplyData_,\\n userSupply_,\\n newWithdrawalLimit_\\n );\\n\\n // Converting user's supply into BigNumber\\n userSupply_ = userSupply_.toBigNumber(\\n DEFAULT_COEFFICIENT_SIZE,\\n DEFAULT_EXPONENT_SIZE,\\n BigMathMinified.ROUND_DOWN\\n );\\n if (((userSupplyData_ >> LiquiditySlotsLink.BITS_USER_SUPPLY_AMOUNT) & X64) == userSupply_) {\\n // make sure that operate amount is not so small that it wouldn't affect storage update. if a difference\\n // is present then rounding will be in the right direction to avoid any potential manipulation.\\n revert FluidLiquidityError(ErrorTypes.UserModule__OperateAmountInsufficient);\\n }\\n\\n // Converting withdrawal limit into BigNumber\\n newWithdrawalLimit_ = newWithdrawalLimit_.toBigNumber(\\n DEFAULT_COEFFICIENT_SIZE,\\n DEFAULT_EXPONENT_SIZE,\\n BigMathMinified.ROUND_DOWN\\n );\\n\\n // Updating on storage\\n _userSupplyData[msg.sender][token_] =\\n // mask to update bits 1-161 (supply amount, withdrawal limit, timestamp)\\n (userSupplyData_ & 0xfffffffffffffffffffffffc0000000000000000000000000000000000000001) |\\n (userSupply_ << LiquiditySlotsLink.BITS_USER_SUPPLY_AMOUNT) | // converted to BigNumber can not overflow\\n (newWithdrawalLimit_ << LiquiditySlotsLink.BITS_USER_SUPPLY_PREVIOUS_WITHDRAWAL_LIMIT) | // converted to BigNumber can not overflow\\n (block.timestamp << LiquiditySlotsLink.BITS_USER_SUPPLY_LAST_UPDATE_TIMESTAMP);\\n }\\n\\n /// @dev borrow or payback for both with interest & interest free.\\n /// positive `amount_` is borrow, negative `amount_` is payback.\\n function _borrowOrPayback(\\n address token_,\\n int256 amount_,\\n uint256 borrowExchangePrice_\\n ) internal returns (int256 newBorrowInterestRaw_, int256 newBorrowInterestFree_) {\\n uint256 userBorrowData_ = _userBorrowData[msg.sender][token_];\\n\\n if (userBorrowData_ == 0) {\\n revert FluidLiquidityError(ErrorTypes.UserModule__UserNotDefined);\\n }\\n if ((userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_IS_PAUSED) & 1 == 1) {\\n revert FluidLiquidityError(ErrorTypes.UserModule__UserPaused);\\n }\\n\\n // extract user borrow amount\\n uint256 userBorrow_ = (userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_AMOUNT) & X64;\\n userBorrow_ = (userBorrow_ >> DEFAULT_EXPONENT_SIZE) << (userBorrow_ & DEFAULT_EXPONENT_MASK);\\n\\n // calculate current, updated (expanded etc.) borrow limit\\n uint256 newBorrowLimit_ = LiquidityCalcs.calcBorrowLimitBeforeOperate(userBorrowData_, userBorrow_);\\n\\n // calculate updated user borrow amount\\n if (userBorrowData_ & 1 == 1) {\\n // with interest\\n if (amount_ > 0) {\\n // convert amount normal to raw (divide by exchange price) -> round up for borrow\\n newBorrowInterestRaw_ = int256(\\n FixedPointMathLib.mulDivUp(uint256(amount_), EXCHANGE_PRICES_PRECISION, borrowExchangePrice_)\\n );\\n userBorrow_ = userBorrow_ + uint256(newBorrowInterestRaw_);\\n } else {\\n // convert amount from normal to raw (divide by exchange price) -> round down for payback\\n newBorrowInterestRaw_ = (amount_ * int256(EXCHANGE_PRICES_PRECISION)) / int256(borrowExchangePrice_);\\n userBorrow_ = userBorrow_ - uint256(-newBorrowInterestRaw_);\\n }\\n } else {\\n // without interest\\n newBorrowInterestFree_ = amount_;\\n if (newBorrowInterestFree_ > 0) {\\n // borrowing\\n userBorrow_ = userBorrow_ + uint256(newBorrowInterestFree_);\\n } else {\\n // payback\\n userBorrow_ = userBorrow_ - uint256(-newBorrowInterestFree_);\\n }\\n }\\n\\n if (amount_ > 0 && userBorrow_ > newBorrowLimit_) {\\n // if borrow, then check the user borrow amount after borrowing is below borrow limit\\n revert FluidLiquidityError(ErrorTypes.UserModule__BorrowLimitReached);\\n }\\n\\n // calculate borrow limit to store as previous borrow limit in storage\\n newBorrowLimit_ = LiquidityCalcs.calcBorrowLimitAfterOperate(userBorrowData_, userBorrow_, newBorrowLimit_);\\n\\n // Converting user's borrowings into bignumber\\n userBorrow_ = userBorrow_.toBigNumber(\\n DEFAULT_COEFFICIENT_SIZE,\\n DEFAULT_EXPONENT_SIZE,\\n BigMathMinified.ROUND_UP\\n );\\n\\n if (((userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_AMOUNT) & X64) == userBorrow_) {\\n // make sure that operate amount is not so small that it wouldn't affect storage update. if a difference\\n // is present then rounding will be in the right direction to avoid any potential manipulation.\\n revert FluidLiquidityError(ErrorTypes.UserModule__OperateAmountInsufficient);\\n }\\n\\n // Converting borrow limit into bignumber\\n newBorrowLimit_ = newBorrowLimit_.toBigNumber(\\n DEFAULT_COEFFICIENT_SIZE,\\n DEFAULT_EXPONENT_SIZE,\\n BigMathMinified.ROUND_DOWN\\n );\\n\\n // Updating on storage\\n _userBorrowData[msg.sender][token_] =\\n // mask to update bits 1-161 (borrow amount, borrow limit, timestamp)\\n (userBorrowData_ & 0xfffffffffffffffffffffffc0000000000000000000000000000000000000001) |\\n (userBorrow_ << LiquiditySlotsLink.BITS_USER_BORROW_AMOUNT) | // converted to BigNumber can not overflow\\n (newBorrowLimit_ << LiquiditySlotsLink.BITS_USER_BORROW_PREVIOUS_BORROW_LIMIT) | // converted to BigNumber can not overflow\\n (block.timestamp << LiquiditySlotsLink.BITS_USER_BORROW_LAST_UPDATE_TIMESTAMP);\\n }\\n\\n /// @dev checks if `supplyAmount_` & borrowAmount amounts balance themselves out (checked before calling this method):\\n /// - supply(+) == borrow(+), withdraw(-) == payback(-). (DEX protocol use-case)\\n /// - `withdrawTo_` / `borrowTo_` must be msg.sender (protocol)\\n /// - `callbackData_` MUST be encoded so that \\\"from\\\" address is at last 20 bytes (if this optimization is desired),\\n /// also for native token operations where liquidityCallback is not triggered!\\n /// from address must come at last position if there is more data. I.e. encode like:\\n /// abi.encode(otherVar1, otherVar2, FROM_ADDRESS). Note dynamic types used with abi.encode come at the end\\n /// so if dynamic types are needed, you must use abi.encodePacked to ensure the from address is at the end.\\n function _isInOutBalancedOut(\\n int256 supplyAmount_,\\n address withdrawTo_,\\n address borrowTo_,\\n bytes memory callbackData_\\n ) internal view returns (bool) {\\n if (callbackData_.length < 20) {\\n return false;\\n }\\n\\n address inFrom_;\\n assembly {\\n inFrom_ := mload(\\n add(\\n // add padding for length as present for dynamic arrays in memory\\n add(callbackData_, 32),\\n // assembly expects address with leading zeros / left padded so need to use 32 as length here\\n sub(mload(callbackData_), 32)\\n )\\n )\\n }\\n return\\n // case: supply & borrow. borrow receiver must be the same as depositor and must be protocol\\n (supplyAmount_ > 0 && inFrom_ == borrowTo_ && inFrom_ == msg.sender) ||\\n // case: withdraw & payback. withdraw receiver must be the same as depositor and must be protocol\\n (supplyAmount_ < 0 && inFrom_ == withdrawTo_ && inFrom_ == msg.sender);\\n }\\n}\\n\\ninterface IZtakingPool {\\n ///@notice Stake a specified amount of a particular supported token into the Ztaking Pool\\n ///@param _token The token to deposit/stake in the Ztaking Pool\\n ///@param _for The user to deposit/stake on behalf of\\n ///@param _amount The amount of token to deposit/stake into the Ztaking Pool\\n function depositFor(address _token, address _for, uint256 _amount) external;\\n\\n ///@notice Withdraw a specified amount of a particular supported token previously staked into the Ztaking Pool\\n ///@param _token The token to withdraw from the Ztaking Pool\\n ///@param _amount The amount of token to withdraw from the Ztaking Pool\\n function withdraw(address _token, uint256 _amount) external;\\n}\\n\\n/// @title Fluid Liquidity UserModule\\n/// @notice Fluid Liquidity public facing endpoint logic contract that implements the `operate()` method.\\n/// operate can be used to deposit, withdraw, borrow & payback funds, given that they have the necessary\\n/// user config allowance. Interacting users must be allowed via the Fluid Liquidity AdminModule first.\\n/// Intended users are thus allow-listed protocols, e.g. the Lending protocol (fTokens), Vault protocol etc.\\n/// @dev For view methods / accessing data, use the \\\"LiquidityResolver\\\" periphery contract.\\ncontract FluidLiquidityUserModule is CoreInternals {\\n using SafeERC20 for IERC20;\\n using BigMathMinified for uint256;\\n\\n address private constant WEETH = 0xCd5fE23C85820F7B72D0926FC9b05b43E359b7ee;\\n IZtakingPool private constant ZIRCUIT = IZtakingPool(0xF047ab4c75cebf0eB9ed34Ae2c186f3611aEAfa6);\\n\\n /// @dev struct for vars used in operate() that would otherwise cause a Stack too deep error\\n struct OperateMemoryVars {\\n bool skipTransfers;\\n uint256 supplyExchangePrice;\\n uint256 borrowExchangePrice;\\n uint256 supplyRawInterest;\\n uint256 supplyInterestFree;\\n uint256 borrowRawInterest;\\n uint256 borrowInterestFree;\\n uint256 totalAmounts;\\n uint256 exchangePricesAndConfig;\\n }\\n\\n /// @notice inheritdoc IFluidLiquidity\\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 reentrancy returns (uint256 memVar3_, uint256 memVar4_) {\\n if (supplyAmount_ == 0 && borrowAmount_ == 0) {\\n revert FluidLiquidityError(ErrorTypes.UserModule__OperateAmountsZero);\\n }\\n if (\\n supplyAmount_ < type(int128).min ||\\n supplyAmount_ > type(int128).max ||\\n borrowAmount_ < type(int128).min ||\\n borrowAmount_ > type(int128).max\\n ) {\\n revert FluidLiquidityError(ErrorTypes.UserModule__OperateAmountOutOfBounds);\\n }\\n if ((supplyAmount_ < 0 && withdrawTo_ == address(0)) || (borrowAmount_ > 0 && borrowTo_ == address(0))) {\\n revert FluidLiquidityError(ErrorTypes.UserModule__ReceiverNotDefined);\\n }\\n if (token_ != NATIVE_TOKEN_ADDRESS && msg.value > 0) {\\n // revert: there should not be msg.value if the token is not the native token\\n revert FluidLiquidityError(ErrorTypes.UserModule__MsgValueForNonNativeToken);\\n }\\n\\n OperateMemoryVars memory o_;\\n\\n // @dev temporary memory variables used as helper in between to avoid assigning new memory variables\\n uint256 memVar_;\\n // memVar2_ => operateAmountIn: deposit + payback\\n uint256 memVar2_ = uint256((supplyAmount_ > 0 ? supplyAmount_ : int256(0))) +\\n uint256((borrowAmount_ < 0 ? -borrowAmount_ : int256(0)));\\n // check if in & output amounts balance themselves out:\\n // supply(+) == borrow(+), withdraw(-) == payback(-). (DEX protocol use-case)\\n // AND msg.value must be 0 otherwise we assume protocol wants normal transfers to happen\\n if (\\n supplyAmount_ == borrowAmount_ &&\\n msg.value == 0 &&\\n _isInOutBalancedOut(supplyAmount_, withdrawTo_, borrowTo_, callbackData_)\\n ) {\\n memVar2_ = 0; // set to 0 to skip transfers IN\\n o_.skipTransfers = true; // set flag to true to skip transfers OUT\\n }\\n if (token_ == NATIVE_TOKEN_ADDRESS) {\\n unchecked {\\n // check supply and payback amount is covered by available sent msg.value and\\n // protection that msg.value is not unintentionally way more than actually used in operate()\\n if (memVar2_ > msg.value || msg.value > memVar2_ + NATIVE_AMOUNT_EXCESS_LIMIT) {\\n revert FluidLiquidityError(ErrorTypes.UserModule__TransferAmountOutOfBounds);\\n }\\n }\\n memVar2_ = 0; // set to 0 to skip transfers IN more gas efficient. No need for native token.\\n }\\n // if supply or payback or both -> transfer token amount from sender to here.\\n // for native token this is already covered by msg.value checks in operate(). memVar2_ is set to 0\\n // for same amounts in same operate(): supply(+) == borrow(+), withdraw(-) == payback(-). memVar2_ is set to 0\\n if (memVar2_ > 0) {\\n // memVar_ => initial token balance of this contract\\n memVar_ = IERC20(token_).balanceOf(address(this));\\n // trigger protocol to send token amount and pass callback data\\n IProtocol(msg.sender).liquidityCallback(token_, memVar2_, callbackData_);\\n // memVar_ => current token balance of this contract - initial balance\\n memVar_ = IERC20(token_).balanceOf(address(this)) - memVar_;\\n unchecked {\\n if (memVar_ < memVar2_ || memVar_ > (memVar2_ + 10)) {\\n // revert if protocol did not send enough to cover supply / payback\\n // or if protocol sent more than expected, with minor tolerance for any potential rounding issues,\\n // even though that should not be needed (liquidityCallback should send exact amount as in params).\\n revert FluidLiquidityError(ErrorTypes.UserModule__TransferAmountOutOfBounds);\\n }\\n }\\n\\n // ---------- temporary code start -----------------------\\n // temporary addition for weETH: if token is weETH -> deposit to Zircuit\\n if ((token_ == WEETH) && (IERC20(WEETH).allowance(address(this), address(ZIRCUIT)) > 0)) {\\n ZIRCUIT.depositFor(WEETH, address(this), memVar_);\\n }\\n // temporary code also includes: WEETH & ZIRCUIT constant, IZtakingPool interface\\n // ---------- temporary code end -----------------------\\n }\\n\\n o_.exchangePricesAndConfig = _exchangePricesAndConfig[token_];\\n\\n // calculate updated exchange prices\\n (o_.supplyExchangePrice, o_.borrowExchangePrice) = LiquidityCalcs.calcExchangePrices(\\n o_.exchangePricesAndConfig\\n );\\n\\n // Extract total supply / borrow amounts for the token\\n o_.totalAmounts = _totalAmounts[token_];\\n memVar_ = o_.totalAmounts & X64;\\n o_.supplyRawInterest = (memVar_ >> DEFAULT_EXPONENT_SIZE) << (memVar_ & DEFAULT_EXPONENT_MASK);\\n memVar_ = (o_.totalAmounts >> LiquiditySlotsLink.BITS_TOTAL_AMOUNTS_SUPPLY_INTEREST_FREE) & X64;\\n o_.supplyInterestFree = (memVar_ >> DEFAULT_EXPONENT_SIZE) << (memVar_ & DEFAULT_EXPONENT_MASK);\\n memVar_ = (o_.totalAmounts >> LiquiditySlotsLink.BITS_TOTAL_AMOUNTS_BORROW_WITH_INTEREST) & X64;\\n o_.borrowRawInterest = (memVar_ >> DEFAULT_EXPONENT_SIZE) << (memVar_ & DEFAULT_EXPONENT_MASK);\\n // no & mask needed for borrow interest free as it occupies the last bits in the storage slot\\n memVar_ = (o_.totalAmounts >> LiquiditySlotsLink.BITS_TOTAL_AMOUNTS_BORROW_INTEREST_FREE);\\n o_.borrowInterestFree = (memVar_ >> DEFAULT_EXPONENT_SIZE) << (memVar_ & DEFAULT_EXPONENT_MASK);\\n\\n if (supplyAmount_ != 0) {\\n // execute supply or withdraw and update total amounts\\n {\\n uint256 totalAmountsBefore_ = o_.totalAmounts;\\n (int256 newSupplyInterestRaw_, int256 newSupplyInterestFree_) = _supplyOrWithdraw(\\n token_,\\n supplyAmount_,\\n o_.supplyExchangePrice\\n );\\n // update total amounts. this is done here so that values are only written to storage once\\n // if a borrow / payback also happens in the same `operate()` call\\n if (newSupplyInterestFree_ == 0) {\\n // Note newSupplyInterestFree_ can ONLY be 0 if mode is with interest,\\n // easy to check as that variable is NOT the result of a dvision etc.\\n // supply or withdraw with interest -> raw amount\\n if (newSupplyInterestRaw_ > 0) {\\n o_.supplyRawInterest += uint256(newSupplyInterestRaw_);\\n } else {\\n unchecked {\\n o_.supplyRawInterest = o_.supplyRawInterest > uint256(-newSupplyInterestRaw_)\\n ? o_.supplyRawInterest - uint256(-newSupplyInterestRaw_)\\n : 0; // withdraw amount is > total supply -> withdraw total supply down to 0\\n // Note no risk here as if the user withdraws more than supplied it would revert already\\n // earlier. Total amounts can end up < sum of user amounts because of rounding\\n }\\n }\\n\\n // Note check for revert {UserModule}__ValueOverflow__TOTAL_SUPPLY is further down when we anyway\\n // calculate the normal amount from raw\\n\\n // Converting the updated total amount into big number for storage\\n memVar_ = o_.supplyRawInterest.toBigNumber(\\n DEFAULT_COEFFICIENT_SIZE,\\n DEFAULT_EXPONENT_SIZE,\\n BigMathMinified.ROUND_DOWN\\n );\\n // update total supply with interest at total amounts in storage (only update changed values)\\n o_.totalAmounts =\\n // mask to update bits 0-63\\n (o_.totalAmounts & 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) |\\n memVar_; // converted to BigNumber can not overflow\\n } else {\\n // supply or withdraw interest free -> normal amount\\n if (newSupplyInterestFree_ > 0) {\\n o_.supplyInterestFree += uint256(newSupplyInterestFree_);\\n } else {\\n unchecked {\\n o_.supplyInterestFree = o_.supplyInterestFree > uint256(-newSupplyInterestFree_)\\n ? o_.supplyInterestFree - uint256(-newSupplyInterestFree_)\\n : 0; // withdraw amount is > total supply -> withdraw total supply down to 0\\n // Note no risk here as if the user withdraws more than supplied it would revert already\\n // earlier. Total amounts can end up < sum of user amounts because of rounding\\n }\\n }\\n if (o_.supplyInterestFree > MAX_TOKEN_AMOUNT_CAP) {\\n // only withdrawals allowed if total supply interest free reaches MAX_TOKEN_AMOUNT_CAP\\n revert FluidLiquidityError(ErrorTypes.UserModule__ValueOverflow__TOTAL_SUPPLY);\\n }\\n // Converting the updated total amount into big number for storage\\n memVar_ = o_.supplyInterestFree.toBigNumber(\\n DEFAULT_COEFFICIENT_SIZE,\\n DEFAULT_EXPONENT_SIZE,\\n BigMathMinified.ROUND_DOWN\\n );\\n // update total supply interest free at total amounts in storage (only update changed values)\\n o_.totalAmounts =\\n // mask to update bits 64-127\\n (o_.totalAmounts & 0xffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff) |\\n (memVar_ << LiquiditySlotsLink.BITS_TOTAL_AMOUNTS_SUPPLY_INTEREST_FREE); // converted to BigNumber can not overflow\\n }\\n if (totalAmountsBefore_ == o_.totalAmounts) {\\n // make sure that operate amount is not so small that it wouldn't affect storage update. if a difference\\n // is present then rounding will be in the right direction to avoid any potential manipulation.\\n revert FluidLiquidityError(ErrorTypes.UserModule__OperateAmountInsufficient);\\n }\\n }\\n }\\n if (borrowAmount_ != 0) {\\n // execute borrow or payback and update total amounts\\n {\\n uint256 totalAmountsBefore_ = o_.totalAmounts;\\n (int256 newBorrowInterestRaw_, int256 newBorrowInterestFree_) = _borrowOrPayback(\\n token_,\\n borrowAmount_,\\n o_.borrowExchangePrice\\n );\\n // update total amounts. this is done here so that values are only written to storage once\\n // if a supply / withdraw also happens in the same `operate()` call\\n if (newBorrowInterestFree_ == 0) {\\n // Note newBorrowInterestFree_ can ONLY be 0 if mode is with interest,\\n // easy to check as that variable is NOT the result of a dvision etc.\\n // borrow or payback with interest -> raw amount\\n if (newBorrowInterestRaw_ > 0) {\\n o_.borrowRawInterest += uint256(newBorrowInterestRaw_);\\n } else {\\n unchecked {\\n o_.borrowRawInterest = o_.borrowRawInterest > uint256(-newBorrowInterestRaw_)\\n ? o_.borrowRawInterest - uint256(-newBorrowInterestRaw_)\\n : 0; // payback amount is > total borrow -> payback total borrow down to 0\\n }\\n }\\n\\n // Note check for revert UserModule__ValueOverflow__TOTAL_BORROW is further down when we anyway\\n // calculate the normal amount from raw\\n\\n // Converting the updated total amount into big number for storage\\n memVar_ = o_.borrowRawInterest.toBigNumber(\\n DEFAULT_COEFFICIENT_SIZE,\\n DEFAULT_EXPONENT_SIZE,\\n BigMathMinified.ROUND_UP\\n );\\n // update total borrow with interest at total amounts in storage (only update changed values)\\n o_.totalAmounts =\\n // mask to update bits 128-191\\n (o_.totalAmounts & 0xffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff) |\\n (memVar_ << LiquiditySlotsLink.BITS_TOTAL_AMOUNTS_BORROW_WITH_INTEREST); // converted to BigNumber can not overflow\\n } else {\\n // borrow or payback interest free -> normal amount\\n if (newBorrowInterestFree_ > 0) {\\n o_.borrowInterestFree += uint256(newBorrowInterestFree_);\\n } else {\\n unchecked {\\n o_.borrowInterestFree = o_.borrowInterestFree > uint256(-newBorrowInterestFree_)\\n ? o_.borrowInterestFree - uint256(-newBorrowInterestFree_)\\n : 0; // payback amount is > total borrow -> payback total borrow down to 0\\n }\\n }\\n if (o_.borrowInterestFree > MAX_TOKEN_AMOUNT_CAP) {\\n // only payback allowed if total borrow interest free reaches MAX_TOKEN_AMOUNT_CAP\\n revert FluidLiquidityError(ErrorTypes.UserModule__ValueOverflow__TOTAL_BORROW);\\n }\\n // Converting the updated total amount into big number for storage\\n memVar_ = o_.borrowInterestFree.toBigNumber(\\n DEFAULT_COEFFICIENT_SIZE,\\n DEFAULT_EXPONENT_SIZE,\\n BigMathMinified.ROUND_UP\\n );\\n // update total borrow interest free at total amounts in storage (only update changed values)\\n o_.totalAmounts =\\n // mask to update bits 192-255\\n (o_.totalAmounts & 0x0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff) |\\n (memVar_ << LiquiditySlotsLink.BITS_TOTAL_AMOUNTS_BORROW_INTEREST_FREE); // converted to BigNumber can not overflow\\n }\\n if (totalAmountsBefore_ == o_.totalAmounts) {\\n // make sure that operate amount is not so small that it wouldn't affect storage update. if a difference\\n // is present then rounding will be in the right direction to avoid any potential manipulation.\\n revert FluidLiquidityError(ErrorTypes.UserModule__OperateAmountInsufficient);\\n }\\n }\\n }\\n // Updating total amounts on storage\\n _totalAmounts[token_] = o_.totalAmounts;\\n {\\n // update exchange prices / utilization / ratios\\n // exchangePricesAndConfig is only written to storage if either utilization, supplyRatio or borrowRatio\\n // change is above the required storageUpdateThreshold config value or if the last write was > 1 day ago.\\n\\n // 1. calculate new supply ratio, borrow ratio & utilization.\\n // 2. check if last storage write was > 1 day ago.\\n // 3. If false -> check if utilization is above update threshold\\n // 4. If false -> check if supply ratio is above update threshold\\n // 5. If false -> check if borrow ratio is above update threshold\\n // 6. If any true, then update on storage\\n\\n // ########## calculating supply ratio ##########\\n // supplyWithInterest in normal amount\\n memVar3_ = ((o_.supplyRawInterest * o_.supplyExchangePrice) / EXCHANGE_PRICES_PRECISION);\\n if (memVar3_ > MAX_TOKEN_AMOUNT_CAP && supplyAmount_ > 0) {\\n // only withdrawals allowed if total supply raw reaches MAX_TOKEN_AMOUNT_CAP\\n revert FluidLiquidityError(ErrorTypes.UserModule__ValueOverflow__TOTAL_SUPPLY);\\n }\\n // memVar_ => total supply. set here so supplyWithInterest (memVar3_) is only calculated once. For utilization\\n memVar_ = o_.supplyInterestFree + memVar3_;\\n if (memVar3_ > o_.supplyInterestFree) {\\n // memVar3_ is ratio with 1 bit as 0 as supply interest raw is bigger\\n memVar3_ = ((o_.supplyInterestFree * FOUR_DECIMALS) / memVar3_) << 1;\\n // because of checking to divide by bigger amount, ratio can never be > 100%\\n } else if (memVar3_ < o_.supplyInterestFree) {\\n // memVar3_ is ratio with 1 bit as 1 as supply interest free is bigger\\n memVar3_ = (((memVar3_ * FOUR_DECIMALS) / o_.supplyInterestFree) << 1) | 1;\\n // because of checking to divide by bigger amount, ratio can never be > 100%\\n } else if (memVar_ > 0) {\\n // supplies match exactly (memVar3_ == o_.supplyInterestFree) and total supplies are not 0\\n // -> set ratio to 1 (with first bit set to 0, doesn't matter)\\n memVar3_ = FOUR_DECIMALS << 1;\\n } // else if total supply = 0, memVar3_ (supplyRatio) is already 0.\\n\\n // ########## calculating borrow ratio ##########\\n // borrowWithInterest in normal amount\\n memVar4_ = ((o_.borrowRawInterest * o_.borrowExchangePrice) / EXCHANGE_PRICES_PRECISION);\\n if (memVar4_ > MAX_TOKEN_AMOUNT_CAP && borrowAmount_ > 0) {\\n // only payback allowed if total borrow raw reaches MAX_TOKEN_AMOUNT_CAP\\n revert FluidLiquidityError(ErrorTypes.UserModule__ValueOverflow__TOTAL_BORROW);\\n }\\n // memVar2_ => total borrow. set here so borrowWithInterest (memVar4_) is only calculated once. For utilization\\n memVar2_ = o_.borrowInterestFree + memVar4_;\\n if (memVar4_ > o_.borrowInterestFree) {\\n // memVar4_ is ratio with 1 bit as 0 as borrow interest raw is bigger\\n memVar4_ = ((o_.borrowInterestFree * FOUR_DECIMALS) / memVar4_) << 1;\\n // because of checking to divide by bigger amount, ratio can never be > 100%\\n } else if (memVar4_ < o_.borrowInterestFree) {\\n // memVar4_ is ratio with 1 bit as 1 as borrow interest free is bigger\\n memVar4_ = (((memVar4_ * FOUR_DECIMALS) / o_.borrowInterestFree) << 1) | 1;\\n // because of checking to divide by bigger amount, ratio can never be > 100%\\n } else if (memVar2_ > 0) {\\n // borrows match exactly (memVar4_ == o_.borrowInterestFree) and total borrows are not 0\\n // -> set ratio to 1 (with first bit set to 0, doesn't matter)\\n memVar4_ = FOUR_DECIMALS << 1;\\n } // else if total borrow = 0, memVar4_ (borrowRatio) is already 0.\\n\\n // calculate utilization. If there is no supply, utilization must be 0 (avoid division by 0)\\n uint256 utilization_;\\n if (memVar_ > 0) {\\n utilization_ = ((memVar2_ * FOUR_DECIMALS) / memVar_);\\n if (utilization_ > FOUR_DECIMALS && borrowAmount_ > 0) {\\n // revert on new borrows when utilization is above 100%\\n revert FluidLiquidityError(ErrorTypes.UserModule__MaxUtilizationReached);\\n }\\n }\\n\\n // check if time difference is big enough (> 1 day)\\n unchecked {\\n if (\\n block.timestamp >\\n // extract last update timestamp + 1 day\\n (((o_.exchangePricesAndConfig >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_LAST_TIMESTAMP) & X33) +\\n FORCE_STORAGE_WRITE_AFTER_TIME)\\n ) {\\n memVar_ = 1; // set write to storage flag\\n } else {\\n memVar_ = 0;\\n }\\n }\\n\\n if (memVar_ == 0) {\\n // time difference is not big enough to cause storage write -> check utilization\\n\\n // memVar_ => extract last utilization\\n memVar_ = (o_.exchangePricesAndConfig >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_UTILIZATION) & X14;\\n // memVar2_ => storage update threshold in percent\\n memVar2_ =\\n (o_.exchangePricesAndConfig >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_UPDATE_THRESHOLD) &\\n X14;\\n unchecked {\\n // set memVar_ to 1 if current utilization to previous utilization difference is > update storage threshold\\n memVar_ = (utilization_ > memVar_ ? utilization_ - memVar_ : memVar_ - utilization_) > memVar2_\\n ? 1\\n : 0;\\n if (memVar_ == 0) {\\n // utilization & time difference is not big enough -> check supplyRatio difference\\n // memVar_ => extract last supplyRatio\\n memVar_ =\\n (o_.exchangePricesAndConfig >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_SUPPLY_RATIO) &\\n X15;\\n // set memVar_ to 1 if current supplyRatio to previous supplyRatio difference is > update storage threshold\\n if ((memVar_ & 1) == (memVar3_ & 1)) {\\n memVar_ = memVar_ >> 1;\\n memVar_ = (\\n (memVar3_ >> 1) > memVar_ ? (memVar3_ >> 1) - memVar_ : memVar_ - (memVar3_ >> 1)\\n ) > memVar2_\\n ? 1\\n : 0; // memVar3_ = supplyRatio, memVar_ = previous supplyRatio, memVar2_ = update storage threshold\\n } else {\\n // if inverse bit is changing then always update on storage\\n memVar_ = 1;\\n }\\n if (memVar_ == 0) {\\n // utilization, time, and supplyRatio difference is not big enough -> check borrowRatio difference\\n // memVar_ => extract last borrowRatio\\n memVar_ =\\n (o_.exchangePricesAndConfig >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_BORROW_RATIO) &\\n X15;\\n // set memVar_ to 1 if current borrowRatio to previous borrowRatio difference is > update storage threshold\\n if ((memVar_ & 1) == (memVar4_ & 1)) {\\n memVar_ = memVar_ >> 1;\\n memVar_ = (\\n (memVar4_ >> 1) > memVar_ ? (memVar4_ >> 1) - memVar_ : memVar_ - (memVar4_ >> 1)\\n ) > memVar2_\\n ? 1\\n : 0; // memVar4_ = borrowRatio, memVar_ = previous borrowRatio, memVar2_ = update storage threshold\\n } else {\\n // if inverse bit is changing then always update on storage\\n memVar_ = 1;\\n }\\n }\\n }\\n }\\n }\\n\\n // memVar_ is 1 if either time diff was enough or if\\n // utilization, supplyRatio or borrowRatio difference was > update storage threshold\\n if (memVar_ == 1) {\\n // memVar_ => calculate new borrow rate for utilization. includes value overflow check.\\n memVar_ = LiquidityCalcs.calcBorrowRateFromUtilization(_rateData[token_], utilization_);\\n // ensure values written to storage do not exceed the dedicated bit space in packed uint256 slots\\n if (o_.supplyExchangePrice > X64 || o_.borrowExchangePrice > X64) {\\n revert FluidLiquidityError(ErrorTypes.UserModule__ValueOverflow__EXCHANGE_PRICES);\\n }\\n if (utilization_ > X14) {\\n revert FluidLiquidityError(ErrorTypes.UserModule__ValueOverflow__UTILIZATION);\\n }\\n o_.exchangePricesAndConfig =\\n (o_.exchangePricesAndConfig &\\n // mask to update bits: 0-15 (borrow rate), 30-43 (utilization), 58-248 (timestamp, exchange prices, ratios)\\n 0xfe000000000000000000000000000000000000000000000003fff0003fff0000) |\\n memVar_ | // calcBorrowRateFromUtilization already includes an overflow check\\n (utilization_ << LiquiditySlotsLink.BITS_EXCHANGE_PRICES_UTILIZATION) |\\n (block.timestamp << LiquiditySlotsLink.BITS_EXCHANGE_PRICES_LAST_TIMESTAMP) |\\n (o_.supplyExchangePrice << LiquiditySlotsLink.BITS_EXCHANGE_PRICES_SUPPLY_EXCHANGE_PRICE) |\\n (o_.borrowExchangePrice << LiquiditySlotsLink.BITS_EXCHANGE_PRICES_BORROW_EXCHANGE_PRICE) |\\n // ratios can never be > 100%, no overflow check needed\\n (memVar3_ << LiquiditySlotsLink.BITS_EXCHANGE_PRICES_SUPPLY_RATIO) | // supplyRatio (memVar3_ holds that value)\\n (memVar4_ << LiquiditySlotsLink.BITS_EXCHANGE_PRICES_BORROW_RATIO); // borrowRatio (memVar4_ holds that value)\\n // Updating on storage\\n _exchangePricesAndConfig[token_] = o_.exchangePricesAndConfig;\\n } else {\\n // do not update in storage but update o_.exchangePricesAndConfig for updated exchange prices at\\n // event emit of LogOperate\\n o_.exchangePricesAndConfig =\\n (o_.exchangePricesAndConfig &\\n // mask to update bits: 91-218 (exchange prices)\\n 0xfffffffffc00000000000000000000000000000007ffffffffffffffffffffff) |\\n (o_.supplyExchangePrice << LiquiditySlotsLink.BITS_EXCHANGE_PRICES_SUPPLY_EXCHANGE_PRICE) |\\n (o_.borrowExchangePrice << LiquiditySlotsLink.BITS_EXCHANGE_PRICES_BORROW_EXCHANGE_PRICE);\\n }\\n }\\n // sending tokens to user at the end after updating everything\\n // only transfer to user in case of withdraw or borrow.\\n // do not transfer for same amounts in same operate(): supply(+) == borrow(+), withdraw(-) == payback(-). (DEX protocol use-case)\\n if ((supplyAmount_ < 0 || borrowAmount_ > 0) && !o_.skipTransfers) {\\n // sending tokens to user at the end after updating everything\\n // set memVar2_ to borrowAmount (if borrow) or reset memVar2_ var to 0 because\\n // it is used with > 0 check below to transfer withdraw / borrow / both\\n memVar2_ = borrowAmount_ > 0 ? uint256(borrowAmount_) : 0;\\n if (supplyAmount_ < 0) {\\n unchecked {\\n memVar_ = uint256(-supplyAmount_);\\n }\\n } else {\\n memVar_ = 0;\\n }\\n if (memVar_ > 0 && memVar2_ > 0 && withdrawTo_ == borrowTo_) {\\n // if user is doing borrow & withdraw together and address for both is the same\\n // then transfer tokens of borrow & withdraw together to save on gas\\n if (token_ == NATIVE_TOKEN_ADDRESS) {\\n Address.sendValue(payable(withdrawTo_), memVar_ + memVar2_);\\n } else {\\n IERC20(token_).safeTransfer(withdrawTo_, memVar_ + memVar2_);\\n }\\n } else {\\n if (token_ == NATIVE_TOKEN_ADDRESS) {\\n // if withdraw\\n if (memVar_ > 0) {\\n Address.sendValue(payable(withdrawTo_), memVar_);\\n }\\n // if borrow\\n if (memVar2_ > 0) {\\n Address.sendValue(payable(borrowTo_), memVar2_);\\n }\\n } else {\\n // if withdraw\\n if (memVar_ > 0) {\\n // ---------- temporary code start -----------------------\\n // temporary addition for weETH: if token is weETH -> withdraw from Zircuit first\\n if ((token_ == WEETH) && (IERC20(WEETH).balanceOf(address(this)) < memVar_)) {\\n ZIRCUIT.withdraw(WEETH, memVar_);\\n }\\n // temporary code also includes: WEETH & ZIRCUIT constant, IZtakingPool interface\\n // ---------- temporary code end -----------------------\\n\\n IERC20(token_).safeTransfer(withdrawTo_, memVar_);\\n }\\n // if borrow\\n if (memVar2_ > 0) {\\n IERC20(token_).safeTransfer(borrowTo_, memVar2_);\\n }\\n }\\n }\\n }\\n // emit Operate event\\n emit LogOperate(\\n msg.sender,\\n token_,\\n supplyAmount_,\\n borrowAmount_,\\n withdrawTo_,\\n borrowTo_,\\n o_.totalAmounts,\\n o_.exchangePricesAndConfig\\n );\\n // set return values\\n memVar3_ = o_.supplyExchangePrice;\\n memVar4_ = o_.borrowExchangePrice;\\n }\\n}\\n\",\"keccak256\":\"0x927e6bd84783939720fe59ce51251db34f62a39b23a57a5f9b6821ee00120331\",\"license\":\"BUSL-1.1\"},\"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 // Revert immediately if x ** 2 would overflow.\\n // Equivalent to iszero(eq(div(xx, x), x)) here.\\n if shr(128, x) {\\n revert(0, 0)\\n }\\n\\n // Store x squared.\\n let xx := mul(x, x)\\n\\n // Round to the nearest number.\\n let xxRound := add(xx, half)\\n\\n // Revert if xx + half overflowed.\\n if lt(xxRound, xx) {\\n revert(0, 0)\\n }\\n\\n // Set x to scaled xxRound.\\n x := div(xxRound, scalar)\\n\\n // If n is even:\\n if mod(n, 2) {\\n // Compute z * x.\\n let zx := mul(z, x)\\n\\n // If z * x overflowed:\\n if iszero(eq(div(zx, x), z)) {\\n // Revert if x is non-zero.\\n if iszero(iszero(x)) {\\n revert(0, 0)\\n }\\n }\\n\\n // Round to the nearest number.\\n let zxRound := add(zx, half)\\n\\n // Revert if zx + half overflowed.\\n if lt(zxRound, zx) {\\n revert(0, 0)\\n }\\n\\n // Return properly scaled zxRound.\\n z := div(zxRound, scalar)\\n }\\n }\\n }\\n }\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n GENERAL NUMBER UTILITIES\\n //////////////////////////////////////////////////////////////*/\\n\\n function sqrt(uint256 x) internal pure returns (uint256 z) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n let y := x // We start y at x, which will help us make our initial estimate.\\n\\n z := 181 // The \\\"correct\\\" value is 1, but this saves a multiplication later.\\n\\n // This segment is to get a reasonable initial estimate for the Babylonian method. With a bad\\n // start, the correct # of bits increases ~linearly each iteration instead of ~quadratically.\\n\\n // We check y >= 2^(k + 8) but shift right by k bits\\n // each branch to ensure that if x >= 256, then y >= 256.\\n if iszero(lt(y, 0x10000000000000000000000000000000000)) {\\n y := shr(128, y)\\n z := shl(64, z)\\n }\\n if iszero(lt(y, 0x1000000000000000000)) {\\n y := shr(64, y)\\n z := shl(32, z)\\n }\\n if iszero(lt(y, 0x10000000000)) {\\n y := shr(32, y)\\n z := shl(16, z)\\n }\\n if iszero(lt(y, 0x1000000)) {\\n y := shr(16, y)\\n z := shl(8, z)\\n }\\n\\n // Goal was to get z*z*y within a small factor of x. More iterations could\\n // get y in a tighter range. Currently, we will have y in [256, 256*2^16).\\n // We ensured y >= 256 so that the relative difference between y and y+1 is small.\\n // That's not possible if x < 256 but we can just verify those cases exhaustively.\\n\\n // Now, z*z*y <= x < z*z*(y+1), and y <= 2^(16+8), and either y >= 256, or x < 256.\\n // Correctness can be checked exhaustively for x < 256, so we assume y >= 256.\\n // Then z*sqrt(y) is within sqrt(257)/sqrt(256) of sqrt(x), or about 20bps.\\n\\n // For s in the range [1/256, 256], the estimate f(s) = (181/1024) * (s+1) is in the range\\n // (1/2.84 * sqrt(s), 2.84 * sqrt(s)), with largest error when s = 1 and when s = 256 or 1/256.\\n\\n // Since y is in [256, 256*2^16), let a = y/65536, so that a is in [1/256, 256). Then we can estimate\\n // sqrt(y) using sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2^18.\\n\\n // There is no overflow risk here since y < 2^136 after the first branch above.\\n z := shr(18, mul(z, add(y, 65536))) // A mul() is saved from starting z at 181.\\n\\n // Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough.\\n z := shr(1, add(z, div(x, z)))\\n z := shr(1, add(z, div(x, z)))\\n z := shr(1, add(z, div(x, z)))\\n z := shr(1, add(z, div(x, z)))\\n z := shr(1, add(z, div(x, z)))\\n z := shr(1, add(z, div(x, z)))\\n z := shr(1, add(z, div(x, z)))\\n\\n // If x+1 is a perfect square, the Babylonian method cycles between\\n // floor(sqrt(x)) and ceil(sqrt(x)). This statement ensures we return floor.\\n // See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division\\n // Since the ceil is rare, we save gas on the assignment and repeat division in the rare case.\\n // If you don't care whether the floor or ceil square root is returned, you can remove this statement.\\n z := sub(z, lt(div(x, z), z))\\n }\\n }\\n\\n function unsafeMod(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Mod x by y. Note this will return\\n // 0 instead of reverting if y is zero.\\n z := mod(x, y)\\n }\\n }\\n\\n function unsafeDiv(uint256 x, uint256 y) internal pure returns (uint256 r) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Divide x by y. Note this will return\\n // 0 instead of reverting if y is zero.\\n r := div(x, y)\\n }\\n }\\n\\n function unsafeDivUp(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Add 1 to x * y if x % y > 0. Note this will\\n // return 0 instead of reverting if y is zero.\\n z := add(gt(mod(x, y), 0), div(x, y))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x1b62af9baf5b8e991ed7531bc87f45550ba9d61e8dbff5caf237ccaf3a3fd843\",\"license\":\"AGPL-3.0-only\"}},\"version\":1}",
"bytecode": "0x608060405234801561001057600080fd5b506002600155612bf2806100256000396000f3fe60806040526004361061001e5760003560e01c8063ad967e1514610023575b600080fd5b61003661003136600461282c565b61004f565b6040805192835260208301919091520160405180910390f35b600080600260ff166001540361009a576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612ee160048201526024015b60405180910390fd5b6002600155871580156100ab575086155b156100e6576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612afd6004820152602401610091565b7fffffffffffffffffffffffffffffffff8000000000000000000000000000000088128061012357506f7fffffffffffffffffffffffffffffff88135b8061014d57507fffffffffffffffffffffffffffffffff8000000000000000000000000000000087125b8061016757506f7fffffffffffffffffffffffffffffff87135b156101a2576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612afe6004820152602401610091565b6000881280156101c6575073ffffffffffffffffffffffffffffffffffffffff8616155b806101f057506000871380156101f0575073ffffffffffffffffffffffffffffffffffffffff8516155b1561022b576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612b006004820152602401610091565b73ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee148015906102655750600034115b156102a0576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612b026004820152602401610091565b6102f160405180610120016040528060001515815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b60008060008a1261030357600061030c565b61030c8a612913565b60008c1361031b57600061031d565b8b5b610327919061294b565b9050898b148015610336575034155b801561037f575061037f8b8a8a8a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115ac92505050565b1561038c57506001825260005b7fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8d160161041b57348111806103dc5750633b9aca00810134115b15610417576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612b016004820152602401610091565b5060005b8015610790576040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8d16906370a0823190602401602060405180830381865afa15801561048b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104af919061295e565b6040517fad207501000000000000000000000000000000000000000000000000000000008152909250339063ad207501906104f4908f9085908c908c90600401612977565b600060405180830381600087803b15801561050e57600080fd5b505af1158015610522573d6000803e3d6000fd5b50506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015284925073ffffffffffffffffffffffffffffffffffffffff8f1691506370a0823190602401602060405180830381865afa158015610592573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105b6919061295e565b6105c091906129e8565b9150808210806105d2575080600a0182115b1561060d576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612b016004820152602401610091565b73ffffffffffffffffffffffffffffffffffffffff8c1673cd5fe23c85820f7b72d0926fc9b05b43e359b7ee1480156106ec57506040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273f047ab4c75cebf0eb9ed34ae2c186f3611aeafa6602482015260009073cd5fe23c85820f7b72d0926fc9b05b43e359b7ee9063dd62ed3e90604401602060405180830381865afa1580156106c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106ea919061295e565b115b15610790576040517fb3db428b00000000000000000000000000000000000000000000000000000000815273cd5fe23c85820f7b72d0926fc9b05b43e359b7ee60048201523060248201526044810183905273f047ab4c75cebf0eb9ed34ae2c186f3611aeafa69063b3db428b90606401600060405180830381600087803b15801561077757600080fd5b505af115801561078b573d6000803e3d6000fd5b505050505b73ffffffffffffffffffffffffffffffffffffffff8c1660009081526005602052604090205461010084018190526107c79061168f565b60408086019190915260208086019290925273ffffffffffffffffffffffffffffffffffffffff8e1660009081526007909252908190205460e0850181905266ffffffffffffff600882901c811660ff8084169190911b6060880152604883901c82169383901c81169390931b608080880191909152608883901c9091169082901c83161b60a086015260c881901c60c091821c9283161b9085015291508a15610a435760008360e0015190506000806108868f8f886020015161189d565b915091508060000361091f5760008213156108b55781866060018181516108ad919061294b565b9052506108d8565b816000038660600151116108ca5760006108d2565b606086015182015b60608701525b60608601516108ec90603860086000611b56565b60e0870180517fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000168217905294506109fe565b600081131561094257808660800181815161093a919061294b565b905250610965565b8060000386608001511161095757600061095f565b608086015181015b60808701525b60808601516f7fffffffffffffffffffffffffffffff10156109b7576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612b066004820152602401610091565b60808601516109cb90603860086000611b56565b60e0870180517fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff16604083901b17905294505b8560e001518303610a3f576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612aff6004820152602401610091565b5050505b8915610c1d5760008360e001519050600080610a648f8e8860400151611c7f565b9150915080600003610b01576000821315610a9357818660a001818151610a8b919061294b565b905250610ab6565b816000038660a0015111610aa8576000610ab0565b60a086015182015b60a08701525b60a0860151610aca90603860086001611b56565b60e0870180517fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff16608083901b1790529450610bd8565b6000811315610b2457808660c001818151610b1c919061294b565b905250610b47565b806000038660c0015111610b39576000610b41565b60c086015181015b60c08701525b60c08601516f7fffffffffffffffffffffffffffffff1015610b99576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612b076004820152602401610091565b60c0860151610bad90603860086001611b56565b60e08701805177ffffffffffffffffffffffffffffffffffffffffffffffff1660c083901b17905294505b8560e001518303610c19576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612aff6004820152602401610091565b5050505b60e083015173ffffffffffffffffffffffffffffffffffffffff8d16600090815260076020908152604090912091909155830151606084015164e8d4a5100091610c66916129fb565b610c709190612a41565b94506f7fffffffffffffffffffffffffffffff85118015610c91575060008b135b15610ccc576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612b066004820152602401610091565b848360800151610cdc919061294b565b91508260800151851115610d12576001856127108560800151610cff91906129fb565b610d099190612a41565b901b9450610d54565b8260800151851015610d48576080830151600190610d32612710886129fb565b610d3c9190612a41565b901b6001179450610d54565b8115610d5457614e2094505b64e8d4a5100083604001518460a00151610d6e91906129fb565b610d789190612a41565b93506f7fffffffffffffffffffffffffffffff84118015610d99575060008a135b15610dd4576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612b076004820152602401610091565b838360c00151610de4919061294b565b90508260c00151841115610e1a576001846127108560c00151610e0791906129fb565b610e119190612a41565b901b9350610e5c565b8260c00151841015610e505760c0830151600190610e3a612710876129fb565b610e449190612a41565b901b6001179350610e5c565b8015610e5c57614e2093505b60008215610ec95782610e71612710846129fb565b610e7b9190612a41565b905061271081118015610e8e575060008b135b15610ec9576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612b036004820152602401610091565b610100840151603a1c6401ffffffff166201518001421115610eee5760019250610ef3565b600092505b8260000361101757613fff601e856101000151901c169250613fff602c856101000151901c16915081838211610f2b57818403610f2f565b8382035b11610f3b576000610f3e565b60015b60ff1692508260000361101757617fff60db856101000151901c169250856001168360011603610fa857600183901c92508183600188901c11610f8757600187901c8403610f8f565b83600188901c035b11610f9b576000610f9e565b60015b60ff169250610fad565b600192505b8260000361101757617fff60ea856101000151901c16925084600116836001160361101257600183901c92508183600187901c11610ff157600186901c8403610ff9565b83600187901c035b11611005576000611008565b60015b60ff169250611017565b600192505b8260010361119f5773ffffffffffffffffffffffffffffffffffffffff8d1660009081526006602052604090205461104f9082611f27565b925067ffffffffffffffff84602001511180611076575067ffffffffffffffff8460400151115b156110b1576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612b046004820152602401610091565b613fff8111156110f1576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612b056004820152602401610091565b60ea85901b60db87901b609b8660400151901b605b8760200151901b603a42901b601e86901b888a61010001517ffe000000000000000000000000000000000000000000000003fff0003fff0000161717171717171784610100018181525050836101000151600560008f73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506111e6565b609b8460400151901b605b8560200151901b8561010001517ffffffffffc00000000000000000000000000000007ffffffffffffffffffffff161717846101000181815250505b5060008b12806111f6575060008a135b801561120157508251155b1561150c5760008a13611215576000611217565b895b905060008b121561122d578a6000039150611232565b600091505b6000821180156112425750600081115b801561127957508773ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff16145b156112ff577fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8d16016112d3576112ce896112c9838561294b565b611fd0565b61150c565b6112ce896112e1838561294b565b73ffffffffffffffffffffffffffffffffffffffff8f16919061212f565b7fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8d160161135c57811561134c5761134c8983611fd0565b80156112ce576112ce8882611fd0565b81156114e55773ffffffffffffffffffffffffffffffffffffffff8c1673cd5fe23c85820f7b72d0926fc9b05b43e359b7ee14801561142657506040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152829073cd5fe23c85820f7b72d0926fc9b05b43e359b7ee906370a0823190602401602060405180830381865afa158015611400573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611424919061295e565b105b156114c4576040517ff3fef3a300000000000000000000000000000000000000000000000000000000815273cd5fe23c85820f7b72d0926fc9b05b43e359b7ee60048201526024810183905273f047ab4c75cebf0eb9ed34ae2c186f3611aeafa69063f3fef3a390604401600060405180830381600087803b1580156114ab57600080fd5b505af11580156114bf573d6000803e3d6000fd5b505050505b6114e573ffffffffffffffffffffffffffffffffffffffff8d168a8461212f565b801561150c5761150c73ffffffffffffffffffffffffffffffffffffffff8d16898361212f565b60e0830151610100840151604080518e8152602081018e905273ffffffffffffffffffffffffffffffffffffffff8d8116828401528c81166060830152608082019490945260a081019290925251918e169133917f4d93b232a24e82b284ced7461bf4deacffe66759d5c24513e6f29e571ad78d15919081900360c00190a35050602081015160409091015160018055909a909950975050505050505050565b60006014825110156115c057506000611687565b815182015160008613801561160057508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b8015611621575073ffffffffffffffffffffffffffffffffffffffff811633145b80611683575060008612801561166257508473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b8015611683575073ffffffffffffffffffffffffffffffffffffffff811633145b9150505b949350505050565b67ffffffffffffffff605b82901c811690609b83901c168115806116b1575080155b156116ed576040517fd50d7512000000000000000000000000000000000000000000000000000000008152620111716004820152602401610091565b61ffff8316603a84901c6401ffffffff16428181039160ea87901c617fff16911480611717575082155b806117225750806001145b1561172f57505050915091565b64496cebb80084840283020484019350617fff60db87901c1692508260010361175a57505050915091565b826001166001036117af5760019290921c91826c7e37be2022c0914b26800000008161178857611788612a12565b049250612710601e87901c613fff166b033b2e3c9fd0803ce80000008501020492506117dc565b60019290921c916305f5e100601e87901c613fff166127108501026b033b2e3c9fd0803ce8000000020492505b806001166001036118135760011c61271081016b033b2e3c9fd0803ce800000082028161180b5761180b612a12565b049050611849565b60011c61271081016b033b2e3c9fd0803ce800000082028161183757611837612a12565b046b033b2e3c9fd0803ce80000000390505b760a70c3c40a64e6c51999090b65f67d92400000000000008382026127100261ffff881691900402601087901c613fff16612710030292506801b5a660ea44b8000085840283020485019450505050915091565b33600090815260086020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152812054819080820361190d576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612af96004820152602401610091565b60ff81901c60010361194f576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612afa6004820152602401610091565b66ffffffffffffff600982901c1660ff600183901c161b600061197283836121bc565b9050826001166001036119eb5760008713156119b5578561199864e8d4a5100089612a55565b6119a29190612aa1565b94506119ae858361294b565b9150611a17565b6119cd6119c188612913565b64e8d4a5100088612251565b6119d690612913565b94506119e185612913565b6119ae90836129e8565b8693506000841315611a01576119ae848361294b565b611a0a84612913565b611a1490836129e8565b91505b600087128015611a2657508082105b15611a61576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612afb6004820152602401610091565b611a6c838383612295565b9050611a7d82603860086000611b56565b91508167ffffffffffffffff600185901c1603611aca576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612aff6004820152602401610091565b611ad981603860086000611b56565b33600090815260086020908152604080832073ffffffffffffffffffffffffffffffffffffffff9c909c1683529a9052989098207ffffffffffffffffffffffffc000000000000000000000000000000000000000190931660019290921b9190911760419790971b969096174260811b1790559094909350915050565b600080856fffffffffffffffffffffffffffffffff811115611b795760809150811c5b67ffffffffffffffff811115611b91576040918201911c5b63ffffffff811115611ba5576020918201911c5b61ffff811115611bb7576010918201911c5b60ff811115611bc8576008918201911c5b600f811115611bd9576004918201911c5b6003811115611bea576002918201911c5b6001811115611bfa576001820191505b8015611c07576001820191505b5084811015611c135750835b848103905085811c60008211841615611c6257600181019050806001871b03611c6257506001908101907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff86011b5b6001851b8210611c7157600080fd5b90931b909201949350505050565b33600090815260096020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120548190808203611cef576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612af96004820152602401610091565b60ff81901c600103611d31576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612afa6004820152602401610091565b66ffffffffffffff600982901c1660ff600183901c161b6000611d5483836122e8565b905082600116600103611dbc576000871315611d8d57611d7a8764e8d4a5100088612251565b9450611d86858361294b565b9150611de8565b85611d9d64e8d4a5100089612a55565b611da79190612aa1565b9450611db285612913565b611d8690836129e8565b8693506000841315611dd257611d86848361294b565b611ddb84612913565b611de590836129e8565b91505b600087138015611df757508082115b15611e32576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612afc6004820152602401610091565b611e3d8383836123a0565b9050611e4e82603860086001611b56565b91508167ffffffffffffffff600185901c1603611e9b576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612aff6004820152602401610091565b611eaa81603860086000611b56565b33600090815260096020908152604080832073ffffffffffffffffffffffffffffffffffffffff9c909c1683529a9052989098207ffffffffffffffffffffffffc000000000000000000000000000000000000000190931660019290921b9190911760419790971b969096174260811b1790559094909350915050565b6000600f83166001819003611f4757611f4084846123ff565b9150611f90565b80600203611f5957611f4084846124de565b6040517fd50d7512000000000000000000000000000000000000000000000000000000008152620111726004820152602401610091565b61ffff821115611fc95760405161ffff92507fe41708b2641eb1f7442f6a1e760ae5098fd7ba9f85e0c101513add0fbb27bcd790600090a15b5092915050565b8047101561203a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606401610091565b60008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114612094576040519150601f19603f3d011682016040523d82523d6000602084013e612099565b606091505b505090508061212a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401610091565b505050565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905261212a908490612586565b600066ffffffffffffff604984901c1660ff604185901c161b8082036121e657600091505061224b565b612710613fff60a286901c168402046401ffffffff608186901c16420362ffffff60b087901c1661221782846129fb565b6122219190612a41565b9050808311612231576000612235565b8083035b93505080840383811115612247578093505b5050505b92915050565b6000827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048411830215820261228657600080fd5b50910281810615159190040190565b60006103ff60d085901c1660ff60c886901c161b808410156122bb5760009150506122e1565b50612710613fff60a286901c168402048303828111156122dc5790506122e1565b829150505b9392505050565b60d082901c6103ff1660c883901c60ff161b613fff60a284901c16612710838202048084018381101561231d5750505061224b565b608186901c6401ffffffff164203925066ffffffffffffff604987901c1660ff604188901c161b60b087901c62ffffff1661235885856129fb565b6123629190612a41565b61236c919061294b565b93508084111561237a578093505b6103ff60e287901c1660ff60da88901c161b925082841115612247575090949350505050565b612710613fff60a285901c16830204820160d084901c6103ff1660c885901c60ff161b808210156123d25790506122e1565b506103ff60e285901c1660ff60da86901c161b808211156123f1578091505b818311156122dc57506122e1565b600080808080601487901c61ffff16808710156124385761ffff600489901c16945061ffff602489901c16935060009250809150612457565b61ffff602489901c16945061ffff603489901c16935080925061271091505b60008084840364e8d4a51000888803028161247457612474612a12565b0585810264e8d4a51000890203925089028201905060008112156124c9576040517fd50d7512000000000000000000000000000000000000000000000000000000008152620111736004820152602401610091565b64e8d4a5100090049998505050505050505050565b600080808080601487901c61ffff16808710156125175761ffff600489901c16945061ffff602489901c16935060009250809150612457565b603488901c61ffff16808810156125495761ffff60248a901c16955061ffff60448a901c169450819350809250612568565b61ffff60448a901c16955061ffff60548a901c16945080935061271092505b5060008084840364e8d4a51000888803028161247457612474612a12565b60006125e8826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166126929092919063ffffffff16565b80519091501561212a57808060200190518101906126069190612b09565b61212a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610091565b60606116878484600085856000808673ffffffffffffffffffffffffffffffffffffffff1685876040516126c69190612b4f565b60006040518083038185875af1925050503d8060008114612703576040519150601f19603f3d011682016040523d82523d6000602084013e612708565b606091505b509150915061271987838387612724565b979650505050505050565b606083156127ba5782516000036127b35773ffffffffffffffffffffffffffffffffffffffff85163b6127b3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610091565b5081611687565b61168783838151156127cf5781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100919190612b6b565b803573ffffffffffffffffffffffffffffffffffffffff8116811461282757600080fd5b919050565b600080600080600080600060c0888a03121561284757600080fd5b61285088612803565b9650602088013595506040880135945061286c60608901612803565b935061287a60808901612803565b925060a088013567ffffffffffffffff8082111561289757600080fd5b818a0191508a601f8301126128ab57600080fd5b8135818111156128ba57600080fd5b8b60208285010111156128cc57600080fd5b60208301945080935050505092959891949750929550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007f80000000000000000000000000000000000000000000000000000000000000008203612944576129446128e4565b5060000390565b8082018082111561224b5761224b6128e4565b60006020828403121561297057600080fd5b5051919050565b73ffffffffffffffffffffffffffffffffffffffff8516815283602082015260606040820152816060820152818360808301376000818301608090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01601019392505050565b8181038181111561224b5761224b6128e4565b808202811582820484141761224b5761224b6128e4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082612a5057612a50612a12565b500490565b808202600082127f800000000000000000000000000000000000000000000000000000000000000084141615612a8d57612a8d6128e4565b818105831482151761224b5761224b6128e4565b600082612ab057612ab0612a12565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f800000000000000000000000000000000000000000000000000000000000000083141615612b0457612b046128e4565b500590565b600060208284031215612b1b57600080fd5b815180151581146122e157600080fd5b60005b83811015612b46578181015183820152602001612b2e565b50506000910152565b60008251612b61818460208701612b2b565b9190910192915050565b6020815260008251806020840152612b8a816040850160208701612b2b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fea264697066735822122040fdd528007774f9aa724861fa936b0f3add5371aa6d07ea527379a35807e51364736f6c63430008150033",
"deployedBytecode": "0x60806040526004361061001e5760003560e01c8063ad967e1514610023575b600080fd5b61003661003136600461282c565b61004f565b6040805192835260208301919091520160405180910390f35b600080600260ff166001540361009a576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612ee160048201526024015b60405180910390fd5b6002600155871580156100ab575086155b156100e6576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612afd6004820152602401610091565b7fffffffffffffffffffffffffffffffff8000000000000000000000000000000088128061012357506f7fffffffffffffffffffffffffffffff88135b8061014d57507fffffffffffffffffffffffffffffffff8000000000000000000000000000000087125b8061016757506f7fffffffffffffffffffffffffffffff87135b156101a2576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612afe6004820152602401610091565b6000881280156101c6575073ffffffffffffffffffffffffffffffffffffffff8616155b806101f057506000871380156101f0575073ffffffffffffffffffffffffffffffffffffffff8516155b1561022b576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612b006004820152602401610091565b73ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee148015906102655750600034115b156102a0576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612b026004820152602401610091565b6102f160405180610120016040528060001515815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b60008060008a1261030357600061030c565b61030c8a612913565b60008c1361031b57600061031d565b8b5b610327919061294b565b9050898b148015610336575034155b801561037f575061037f8b8a8a8a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115ac92505050565b1561038c57506001825260005b7fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8d160161041b57348111806103dc5750633b9aca00810134115b15610417576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612b016004820152602401610091565b5060005b8015610790576040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8d16906370a0823190602401602060405180830381865afa15801561048b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104af919061295e565b6040517fad207501000000000000000000000000000000000000000000000000000000008152909250339063ad207501906104f4908f9085908c908c90600401612977565b600060405180830381600087803b15801561050e57600080fd5b505af1158015610522573d6000803e3d6000fd5b50506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015284925073ffffffffffffffffffffffffffffffffffffffff8f1691506370a0823190602401602060405180830381865afa158015610592573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105b6919061295e565b6105c091906129e8565b9150808210806105d2575080600a0182115b1561060d576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612b016004820152602401610091565b73ffffffffffffffffffffffffffffffffffffffff8c1673cd5fe23c85820f7b72d0926fc9b05b43e359b7ee1480156106ec57506040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273f047ab4c75cebf0eb9ed34ae2c186f3611aeafa6602482015260009073cd5fe23c85820f7b72d0926fc9b05b43e359b7ee9063dd62ed3e90604401602060405180830381865afa1580156106c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106ea919061295e565b115b15610790576040517fb3db428b00000000000000000000000000000000000000000000000000000000815273cd5fe23c85820f7b72d0926fc9b05b43e359b7ee60048201523060248201526044810183905273f047ab4c75cebf0eb9ed34ae2c186f3611aeafa69063b3db428b90606401600060405180830381600087803b15801561077757600080fd5b505af115801561078b573d6000803e3d6000fd5b505050505b73ffffffffffffffffffffffffffffffffffffffff8c1660009081526005602052604090205461010084018190526107c79061168f565b60408086019190915260208086019290925273ffffffffffffffffffffffffffffffffffffffff8e1660009081526007909252908190205460e0850181905266ffffffffffffff600882901c811660ff8084169190911b6060880152604883901c82169383901c81169390931b608080880191909152608883901c9091169082901c83161b60a086015260c881901c60c091821c9283161b9085015291508a15610a435760008360e0015190506000806108868f8f886020015161189d565b915091508060000361091f5760008213156108b55781866060018181516108ad919061294b565b9052506108d8565b816000038660600151116108ca5760006108d2565b606086015182015b60608701525b60608601516108ec90603860086000611b56565b60e0870180517fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000168217905294506109fe565b600081131561094257808660800181815161093a919061294b565b905250610965565b8060000386608001511161095757600061095f565b608086015181015b60808701525b60808601516f7fffffffffffffffffffffffffffffff10156109b7576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612b066004820152602401610091565b60808601516109cb90603860086000611b56565b60e0870180517fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff16604083901b17905294505b8560e001518303610a3f576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612aff6004820152602401610091565b5050505b8915610c1d5760008360e001519050600080610a648f8e8860400151611c7f565b9150915080600003610b01576000821315610a9357818660a001818151610a8b919061294b565b905250610ab6565b816000038660a0015111610aa8576000610ab0565b60a086015182015b60a08701525b60a0860151610aca90603860086001611b56565b60e0870180517fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff16608083901b1790529450610bd8565b6000811315610b2457808660c001818151610b1c919061294b565b905250610b47565b806000038660c0015111610b39576000610b41565b60c086015181015b60c08701525b60c08601516f7fffffffffffffffffffffffffffffff1015610b99576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612b076004820152602401610091565b60c0860151610bad90603860086001611b56565b60e08701805177ffffffffffffffffffffffffffffffffffffffffffffffff1660c083901b17905294505b8560e001518303610c19576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612aff6004820152602401610091565b5050505b60e083015173ffffffffffffffffffffffffffffffffffffffff8d16600090815260076020908152604090912091909155830151606084015164e8d4a5100091610c66916129fb565b610c709190612a41565b94506f7fffffffffffffffffffffffffffffff85118015610c91575060008b135b15610ccc576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612b066004820152602401610091565b848360800151610cdc919061294b565b91508260800151851115610d12576001856127108560800151610cff91906129fb565b610d099190612a41565b901b9450610d54565b8260800151851015610d48576080830151600190610d32612710886129fb565b610d3c9190612a41565b901b6001179450610d54565b8115610d5457614e2094505b64e8d4a5100083604001518460a00151610d6e91906129fb565b610d789190612a41565b93506f7fffffffffffffffffffffffffffffff84118015610d99575060008a135b15610dd4576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612b076004820152602401610091565b838360c00151610de4919061294b565b90508260c00151841115610e1a576001846127108560c00151610e0791906129fb565b610e119190612a41565b901b9350610e5c565b8260c00151841015610e505760c0830151600190610e3a612710876129fb565b610e449190612a41565b901b6001179350610e5c565b8015610e5c57614e2093505b60008215610ec95782610e71612710846129fb565b610e7b9190612a41565b905061271081118015610e8e575060008b135b15610ec9576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612b036004820152602401610091565b610100840151603a1c6401ffffffff166201518001421115610eee5760019250610ef3565b600092505b8260000361101757613fff601e856101000151901c169250613fff602c856101000151901c16915081838211610f2b57818403610f2f565b8382035b11610f3b576000610f3e565b60015b60ff1692508260000361101757617fff60db856101000151901c169250856001168360011603610fa857600183901c92508183600188901c11610f8757600187901c8403610f8f565b83600188901c035b11610f9b576000610f9e565b60015b60ff169250610fad565b600192505b8260000361101757617fff60ea856101000151901c16925084600116836001160361101257600183901c92508183600187901c11610ff157600186901c8403610ff9565b83600187901c035b11611005576000611008565b60015b60ff169250611017565b600192505b8260010361119f5773ffffffffffffffffffffffffffffffffffffffff8d1660009081526006602052604090205461104f9082611f27565b925067ffffffffffffffff84602001511180611076575067ffffffffffffffff8460400151115b156110b1576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612b046004820152602401610091565b613fff8111156110f1576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612b056004820152602401610091565b60ea85901b60db87901b609b8660400151901b605b8760200151901b603a42901b601e86901b888a61010001517ffe000000000000000000000000000000000000000000000003fff0003fff0000161717171717171784610100018181525050836101000151600560008f73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506111e6565b609b8460400151901b605b8560200151901b8561010001517ffffffffffc00000000000000000000000000000007ffffffffffffffffffffff161717846101000181815250505b5060008b12806111f6575060008a135b801561120157508251155b1561150c5760008a13611215576000611217565b895b905060008b121561122d578a6000039150611232565b600091505b6000821180156112425750600081115b801561127957508773ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff16145b156112ff577fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8d16016112d3576112ce896112c9838561294b565b611fd0565b61150c565b6112ce896112e1838561294b565b73ffffffffffffffffffffffffffffffffffffffff8f16919061212f565b7fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8d160161135c57811561134c5761134c8983611fd0565b80156112ce576112ce8882611fd0565b81156114e55773ffffffffffffffffffffffffffffffffffffffff8c1673cd5fe23c85820f7b72d0926fc9b05b43e359b7ee14801561142657506040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152829073cd5fe23c85820f7b72d0926fc9b05b43e359b7ee906370a0823190602401602060405180830381865afa158015611400573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611424919061295e565b105b156114c4576040517ff3fef3a300000000000000000000000000000000000000000000000000000000815273cd5fe23c85820f7b72d0926fc9b05b43e359b7ee60048201526024810183905273f047ab4c75cebf0eb9ed34ae2c186f3611aeafa69063f3fef3a390604401600060405180830381600087803b1580156114ab57600080fd5b505af11580156114bf573d6000803e3d6000fd5b505050505b6114e573ffffffffffffffffffffffffffffffffffffffff8d168a8461212f565b801561150c5761150c73ffffffffffffffffffffffffffffffffffffffff8d16898361212f565b60e0830151610100840151604080518e8152602081018e905273ffffffffffffffffffffffffffffffffffffffff8d8116828401528c81166060830152608082019490945260a081019290925251918e169133917f4d93b232a24e82b284ced7461bf4deacffe66759d5c24513e6f29e571ad78d15919081900360c00190a35050602081015160409091015160018055909a909950975050505050505050565b60006014825110156115c057506000611687565b815182015160008613801561160057508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b8015611621575073ffffffffffffffffffffffffffffffffffffffff811633145b80611683575060008612801561166257508473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b8015611683575073ffffffffffffffffffffffffffffffffffffffff811633145b9150505b949350505050565b67ffffffffffffffff605b82901c811690609b83901c168115806116b1575080155b156116ed576040517fd50d7512000000000000000000000000000000000000000000000000000000008152620111716004820152602401610091565b61ffff8316603a84901c6401ffffffff16428181039160ea87901c617fff16911480611717575082155b806117225750806001145b1561172f57505050915091565b64496cebb80084840283020484019350617fff60db87901c1692508260010361175a57505050915091565b826001166001036117af5760019290921c91826c7e37be2022c0914b26800000008161178857611788612a12565b049250612710601e87901c613fff166b033b2e3c9fd0803ce80000008501020492506117dc565b60019290921c916305f5e100601e87901c613fff166127108501026b033b2e3c9fd0803ce8000000020492505b806001166001036118135760011c61271081016b033b2e3c9fd0803ce800000082028161180b5761180b612a12565b049050611849565b60011c61271081016b033b2e3c9fd0803ce800000082028161183757611837612a12565b046b033b2e3c9fd0803ce80000000390505b760a70c3c40a64e6c51999090b65f67d92400000000000008382026127100261ffff881691900402601087901c613fff16612710030292506801b5a660ea44b8000085840283020485019450505050915091565b33600090815260086020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152812054819080820361190d576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612af96004820152602401610091565b60ff81901c60010361194f576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612afa6004820152602401610091565b66ffffffffffffff600982901c1660ff600183901c161b600061197283836121bc565b9050826001166001036119eb5760008713156119b5578561199864e8d4a5100089612a55565b6119a29190612aa1565b94506119ae858361294b565b9150611a17565b6119cd6119c188612913565b64e8d4a5100088612251565b6119d690612913565b94506119e185612913565b6119ae90836129e8565b8693506000841315611a01576119ae848361294b565b611a0a84612913565b611a1490836129e8565b91505b600087128015611a2657508082105b15611a61576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612afb6004820152602401610091565b611a6c838383612295565b9050611a7d82603860086000611b56565b91508167ffffffffffffffff600185901c1603611aca576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612aff6004820152602401610091565b611ad981603860086000611b56565b33600090815260086020908152604080832073ffffffffffffffffffffffffffffffffffffffff9c909c1683529a9052989098207ffffffffffffffffffffffffc000000000000000000000000000000000000000190931660019290921b9190911760419790971b969096174260811b1790559094909350915050565b600080856fffffffffffffffffffffffffffffffff811115611b795760809150811c5b67ffffffffffffffff811115611b91576040918201911c5b63ffffffff811115611ba5576020918201911c5b61ffff811115611bb7576010918201911c5b60ff811115611bc8576008918201911c5b600f811115611bd9576004918201911c5b6003811115611bea576002918201911c5b6001811115611bfa576001820191505b8015611c07576001820191505b5084811015611c135750835b848103905085811c60008211841615611c6257600181019050806001871b03611c6257506001908101907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff86011b5b6001851b8210611c7157600080fd5b90931b909201949350505050565b33600090815260096020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120548190808203611cef576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612af96004820152602401610091565b60ff81901c600103611d31576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612afa6004820152602401610091565b66ffffffffffffff600982901c1660ff600183901c161b6000611d5483836122e8565b905082600116600103611dbc576000871315611d8d57611d7a8764e8d4a5100088612251565b9450611d86858361294b565b9150611de8565b85611d9d64e8d4a5100089612a55565b611da79190612aa1565b9450611db285612913565b611d8690836129e8565b8693506000841315611dd257611d86848361294b565b611ddb84612913565b611de590836129e8565b91505b600087138015611df757508082115b15611e32576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612afc6004820152602401610091565b611e3d8383836123a0565b9050611e4e82603860086001611b56565b91508167ffffffffffffffff600185901c1603611e9b576040517fdcab82e2000000000000000000000000000000000000000000000000000000008152612aff6004820152602401610091565b611eaa81603860086000611b56565b33600090815260096020908152604080832073ffffffffffffffffffffffffffffffffffffffff9c909c1683529a9052989098207ffffffffffffffffffffffffc000000000000000000000000000000000000000190931660019290921b9190911760419790971b969096174260811b1790559094909350915050565b6000600f83166001819003611f4757611f4084846123ff565b9150611f90565b80600203611f5957611f4084846124de565b6040517fd50d7512000000000000000000000000000000000000000000000000000000008152620111726004820152602401610091565b61ffff821115611fc95760405161ffff92507fe41708b2641eb1f7442f6a1e760ae5098fd7ba9f85e0c101513add0fbb27bcd790600090a15b5092915050565b8047101561203a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606401610091565b60008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114612094576040519150601f19603f3d011682016040523d82523d6000602084013e612099565b606091505b505090508061212a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401610091565b505050565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905261212a908490612586565b600066ffffffffffffff604984901c1660ff604185901c161b8082036121e657600091505061224b565b612710613fff60a286901c168402046401ffffffff608186901c16420362ffffff60b087901c1661221782846129fb565b6122219190612a41565b9050808311612231576000612235565b8083035b93505080840383811115612247578093505b5050505b92915050565b6000827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048411830215820261228657600080fd5b50910281810615159190040190565b60006103ff60d085901c1660ff60c886901c161b808410156122bb5760009150506122e1565b50612710613fff60a286901c168402048303828111156122dc5790506122e1565b829150505b9392505050565b60d082901c6103ff1660c883901c60ff161b613fff60a284901c16612710838202048084018381101561231d5750505061224b565b608186901c6401ffffffff164203925066ffffffffffffff604987901c1660ff604188901c161b60b087901c62ffffff1661235885856129fb565b6123629190612a41565b61236c919061294b565b93508084111561237a578093505b6103ff60e287901c1660ff60da88901c161b925082841115612247575090949350505050565b612710613fff60a285901c16830204820160d084901c6103ff1660c885901c60ff161b808210156123d25790506122e1565b506103ff60e285901c1660ff60da86901c161b808211156123f1578091505b818311156122dc57506122e1565b600080808080601487901c61ffff16808710156124385761ffff600489901c16945061ffff602489901c16935060009250809150612457565b61ffff602489901c16945061ffff603489901c16935080925061271091505b60008084840364e8d4a51000888803028161247457612474612a12565b0585810264e8d4a51000890203925089028201905060008112156124c9576040517fd50d7512000000000000000000000000000000000000000000000000000000008152620111736004820152602401610091565b64e8d4a5100090049998505050505050505050565b600080808080601487901c61ffff16808710156125175761ffff600489901c16945061ffff602489901c16935060009250809150612457565b603488901c61ffff16808810156125495761ffff60248a901c16955061ffff60448a901c169450819350809250612568565b61ffff60448a901c16955061ffff60548a901c16945080935061271092505b5060008084840364e8d4a51000888803028161247457612474612a12565b60006125e8826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166126929092919063ffffffff16565b80519091501561212a57808060200190518101906126069190612b09565b61212a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610091565b60606116878484600085856000808673ffffffffffffffffffffffffffffffffffffffff1685876040516126c69190612b4f565b60006040518083038185875af1925050503d8060008114612703576040519150601f19603f3d011682016040523d82523d6000602084013e612708565b606091505b509150915061271987838387612724565b979650505050505050565b606083156127ba5782516000036127b35773ffffffffffffffffffffffffffffffffffffffff85163b6127b3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610091565b5081611687565b61168783838151156127cf5781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100919190612b6b565b803573ffffffffffffffffffffffffffffffffffffffff8116811461282757600080fd5b919050565b600080600080600080600060c0888a03121561284757600080fd5b61285088612803565b9650602088013595506040880135945061286c60608901612803565b935061287a60808901612803565b925060a088013567ffffffffffffffff8082111561289757600080fd5b818a0191508a601f8301126128ab57600080fd5b8135818111156128ba57600080fd5b8b60208285010111156128cc57600080fd5b60208301945080935050505092959891949750929550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007f80000000000000000000000000000000000000000000000000000000000000008203612944576129446128e4565b5060000390565b8082018082111561224b5761224b6128e4565b60006020828403121561297057600080fd5b5051919050565b73ffffffffffffffffffffffffffffffffffffffff8516815283602082015260606040820152816060820152818360808301376000818301608090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01601019392505050565b8181038181111561224b5761224b6128e4565b808202811582820484141761224b5761224b6128e4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082612a5057612a50612a12565b500490565b808202600082127f800000000000000000000000000000000000000000000000000000000000000084141615612a8d57612a8d6128e4565b818105831482151761224b5761224b6128e4565b600082612ab057612ab0612a12565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f800000000000000000000000000000000000000000000000000000000000000083141615612b0457612b046128e4565b500590565b600060208284031215612b1b57600080fd5b815180151581146122e157600080fd5b60005b83811015612b46578181015183820152602001612b2e565b50506000910152565b60008251612b61818460208701612b2b565b9190910192915050565b6020815260008251806020840152612b8a816040850160208701612b2b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fea264697066735822122040fdd528007774f9aa724861fa936b0f3add5371aa6d07ea527379a35807e51364736f6c63430008150033",
"devdoc": {
"details": "For view methods / accessing data, use the \"LiquidityResolver\" periphery contract.",
"events": {
"LogOperate(address,address,int256,int256,address,address,uint256,uint256)": {
"params": {
"borrowAmount": "borrow amount for the operation. if >0 then a borrow happened, if <0 then a payback happened. if 0 then nothing.",
"borrowTo": "address that funds where borrowed to (if borrowAmount >0)",
"exchangePricesAndConfig": "updated exchange prices and configs storage slot. Contains updated supply & borrow exchange price: First 16 bits => 0- 15 => borrow rate (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535) Next 14 bits => 16- 29 => fee on interest from borrowers to lenders (in 1e2: 100% = 10_000; 1% = 100 -> max value 16_383). configurable. Next 14 bits => 30- 43 => last stored utilization (in 1e2: 100% = 10_000; 1% = 100 -> max value 16_383) Next 14 bits => 44- 57 => update on storage threshold (in 1e2: 100% = 10_000; 1% = 100 -> max value 16_383). configurable. Next 33 bits => 58- 90 => last update timestamp (enough until 16 March 2242 -> max value 8589934591) Next 64 bits => 91-154 => supply exchange price (1e12 -> max value 18_446_744,073709551615) Next 64 bits => 155-218 => borrow exchange price (1e12 -> max value 18_446_744,073709551615) Next 1 bit => 219-219 => if 0 then ratio is supplyInterestFree / supplyWithInterest else ratio is supplyWithInterest / supplyInterestFree Next 14 bits => 220-233 => supplyRatio: supplyInterestFree / supplyWithInterest (in 1e2: 100% = 10_000; 1% = 100 -> max value 16_383) Next 1 bit => 234-234 => if 0 then ratio is borrowInterestFree / borrowWithInterest else ratio is borrowWithInterest / borrowInterestFree Next 14 bits => 235-248 => borrowRatio: borrowInterestFree / borrowWithInterest (in 1e2: 100% = 10_000; 1% = 100 -> max value 16_383)",
"supplyAmount": "supply amount for the operation. if >0 then a deposit happened, if <0 then a withdrawal happened. if 0 then nothing.",
"token": "token address for which this operation was executed",
"totalAmounts": "updated total amounts, stacked uint256 as written to storage: First 64 bits => 0- 63 => total supply with interest in raw (totalSupply = totalSupplyRaw * supplyExchangePrice); BigMath: 56 | 8 Next 64 bits => 64-127 => total interest free supply in normal token amount (totalSupply = totalSupply); BigMath: 56 | 8 Next 64 bits => 128-191 => total borrow with interest in raw (totalBorrow = totalBorrowRaw * borrowExchangePrice); BigMath: 56 | 8 Next 64 bits => 192-255 => total interest free borrow in normal token amount (totalBorrow = totalBorrow); BigMath: 56 | 8",
"user": "protocol that triggered this operation (e.g. via an fToken or via Vault protocol)",
"withdrawTo": "address that funds where withdrawn to (if supplyAmount <0)"
}
}
},
"kind": "dev",
"methods": {},
"title": "Fluid Liquidity UserModule",
"version": 1
},
"userdoc": {
"events": {
"BorrowRateMaxCap()": {
"notice": "emitted if the calculated borrow rate surpassed max borrow rate (16 bits) and was capped at maximum value 65535"
},
"LogOperate(address,address,int256,int256,address,address,uint256,uint256)": {
"notice": "emitted on any `operate()` execution: deposit / supply / withdraw / borrow. includes info related to the executed operation, new total amounts (packed uint256 of BigMath numbers as in storage) and exchange prices (packed uint256 as in storage)."
}
},
"kind": "user",
"methods": {
"operate(address,int256,int256,address,address,bytes)": {
"notice": "inheritdoc IFluidLiquidity"
}
},
"notice": "Fluid Liquidity public facing endpoint logic contract that implements the `operate()` method. operate can be used to deposit, withdraw, borrow & payback funds, given that they have the necessary user config allowance. Interacting users must be allowed via the Fluid Liquidity AdminModule first. Intended users are thus allow-listed protocols, e.g. the Lending protocol (fTokens), Vault protocol etc.",
"version": 1
},
"storageLayout": {
"storage": [
{
"astId": 13425,
"contract": "contracts/liquidity/userModule/main.sol:FluidLiquidityUserModule",
"label": "_revenueCollector",
"offset": 0,
"slot": "0",
"type": "t_address"
},
{
"astId": 13428,
"contract": "contracts/liquidity/userModule/main.sol:FluidLiquidityUserModule",
"label": "_status",
"offset": 0,
"slot": "1",
"type": "t_uint256"
},
{
"astId": 13433,
"contract": "contracts/liquidity/userModule/main.sol:FluidLiquidityUserModule",
"label": "_isAuth",
"offset": 0,
"slot": "2",
"type": "t_mapping(t_address,t_uint256)"
},
{
"astId": 13438,
"contract": "contracts/liquidity/userModule/main.sol:FluidLiquidityUserModule",
"label": "_isGuardian",
"offset": 0,
"slot": "3",
"type": "t_mapping(t_address,t_uint256)"
},
{
"astId": 13443,
"contract": "contracts/liquidity/userModule/main.sol:FluidLiquidityUserModule",
"label": "_userClass",
"offset": 0,
"slot": "4",
"type": "t_mapping(t_address,t_uint256)"
},
{
"astId": 13448,
"contract": "contracts/liquidity/userModule/main.sol:FluidLiquidityUserModule",
"label": "_exchangePricesAndConfig",
"offset": 0,
"slot": "5",
"type": "t_mapping(t_address,t_uint256)"
},
{
"astId": 13453,
"contract": "contracts/liquidity/userModule/main.sol:FluidLiquidityUserModule",
"label": "_rateData",
"offset": 0,
"slot": "6",
"type": "t_mapping(t_address,t_uint256)"
},
{
"astId": 13458,
"contract": "contracts/liquidity/userModule/main.sol:FluidLiquidityUserModule",
"label": "_totalAmounts",
"offset": 0,
"slot": "7",
"type": "t_mapping(t_address,t_uint256)"
},
{
"astId": 13465,
"contract": "contracts/liquidity/userModule/main.sol:FluidLiquidityUserModule",
"label": "_userSupplyData",
"offset": 0,
"slot": "8",
"type": "t_mapping(t_address,t_mapping(t_address,t_uint256))"
},
{
"astId": 13472,
"contract": "contracts/liquidity/userModule/main.sol:FluidLiquidityUserModule",
"label": "_userBorrowData",
"offset": 0,
"slot": "9",
"type": "t_mapping(t_address,t_mapping(t_address,t_uint256))"
},
{
"astId": 13476,
"contract": "contracts/liquidity/userModule/main.sol:FluidLiquidityUserModule",
"label": "_listedTokens",
"offset": 0,
"slot": "10",
"type": "t_array(t_address)dyn_storage"
}
],
"types": {
"t_address": {
"encoding": "inplace",
"label": "address",
"numberOfBytes": "20"
},
"t_array(t_address)dyn_storage": {
"base": "t_address",
"encoding": "dynamic_array",
"label": "address[]",
"numberOfBytes": "32"
},
"t_mapping(t_address,t_mapping(t_address,t_uint256))": {
"encoding": "mapping",
"key": "t_address",
"label": "mapping(address => mapping(address => uint256))",
"numberOfBytes": "32",
"value": "t_mapping(t_address,t_uint256)"
},
"t_mapping(t_address,t_uint256)": {
"encoding": "mapping",
"key": "t_address",
"label": "mapping(address => uint256)",
"numberOfBytes": "32",
"value": "t_uint256"
},
"t_uint256": {
"encoding": "inplace",
"label": "uint256",
"numberOfBytes": "32"
}
}
}
}