{ "address": "0xFe4affaD55c7AeC012346195654634F7C786fA2c", "abi": [ { "inputs": [ { "internalType": "contract IFluidLiquidity", "name": "liquidity_", "type": "address" } ], "stateMutability": "nonpayable", "type": "constructor" }, { "inputs": [ { "internalType": "uint256", "name": "errorId_", "type": "uint256" } ], "name": "FluidCalcsSimulatedTimeError", "type": "error" }, { "inputs": [], "name": "FluidCalcsSimulatedTimeInvalidTimestamp", "type": "error" }, { "inputs": [], "name": "FluidCalcsVaultSimulatedTimeError", "type": "error" }, { "inputs": [ { "internalType": "uint256", "name": "errorId_", "type": "uint256" } ], "name": "FluidLiquidityCalcsError", "type": "error" }, { "inputs": [], "name": "LIQUIDITY", "outputs": [ { "internalType": "contract IFluidLiquidity", "name": "", "type": "address" } ], "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "uint256", "name": "exchangePricesAndConfig_", "type": "uint256" }, { "internalType": "uint256", "name": "simulatedTimestamp_", "type": "uint256" } ], "name": "calcLiquidityExchangePricesSimulatedTime", "outputs": [ { "internalType": "uint256", "name": "supplyExchangePrice_", "type": "uint256" }, { "internalType": "uint256", "name": "borrowExchangePrice_", "type": "uint256" } ], "stateMutability": "pure", "type": "function" }, { "inputs": [ { "internalType": "uint256", "name": "totalAmounts_", "type": "uint256" }, { "internalType": "uint256", "name": "exchangePricesAndConfig_", "type": "uint256" }, { "internalType": "uint256", "name": "simulatedTimestamp_", "type": "uint256" } ], "name": "calcLiquidityTotalAmountsSimulatedTime", "outputs": [ { "internalType": "uint256", "name": "totalSupply_", "type": "uint256" }, { "internalType": "uint256", "name": "totalBorrow_", "type": "uint256" }, { "internalType": "uint256", "name": "supplyExchangePrice_", "type": "uint256" }, { "internalType": "uint256", "name": "borrowExchangePrice_", "type": "uint256" } ], "stateMutability": "pure", "type": "function" }, { "inputs": [ { "internalType": "uint256", "name": "userSupplyData_", "type": "uint256" }, { "internalType": "uint256", "name": "userBorrowData_", "type": "uint256" }, { "internalType": "uint256", "name": "liquiditySupplyExchangePricesAndConfig_", "type": "uint256" }, { "internalType": "uint256", "name": "liquidityBorrowExchangePricesAndConfig_", "type": "uint256" }, { "internalType": "uint256", "name": "simulatedTimestamp_", "type": "uint256" } ], "name": "calcLiquidityUserAmountsSimulatedTime", "outputs": [ { "internalType": "uint256", "name": "supply_", "type": "uint256" }, { "internalType": "uint256", "name": "borrow_", "type": "uint256" }, { "internalType": "uint256", "name": "supplyExchangePrice_", "type": "uint256" }, { "internalType": "uint256", "name": "borrowExchangePrice_", "type": "uint256" } ], "stateMutability": "pure", "type": "function" }, { "inputs": [ { "internalType": "uint256", "name": "totalAmounts_", "type": "uint256" }, { "internalType": "uint256", "name": "exchangePricesAndConfig_", "type": "uint256" }, { "internalType": "uint256", "name": "liquidityTokenBalance_", "type": "uint256" } ], "name": "calcRevenue", "outputs": [ { "internalType": "uint256", "name": "revenueAmount_", "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "uint256", "name": "totalAmounts_", "type": "uint256" }, { "internalType": "uint256", "name": "exchangePricesAndConfig_", "type": "uint256" }, { "internalType": "uint256", "name": "liquidityTokenBalance_", "type": "uint256" }, { "internalType": "uint256", "name": "simulatedTimestamp_", "type": "uint256" } ], "name": "calcRevenueSimulatedTime", "outputs": [ { "internalType": "uint256", "name": "revenueAmount_", "type": "uint256" } ], "stateMutability": "pure", "type": "function" }, { "inputs": [ { "internalType": "uint256", "name": "vaultVariables2_", "type": "uint256" }, { "internalType": "uint256", "name": "vaultRates_", "type": "uint256" }, { "internalType": "uint256", "name": "liquiditySupplyExchangePricesAndConfig_", "type": "uint256" }, { "internalType": "uint256", "name": "liquidityBorrowExchangePricesAndConfig_", "type": "uint256" }, { "internalType": "uint256", "name": "simulatedTimestamp_", "type": "uint256" } ], "name": "calcVaultExchangePricesSimulatedTime", "outputs": [ { "internalType": "uint256", "name": "liqSupplyExPrice_", "type": "uint256" }, { "internalType": "uint256", "name": "liqBorrowExPrice_", "type": "uint256" }, { "internalType": "uint256", "name": "vaultSupplyExPrice_", "type": "uint256" }, { "internalType": "uint256", "name": "vaultBorrowExPrice_", "type": "uint256" } ], "stateMutability": "pure", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "token_", "type": "address" } ], "name": "getRevenue", "outputs": [ { "internalType": "uint256", "name": "revenueAmount_", "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "getRevenueCollector", "outputs": [ { "internalType": "address", "name": "", "type": "address" } ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "getRevenues", "outputs": [ { "components": [ { "internalType": "address", "name": "token", "type": "address" }, { "internalType": "uint256", "name": "revenueAmount", "type": "uint256" } ], "internalType": "struct FluidRevenueResolver.TokenRevenue[]", "name": "tokenRevenues_", "type": "tuple[]" } ], "stateMutability": "view", "type": "function" } ], "transactionHash": "0x0d99cdfa27ccf2b10a3bf7b4719e351a42b7bcaeda1121dbfcdf91939c97eba1", "receipt": { "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", "from": "0x0Ed35B1609Ec45c7079E80d11149a52717e4859A", "contractAddress": null, "transactionIndex": 1, "gasUsed": "1851169", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "blockHash": "0xd3822bb6ad6c3a3bb5db162510148500f34aff3036853a860b1fe2e9e53a2094", "transactionHash": "0x0d99cdfa27ccf2b10a3bf7b4719e351a42b7bcaeda1121dbfcdf91939c97eba1", "logs": [], "blockNumber": 228011436, "cumulativeGasUsed": "1851169", "status": 1, "byzantium": true }, "args": [ "0x52Aa899454998Be5b000Ad077a46Bbe360F4e497" ], "numDeployments": 2, "solcInputHash": "7ea6a03437971b2bd8979b983d3f0850", "metadata": "{\"compiler\":{\"version\":\"0.8.21+commit.d9974bed\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IFluidLiquidity\",\"name\":\"liquidity_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"errorId_\",\"type\":\"uint256\"}],\"name\":\"FluidCalcsSimulatedTimeError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FluidCalcsSimulatedTimeInvalidTimestamp\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FluidCalcsVaultSimulatedTimeError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"errorId_\",\"type\":\"uint256\"}],\"name\":\"FluidLiquidityCalcsError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LIQUIDITY\",\"outputs\":[{\"internalType\":\"contract IFluidLiquidity\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"exchangePricesAndConfig_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"simulatedTimestamp_\",\"type\":\"uint256\"}],\"name\":\"calcLiquidityExchangePricesSimulatedTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"supplyExchangePrice_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowExchangePrice_\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"totalAmounts_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"exchangePricesAndConfig_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"simulatedTimestamp_\",\"type\":\"uint256\"}],\"name\":\"calcLiquidityTotalAmountsSimulatedTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"totalSupply_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrow_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyExchangePrice_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowExchangePrice_\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"userSupplyData_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"userBorrowData_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquiditySupplyExchangePricesAndConfig_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidityBorrowExchangePricesAndConfig_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"simulatedTimestamp_\",\"type\":\"uint256\"}],\"name\":\"calcLiquidityUserAmountsSimulatedTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"supply_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrow_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyExchangePrice_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowExchangePrice_\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"totalAmounts_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"exchangePricesAndConfig_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidityTokenBalance_\",\"type\":\"uint256\"}],\"name\":\"calcRevenue\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"revenueAmount_\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"totalAmounts_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"exchangePricesAndConfig_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidityTokenBalance_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"simulatedTimestamp_\",\"type\":\"uint256\"}],\"name\":\"calcRevenueSimulatedTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"revenueAmount_\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"vaultVariables2_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"vaultRates_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquiditySupplyExchangePricesAndConfig_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidityBorrowExchangePricesAndConfig_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"simulatedTimestamp_\",\"type\":\"uint256\"}],\"name\":\"calcVaultExchangePricesSimulatedTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"liqSupplyExPrice_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liqBorrowExPrice_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"vaultSupplyExPrice_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"vaultBorrowExPrice_\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token_\",\"type\":\"address\"}],\"name\":\"getRevenue\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"revenueAmount_\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRevenueCollector\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRevenues\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"revenueAmount\",\"type\":\"uint256\"}],\"internalType\":\"struct FluidRevenueResolver.TokenRevenue[]\",\"name\":\"tokenRevenues_\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"calcLiquidityExchangePricesSimulatedTime(uint256,uint256)\":{\"params\":{\"exchangePricesAndConfig_\":\"exchange prices and config packed uint256 read from storage\",\"simulatedTimestamp_\":\"simulated block.timestamp\"},\"returns\":{\"borrowExchangePrice_\":\"updated borrowExchangePrice\",\"supplyExchangePrice_\":\"updated supplyExchangePrice\"}},\"calcRevenue(uint256,uint256,uint256)\":{\"details\":\"exposed for advanced revenue calculations\",\"params\":{\"exchangePricesAndConfig_\":\"exchange prices and config packed uint256 read from storage\",\"liquidityTokenBalance_\":\"current balance of Liquidity contract (IERC20(token_).balanceOf(address(this)))\",\"totalAmounts_\":\"total amounts packed uint256 read from storage\"},\"returns\":{\"revenueAmount_\":\"collectable revenue amount\"}},\"calcVaultExchangePricesSimulatedTime(uint256,uint256,uint256,uint256,uint256)\":{\"params\":{\"liquidityBorrowExchangePricesAndConfig_\":\"exchange prices and config packed uint256 read from storage for borrow token\",\"liquiditySupplyExchangePricesAndConfig_\":\"exchange prices and config packed uint256 read from storage for supply token\",\"simulatedTimestamp_\":\"simulated block.timestamp\",\"vaultRates_\":\"rates read from storage for the vault (VaultResolver.getVaultVariables2Raw)\",\"vaultVariables2_\":\"vaultVariables2 read from storage for the vault (VaultResolver.getRateRaw)\"},\"returns\":{\"liqBorrowExPrice_\":\"latest liquidity's borrow token borrow exchange price\",\"liqSupplyExPrice_\":\"latest liquidity's supply token supply exchange price\",\"vaultBorrowExPrice_\":\"latest vault's borrow token exchange price\",\"vaultSupplyExPrice_\":\"latest vault's supply token exchange price\"}}},\"stateVariables\":{\"_NATIVE_TOKEN_ADDRESS\":{\"details\":\"address that is mapped to the chain native token\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"LIQUIDITY()\":{\"notice\":\"address of the liquidity contract\"},\"calcLiquidityExchangePricesSimulatedTime(uint256,uint256)\":{\"notice\":\"calculates interest (exchange prices) at Liquidity for a token given its' exchangePricesAndConfig from storage for a simulated `block.timestamp` set via `simulatedTimestamp_`.\"},\"calcLiquidityTotalAmountsSimulatedTime(uint256,uint256,uint256)\":{\"notice\":\"returns the `totalSupply_` and `totalBorrow_` at Liquidity at a certain point in time given the stacked uint256 storage data for total amounts and exchange prices and config.\"},\"calcLiquidityUserAmountsSimulatedTime(uint256,uint256,uint256,uint256,uint256)\":{\"notice\":\"returns the `supply_` and `borrow_` for a user (protocol) at Liquidity at a certain point in time given the stacked uint256 storage data for total amounts and exchange prices and config.\"},\"calcRevenue(uint256,uint256,uint256)\":{\"notice\":\"gets the `revenueAmount_` for a token given its' totalAmounts and exchangePricesAndConfig from stacked uint256 storage slots and the balance of the Fluid liquidity contract for the token.\"},\"calcRevenueSimulatedTime(uint256,uint256,uint256,uint256)\":{\"notice\":\"same as `calcRevenue`, but for a simulated `block.timestamp` set via `simulatedTimestamp_`.\"},\"calcVaultExchangePricesSimulatedTime(uint256,uint256,uint256,uint256,uint256)\":{\"notice\":\"Calculates new vault exchange prices based on storage data for a simulated `block.timestamp` set via `simulatedTimestamp_`.\"},\"getRevenue(address)\":{\"notice\":\"gets the currently uncollected `revenueAmount_` for a `token_`.\"},\"getRevenueCollector()\":{\"notice\":\"address of contract that gets sent the revenue. Configurable by governance\"},\"getRevenues()\":{\"notice\":\"gets the currently uncollected revenues for all listed tokens at Liquidity\"}},\"notice\":\"Fluid Revenue resolver\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/periphery/resolvers/revenue/main.sol\":\"FluidRevenueResolver\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000000},\"remappings\":[]},\"sources\":{\"@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\"},\"contracts/infiniteProxy/interfaces/iProxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.21;\\n\\ninterface IProxy {\\n function setAdmin(address newAdmin_) external;\\n\\n function setDummyImplementation(address newDummyImplementation_) external;\\n\\n function addImplementation(address implementation_, bytes4[] calldata sigs_) external;\\n\\n function removeImplementation(address implementation_) external;\\n\\n function getAdmin() external view returns (address);\\n\\n function getDummyImplementation() external view returns (address);\\n\\n function getImplementationSigs(address impl_) external view returns (bytes4[] memory);\\n\\n function getSigsImplementation(bytes4 sig_) external view returns (address);\\n\\n function readFromStorage(bytes32 slot_) external view returns (uint256 result_);\\n}\\n\",\"keccak256\":\"0xbb605491d4bac08e816248feecae7dd17cfc1877c88b2e555abece2970f5ea00\",\"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 /// @dev storage slot for listed tokens array at Liquidity\\n uint256 internal constant LIQUIDITY_CONFIGS2_MAPPING_SLOT = 11;\\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 uint256 internal constant BITS_EXCHANGE_PRICES_USES_CONFIGS2 = 249;\\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 // Configs2\\n uint256 internal constant BITS_CONFIGS2_MAX_UTILIZATION = 0;\\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\":\"0x0ae3e1d231bb6c14b54fc1f5ffa306edc0ac827a6a92279c77c0c09627fe08ae\",\"license\":\"BUSL-1.1\"},\"contracts/liquidity/adminModule/structs.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity 0.8.21;\\n\\nabstract contract Structs {\\n struct AddressBool {\\n address addr;\\n bool value;\\n }\\n\\n struct AddressUint256 {\\n address addr;\\n uint256 value;\\n }\\n\\n /// @notice struct to set borrow rate data for version 1\\n struct RateDataV1Params {\\n ///\\n /// @param token for rate data\\n address token;\\n ///\\n /// @param kink in borrow rate. in 1e2: 100% = 10_000; 1% = 100\\n /// utilization below kink usually means slow increase in rate, once utilization is above kink borrow rate increases fast\\n uint256 kink;\\n ///\\n /// @param rateAtUtilizationZero desired borrow rate when utilization is zero. in 1e2: 100% = 10_000; 1% = 100\\n /// i.e. constant minimum borrow rate\\n /// e.g. at utilization = 0.01% rate could still be at least 4% (rateAtUtilizationZero would be 400 then)\\n uint256 rateAtUtilizationZero;\\n ///\\n /// @param rateAtUtilizationKink borrow rate when utilization is at kink. in 1e2: 100% = 10_000; 1% = 100\\n /// e.g. when rate should be 7% at kink then rateAtUtilizationKink would be 700\\n uint256 rateAtUtilizationKink;\\n ///\\n /// @param rateAtUtilizationMax borrow rate when utilization is maximum at 100%. in 1e2: 100% = 10_000; 1% = 100\\n /// e.g. when rate should be 125% at 100% then rateAtUtilizationMax would be 12_500\\n uint256 rateAtUtilizationMax;\\n }\\n\\n /// @notice struct to set borrow rate data for version 2\\n struct RateDataV2Params {\\n ///\\n /// @param token for rate data\\n address token;\\n ///\\n /// @param kink1 first kink in borrow rate. in 1e2: 100% = 10_000; 1% = 100\\n /// utilization below kink 1 usually means slow increase in rate, once utilization is above kink 1 borrow rate increases faster\\n uint256 kink1;\\n ///\\n /// @param kink2 second kink in borrow rate. in 1e2: 100% = 10_000; 1% = 100\\n /// utilization below kink 2 usually means slow / medium increase in rate, once utilization is above kink 2 borrow rate increases fast\\n uint256 kink2;\\n ///\\n /// @param rateAtUtilizationZero desired borrow rate when utilization is zero. in 1e2: 100% = 10_000; 1% = 100\\n /// i.e. constant minimum borrow rate\\n /// e.g. at utilization = 0.01% rate could still be at least 4% (rateAtUtilizationZero would be 400 then)\\n uint256 rateAtUtilizationZero;\\n ///\\n /// @param rateAtUtilizationKink1 desired borrow rate when utilization is at first kink. in 1e2: 100% = 10_000; 1% = 100\\n /// e.g. when rate should be 7% at first kink then rateAtUtilizationKink would be 700\\n uint256 rateAtUtilizationKink1;\\n ///\\n /// @param rateAtUtilizationKink2 desired borrow rate when utilization is at second kink. in 1e2: 100% = 10_000; 1% = 100\\n /// e.g. when rate should be 7% at second kink then rateAtUtilizationKink would be 1_200\\n uint256 rateAtUtilizationKink2;\\n ///\\n /// @param rateAtUtilizationMax desired borrow rate when utilization is maximum at 100%. in 1e2: 100% = 10_000; 1% = 100\\n /// e.g. when rate should be 125% at 100% then rateAtUtilizationMax would be 12_500\\n uint256 rateAtUtilizationMax;\\n }\\n\\n /// @notice struct to set token config\\n struct TokenConfig {\\n ///\\n /// @param token address\\n address token;\\n ///\\n /// @param fee charges on borrower's interest. in 1e2: 100% = 10_000; 1% = 100\\n uint256 fee;\\n ///\\n /// @param threshold on when to update the storage slot. in 1e2: 100% = 10_000; 1% = 100\\n uint256 threshold;\\n ///\\n /// @param maxUtilization maximum allowed utilization. in 1e2: 100% = 10_000; 1% = 100\\n /// set to 100% to disable and have default limit of 100% (avoiding SLOAD).\\n uint256 maxUtilization;\\n }\\n\\n /// @notice struct to set user supply & withdrawal config\\n struct UserSupplyConfig {\\n ///\\n /// @param user address\\n address user;\\n ///\\n /// @param token address\\n address token;\\n ///\\n /// @param mode: 0 = without interest. 1 = with interest\\n uint8 mode;\\n ///\\n /// @param expandPercent withdrawal limit expand percent. in 1e2: 100% = 10_000; 1% = 100\\n /// Also used to calculate rate at which withdrawal limit should decrease (instant).\\n uint256 expandPercent;\\n ///\\n /// @param expandDuration withdrawal limit expand duration in seconds.\\n /// used to calculate rate together with expandPercent\\n uint256 expandDuration;\\n ///\\n /// @param baseWithdrawalLimit base limit, below this, user can withdraw the entire amount.\\n /// amount in raw (to be multiplied with exchange price) or normal depends on configured mode in user config for the token:\\n /// with interest -> raw, without interest -> normal\\n uint256 baseWithdrawalLimit;\\n }\\n\\n /// @notice struct to set user borrow & payback config\\n struct UserBorrowConfig {\\n ///\\n /// @param user address\\n address user;\\n ///\\n /// @param token address\\n address token;\\n ///\\n /// @param mode: 0 = without interest. 1 = with interest\\n uint8 mode;\\n ///\\n /// @param expandPercent debt limit expand percent. in 1e2: 100% = 10_000; 1% = 100\\n /// Also used to calculate rate at which debt limit should decrease (instant).\\n uint256 expandPercent;\\n ///\\n /// @param expandDuration debt limit expand duration in seconds.\\n /// used to calculate rate together with expandPercent\\n uint256 expandDuration;\\n ///\\n /// @param baseDebtCeiling base borrow limit. until here, borrow limit remains as baseDebtCeiling\\n /// (user can borrow until this point at once without stepped expansion). Above this, automated limit comes in place.\\n /// amount in raw (to be multiplied with exchange price) or normal depends on configured mode in user config for the token:\\n /// with interest -> raw, without interest -> normal\\n uint256 baseDebtCeiling;\\n ///\\n /// @param maxDebtCeiling max borrow ceiling, maximum amount the user can borrow.\\n /// amount in raw (to be multiplied with exchange price) or normal depends on configured mode in user config for the token:\\n /// with interest -> raw, without interest -> normal\\n uint256 maxDebtCeiling;\\n }\\n}\\n\",\"keccak256\":\"0x10353c70015f27b880125cefab806dbed24a4458f187da66964f3ef60488f757\",\"license\":\"BUSL-1.1\"},\"contracts/liquidity/interfaces/iLiquidity.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity 0.8.21;\\n\\nimport { IProxy } from \\\"../../infiniteProxy/interfaces/iProxy.sol\\\";\\nimport { Structs as AdminModuleStructs } from \\\"../adminModule/structs.sol\\\";\\n\\ninterface IFluidLiquidityAdmin {\\n /// @notice adds/removes auths. Auths generally could be contracts which can have restricted actions defined on contract.\\n /// auths can be helpful in reducing governance overhead where it's not needed.\\n /// @param authsStatus_ array of structs setting allowed status for an address.\\n /// status true => add auth, false => remove auth\\n function updateAuths(AdminModuleStructs.AddressBool[] calldata authsStatus_) external;\\n\\n /// @notice adds/removes guardians. Only callable by Governance.\\n /// @param guardiansStatus_ array of structs setting allowed status for an address.\\n /// status true => add guardian, false => remove guardian\\n function updateGuardians(AdminModuleStructs.AddressBool[] calldata guardiansStatus_) external;\\n\\n /// @notice changes the revenue collector address (contract that is sent revenue). Only callable by Governance.\\n /// @param revenueCollector_ new revenue collector address\\n function updateRevenueCollector(address revenueCollector_) external;\\n\\n /// @notice changes current status, e.g. for pausing or unpausing all user operations. Only callable by Auths.\\n /// @param newStatus_ new status\\n /// status = 2 -> pause, status = 1 -> resume.\\n function changeStatus(uint256 newStatus_) external;\\n\\n /// @notice update tokens rate data version 1. Only callable by Auths.\\n /// @param tokensRateData_ array of RateDataV1Params with rate data to set for each token\\n function updateRateDataV1s(AdminModuleStructs.RateDataV1Params[] calldata tokensRateData_) external;\\n\\n /// @notice update tokens rate data version 2. Only callable by Auths.\\n /// @param tokensRateData_ array of RateDataV2Params with rate data to set for each token\\n function updateRateDataV2s(AdminModuleStructs.RateDataV2Params[] calldata tokensRateData_) external;\\n\\n /// @notice updates token configs: fee charge on borrowers interest & storage update utilization threshold.\\n /// Only callable by Auths.\\n /// @param tokenConfigs_ contains token address, fee & utilization threshold\\n function updateTokenConfigs(AdminModuleStructs.TokenConfig[] calldata tokenConfigs_) external;\\n\\n /// @notice updates user classes: 0 is for new protocols, 1 is for established protocols.\\n /// Only callable by Auths.\\n /// @param userClasses_ struct array of uint256 value to assign for each user address\\n function updateUserClasses(AdminModuleStructs.AddressUint256[] calldata userClasses_) external;\\n\\n /// @notice sets user supply configs per token basis. Eg: with interest or interest-free and automated limits.\\n /// Only callable by Auths.\\n /// @param userSupplyConfigs_ struct array containing user supply config, see `UserSupplyConfig` struct for more info\\n function updateUserSupplyConfigs(AdminModuleStructs.UserSupplyConfig[] memory userSupplyConfigs_) external;\\n\\n /// @notice setting user borrow configs per token basis. Eg: with interest or interest-free and automated limits.\\n /// Only callable by Auths.\\n /// @param userBorrowConfigs_ struct array containing user borrow config, see `UserBorrowConfig` struct for more info\\n function updateUserBorrowConfigs(AdminModuleStructs.UserBorrowConfig[] memory userBorrowConfigs_) external;\\n\\n /// @notice pause operations for a particular user in class 0 (class 1 users can't be paused by guardians).\\n /// Only callable by Guardians.\\n /// @param user_ address of user to pause operations for\\n /// @param supplyTokens_ token addresses to pause withdrawals for\\n /// @param borrowTokens_ token addresses to pause borrowings for\\n function pauseUser(address user_, address[] calldata supplyTokens_, address[] calldata borrowTokens_) external;\\n\\n /// @notice unpause operations for a particular user in class 0 (class 1 users can't be paused by guardians).\\n /// Only callable by Guardians.\\n /// @param user_ address of user to unpause operations for\\n /// @param supplyTokens_ token addresses to unpause withdrawals for\\n /// @param borrowTokens_ token addresses to unpause borrowings for\\n function unpauseUser(address user_, address[] calldata supplyTokens_, address[] calldata borrowTokens_) external;\\n\\n /// @notice collects revenue for tokens to configured revenueCollector address.\\n /// @param tokens_ array of tokens to collect revenue for\\n /// @dev Note that this can revert if token balance is < revenueAmount (utilization > 100%)\\n function collectRevenue(address[] calldata tokens_) external;\\n\\n /// @notice gets the current updated exchange prices for n tokens and updates all prices, rates related data in storage.\\n /// @param tokens_ tokens to update exchange prices for\\n /// @return supplyExchangePrices_ new supply rates of overall system for each token\\n /// @return borrowExchangePrices_ new borrow rates of overall system for each token\\n function updateExchangePrices(\\n address[] calldata tokens_\\n ) external returns (uint256[] memory supplyExchangePrices_, uint256[] memory borrowExchangePrices_);\\n}\\n\\ninterface IFluidLiquidityLogic is IFluidLiquidityAdmin {\\n /// @notice Single function which handles supply, withdraw, borrow & payback\\n /// @param token_ address of token (0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE for native)\\n /// @param supplyAmount_ if +ve then supply, if -ve then withdraw, if 0 then nothing\\n /// @param borrowAmount_ if +ve then borrow, if -ve then payback, if 0 then nothing\\n /// @param withdrawTo_ if withdrawal then to which address\\n /// @param borrowTo_ if borrow then to which address\\n /// @param callbackData_ callback data passed to `liquidityCallback` method of protocol\\n /// @return memVar3_ updated supplyExchangePrice\\n /// @return memVar4_ updated borrowExchangePrice\\n /// @dev to trigger skipping in / out transfers when in&out amounts balance themselves out (gas optimization):\\n /// - supply(+) == borrow(+), withdraw(-) == payback(-).\\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 operate(\\n address token_,\\n int256 supplyAmount_,\\n int256 borrowAmount_,\\n address withdrawTo_,\\n address borrowTo_,\\n bytes calldata callbackData_\\n ) external payable returns (uint256 memVar3_, uint256 memVar4_);\\n}\\n\\ninterface IFluidLiquidity is IProxy, IFluidLiquidityLogic {}\\n\",\"keccak256\":\"0xc81ac0cfc8183ec57ec4e488b07a4f6d1ecd79787e0aaf0dcfdd0b9b7ac0fc84\",\"license\":\"MIT\"},\"contracts/periphery/resolvers/revenue/calcsSimulatedTime.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity 0.8.21;\\n\\nimport { LibsErrorTypes as ErrorTypes } from \\\"../../../libraries/errorTypes.sol\\\";\\nimport { LiquiditySlotsLink } from \\\"../../../libraries/liquiditySlotsLink.sol\\\";\\nimport { BigMathMinified } from \\\"../../../libraries/bigMathMinified.sol\\\";\\n\\n/// @dev this is the exact same code as `LiquidityCalcs` library, just that it supports a simulated\\n/// block.timestamp to expose historical calculations.\\nlibrary CalcsSimulatedTime {\\n error FluidCalcsSimulatedTimeError(uint256 errorId_);\\n error FluidCalcsSimulatedTimeInvalidTimestamp();\\n\\n /// @dev constants as from Liquidity variables.sol\\n uint256 internal constant EXCHANGE_PRICES_PRECISION = 1e12;\\n\\n /// @dev Ignoring leap years\\n uint256 internal constant SECONDS_PER_YEAR = 365 days;\\n // constants used for BigMath conversion from and to storage\\n uint256 internal constant DEFAULT_EXPONENT_SIZE = 8;\\n uint256 internal constant DEFAULT_EXPONENT_MASK = 0xFF;\\n\\n uint256 internal constant FOUR_DECIMALS = 1e4;\\n uint256 internal constant TWELVE_DECIMALS = 1e12;\\n uint256 internal constant X14 = 0x3fff;\\n uint256 internal constant X15 = 0x7fff;\\n uint256 internal constant X16 = 0xffff;\\n uint256 internal constant X18 = 0x3ffff;\\n uint256 internal constant X24 = 0xffffff;\\n uint256 internal constant X33 = 0x1ffffffff;\\n uint256 internal constant X64 = 0xffffffffffffffff;\\n\\n ///////////////////////////////////////////////////////////////////////////\\n ////////// CALC EXCHANGE PRICES /////////\\n ///////////////////////////////////////////////////////////////////////////\\n\\n /// @dev calculates interest (exchange prices) for a token given its' exchangePricesAndConfig from storage.\\n /// @param exchangePricesAndConfig_ exchange prices and config packed uint256 read from storage\\n /// @param blockTimestamp_ simulated block.timestamp\\n /// @return supplyExchangePrice_ updated supplyExchangePrice\\n /// @return borrowExchangePrice_ updated borrowExchangePrice\\n function calcExchangePrices(\\n uint256 exchangePricesAndConfig_,\\n uint256 blockTimestamp_\\n ) internal pure returns (uint256 supplyExchangePrice_, uint256 borrowExchangePrice_) {\\n // Extracting exchange prices\\n supplyExchangePrice_ =\\n (exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_SUPPLY_EXCHANGE_PRICE) &\\n X64;\\n borrowExchangePrice_ =\\n (exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_BORROW_EXCHANGE_PRICE) &\\n X64;\\n\\n if (supplyExchangePrice_ == 0 || borrowExchangePrice_ == 0) {\\n revert FluidCalcsSimulatedTimeError(ErrorTypes.LiquidityCalcs__ExchangePriceZero);\\n }\\n\\n uint256 temp_ = exchangePricesAndConfig_ & X16; // temp_ = borrowRate\\n\\n // @dev HERE CUSTOM: added check for simulated timestamp\\n if (\\n blockTimestamp_ <\\n ((exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_LAST_TIMESTAMP) & X33)\\n ) {\\n revert FluidCalcsSimulatedTimeInvalidTimestamp();\\n }\\n\\n unchecked {\\n // last timestamp can not be > current timestamp\\n uint256 secondsSinceLastUpdate_ = blockTimestamp_ -\\n ((exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_LAST_TIMESTAMP) & X33);\\n\\n uint256 borrowRatio_ = (exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_BORROW_RATIO) &\\n X15;\\n if (secondsSinceLastUpdate_ == 0 || temp_ == 0 || borrowRatio_ == 1) {\\n // if no time passed, borrow rate is 0, or no raw borrowings: no exchange price update needed\\n // (if borrowRatio_ == 1 means there is only borrowInterestFree, as first bit is 1 and rest is 0)\\n return (supplyExchangePrice_, borrowExchangePrice_);\\n }\\n\\n // 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 /// @param blockTimestamp_ simulated block.timestamp\\n /// @return revenueAmount_ collectable revenue amount\\n function calcRevenue(\\n uint256 totalAmounts_,\\n uint256 exchangePricesAndConfig_,\\n uint256 liquidityTokenBalance_,\\n uint256 blockTimestamp_\\n ) internal pure 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(\\n exchangePricesAndConfig_,\\n blockTimestamp_\\n );\\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 /// @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\":\"0xab5d42aa7508973a3c6e5fb94784f0a585343408b0eefeceb9bae6f46bfd9d11\",\"license\":\"BUSL-1.1\"},\"contracts/periphery/resolvers/revenue/calcsVaultSimulatedTime.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity 0.8.21;\\n\\nimport { CalcsSimulatedTime } from \\\"./calcsSimulatedTime.sol\\\";\\n\\n/// @dev this is the exact same code as in vault protocol codebase, just that it supports a simulated\\n/// block.timestamp to expose historical calculations.\\nlibrary CalcsVaultSimulatedTime {\\n error FluidCalcsVaultSimulatedTimeError();\\n\\n uint256 internal constant X16 = 0xffff;\\n uint256 internal constant X64 = 0xffffffffffffffff;\\n\\n // @dev copied from vault protocol helper.sol and adjusted to have liquidity storage data and vault rates\\n // storage data passed in instead of read\\n\\n /// @dev Calculates new vault exchange prices.\\n /// @param vaultVariables2_ vaultVariables2 read from storage for the vault (VaultResolver.getRateRaw)\\n /// @param vaultRates_ rates read from storage for the vault (VaultResolver.getVaultVariables2Raw)\\n /// @param liquiditySupplyExchangePricesAndConfig_ exchange prices and config packed uint256 read from storage for supply token\\n /// @param liquidityBorrowExchangePricesAndConfig_ exchange prices and config packed uint256 read from storage for borrow token\\n /// @param blockTimestamp_ simulated block.timestamp\\n /// @return liqSupplyExPrice_ latest liquidity's supply token supply exchange price\\n /// @return liqBorrowExPrice_ latest liquidity's borrow token borrow exchange price\\n /// @return vaultSupplyExPrice_ latest vault's supply token exchange price\\n /// @return vaultBorrowExPrice_ latest vault's borrow token exchange price\\n function updateExchangePrices(\\n uint256 vaultVariables2_,\\n uint256 vaultRates_,\\n uint256 liquiditySupplyExchangePricesAndConfig_,\\n uint256 liquidityBorrowExchangePricesAndConfig_,\\n uint256 blockTimestamp_\\n )\\n internal\\n pure\\n returns (\\n uint256 liqSupplyExPrice_,\\n uint256 liqBorrowExPrice_,\\n uint256 vaultSupplyExPrice_,\\n uint256 vaultBorrowExPrice_\\n )\\n {\\n (liqSupplyExPrice_, ) = CalcsSimulatedTime.calcExchangePrices(\\n liquiditySupplyExchangePricesAndConfig_,\\n blockTimestamp_\\n );\\n (, liqBorrowExPrice_) = CalcsSimulatedTime.calcExchangePrices(\\n liquidityBorrowExchangePricesAndConfig_,\\n blockTimestamp_\\n );\\n\\n uint256 oldLiqSupplyExPrice_ = (vaultRates_ & X64);\\n uint256 oldLiqBorrowExPrice_ = ((vaultRates_ >> 64) & X64);\\n if (liqSupplyExPrice_ < oldLiqSupplyExPrice_ || liqBorrowExPrice_ < oldLiqBorrowExPrice_) {\\n // new liquidity exchange price is < than the old one. liquidity exchange price should only ever increase.\\n // If not, something went wrong and avoid proceeding with unknown outcome.\\n revert FluidCalcsVaultSimulatedTimeError();\\n }\\n\\n // liquidity Exchange Prices always increases in next block. Hence substraction with old will never be negative\\n // uint64 * 1e18 is the max the number that could be\\n unchecked {\\n // Calculating increase in supply exchange price w.r.t last stored liquidity's exchange price\\n // vaultSupplyExPrice_ => supplyIncreaseInPercent_\\n vaultSupplyExPrice_ =\\n ((((liqSupplyExPrice_ * 1e18) / oldLiqSupplyExPrice_) - 1e18) * (vaultVariables2_ & X16)) /\\n 10000; // supply rate magnifier\\n\\n // Calculating increase in borrow exchange price w.r.t last stored liquidity's exchange price\\n // vaultBorrowExPrice_ => borrowIncreaseInPercent_\\n vaultBorrowExPrice_ =\\n ((((liqBorrowExPrice_ * 1e18) / oldLiqBorrowExPrice_) - 1e18) * ((vaultVariables2_ >> 16) & X16)) /\\n 10000; // borrow rate magnifier\\n\\n // It's extremely hard the exchange prices to overflow even in 100 years but if it does it's not an\\n // issue here as we are not updating on storage\\n // (vaultRates_ >> 128) & X64) -> last stored vault's supply token exchange price\\n vaultSupplyExPrice_ = (((vaultRates_ >> 128) & X64) * (1e18 + vaultSupplyExPrice_)) / 1e18;\\n // (vaultRates_ >> 192) -> last stored vault's borrow token exchange price (no need to mask with & X64 as it is anyway max 64 bits)\\n vaultBorrowExPrice_ = ((vaultRates_ >> 192) * (1e18 + vaultBorrowExPrice_)) / 1e18;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2b279dd523c2aac7bebe2060d56fd6460c802d399c7ac84c45bdae32a6ddcaad\",\"license\":\"BUSL-1.1\"},\"contracts/periphery/resolvers/revenue/main.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity 0.8.21;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport { IFluidLiquidity } from \\\"../../../liquidity/interfaces/iLiquidity.sol\\\";\\nimport { LiquidityCalcs } from \\\"../../../libraries/liquidityCalcs.sol\\\";\\nimport { LiquiditySlotsLink } from \\\"../../../libraries/liquiditySlotsLink.sol\\\";\\nimport { BigMathMinified } from \\\"../../../libraries/bigMathMinified.sol\\\";\\nimport { CalcsSimulatedTime } from \\\"./calcsSimulatedTime.sol\\\";\\nimport { CalcsVaultSimulatedTime } from \\\"./calcsVaultSimulatedTime.sol\\\";\\n\\n/// @notice Fluid Revenue resolver\\ncontract FluidRevenueResolver {\\n /// @notice address of the liquidity contract\\n IFluidLiquidity public immutable LIQUIDITY;\\n\\n /// @dev address that is mapped to the chain native token\\n address internal constant _NATIVE_TOKEN_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\\n\\n uint256 internal constant X64 = 0xffffffffffffffff;\\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 struct TokenRevenue {\\n address token;\\n uint256 revenueAmount;\\n }\\n\\n constructor(IFluidLiquidity liquidity_) {\\n LIQUIDITY = IFluidLiquidity(liquidity_);\\n }\\n\\n /// @notice address of contract that gets sent the revenue. Configurable by governance\\n function getRevenueCollector() public view returns (address) {\\n return address(uint160(LIQUIDITY.readFromStorage(bytes32(0))));\\n }\\n\\n /// @notice gets the currently uncollected `revenueAmount_` for a `token_`.\\n function getRevenue(address token_) public view returns (uint256 revenueAmount_) {\\n uint256 exchangePricesAndConfig_ = LIQUIDITY.readFromStorage(\\n LiquiditySlotsLink.calculateMappingStorageSlot(\\n LiquiditySlotsLink.LIQUIDITY_EXCHANGE_PRICES_MAPPING_SLOT,\\n token_\\n )\\n );\\n if (exchangePricesAndConfig_ == 0) {\\n // token is not configured at Liquidity -> revenue is 0\\n return 0;\\n }\\n\\n uint256 liquidityTokenBalance_ = token_ == _NATIVE_TOKEN_ADDRESS\\n ? address(LIQUIDITY).balance\\n : IERC20(token_).balanceOf(address(LIQUIDITY));\\n\\n uint256 totalAmounts_ = LIQUIDITY.readFromStorage(\\n LiquiditySlotsLink.calculateMappingStorageSlot(\\n LiquiditySlotsLink.LIQUIDITY_TOTAL_AMOUNTS_MAPPING_SLOT,\\n token_\\n )\\n );\\n\\n return LiquidityCalcs.calcRevenue(totalAmounts_, exchangePricesAndConfig_, liquidityTokenBalance_);\\n }\\n\\n /// @notice gets the currently uncollected revenues for all listed tokens at Liquidity\\n function getRevenues() public view returns (TokenRevenue[] memory tokenRevenues_) {\\n uint256 length_ = LIQUIDITY.readFromStorage(bytes32(LiquiditySlotsLink.LIQUIDITY_LISTED_TOKENS_ARRAY_SLOT));\\n\\n tokenRevenues_ = new TokenRevenue[](length_);\\n\\n uint256 startingSlotForArrayElements_ = uint256(\\n keccak256(abi.encode(LiquiditySlotsLink.LIQUIDITY_LISTED_TOKENS_ARRAY_SLOT))\\n );\\n\\n for (uint256 i; i < length_; i++) {\\n tokenRevenues_[i].token = address(\\n uint160(LIQUIDITY.readFromStorage(bytes32(startingSlotForArrayElements_ + i)))\\n );\\n tokenRevenues_[i].revenueAmount = getRevenue(tokenRevenues_[i].token);\\n }\\n }\\n\\n /// @notice gets the `revenueAmount_` for a token given its' totalAmounts and exchangePricesAndConfig from stacked\\n /// uint256 storage slots and the balance of the Fluid liquidity contract for the token.\\n /// @dev exposed for advanced revenue calculations\\n /// @param totalAmounts_ total amounts packed uint256 read from storage\\n /// @param exchangePricesAndConfig_ exchange prices and config packed uint256 read from storage\\n /// @param liquidityTokenBalance_ current balance of Liquidity contract (IERC20(token_).balanceOf(address(this)))\\n /// @return revenueAmount_ collectable revenue amount\\n function calcRevenue(\\n uint256 totalAmounts_,\\n uint256 exchangePricesAndConfig_,\\n uint256 liquidityTokenBalance_\\n ) public view returns (uint256 revenueAmount_) {\\n if (exchangePricesAndConfig_ == 0) {\\n // token is not configured at Liquidity -> revenue is 0\\n return 0;\\n }\\n return LiquidityCalcs.calcRevenue(totalAmounts_, exchangePricesAndConfig_, liquidityTokenBalance_);\\n }\\n\\n /// @notice same as `calcRevenue`, but for a simulated `block.timestamp` set via `simulatedTimestamp_`.\\n function calcRevenueSimulatedTime(\\n uint256 totalAmounts_,\\n uint256 exchangePricesAndConfig_,\\n uint256 liquidityTokenBalance_,\\n uint256 simulatedTimestamp_\\n ) public pure returns (uint256 revenueAmount_) {\\n if (exchangePricesAndConfig_ == 0) {\\n // token is not configured at Liquidity -> revenue is 0\\n return 0;\\n }\\n return\\n CalcsSimulatedTime.calcRevenue(\\n totalAmounts_,\\n exchangePricesAndConfig_,\\n liquidityTokenBalance_,\\n simulatedTimestamp_\\n );\\n }\\n\\n /// @notice calculates interest (exchange prices) at Liquidity for a token given its' exchangePricesAndConfig from storage\\n /// for a simulated `block.timestamp` set via `simulatedTimestamp_`.\\n /// @param exchangePricesAndConfig_ exchange prices and config packed uint256 read from storage\\n /// @param simulatedTimestamp_ simulated block.timestamp\\n /// @return supplyExchangePrice_ updated supplyExchangePrice\\n /// @return borrowExchangePrice_ updated borrowExchangePrice\\n function calcLiquidityExchangePricesSimulatedTime(\\n uint256 exchangePricesAndConfig_,\\n uint256 simulatedTimestamp_\\n ) public pure returns (uint256 supplyExchangePrice_, uint256 borrowExchangePrice_) {\\n if (exchangePricesAndConfig_ == 0) {\\n // token is not configured at Liquidity -> exchange prices are 0\\n return (0, 0);\\n }\\n return CalcsSimulatedTime.calcExchangePrices(exchangePricesAndConfig_, simulatedTimestamp_);\\n }\\n\\n /// @notice Calculates new vault exchange prices based on storage data for a simulated `block.timestamp` set via `simulatedTimestamp_`.\\n /// @param vaultVariables2_ vaultVariables2 read from storage for the vault (VaultResolver.getRateRaw)\\n /// @param vaultRates_ rates read from storage for the vault (VaultResolver.getVaultVariables2Raw)\\n /// @param liquiditySupplyExchangePricesAndConfig_ exchange prices and config packed uint256 read from storage for supply token\\n /// @param liquidityBorrowExchangePricesAndConfig_ exchange prices and config packed uint256 read from storage for borrow token\\n /// @param simulatedTimestamp_ simulated block.timestamp\\n /// @return liqSupplyExPrice_ latest liquidity's supply token supply exchange price\\n /// @return liqBorrowExPrice_ latest liquidity's borrow token borrow exchange price\\n /// @return vaultSupplyExPrice_ latest vault's supply token exchange price\\n /// @return vaultBorrowExPrice_ latest vault's borrow token exchange price\\n function calcVaultExchangePricesSimulatedTime(\\n uint256 vaultVariables2_,\\n uint256 vaultRates_,\\n uint256 liquiditySupplyExchangePricesAndConfig_,\\n uint256 liquidityBorrowExchangePricesAndConfig_,\\n uint256 simulatedTimestamp_\\n )\\n public\\n pure\\n returns (\\n uint256 liqSupplyExPrice_,\\n uint256 liqBorrowExPrice_,\\n uint256 vaultSupplyExPrice_,\\n uint256 vaultBorrowExPrice_\\n )\\n {\\n if (liquiditySupplyExchangePricesAndConfig_ == 0 || liquidityBorrowExchangePricesAndConfig_ == 0) {\\n // token is not configured at Liquidity -> exchange prices are 0\\n return (0, 0, 0, 0);\\n }\\n return\\n CalcsVaultSimulatedTime.updateExchangePrices(\\n vaultVariables2_,\\n vaultRates_,\\n liquiditySupplyExchangePricesAndConfig_,\\n liquidityBorrowExchangePricesAndConfig_,\\n simulatedTimestamp_\\n );\\n }\\n\\n /// @notice returns the `totalSupply_` and `totalBorrow_` at Liquidity at a certain point in time given the stacked uint256\\n /// storage data for total amounts and exchange prices and config.\\n function calcLiquidityTotalAmountsSimulatedTime(\\n uint256 totalAmounts_,\\n uint256 exchangePricesAndConfig_,\\n uint256 simulatedTimestamp_\\n )\\n public\\n pure\\n returns (uint256 totalSupply_, uint256 totalBorrow_, uint256 supplyExchangePrice_, uint256 borrowExchangePrice_)\\n {\\n if (exchangePricesAndConfig_ == 0) {\\n // token is not configured at Liquidity -> amounts are 0\\n return (0, 0, 0, 0);\\n }\\n\\n (supplyExchangePrice_, borrowExchangePrice_) = CalcsSimulatedTime.calcExchangePrices(\\n exchangePricesAndConfig_,\\n simulatedTimestamp_\\n );\\n\\n totalSupply_ = CalcsSimulatedTime.getTotalSupply(totalAmounts_, supplyExchangePrice_);\\n totalBorrow_ = CalcsSimulatedTime.getTotalBorrow(totalAmounts_, borrowExchangePrice_);\\n }\\n\\n /// @notice returns the `supply_` and `borrow_` for a user (protocol) at Liquidity at a certain point in time\\n /// given the stacked uint256 storage data for total amounts and exchange prices and config.\\n function calcLiquidityUserAmountsSimulatedTime(\\n uint256 userSupplyData_,\\n uint256 userBorrowData_,\\n uint256 liquiditySupplyExchangePricesAndConfig_,\\n uint256 liquidityBorrowExchangePricesAndConfig_,\\n uint256 simulatedTimestamp_\\n )\\n public\\n pure\\n returns (uint256 supply_, uint256 borrow_, uint256 supplyExchangePrice_, uint256 borrowExchangePrice_)\\n {\\n if (liquiditySupplyExchangePricesAndConfig_ == 0 || liquidityBorrowExchangePricesAndConfig_ == 0) {\\n // token is not configured at Liquidity -> amounts are 0\\n return (0, 0, 0, 0);\\n }\\n\\n (supplyExchangePrice_, ) = CalcsSimulatedTime.calcExchangePrices(\\n liquiditySupplyExchangePricesAndConfig_,\\n simulatedTimestamp_\\n );\\n\\n (, borrowExchangePrice_) = CalcsSimulatedTime.calcExchangePrices(\\n liquidityBorrowExchangePricesAndConfig_,\\n simulatedTimestamp_\\n );\\n\\n if (userSupplyData_ > 0) {\\n // if userSupplyData_ == 0 -> user not configured yet for token at Liquidity\\n\\n bool modeWithInterest_ = userSupplyData_ & 1 == 1;\\n supply_ = BigMathMinified.fromBigNumber(\\n (userSupplyData_ >> LiquiditySlotsLink.BITS_USER_SUPPLY_AMOUNT) & X64,\\n DEFAULT_EXPONENT_SIZE,\\n DEFAULT_EXPONENT_MASK\\n );\\n\\n if (modeWithInterest_) {\\n // convert raw amounts to normal for withInterest mode\\n supply_ = (supply_ * supplyExchangePrice_) / 1e12;\\n }\\n }\\n\\n if (userBorrowData_ > 0) {\\n // if userBorrowData_ == 0 -> user not configured yet for token at Liquidity\\n\\n bool modeWithInterest_ = userBorrowData_ & 1 == 1;\\n borrow_ = BigMathMinified.fromBigNumber(\\n (userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_AMOUNT) & X64,\\n DEFAULT_EXPONENT_SIZE,\\n DEFAULT_EXPONENT_MASK\\n );\\n\\n if (modeWithInterest_) {\\n // convert raw amounts to normal for withInterest mode\\n borrow_ = (borrow_ * borrowExchangePrice_) / 1e12;\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x6eda039c3d8ad31088623a7f34ab2106e6df855a5ffd42a666b1851a588cbc50\",\"license\":\"BUSL-1.1\"}},\"version\":1}", "bytecode": "0x60a060405234801561001057600080fd5b5060405161152238038061152283398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b6080516114676100bb6000396000818160ee015281816102a20152818161044c01528181610573015281816105ed0152818161062a01528181610719015261084f01526114676000f3fe608060405234801561001057600080fd5b50600436106100be5760003560e01c806380f971cc11610076578063ab8921751161005b578063ab892175146101be578063f3bd3c89146101d3578063f7fdd139146101e657600080fd5b806380f971cc1461018357806385b67095146101ab57600080fd5b8063318a5b80116100a7578063318a5b801461013557806334a2e659146101685780636bc6f5801461017057600080fd5b80631170e219146100c35780632861c7d1146100e9575b600080fd5b6100d66100d1366004611156565b6101f9565b6040519081526020015b60405180910390f35b6101107f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100e0565b610148610143366004611156565b610220565b6040805194855260208501939093529183015260608201526080016100e0565b610110610270565b61014861017e366004611182565b610327565b6101966101913660046111bd565b61041b565b604080519283526020830191909152016100e0565b6100d66101b93660046111df565b610447565b6101c66106e4565b6040516100e09190611215565b6101486101e1366004611182565b6109a4565b6100d66101f436600461127a565b6109ea565b60008260000361020b57506000610219565b610216848484610a13565b90505b9392505050565b6000806000808560000361023f57506000925082915081905080610267565b6102498686610a7c565b90925090506102588783610cd6565b93506102648782610d21565b92505b93509350935093565b6040517fb5c736e4000000000000000000000000000000000000000000000000000000008152600060048201819052907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063b5c736e490602401602060405180830381865afa1580156102fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061032291906112ac565b905090565b6000808080861580610337575085155b1561034d5750600092508291508190508061040f565b6103578786610a7c565b5091506103648686610a7c565b91505088156103bb576001808a16811490610394908b901c67ffffffffffffffff16600860ff9082901c91161b90565b945080156103b95764e8d4a510006103ac84876112f4565b6103b6919061133a565b94505b505b871561040f5760018089168114906103e8908a901c67ffffffffffffffff16600860ff9082901c91161b90565b9350801561040d5764e8d4a5100061040083866112f4565b61040a919061133a565b93505b505b95509550955095915050565b6000808360000361043157506000905080610440565b61043b8484610a7c565b915091505b9250929050565b6000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663b5c736e4610491600586610d5b565b6040518263ffffffff1660e01b81526004016104af91815260200190565b602060405180830381865afa1580156104cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104f091906112ac565b9050806000036105035750600092915050565b600073ffffffffffffffffffffffffffffffffffffffff841673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee146105eb576040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301528516906370a0823190602401602060405180830381865afa1580156105c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e691906112ac565b610624565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16315b905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663b5c736e461066f600788610d5b565b6040518263ffffffff1660e01b815260040161068d91815260200190565b602060405180830381865afa1580156106aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106ce91906112ac565b90506106db818484610a13565b95945050505050565b6040517fb5c736e4000000000000000000000000000000000000000000000000000000008152600a60048201526060906000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063b5c736e490602401602060405180830381865afa158015610775573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061079991906112ac565b90508067ffffffffffffffff8111156107b4576107b4611375565b6040519080825280602002602001820160405280156107f957816020015b60408051808201909152600080825260208201528152602001906001900390816107d25790505b5091506000600a60405160200161081291815260200190565b6040516020818303038152906040528051906020012060001c905060005b8281101561099e5773ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001663b5c736e461087e83856113a4565b60405160e083901b7fffffffff000000000000000000000000000000000000000000000000000000001681526004810191909152602401602060405180830381865afa1580156108d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f691906112ac565b848281518110610908576109086113b7565b60200260200101516000019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505061096c84828151811061095b5761095b6113b7565b602002602001015160000151610447565b84828151811061097e5761097e6113b7565b602090810291909101810151015280610996816113e6565b915050610830565b50505090565b60008080808615806109b4575085155b156109ca5750600092508291508190508061040f565b6109d78989898989610da6565b929c919b50995090975095505050505050565b6000836000036109fc57506000610a0b565b610a0885858585610edd565b90505b949350505050565b6000806000610a2185610f48565b915091506000610a318784610cd6565b90508015610a6e57610a438783610d21565b610a4d90866113a4565b9350808411610a5d576000610a67565b610a67818561141e565b9350610a72565b8493505b5050509392505050565b67ffffffffffffffff605b83901c811690609b84901c16811580610a9e575080155b15610adf576040517fb838681e0000000000000000000000000000000000000000000000000000000081526201117160048201526024015b60405180910390fd5b61ffff8416603a85901c6401ffffffff16841015610b29576040517faba77fab00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603a85901c6401ffffffff168085039060ea87901c617fff1690861480610b4e575082155b80610b595750806001145b15610b6657505050610440565b64496cebb80084840283020484019350617fff60db88901c16925082600103610b9157505050610440565b82600116600103610be65760019290921c91826c7e37be2022c0914b268000000081610bbf57610bbf61130b565b049250612710601e88901c613fff166b033b2e3c9fd0803ce8000000850102049250610c13565b60019290921c916305f5e100601e88901c613fff166127108501026b033b2e3c9fd0803ce8000000020492505b80600116600103610c4a5760011c61271081016b033b2e3c9fd0803ce8000000820281610c4257610c4261130b565b049050610c80565b60011c61271081016b033b2e3c9fd0803ce8000000820281610c6e57610c6e61130b565b046b033b2e3c9fd0803ce80000000390505b760a70c3c40a64e6c51999090b65f67d92400000000000008382026127100261ffff891691900402601088901c613fff16612710030292506801b5a660ea44b80000858402830204850194505050509250929050565b66ffffffffffffff604883901c811660ff604085901c81169190911b91600885901c169084161b64e8d4a51000610d0d84836112f4565b610d17919061133a565b610a0b90836113a4565b60c882901c60ff60c084901c81169190911b9066ffffffffffffff608885901c16608085901c9091161b64e8d4a51000610d0d84836112f4565b6040805173ffffffffffffffffffffffffffffffffffffffff831660208201529081018390526000906060016040516020818303038152906040528051906020012090505b92915050565b600080600080610db68786610a7c565b509350610dc38686610a7c565b93505067ffffffffffffffff8881169060408a901c1681861080610de657508085105b15610e1d576040517fea77fd6f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61271061ffff8c16670de0b6b3a76400008489670de0b6b3a76400000281610e4757610e4761130b565b04030281610e5757610e5761130b565b04935061271061ffff60108d901c16670de0b6b3a76400008388670de0b6b3a76400000281610e8857610e8861130b565b04030281610e9857610e9861130b565b049250670de0b6b3a764000060808b901c67ffffffffffffffff1685820102049350670de0b6b3a764000060c08b901c84820102049250505095509550955095915050565b6000806000610eec8685610a7c565b915091506000610efc8884610cd6565b90508015610f3957610f0e8883610d21565b610f1890876113a4565b9350808411610f28576000610f32565b610f32818561141e565b9350610f3d565b8593505b505050949350505050565b67ffffffffffffffff605b82901c811690609b83901c16811580610f6a575080155b15610fa6576040517fd50d7512000000000000000000000000000000000000000000000000000000008152620111716004820152602401610ad6565b61ffff8316603a84901c6401ffffffff16428181039160ea87901c617fff16911480610fd0575082155b80610fdb5750806001145b15610fe857505050915091565b64496cebb80084840283020484019350617fff60db87901c1692508260010361101357505050915091565b826001166001036110685760019290921c91826c7e37be2022c0914b2680000000816110415761104161130b565b049250612710601e87901c613fff166b033b2e3c9fd0803ce8000000850102049250611095565b60019290921c916305f5e100601e87901c613fff166127108501026b033b2e3c9fd0803ce8000000020492505b806001166001036110cc5760011c61271081016b033b2e3c9fd0803ce80000008202816110c4576110c461130b565b049050611102565b60011c61271081016b033b2e3c9fd0803ce80000008202816110f0576110f061130b565b046b033b2e3c9fd0803ce80000000390505b760a70c3c40a64e6c51999090b65f67d92400000000000008382026127100261ffff881691900402601087901c613fff16612710030292506801b5a660ea44b8000085840283020485019450505050915091565b60008060006060848603121561116b57600080fd5b505081359360208301359350604090920135919050565b600080600080600060a0868803121561119a57600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b600080604083850312156111d057600080fd5b50508035926020909101359150565b6000602082840312156111f157600080fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461021957600080fd5b602080825282518282018190526000919060409081850190868401855b8281101561126d578151805173ffffffffffffffffffffffffffffffffffffffff168552860151868501529284019290850190600101611232565b5091979650505050505050565b6000806000806080858703121561129057600080fd5b5050823594602084013594506040840135936060013592509050565b6000602082840312156112be57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082028115828204841417610da057610da06112c5565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082611370577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b80820180821115610da057610da06112c5565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611417576114176112c5565b5060010190565b81810381811115610da057610da06112c556fea2646970667358221220fdcdad644e5fc82687901bb9deff5f23ab1d4bbf2cbb669082942a15c8ec226964736f6c63430008150033", "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100be5760003560e01c806380f971cc11610076578063ab8921751161005b578063ab892175146101be578063f3bd3c89146101d3578063f7fdd139146101e657600080fd5b806380f971cc1461018357806385b67095146101ab57600080fd5b8063318a5b80116100a7578063318a5b801461013557806334a2e659146101685780636bc6f5801461017057600080fd5b80631170e219146100c35780632861c7d1146100e9575b600080fd5b6100d66100d1366004611156565b6101f9565b6040519081526020015b60405180910390f35b6101107f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100e0565b610148610143366004611156565b610220565b6040805194855260208501939093529183015260608201526080016100e0565b610110610270565b61014861017e366004611182565b610327565b6101966101913660046111bd565b61041b565b604080519283526020830191909152016100e0565b6100d66101b93660046111df565b610447565b6101c66106e4565b6040516100e09190611215565b6101486101e1366004611182565b6109a4565b6100d66101f436600461127a565b6109ea565b60008260000361020b57506000610219565b610216848484610a13565b90505b9392505050565b6000806000808560000361023f57506000925082915081905080610267565b6102498686610a7c565b90925090506102588783610cd6565b93506102648782610d21565b92505b93509350935093565b6040517fb5c736e4000000000000000000000000000000000000000000000000000000008152600060048201819052907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063b5c736e490602401602060405180830381865afa1580156102fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061032291906112ac565b905090565b6000808080861580610337575085155b1561034d5750600092508291508190508061040f565b6103578786610a7c565b5091506103648686610a7c565b91505088156103bb576001808a16811490610394908b901c67ffffffffffffffff16600860ff9082901c91161b90565b945080156103b95764e8d4a510006103ac84876112f4565b6103b6919061133a565b94505b505b871561040f5760018089168114906103e8908a901c67ffffffffffffffff16600860ff9082901c91161b90565b9350801561040d5764e8d4a5100061040083866112f4565b61040a919061133a565b93505b505b95509550955095915050565b6000808360000361043157506000905080610440565b61043b8484610a7c565b915091505b9250929050565b6000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663b5c736e4610491600586610d5b565b6040518263ffffffff1660e01b81526004016104af91815260200190565b602060405180830381865afa1580156104cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104f091906112ac565b9050806000036105035750600092915050565b600073ffffffffffffffffffffffffffffffffffffffff841673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee146105eb576040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301528516906370a0823190602401602060405180830381865afa1580156105c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e691906112ac565b610624565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16315b905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663b5c736e461066f600788610d5b565b6040518263ffffffff1660e01b815260040161068d91815260200190565b602060405180830381865afa1580156106aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106ce91906112ac565b90506106db818484610a13565b95945050505050565b6040517fb5c736e4000000000000000000000000000000000000000000000000000000008152600a60048201526060906000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063b5c736e490602401602060405180830381865afa158015610775573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061079991906112ac565b90508067ffffffffffffffff8111156107b4576107b4611375565b6040519080825280602002602001820160405280156107f957816020015b60408051808201909152600080825260208201528152602001906001900390816107d25790505b5091506000600a60405160200161081291815260200190565b6040516020818303038152906040528051906020012060001c905060005b8281101561099e5773ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001663b5c736e461087e83856113a4565b60405160e083901b7fffffffff000000000000000000000000000000000000000000000000000000001681526004810191909152602401602060405180830381865afa1580156108d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f691906112ac565b848281518110610908576109086113b7565b60200260200101516000019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505061096c84828151811061095b5761095b6113b7565b602002602001015160000151610447565b84828151811061097e5761097e6113b7565b602090810291909101810151015280610996816113e6565b915050610830565b50505090565b60008080808615806109b4575085155b156109ca5750600092508291508190508061040f565b6109d78989898989610da6565b929c919b50995090975095505050505050565b6000836000036109fc57506000610a0b565b610a0885858585610edd565b90505b949350505050565b6000806000610a2185610f48565b915091506000610a318784610cd6565b90508015610a6e57610a438783610d21565b610a4d90866113a4565b9350808411610a5d576000610a67565b610a67818561141e565b9350610a72565b8493505b5050509392505050565b67ffffffffffffffff605b83901c811690609b84901c16811580610a9e575080155b15610adf576040517fb838681e0000000000000000000000000000000000000000000000000000000081526201117160048201526024015b60405180910390fd5b61ffff8416603a85901c6401ffffffff16841015610b29576040517faba77fab00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603a85901c6401ffffffff168085039060ea87901c617fff1690861480610b4e575082155b80610b595750806001145b15610b6657505050610440565b64496cebb80084840283020484019350617fff60db88901c16925082600103610b9157505050610440565b82600116600103610be65760019290921c91826c7e37be2022c0914b268000000081610bbf57610bbf61130b565b049250612710601e88901c613fff166b033b2e3c9fd0803ce8000000850102049250610c13565b60019290921c916305f5e100601e88901c613fff166127108501026b033b2e3c9fd0803ce8000000020492505b80600116600103610c4a5760011c61271081016b033b2e3c9fd0803ce8000000820281610c4257610c4261130b565b049050610c80565b60011c61271081016b033b2e3c9fd0803ce8000000820281610c6e57610c6e61130b565b046b033b2e3c9fd0803ce80000000390505b760a70c3c40a64e6c51999090b65f67d92400000000000008382026127100261ffff891691900402601088901c613fff16612710030292506801b5a660ea44b80000858402830204850194505050509250929050565b66ffffffffffffff604883901c811660ff604085901c81169190911b91600885901c169084161b64e8d4a51000610d0d84836112f4565b610d17919061133a565b610a0b90836113a4565b60c882901c60ff60c084901c81169190911b9066ffffffffffffff608885901c16608085901c9091161b64e8d4a51000610d0d84836112f4565b6040805173ffffffffffffffffffffffffffffffffffffffff831660208201529081018390526000906060016040516020818303038152906040528051906020012090505b92915050565b600080600080610db68786610a7c565b509350610dc38686610a7c565b93505067ffffffffffffffff8881169060408a901c1681861080610de657508085105b15610e1d576040517fea77fd6f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61271061ffff8c16670de0b6b3a76400008489670de0b6b3a76400000281610e4757610e4761130b565b04030281610e5757610e5761130b565b04935061271061ffff60108d901c16670de0b6b3a76400008388670de0b6b3a76400000281610e8857610e8861130b565b04030281610e9857610e9861130b565b049250670de0b6b3a764000060808b901c67ffffffffffffffff1685820102049350670de0b6b3a764000060c08b901c84820102049250505095509550955095915050565b6000806000610eec8685610a7c565b915091506000610efc8884610cd6565b90508015610f3957610f0e8883610d21565b610f1890876113a4565b9350808411610f28576000610f32565b610f32818561141e565b9350610f3d565b8593505b505050949350505050565b67ffffffffffffffff605b82901c811690609b83901c16811580610f6a575080155b15610fa6576040517fd50d7512000000000000000000000000000000000000000000000000000000008152620111716004820152602401610ad6565b61ffff8316603a84901c6401ffffffff16428181039160ea87901c617fff16911480610fd0575082155b80610fdb5750806001145b15610fe857505050915091565b64496cebb80084840283020484019350617fff60db87901c1692508260010361101357505050915091565b826001166001036110685760019290921c91826c7e37be2022c0914b2680000000816110415761104161130b565b049250612710601e87901c613fff166b033b2e3c9fd0803ce8000000850102049250611095565b60019290921c916305f5e100601e87901c613fff166127108501026b033b2e3c9fd0803ce8000000020492505b806001166001036110cc5760011c61271081016b033b2e3c9fd0803ce80000008202816110c4576110c461130b565b049050611102565b60011c61271081016b033b2e3c9fd0803ce80000008202816110f0576110f061130b565b046b033b2e3c9fd0803ce80000000390505b760a70c3c40a64e6c51999090b65f67d92400000000000008382026127100261ffff881691900402601087901c613fff16612710030292506801b5a660ea44b8000085840283020485019450505050915091565b60008060006060848603121561116b57600080fd5b505081359360208301359350604090920135919050565b600080600080600060a0868803121561119a57600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b600080604083850312156111d057600080fd5b50508035926020909101359150565b6000602082840312156111f157600080fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461021957600080fd5b602080825282518282018190526000919060409081850190868401855b8281101561126d578151805173ffffffffffffffffffffffffffffffffffffffff168552860151868501529284019290850190600101611232565b5091979650505050505050565b6000806000806080858703121561129057600080fd5b5050823594602084013594506040840135936060013592509050565b6000602082840312156112be57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082028115828204841417610da057610da06112c5565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082611370577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b80820180821115610da057610da06112c5565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611417576114176112c5565b5060010190565b81810381811115610da057610da06112c556fea2646970667358221220fdcdad644e5fc82687901bb9deff5f23ab1d4bbf2cbb669082942a15c8ec226964736f6c63430008150033", "devdoc": { "kind": "dev", "methods": { "calcLiquidityExchangePricesSimulatedTime(uint256,uint256)": { "params": { "exchangePricesAndConfig_": "exchange prices and config packed uint256 read from storage", "simulatedTimestamp_": "simulated block.timestamp" }, "returns": { "borrowExchangePrice_": "updated borrowExchangePrice", "supplyExchangePrice_": "updated supplyExchangePrice" } }, "calcRevenue(uint256,uint256,uint256)": { "details": "exposed for advanced revenue calculations", "params": { "exchangePricesAndConfig_": "exchange prices and config packed uint256 read from storage", "liquidityTokenBalance_": "current balance of Liquidity contract (IERC20(token_).balanceOf(address(this)))", "totalAmounts_": "total amounts packed uint256 read from storage" }, "returns": { "revenueAmount_": "collectable revenue amount" } }, "calcVaultExchangePricesSimulatedTime(uint256,uint256,uint256,uint256,uint256)": { "params": { "liquidityBorrowExchangePricesAndConfig_": "exchange prices and config packed uint256 read from storage for borrow token", "liquiditySupplyExchangePricesAndConfig_": "exchange prices and config packed uint256 read from storage for supply token", "simulatedTimestamp_": "simulated block.timestamp", "vaultRates_": "rates read from storage for the vault (VaultResolver.getVaultVariables2Raw)", "vaultVariables2_": "vaultVariables2 read from storage for the vault (VaultResolver.getRateRaw)" }, "returns": { "liqBorrowExPrice_": "latest liquidity's borrow token borrow exchange price", "liqSupplyExPrice_": "latest liquidity's supply token supply exchange price", "vaultBorrowExPrice_": "latest vault's borrow token exchange price", "vaultSupplyExPrice_": "latest vault's supply token exchange price" } } }, "stateVariables": { "_NATIVE_TOKEN_ADDRESS": { "details": "address that is mapped to the chain native token" } }, "version": 1 }, "userdoc": { "kind": "user", "methods": { "LIQUIDITY()": { "notice": "address of the liquidity contract" }, "calcLiquidityExchangePricesSimulatedTime(uint256,uint256)": { "notice": "calculates interest (exchange prices) at Liquidity for a token given its' exchangePricesAndConfig from storage for a simulated `block.timestamp` set via `simulatedTimestamp_`." }, "calcLiquidityTotalAmountsSimulatedTime(uint256,uint256,uint256)": { "notice": "returns the `totalSupply_` and `totalBorrow_` at Liquidity at a certain point in time given the stacked uint256 storage data for total amounts and exchange prices and config." }, "calcLiquidityUserAmountsSimulatedTime(uint256,uint256,uint256,uint256,uint256)": { "notice": "returns the `supply_` and `borrow_` for a user (protocol) at Liquidity at a certain point in time given the stacked uint256 storage data for total amounts and exchange prices and config." }, "calcRevenue(uint256,uint256,uint256)": { "notice": "gets the `revenueAmount_` for a token given its' totalAmounts and exchangePricesAndConfig from stacked uint256 storage slots and the balance of the Fluid liquidity contract for the token." }, "calcRevenueSimulatedTime(uint256,uint256,uint256,uint256)": { "notice": "same as `calcRevenue`, but for a simulated `block.timestamp` set via `simulatedTimestamp_`." }, "calcVaultExchangePricesSimulatedTime(uint256,uint256,uint256,uint256,uint256)": { "notice": "Calculates new vault exchange prices based on storage data for a simulated `block.timestamp` set via `simulatedTimestamp_`." }, "getRevenue(address)": { "notice": "gets the currently uncollected `revenueAmount_` for a `token_`." }, "getRevenueCollector()": { "notice": "address of contract that gets sent the revenue. Configurable by governance" }, "getRevenues()": { "notice": "gets the currently uncollected revenues for all listed tokens at Liquidity" } }, "notice": "Fluid Revenue resolver", "version": 1 }, "storageLayout": { "storage": [], "types": null } }