ETH Price: $2,033.53 (+0.55%)

Contract

0xB5af15a931dA1B1a7B8DCF6E2Cd31C8a3Dd1E134
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Rebalance207856612024-09-19 15:53:23536 days ago1726761203IN
Fluid: Buffer Rate Handler WSTETH - ETH
0 ETH0.001499117.87182664
Rebalance207685822024-09-17 6:37:11539 days ago1726555031IN
Fluid: Buffer Rate Handler WSTETH - ETH
0 ETH0.000168982.01459797
Rebalance207664332024-09-16 23:23:11539 days ago1726528991IN
Fluid: Buffer Rate Handler WSTETH - ETH
0 ETH0.000170542.03322814
Rebalance207596962024-09-16 0:46:35540 days ago1726447595IN
Fluid: Buffer Rate Handler WSTETH - ETH
0 ETH0.000110841.32801547
Rebalance207391902024-09-13 4:05:11543 days ago1726200311IN
Fluid: Buffer Rate Handler WSTETH - ETH
0 ETH0.000096481.15022197
Rebalance207157602024-09-09 21:32:23546 days ago1725917543IN
Fluid: Buffer Rate Handler WSTETH - ETH
0 ETH0.000311843.71765407
Rebalance207152822024-09-09 19:56:11546 days ago1725911771IN
Fluid: Buffer Rate Handler WSTETH - ETH
0 ETH0.000529556.31396524
Rebalance207135762024-09-09 14:13:23546 days ago1725891203IN
Fluid: Buffer Rate Handler WSTETH - ETH
0 ETH0.000769289.1711236
Rebalance207072672024-09-08 17:04:23547 days ago1725815063IN
Fluid: Buffer Rate Handler WSTETH - ETH
0 ETH0.000122721.4630548
Rebalance206983082024-09-07 11:05:11549 days ago1725707111IN
Fluid: Buffer Rate Handler WSTETH - ETH
0 ETH0.0001261.50217063
Rebalance206980792024-09-07 10:19:23549 days ago1725704363IN
Fluid: Buffer Rate Handler WSTETH - ETH
0 ETH0.000131191.56420198
Rebalance206941192024-09-06 21:04:11549 days ago1725656651IN
Fluid: Buffer Rate Handler WSTETH - ETH
0 ETH0.0015115718.02050234
Rebalance206936852024-09-06 19:37:23549 days ago1725651443IN
Fluid: Buffer Rate Handler WSTETH - ETH
0 ETH0.000298383.55721021
Rebalance206828722024-09-05 7:24:11551 days ago1725521051IN
Fluid: Buffer Rate Handler WSTETH - ETH
0 ETH0.000210282.50726628
Rebalance206827242024-09-05 6:54:11551 days ago1725519251IN
Fluid: Buffer Rate Handler WSTETH - ETH
0 ETH0.000174312.07810336
Rebalance206788912024-09-04 18:04:11551 days ago1725473051IN
Fluid: Buffer Rate Handler WSTETH - ETH
0 ETH0.000289213.44795483

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Method Block
From
To
0x6101c060206118422024-08-26 9:22:59561 days ago1724664179  Contract Creation0 ETH
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
FluidBufferRateHandler

Compiler Version
v0.8.21+commit.d9974bed

Optimization Enabled:
Yes with 10000000 runs

Other Settings:
paris EvmVersion
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.21;

import { IFluidLiquidity } from "../../liquidity/interfaces/iLiquidity.sol";
import { LiquiditySlotsLink } from "../../libraries/liquiditySlotsLink.sol";
import { IFluidReserveContract } from "../../reserve/interfaces/iReserveContract.sol";
import { Error } from "../error.sol";
import { ErrorTypes } from "../errorTypes.sol";
import { FluidConfigHandler } from "../fluidConfigHandler.sol";

import { BigMathMinified } from "../../libraries/bigMathMinified.sol";
import { Structs as AdminModuleStructs } from "../../liquidity/adminModule/structs.sol";

abstract contract Constants {
    IFluidReserveContract public immutable RESERVE_CONTRACT;
    IFluidLiquidity public immutable LIQUIDITY;

    /// @notice supply token at Liquidity which borrow rate is based on
    address public immutable SUPPLY_TOKEN;
    /// @notice borrow token at Liquidity for which the borrow rate is managed
    address public immutable BORROW_TOKEN;

    /// @notice buffer at kink1 for the rate. borrow rate = supply rate + buffer. In percent (100 = 1%, 1 = 0.01%)
    int256 public immutable RATE_BUFFER_KINK1;
    /// @notice buffer at kink2 for the rate. borrow rate = supply rate + buffer. In percent (100 = 1%, 1 = 0.01%)
    /// @dev only used if CURRENT borrow rate mode at Liquidity is V2 (with 2 kinks).
    int256 public immutable RATE_BUFFER_KINK2;

    /// @dev minimum percent difference to trigger an update. In percent (100 = 1%, 1 = 0.01%)
    uint256 public immutable MIN_UPDATE_DIFF;

    bytes32 internal immutable _LIQUDITY_SUPPLY_TOTAL_AMOUNTS_SLOT;
    bytes32 internal immutable _LIQUDITY_SUPPLY_EXCHANGE_PRICES_AND_CONFIG_SLOT;

    bytes32 internal immutable _LIQUDITY_BORROW_RATE_DATA_SLOT;

    uint256 internal constant EXCHANGE_PRICES_PRECISION = 1e12;

    uint256 internal constant DEFAULT_EXPONENT_SIZE = 8;
    uint256 internal constant DEFAULT_EXPONENT_MASK = 0xff;

    uint256 internal constant X14 = 0x3fff;
    uint256 internal constant X16 = 0xffff;
    uint256 internal constant X64 = 0xffffffffffffffff;
    uint256 internal constant FOUR_DECIMALS = 10000;
}

abstract contract Events {
    /// @notice emitted when borrow rate for `BORROW_TOKEN` is updated based on
    ///          supply rate of `SUPPLY_TOKEN` + buffer.
    event LogUpdateRate(
        uint256 supplyRate,
        uint256 oldRateKink1,
        uint256 newRateKink1,
        uint256 oldRateKink2,
        uint256 newRateKink2
    );
}

/// @notice Sets borrow rate for `BORROW_TOKEN` at Liquidaty based on supply rate of `SUPPLY_TOKEN` + buffer.
contract FluidBufferRateHandler is Constants, Error, Events, FluidConfigHandler {
    /// @dev Validates that an address is not the zero address
    modifier validAddress(address value_) {
        if (value_ == address(0)) {
            revert FluidConfigError(ErrorTypes.BufferRateConfigHandler__AddressZero);
        }
        _;
    }

    /// @dev Validates that an address is a rebalancer (taken from reserve contract)
    modifier onlyRebalancer() {
        if (!RESERVE_CONTRACT.isRebalancer(msg.sender)) {
            revert FluidConfigError(ErrorTypes.BufferRateConfigHandler__Unauthorized);
        }
        _;
    }

    constructor(
        IFluidReserveContract reserveContract_,
        IFluidLiquidity liquidity_,
        address supplyToken_,
        address borrowToken_,
        int256 rateBufferKink1_,
        int256 rateBufferKink2_,
        uint256 minUpdateDiff_
    )
        validAddress(address(reserveContract_))
        validAddress(address(liquidity_))
        validAddress(supplyToken_)
        validAddress(borrowToken_)
    {
        if (
            minUpdateDiff_ == 0 ||
            // rate buffer should be within +100% to - 100%
            rateBufferKink1_ > 1e4 ||
            rateBufferKink1_ < -int256(1e4) ||
            rateBufferKink2_ > 1e4 ||
            rateBufferKink2_ < -int256(1e4)
        ) {
            revert FluidConfigError(ErrorTypes.BufferRateConfigHandler__InvalidParams);
        }

        RESERVE_CONTRACT = reserveContract_;
        LIQUIDITY = liquidity_;
        SUPPLY_TOKEN = supplyToken_;
        BORROW_TOKEN = borrowToken_;
        MIN_UPDATE_DIFF = minUpdateDiff_;

        RATE_BUFFER_KINK1 = rateBufferKink1_;
        RATE_BUFFER_KINK2 = rateBufferKink2_;

        _LIQUDITY_SUPPLY_TOTAL_AMOUNTS_SLOT = LiquiditySlotsLink.calculateMappingStorageSlot(
            LiquiditySlotsLink.LIQUIDITY_TOTAL_AMOUNTS_MAPPING_SLOT,
            supplyToken_
        );
        _LIQUDITY_SUPPLY_EXCHANGE_PRICES_AND_CONFIG_SLOT = LiquiditySlotsLink.calculateMappingStorageSlot(
            LiquiditySlotsLink.LIQUIDITY_EXCHANGE_PRICES_MAPPING_SLOT,
            supplyToken_
        );

        _LIQUDITY_BORROW_RATE_DATA_SLOT = LiquiditySlotsLink.calculateMappingStorageSlot(
            LiquiditySlotsLink.LIQUIDITY_RATE_DATA_MAPPING_SLOT,
            borrowToken_
        );
    }

    /// @inheritdoc FluidConfigHandler
    function configPercentDiff() public view override returns (uint256 configPercentDiff_) {
        uint256 rateConfig_ = LIQUIDITY.readFromStorage(_LIQUDITY_BORROW_RATE_DATA_SLOT);

        (uint256 newRateKink1_, uint256 newRateKink2_) = _calcBorrowRates(supplyTokenLendingRate(), rateConfig_);

        uint256 rateVersion_ = rateConfig_ & 0xF;
        if (rateVersion_ == 1) {
            uint256 oldRateKink1_ = (rateConfig_ >> LiquiditySlotsLink.BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_KINK) &
                X16;
            configPercentDiff_ = _percentDiffForValue(oldRateKink1_, newRateKink1_);
        } else if (rateVersion_ == 2) {
            uint256 oldRateKink1_ = (rateConfig_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_KINK1) &
                X16;
            uint256 oldRateKink2_ = (rateConfig_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_KINK2) &
                X16;

            configPercentDiff_ = _percentDiffForValue(oldRateKink1_, newRateKink1_);
            uint256 rateKink2Diff_ = _percentDiffForValue(oldRateKink2_, newRateKink2_);
            // final diff = biggest diff between all config values
            configPercentDiff_ = configPercentDiff_ > rateKink2Diff_ ? configPercentDiff_ : rateKink2Diff_;
        } else {
            revert FluidConfigError(ErrorTypes.BufferRateConfigHandler__RateVersionUnsupported);
        }
    }

    /// @inheritdoc FluidConfigHandler
    function rebalance() external override onlyRebalancer {
        uint256 supplyLendingRate_ = supplyTokenLendingRate();
        uint256 rateConfig_ = LIQUIDITY.readFromStorage(_LIQUDITY_BORROW_RATE_DATA_SLOT);

        uint256 rateVersion_ = rateConfig_ & 0xF;
        if (rateVersion_ == 1) {
            _rebalanceRateV1(supplyLendingRate_, rateConfig_);
        } else if (rateVersion_ == 2) {
            _rebalanceRateV2(supplyLendingRate_, rateConfig_);
        } else {
            revert FluidConfigError(ErrorTypes.BufferRateConfigHandler__RateVersionUnsupported);
        }
    }

    /// @notice returns the current calculcated borrow rates at kink1 and kink 2 (for rate data v2).
    function calcBorrowRates() public view returns (uint256 rateKink1_, uint256 rateKink2_) {
        return _calcBorrowRates(supplyTokenLendingRate(), LIQUIDITY.readFromStorage(_LIQUDITY_BORROW_RATE_DATA_SLOT));
    }

    /// @notice  get current `SUPPLY_TOKEN` lending `rate_` at Liquidity
    function supplyTokenLendingRate() public view returns (uint256 rate_) {
        // @dev logic here based on Liquidity Resolver .getOverallTokenData()
        uint256 totalAmounts_ = LIQUIDITY.readFromStorage(_LIQUDITY_SUPPLY_TOTAL_AMOUNTS_SLOT);

        // Extract supply & borrow amounts
        uint256 supplyRawInterest_ = totalAmounts_ & X64;
        supplyRawInterest_ =
            (supplyRawInterest_ >> DEFAULT_EXPONENT_SIZE) <<
            (supplyRawInterest_ & DEFAULT_EXPONENT_MASK);

        uint256 borrowRawInterest_ = (totalAmounts_ >> LiquiditySlotsLink.BITS_TOTAL_AMOUNTS_BORROW_WITH_INTEREST) &
            X64;
        borrowRawInterest_ =
            (borrowRawInterest_ >> DEFAULT_EXPONENT_SIZE) <<
            (borrowRawInterest_ & DEFAULT_EXPONENT_MASK);

        if (supplyRawInterest_ > 0) {
            uint256 exchangePriceAndConfig_ = LIQUIDITY.readFromStorage(
                _LIQUDITY_SUPPLY_EXCHANGE_PRICES_AND_CONFIG_SLOT
            );

            // use old exchange prices for supply rate to be at same level as borrow rate from storage.
            // Note the rate here can be a tiny bit with higher precision because we use borrowWithInterest_ / supplyWithInterest_
            // which has higher precision than the utilization used from storage in LiquidityCalcs
            uint256 supplyWithInterest_ = (supplyRawInterest_ *
                ((exchangePriceAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_SUPPLY_EXCHANGE_PRICE) & X64)) /
                EXCHANGE_PRICES_PRECISION; // normalized from raw
            uint256 borrowWithInterest_ = (borrowRawInterest_ *
                ((exchangePriceAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_BORROW_EXCHANGE_PRICE) & X64)) /
                EXCHANGE_PRICES_PRECISION; // normalized from raw

            uint256 borrowRate_ = exchangePriceAndConfig_ & X16;
            uint256 fee_ = (exchangePriceAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_FEE) & X14;

            rate_ =
                (borrowRate_ * (FOUR_DECIMALS - fee_) * borrowWithInterest_) /
                (supplyWithInterest_ * FOUR_DECIMALS);
        }
    }

    /// @dev calculates current borrow rates at kinks for supply rate and current rate data
    function _calcBorrowRates(
        uint256 supplyRate_,
        uint256 rateConfig_
    ) internal view returns (uint256 rateKink1_, uint256 rateKink2_) {
        // rate can never be <0, > X16.
        rateKink1_ = (int256(supplyRate_) + RATE_BUFFER_KINK1) > 0
            ? uint256((int256(supplyRate_) + RATE_BUFFER_KINK1))
            : 0;
        // rate can never be > X16
        rateKink1_ = rateKink1_ > X16 ? X16 : rateKink1_;
        if ((rateConfig_ & 0xF) == 1) {
            // v1: only 1 kink
            // rate at last kink must always be <= rate at 100% utilization
            uint256 rateAtUtilizationMax_ = (rateConfig_ >>
                LiquiditySlotsLink.BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_MAX) & X16;
            if (rateKink1_ > rateAtUtilizationMax_) {
                rateKink1_ = rateAtUtilizationMax_;
            }
        } else {
            // v2: 2 kinks
            // rate can never be <0, > X16.
            rateKink2_ = (int256(supplyRate_) + RATE_BUFFER_KINK2) > 0
                ? uint256(int256(supplyRate_) + RATE_BUFFER_KINK2)
                : 0;
            // rate can never be > X16
            rateKink2_ = rateKink2_ > X16 ? X16 : rateKink2_;
            // rate at kink must always be <= rate at 100% utilization
            uint256 rateAtUtilizationMax_ = (rateConfig_ >>
                LiquiditySlotsLink.BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_MAX) & X16;
            if (rateKink1_ > rateAtUtilizationMax_) {
                rateKink1_ = rateAtUtilizationMax_;
            }
            if (rateKink2_ > rateAtUtilizationMax_) {
                rateKink2_ = rateAtUtilizationMax_;
            }
        }
    }

    /// @dev gets the percentage difference between `oldValue_` and `newValue_` in relation to `oldValue_`
    function _percentDiffForValue(
        uint256 oldValue_,
        uint256 newValue_
    ) internal pure returns (uint256 configPercentDiff_) {
        if (oldValue_ == newValue_) {
            return 0;
        }

        if (oldValue_ > newValue_) {
            // % of how much new value would be smaller
            configPercentDiff_ = oldValue_ - newValue_;
            // e.g. 10 - 8 = 2. 2 * 10000 / 10 -> 2000 (20%)
        } else {
            // % of how much new value would be bigger
            configPercentDiff_ = newValue_ - oldValue_;
            // e.g. 10 - 8 = 2. 2 * 10000 / 8 -> 2500 (25%)
        }

        configPercentDiff_ = (configPercentDiff_ * 1e4) / oldValue_;
    }

    /// @dev rebalances for a RateV1 config
    function _rebalanceRateV1(uint256 supplyRate_, uint256 rateConfig_) internal {
        AdminModuleStructs.RateDataV1Params memory rateData_;

        uint256 oldRateKink1_ = (rateConfig_ >> LiquiditySlotsLink.BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_KINK) & X16;
        (rateData_.rateAtUtilizationKink, ) = _calcBorrowRates(supplyRate_, rateConfig_);

        // check if diff is enough to trigger update
        if (_percentDiffForValue(oldRateKink1_, rateData_.rateAtUtilizationKink) < MIN_UPDATE_DIFF) {
            revert FluidConfigError(ErrorTypes.BufferRateConfigHandler__NoUpdate);
        }

        rateData_.token = BORROW_TOKEN;
        // values that stay the same: kink, rate at 0%, rate at 100%
        rateData_.rateAtUtilizationZero =
            (rateConfig_ >> LiquiditySlotsLink.BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_ZERO) &
            X16;
        rateData_.kink = (rateConfig_ >> LiquiditySlotsLink.BITS_RATE_DATA_V1_UTILIZATION_AT_KINK) & X16;
        rateData_.rateAtUtilizationMax =
            (rateConfig_ >> LiquiditySlotsLink.BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_MAX) &
            X16;

        // trigger update
        AdminModuleStructs.RateDataV1Params[] memory params_ = new AdminModuleStructs.RateDataV1Params[](1);
        params_[0] = rateData_;
        LIQUIDITY.updateRateDataV1s(params_);

        // emit event
        emit LogUpdateRate(supplyRate_, oldRateKink1_, rateData_.rateAtUtilizationKink, 0, 0);
    }

    /// @dev rebalances for a RateV2 config
    function _rebalanceRateV2(uint256 supplyRate_, uint256 rateConfig_) internal {
        AdminModuleStructs.RateDataV2Params memory rateData_;

        uint256 oldRateKink1_ = (rateConfig_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_KINK1) & X16;
        uint256 oldRateKink2_ = (rateConfig_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_KINK2) & X16;
        (rateData_.rateAtUtilizationKink1, rateData_.rateAtUtilizationKink2) = _calcBorrowRates(
            supplyRate_,
            rateConfig_
        );

        // check if diff is enough to trigger update
        if (
            _percentDiffForValue(oldRateKink1_, rateData_.rateAtUtilizationKink1) < MIN_UPDATE_DIFF &&
            _percentDiffForValue(oldRateKink2_, rateData_.rateAtUtilizationKink2) < MIN_UPDATE_DIFF
        ) {
            revert FluidConfigError(ErrorTypes.BufferRateConfigHandler__NoUpdate);
        }

        rateData_.token = BORROW_TOKEN;
        // values that stay the same: kink1, kink2, rate at 0%, rate at 100%
        rateData_.rateAtUtilizationZero =
            (rateConfig_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_ZERO) &
            X16;
        rateData_.kink1 = (rateConfig_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_UTILIZATION_AT_KINK1) & X16;
        rateData_.kink2 = (rateConfig_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_UTILIZATION_AT_KINK2) & X16;
        rateData_.rateAtUtilizationMax =
            (rateConfig_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_MAX) &
            X16;

        // trigger update
        AdminModuleStructs.RateDataV2Params[] memory params_ = new AdminModuleStructs.RateDataV2Params[](1);
        params_[0] = rateData_;
        LIQUIDITY.updateRateDataV2s(params_);

        // emit event
        emit LogUpdateRate(
            supplyRate_,
            oldRateKink1_,
            rateData_.rateAtUtilizationKink1,
            oldRateKink2_,
            rateData_.rateAtUtilizationKink2
        );
    }
}

File 2 of 11 : error.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.21;

contract Error {
    error FluidConfigError(uint256 errorId_);
}

File 3 of 11 : errorTypes.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.21;

library ErrorTypes {
    /***********************************|
    |    ExpandPercentConfigHandler     | 
    |__________________________________*/

    /// @notice thrown when an input address is zero
    uint256 internal constant ExpandPercentConfigHandler__AddressZero = 100001;

    /// @notice thrown when an unauthorized `msg.sender` calls a protected method
    uint256 internal constant ExpandPercentConfigHandler__Unauthorized = 100002;

    /// @notice thrown when invalid params are passed into a method
    uint256 internal constant ExpandPercentConfigHandler__InvalidParams = 100003;

    /// @notice thrown when no update is currently needed
    uint256 internal constant ExpandPercentConfigHandler__NoUpdate = 100004;

    /// @notice thrown when slot is not used, e.g. when borrow token is 0 there is no borrow data
    uint256 internal constant ExpandPercentConfigHandler__SlotDoesNotExist = 100005;

    /***********************************|
    |      EthenaRateConfigHandler      | 
    |__________________________________*/

    /// @notice thrown when an input address is zero
    uint256 internal constant EthenaRateConfigHandler__AddressZero = 100011;

    /// @notice thrown when an unauthorized `msg.sender` calls a protected method
    uint256 internal constant EthenaRateConfigHandler__Unauthorized = 100012;

    /// @notice thrown when invalid params are passed into a method
    uint256 internal constant EthenaRateConfigHandler__InvalidParams = 100013;

    /// @notice thrown when no update is currently needed
    uint256 internal constant EthenaRateConfigHandler__NoUpdate = 100014;

    /***********************************|
    |       MaxBorrowConfigHandler      | 
    |__________________________________*/

    /// @notice thrown when an input address is zero
    uint256 internal constant MaxBorrowConfigHandler__AddressZero = 100021;

    /// @notice thrown when an unauthorized `msg.sender` calls a protected method
    uint256 internal constant MaxBorrowConfigHandler__Unauthorized = 100022;

    /// @notice thrown when invalid params are passed into a method
    uint256 internal constant MaxBorrowConfigHandler__InvalidParams = 100023;

    /// @notice thrown when no update is currently needed
    uint256 internal constant MaxBorrowConfigHandler__NoUpdate = 100024;

    /***********************************|
    |       BufferRateConfigHandler     | 
    |__________________________________*/

    /// @notice thrown when an input address is zero
    uint256 internal constant BufferRateConfigHandler__AddressZero = 100031;

    /// @notice thrown when an unauthorized `msg.sender` calls a protected method
    uint256 internal constant BufferRateConfigHandler__Unauthorized = 100032;

    /// @notice thrown when invalid params are passed into a method
    uint256 internal constant BufferRateConfigHandler__InvalidParams = 100033;

    /// @notice thrown when no update is currently needed
    uint256 internal constant BufferRateConfigHandler__NoUpdate = 100034;

    /// @notice thrown when rate data version is not supported
    uint256 internal constant BufferRateConfigHandler__RateVersionUnsupported = 100035;

    /***********************************|
    |          FluidRatesAuth           | 
    |__________________________________*/

    /// @notice thrown when no update is currently needed
    uint256 internal constant RatesAuth__NoUpdate = 100041;

    /// @notice thrown when an unauthorized `msg.sender` calls a protected method
    uint256 internal constant RatesAuth__Unauthorized = 100042;

    /// @notice thrown when invalid params are passed into a method
    uint256 internal constant RatesAuth__InvalidParams = 100043;

    /// @notice thrown when cooldown is not yet expired
    uint256 internal constant RatesAuth__CooldownLeft = 100044;

    /// @notice thrown when version is invalid
    uint256 internal constant RatesAuth__InvalidVersion = 100045;

    /***********************************|
    |          ListTokenAuth            | 
    |__________________________________*/

    /// @notice thrown when an unauthorized `msg.sender` calls a protected method
    uint256 internal constant ListTokenAuth__Unauthorized = 100051;

    /// @notice thrown when invalid params are passed into a method
    uint256 internal constant ListTokenAuth_AlreadyInitialized = 100052;

    /// @notice thrown when invalid params are passed into a method
    uint256 internal constant ListTokenAuth__InvalidParams = 100053;

    /***********************************|
    |       CollectRevenueAuth          | 
    |__________________________________*/

    /// @notice thrown when an unauthorized `msg.sender` calls a protected method
    uint256 internal constant CollectRevenueAuth__Unauthorized = 100061;

    /// @notice thrown when invalid params are passed into a method
    uint256 internal constant CollectRevenueAuth__InvalidParams = 100062;
}

File 4 of 11 : fluidConfigHandler.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.21;

import { IFluidConfigHandler } from "./interfaces/iFluidConfigHandler.sol";

/// @title   FluidConfigHandler
/// @notice  Base contract that any Fluid Config Handler must implement
abstract contract FluidConfigHandler is IFluidConfigHandler {
    /// @inheritdoc IFluidConfigHandler
    function configPercentDiff() public view virtual returns (uint256 configPercentDiff_);

    /// @inheritdoc IFluidConfigHandler
    function rebalance() external virtual;
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.21;

interface IFluidConfigHandler {
    /// @notice returns how much the new config would be different from current config in percent (100 = 1%, 1 = 0.01%).
    function configPercentDiff() external view returns (uint256 configPercentDiff_);

    /// @notice Rebalances the configs at Fluid Liquidity based on config handler target.
    /// Reverts if no update is needed.
    /// Can only be called by an authorized rebalancer.
    function rebalance() external;
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.21;

interface IProxy {
    function setAdmin(address newAdmin_) external;

    function setDummyImplementation(address newDummyImplementation_) external;

    function addImplementation(address implementation_, bytes4[] calldata sigs_) external;

    function removeImplementation(address implementation_) external;

    function getAdmin() external view returns (address);

    function getDummyImplementation() external view returns (address);

    function getImplementationSigs(address impl_) external view returns (bytes4[] memory);

    function getSigsImplementation(bytes4 sig_) external view returns (address);

    function readFromStorage(bytes32 slot_) external view returns (uint256 result_);
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.21;

/// @title library that represents a number in BigNumber(coefficient and exponent) format to store in smaller bits.
/// @notice the number is divided into two parts: a coefficient and an exponent. This comes at a cost of losing some precision
/// at the end of the number because the exponent simply fills it with zeroes. This precision is oftentimes negligible and can
/// result in significant gas cost reduction due to storage space reduction.
/// 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.
/// @dev roundUp is more like a increase 1, which happens everytime for the same number.
/// roundDown simply sets trailing digits after coefficientSize to zero (floor), only once for the same number.
library BigMathMinified {
    /// @dev constants to use for `roundUp` input param to increase readability
    bool internal constant ROUND_DOWN = false;
    bool internal constant ROUND_UP = true;

    /// @dev converts `normal` number to BigNumber with `exponent` and `coefficient` (or precision).
    /// e.g.:
    /// 5035703444687813576399599 (normal) = (coefficient[32bits], exponent[8bits])[40bits]
    /// 5035703444687813576399599 (decimal) => 10000101010010110100000011111011110010100110100000000011100101001101001101011101111 (binary)
    ///                                     => 10000101010010110100000011111011000000000000000000000000000000000000000000000000000
    ///                                                                        ^-------------------- 51(exponent) -------------- ^
    /// coefficient = 1000,0101,0100,1011,0100,0000,1111,1011               (2236301563)
    /// exponent =                                            0011,0011     (51)
    /// bigNumber =   1000,0101,0100,1011,0100,0000,1111,1011,0011,0011     (572493200179)
    ///
    /// @param normal number which needs to be converted into Big Number
    /// @param coefficientSize at max how many bits of precision there should be (64 = uint64 (64 bits precision))
    /// @param exponentSize at max how many bits of exponent there should be (8 = uint8 (8 bits exponent))
    /// @param roundUp signals if result should be rounded down or up
    /// @return bigNumber converted bigNumber (coefficient << exponent)
    function toBigNumber(
        uint256 normal,
        uint256 coefficientSize,
        uint256 exponentSize,
        bool roundUp
    ) internal pure returns (uint256 bigNumber) {
        assembly {
            let lastBit_
            let number_ := normal
            if gt(number_, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) {
                number_ := shr(0x80, number_)
                lastBit_ := 0x80
            }
            if gt(number_, 0xFFFFFFFFFFFFFFFF) {
                number_ := shr(0x40, number_)
                lastBit_ := add(lastBit_, 0x40)
            }
            if gt(number_, 0xFFFFFFFF) {
                number_ := shr(0x20, number_)
                lastBit_ := add(lastBit_, 0x20)
            }
            if gt(number_, 0xFFFF) {
                number_ := shr(0x10, number_)
                lastBit_ := add(lastBit_, 0x10)
            }
            if gt(number_, 0xFF) {
                number_ := shr(0x8, number_)
                lastBit_ := add(lastBit_, 0x8)
            }
            if gt(number_, 0xF) {
                number_ := shr(0x4, number_)
                lastBit_ := add(lastBit_, 0x4)
            }
            if gt(number_, 0x3) {
                number_ := shr(0x2, number_)
                lastBit_ := add(lastBit_, 0x2)
            }
            if gt(number_, 0x1) {
                lastBit_ := add(lastBit_, 1)
            }
            if gt(number_, 0) {
                lastBit_ := add(lastBit_, 1)
            }
            if lt(lastBit_, coefficientSize) {
                // for throw exception
                lastBit_ := coefficientSize
            }
            let exponent := sub(lastBit_, coefficientSize)
            let coefficient := shr(exponent, normal)
            if and(roundUp, gt(exponent, 0)) {
                // rounding up is only needed if exponent is > 0, as otherwise the coefficient fully holds the original number
                coefficient := add(coefficient, 1)
                if eq(shl(coefficientSize, 1), coefficient) {
                    // case were coefficient was e.g. 111, with adding 1 it became 1000 (in binary) and coefficientSize 3 bits
                    // final coefficient would exceed it's size. -> reduce coefficent to 100 and increase exponent by 1.
                    coefficient := shl(sub(coefficientSize, 1), 1)
                    exponent := add(exponent, 1)
                }
            }
            if iszero(lt(exponent, shl(exponentSize, 1))) {
                // if exponent is >= exponentSize, the normal number is too big to fit within
                // BigNumber with too small sizes for coefficient and exponent
                revert(0, 0)
            }
            bigNumber := shl(exponentSize, coefficient)
            bigNumber := add(bigNumber, exponent)
        }
    }

    /// @dev get `normal` number from `bigNumber`, `exponentSize` and `exponentMask`
    function fromBigNumber(
        uint256 bigNumber,
        uint256 exponentSize,
        uint256 exponentMask
    ) internal pure returns (uint256 normal) {
        assembly {
            let coefficient := shr(exponentSize, bigNumber)
            let exponent := and(bigNumber, exponentMask)
            normal := shl(exponent, coefficient)
        }
    }

    /// @dev gets the most significant bit `lastBit` of a `normal` number (length of given number of binary format).
    /// e.g.
    /// 5035703444687813576399599 = 10000101010010110100000011111011110010100110100000000011100101001101001101011101111
    /// lastBit =                   ^---------------------------------   83   ----------------------------------------^
    function mostSignificantBit(uint256 normal) internal pure returns (uint lastBit) {
        assembly {
            let number_ := normal
            if gt(normal, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) {
                number_ := shr(0x80, number_)
                lastBit := 0x80
            }
            if gt(number_, 0xFFFFFFFFFFFFFFFF) {
                number_ := shr(0x40, number_)
                lastBit := add(lastBit, 0x40)
            }
            if gt(number_, 0xFFFFFFFF) {
                number_ := shr(0x20, number_)
                lastBit := add(lastBit, 0x20)
            }
            if gt(number_, 0xFFFF) {
                number_ := shr(0x10, number_)
                lastBit := add(lastBit, 0x10)
            }
            if gt(number_, 0xFF) {
                number_ := shr(0x8, number_)
                lastBit := add(lastBit, 0x8)
            }
            if gt(number_, 0xF) {
                number_ := shr(0x4, number_)
                lastBit := add(lastBit, 0x4)
            }
            if gt(number_, 0x3) {
                number_ := shr(0x2, number_)
                lastBit := add(lastBit, 0x2)
            }
            if gt(number_, 0x1) {
                lastBit := add(lastBit, 1)
            }
            if gt(number_, 0) {
                lastBit := add(lastBit, 1)
            }
        }
    }
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.21;

/// @notice library that helps in reading / working with storage slot data of Fluid Liquidity.
/// @dev as all data for Fluid Liquidity is internal, any data must be fetched directly through manual
/// slot reading through this library or, if gas usage is less important, through the FluidLiquidityResolver.
library LiquiditySlotsLink {
    /// @dev storage slot for status at Liquidity
    uint256 internal constant LIQUIDITY_STATUS_SLOT = 1;
    /// @dev storage slot for auths mapping at Liquidity
    uint256 internal constant LIQUIDITY_AUTHS_MAPPING_SLOT = 2;
    /// @dev storage slot for guardians mapping at Liquidity
    uint256 internal constant LIQUIDITY_GUARDIANS_MAPPING_SLOT = 3;
    /// @dev storage slot for user class mapping at Liquidity
    uint256 internal constant LIQUIDITY_USER_CLASS_MAPPING_SLOT = 4;
    /// @dev storage slot for exchangePricesAndConfig mapping at Liquidity
    uint256 internal constant LIQUIDITY_EXCHANGE_PRICES_MAPPING_SLOT = 5;
    /// @dev storage slot for rateData mapping at Liquidity
    uint256 internal constant LIQUIDITY_RATE_DATA_MAPPING_SLOT = 6;
    /// @dev storage slot for totalAmounts mapping at Liquidity
    uint256 internal constant LIQUIDITY_TOTAL_AMOUNTS_MAPPING_SLOT = 7;
    /// @dev storage slot for user supply double mapping at Liquidity
    uint256 internal constant LIQUIDITY_USER_SUPPLY_DOUBLE_MAPPING_SLOT = 8;
    /// @dev storage slot for user borrow double mapping at Liquidity
    uint256 internal constant LIQUIDITY_USER_BORROW_DOUBLE_MAPPING_SLOT = 9;
    /// @dev storage slot for listed tokens array at Liquidity
    uint256 internal constant LIQUIDITY_LISTED_TOKENS_ARRAY_SLOT = 10;
    /// @dev storage slot for listed tokens array at Liquidity
    uint256 internal constant LIQUIDITY_CONFIGS2_MAPPING_SLOT = 11;

    // --------------------------------
    // @dev stacked uint256 storage slots bits position data for each:

    // ExchangePricesAndConfig
    uint256 internal constant BITS_EXCHANGE_PRICES_BORROW_RATE = 0;
    uint256 internal constant BITS_EXCHANGE_PRICES_FEE = 16;
    uint256 internal constant BITS_EXCHANGE_PRICES_UTILIZATION = 30;
    uint256 internal constant BITS_EXCHANGE_PRICES_UPDATE_THRESHOLD = 44;
    uint256 internal constant BITS_EXCHANGE_PRICES_LAST_TIMESTAMP = 58;
    uint256 internal constant BITS_EXCHANGE_PRICES_SUPPLY_EXCHANGE_PRICE = 91;
    uint256 internal constant BITS_EXCHANGE_PRICES_BORROW_EXCHANGE_PRICE = 155;
    uint256 internal constant BITS_EXCHANGE_PRICES_SUPPLY_RATIO = 219;
    uint256 internal constant BITS_EXCHANGE_PRICES_BORROW_RATIO = 234;
    uint256 internal constant BITS_EXCHANGE_PRICES_USES_CONFIGS2 = 249;

    // RateData:
    uint256 internal constant BITS_RATE_DATA_VERSION = 0;
    // RateData: V1
    uint256 internal constant BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_ZERO = 4;
    uint256 internal constant BITS_RATE_DATA_V1_UTILIZATION_AT_KINK = 20;
    uint256 internal constant BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_KINK = 36;
    uint256 internal constant BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_MAX = 52;
    // RateData: V2
    uint256 internal constant BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_ZERO = 4;
    uint256 internal constant BITS_RATE_DATA_V2_UTILIZATION_AT_KINK1 = 20;
    uint256 internal constant BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_KINK1 = 36;
    uint256 internal constant BITS_RATE_DATA_V2_UTILIZATION_AT_KINK2 = 52;
    uint256 internal constant BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_KINK2 = 68;
    uint256 internal constant BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_MAX = 84;

    // TotalAmounts
    uint256 internal constant BITS_TOTAL_AMOUNTS_SUPPLY_WITH_INTEREST = 0;
    uint256 internal constant BITS_TOTAL_AMOUNTS_SUPPLY_INTEREST_FREE = 64;
    uint256 internal constant BITS_TOTAL_AMOUNTS_BORROW_WITH_INTEREST = 128;
    uint256 internal constant BITS_TOTAL_AMOUNTS_BORROW_INTEREST_FREE = 192;

    // UserSupplyData
    uint256 internal constant BITS_USER_SUPPLY_MODE = 0;
    uint256 internal constant BITS_USER_SUPPLY_AMOUNT = 1;
    uint256 internal constant BITS_USER_SUPPLY_PREVIOUS_WITHDRAWAL_LIMIT = 65;
    uint256 internal constant BITS_USER_SUPPLY_LAST_UPDATE_TIMESTAMP = 129;
    uint256 internal constant BITS_USER_SUPPLY_EXPAND_PERCENT = 162;
    uint256 internal constant BITS_USER_SUPPLY_EXPAND_DURATION = 176;
    uint256 internal constant BITS_USER_SUPPLY_BASE_WITHDRAWAL_LIMIT = 200;
    uint256 internal constant BITS_USER_SUPPLY_IS_PAUSED = 255;

    // UserBorrowData
    uint256 internal constant BITS_USER_BORROW_MODE = 0;
    uint256 internal constant BITS_USER_BORROW_AMOUNT = 1;
    uint256 internal constant BITS_USER_BORROW_PREVIOUS_BORROW_LIMIT = 65;
    uint256 internal constant BITS_USER_BORROW_LAST_UPDATE_TIMESTAMP = 129;
    uint256 internal constant BITS_USER_BORROW_EXPAND_PERCENT = 162;
    uint256 internal constant BITS_USER_BORROW_EXPAND_DURATION = 176;
    uint256 internal constant BITS_USER_BORROW_BASE_BORROW_LIMIT = 200;
    uint256 internal constant BITS_USER_BORROW_MAX_BORROW_LIMIT = 218;
    uint256 internal constant BITS_USER_BORROW_IS_PAUSED = 255;

    // Configs2
    uint256 internal constant BITS_CONFIGS2_MAX_UTILIZATION = 0;

    // --------------------------------

    /// @notice Calculating the slot ID for Liquidity contract for single mapping at `slot_` for `key_`
    function calculateMappingStorageSlot(uint256 slot_, address key_) internal pure returns (bytes32) {
        return keccak256(abi.encode(key_, slot_));
    }

    /// @notice Calculating the slot ID for Liquidity contract for double mapping at `slot_` for `key1_` and `key2_`
    function calculateDoubleMappingStorageSlot(
        uint256 slot_,
        address key1_,
        address key2_
    ) internal pure returns (bytes32) {
        bytes32 intermediateSlot_ = keccak256(abi.encode(key1_, slot_));
        return keccak256(abi.encode(key2_, intermediateSlot_));
    }
}

File 9 of 11 : structs.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.21;

abstract contract Structs {
    struct AddressBool {
        address addr;
        bool value;
    }

    struct AddressUint256 {
        address addr;
        uint256 value;
    }

    /// @notice struct to set borrow rate data for version 1
    struct RateDataV1Params {
        ///
        /// @param token for rate data
        address token;
        ///
        /// @param kink in borrow rate. in 1e2: 100% = 10_000; 1% = 100
        /// utilization below kink usually means slow increase in rate, once utilization is above kink borrow rate increases fast
        uint256 kink;
        ///
        /// @param rateAtUtilizationZero desired borrow rate when utilization is zero. in 1e2: 100% = 10_000; 1% = 100
        /// i.e. constant minimum borrow rate
        /// e.g. at utilization = 0.01% rate could still be at least 4% (rateAtUtilizationZero would be 400 then)
        uint256 rateAtUtilizationZero;
        ///
        /// @param rateAtUtilizationKink borrow rate when utilization is at kink. in 1e2: 100% = 10_000; 1% = 100
        /// e.g. when rate should be 7% at kink then rateAtUtilizationKink would be 700
        uint256 rateAtUtilizationKink;
        ///
        /// @param rateAtUtilizationMax borrow rate when utilization is maximum at 100%. in 1e2: 100% = 10_000; 1% = 100
        /// e.g. when rate should be 125% at 100% then rateAtUtilizationMax would be 12_500
        uint256 rateAtUtilizationMax;
    }

    /// @notice struct to set borrow rate data for version 2
    struct RateDataV2Params {
        ///
        /// @param token for rate data
        address token;
        ///
        /// @param kink1 first kink in borrow rate. in 1e2: 100% = 10_000; 1% = 100
        /// utilization below kink 1 usually means slow increase in rate, once utilization is above kink 1 borrow rate increases faster
        uint256 kink1;
        ///
        /// @param kink2 second kink in borrow rate. in 1e2: 100% = 10_000; 1% = 100
        /// utilization below kink 2 usually means slow / medium increase in rate, once utilization is above kink 2 borrow rate increases fast
        uint256 kink2;
        ///
        /// @param rateAtUtilizationZero desired borrow rate when utilization is zero. in 1e2: 100% = 10_000; 1% = 100
        /// i.e. constant minimum borrow rate
        /// e.g. at utilization = 0.01% rate could still be at least 4% (rateAtUtilizationZero would be 400 then)
        uint256 rateAtUtilizationZero;
        ///
        /// @param rateAtUtilizationKink1 desired borrow rate when utilization is at first kink. in 1e2: 100% = 10_000; 1% = 100
        /// e.g. when rate should be 7% at first kink then rateAtUtilizationKink would be 700
        uint256 rateAtUtilizationKink1;
        ///
        /// @param rateAtUtilizationKink2 desired borrow rate when utilization is at second kink. in 1e2: 100% = 10_000; 1% = 100
        /// e.g. when rate should be 7% at second kink then rateAtUtilizationKink would be 1_200
        uint256 rateAtUtilizationKink2;
        ///
        /// @param rateAtUtilizationMax desired borrow rate when utilization is maximum at 100%. in 1e2: 100% = 10_000; 1% = 100
        /// e.g. when rate should be 125% at 100% then rateAtUtilizationMax would be 12_500
        uint256 rateAtUtilizationMax;
    }

    /// @notice struct to set token config
    struct TokenConfig {
        ///
        /// @param token address
        address token;
        ///
        /// @param fee charges on borrower's interest. in 1e2: 100% = 10_000; 1% = 100
        uint256 fee;
        ///
        /// @param threshold on when to update the storage slot. in 1e2: 100% = 10_000; 1% = 100
        uint256 threshold;
        ///
        /// @param maxUtilization maximum allowed utilization. in 1e2: 100% = 10_000; 1% = 100
        ///                       set to 100% to disable and have default limit of 100% (avoiding SLOAD).
        uint256 maxUtilization;
    }

    /// @notice struct to set user supply & withdrawal config
    struct UserSupplyConfig {
        ///
        /// @param user address
        address user;
        ///
        /// @param token address
        address token;
        ///
        /// @param mode: 0 = without interest. 1 = with interest
        uint8 mode;
        ///
        /// @param expandPercent withdrawal limit expand percent. in 1e2: 100% = 10_000; 1% = 100
        /// Also used to calculate rate at which withdrawal limit should decrease (instant).
        uint256 expandPercent;
        ///
        /// @param expandDuration withdrawal limit expand duration in seconds.
        /// used to calculate rate together with expandPercent
        uint256 expandDuration;
        ///
        /// @param baseWithdrawalLimit base limit, below this, user can withdraw the entire amount.
        /// amount in raw (to be multiplied with exchange price) or normal depends on configured mode in user config for the token:
        /// with interest -> raw, without interest -> normal
        uint256 baseWithdrawalLimit;
    }

    /// @notice struct to set user borrow & payback config
    struct UserBorrowConfig {
        ///
        /// @param user address
        address user;
        ///
        /// @param token address
        address token;
        ///
        /// @param mode: 0 = without interest. 1 = with interest
        uint8 mode;
        ///
        /// @param expandPercent debt limit expand percent. in 1e2: 100% = 10_000; 1% = 100
        /// Also used to calculate rate at which debt limit should decrease (instant).
        uint256 expandPercent;
        ///
        /// @param expandDuration debt limit expand duration in seconds.
        /// used to calculate rate together with expandPercent
        uint256 expandDuration;
        ///
        /// @param baseDebtCeiling base borrow limit. until here, borrow limit remains as baseDebtCeiling
        /// (user can borrow until this point at once without stepped expansion). Above this, automated limit comes in place.
        /// amount in raw (to be multiplied with exchange price) or normal depends on configured mode in user config for the token:
        /// with interest -> raw, without interest -> normal
        uint256 baseDebtCeiling;
        ///
        /// @param maxDebtCeiling max borrow ceiling, maximum amount the user can borrow.
        /// amount in raw (to be multiplied with exchange price) or normal depends on configured mode in user config for the token:
        /// with interest -> raw, without interest -> normal
        uint256 maxDebtCeiling;
    }
}

//SPDX-License-Identifier: MIT
pragma solidity 0.8.21;

import { IProxy } from "../../infiniteProxy/interfaces/iProxy.sol";
import { Structs as AdminModuleStructs } from "../adminModule/structs.sol";

interface IFluidLiquidityAdmin {
    /// @notice adds/removes auths. Auths generally could be contracts which can have restricted actions defined on contract.
    ///         auths can be helpful in reducing governance overhead where it's not needed.
    /// @param authsStatus_ array of structs setting allowed status for an address.
    ///                     status true => add auth, false => remove auth
    function updateAuths(AdminModuleStructs.AddressBool[] calldata authsStatus_) external;

    /// @notice adds/removes guardians. Only callable by Governance.
    /// @param guardiansStatus_ array of structs setting allowed status for an address.
    ///                         status true => add guardian, false => remove guardian
    function updateGuardians(AdminModuleStructs.AddressBool[] calldata guardiansStatus_) external;

    /// @notice changes the revenue collector address (contract that is sent revenue). Only callable by Governance.
    /// @param revenueCollector_  new revenue collector address
    function updateRevenueCollector(address revenueCollector_) external;

    /// @notice changes current status, e.g. for pausing or unpausing all user operations. Only callable by Auths.
    /// @param newStatus_ new status
    ///        status = 2 -> pause, status = 1 -> resume.
    function changeStatus(uint256 newStatus_) external;

    /// @notice                  update tokens rate data version 1. Only callable by Auths.
    /// @param tokensRateData_   array of RateDataV1Params with rate data to set for each token
    function updateRateDataV1s(AdminModuleStructs.RateDataV1Params[] calldata tokensRateData_) external;

    /// @notice                  update tokens rate data version 2. Only callable by Auths.
    /// @param tokensRateData_   array of RateDataV2Params with rate data to set for each token
    function updateRateDataV2s(AdminModuleStructs.RateDataV2Params[] calldata tokensRateData_) external;

    /// @notice updates token configs: fee charge on borrowers interest & storage update utilization threshold.
    ///         Only callable by Auths.
    /// @param tokenConfigs_ contains token address, fee & utilization threshold
    function updateTokenConfigs(AdminModuleStructs.TokenConfig[] calldata tokenConfigs_) external;

    /// @notice updates user classes: 0 is for new protocols, 1 is for established protocols.
    ///         Only callable by Auths.
    /// @param userClasses_ struct array of uint256 value to assign for each user address
    function updateUserClasses(AdminModuleStructs.AddressUint256[] calldata userClasses_) external;

    /// @notice sets user supply configs per token basis. Eg: with interest or interest-free and automated limits.
    ///         Only callable by Auths.
    /// @param userSupplyConfigs_ struct array containing user supply config, see `UserSupplyConfig` struct for more info
    function updateUserSupplyConfigs(AdminModuleStructs.UserSupplyConfig[] memory userSupplyConfigs_) external;

    /// @notice setting user borrow configs per token basis. Eg: with interest or interest-free and automated limits.
    ///         Only callable by Auths.
    /// @param userBorrowConfigs_ struct array containing user borrow config, see `UserBorrowConfig` struct for more info
    function updateUserBorrowConfigs(AdminModuleStructs.UserBorrowConfig[] memory userBorrowConfigs_) external;

    /// @notice pause operations for a particular user in class 0 (class 1 users can't be paused by guardians).
    /// Only callable by Guardians.
    /// @param user_          address of user to pause operations for
    /// @param supplyTokens_  token addresses to pause withdrawals for
    /// @param borrowTokens_  token addresses to pause borrowings for
    function pauseUser(address user_, address[] calldata supplyTokens_, address[] calldata borrowTokens_) external;

    /// @notice unpause operations for a particular user in class 0 (class 1 users can't be paused by guardians).
    /// Only callable by Guardians.
    /// @param user_          address of user to unpause operations for
    /// @param supplyTokens_  token addresses to unpause withdrawals for
    /// @param borrowTokens_  token addresses to unpause borrowings for
    function unpauseUser(address user_, address[] calldata supplyTokens_, address[] calldata borrowTokens_) external;

    /// @notice         collects revenue for tokens to configured revenueCollector address.
    /// @param tokens_  array of tokens to collect revenue for
    /// @dev            Note that this can revert if token balance is < revenueAmount (utilization > 100%)
    function collectRevenue(address[] calldata tokens_) external;

    /// @notice gets the current updated exchange prices for n tokens and updates all prices, rates related data in storage.
    /// @param tokens_ tokens to update exchange prices for
    /// @return supplyExchangePrices_ new supply rates of overall system for each token
    /// @return borrowExchangePrices_ new borrow rates of overall system for each token
    function updateExchangePrices(
        address[] calldata tokens_
    ) external returns (uint256[] memory supplyExchangePrices_, uint256[] memory borrowExchangePrices_);
}

interface IFluidLiquidityLogic is IFluidLiquidityAdmin {
    /// @notice Single function which handles supply, withdraw, borrow & payback
    /// @param token_ address of token (0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE for native)
    /// @param supplyAmount_ if +ve then supply, if -ve then withdraw, if 0 then nothing
    /// @param borrowAmount_ if +ve then borrow, if -ve then payback, if 0 then nothing
    /// @param withdrawTo_ if withdrawal then to which address
    /// @param borrowTo_ if borrow then to which address
    /// @param callbackData_ callback data passed to `liquidityCallback` method of protocol
    /// @return memVar3_ updated supplyExchangePrice
    /// @return memVar4_ updated borrowExchangePrice
    /// @dev to trigger skipping in / out transfers when in&out amounts balance themselves out (gas optimization):
    /// -   supply(+) == borrow(+), withdraw(-) == payback(-).
    /// -   `withdrawTo_` / `borrowTo_` must be msg.sender (protocol)
    /// -   `callbackData_` MUST be encoded so that "from" address is at last 20 bytes (if this optimization is desired),
    ///     also for native token operations where liquidityCallback is not triggered!
    ///     from address must come at last position if there is more data. I.e. encode like:
    ///     abi.encode(otherVar1, otherVar2, FROM_ADDRESS). Note dynamic types used with abi.encode come at the end
    ///     so if dynamic types are needed, you must use abi.encodePacked to ensure the from address is at the end.
    function operate(
        address token_,
        int256 supplyAmount_,
        int256 borrowAmount_,
        address withdrawTo_,
        address borrowTo_,
        bytes calldata callbackData_
    ) external payable returns (uint256 memVar3_, uint256 memVar4_);
}

interface IFluidLiquidity is IProxy, IFluidLiquidityLogic {}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.21;

import { IFluidLiquidity } from "../../liquidity/interfaces/iLiquidity.sol";

interface IFluidReserveContract {
    function isRebalancer(address user) external returns (bool);

    function initialize(
        address[] memory _auths,
        address[] memory _rebalancers,
        IFluidLiquidity liquidity_,
        address owner_
    ) external;

    function rebalanceFToken(address protocol_) external;

    function rebalanceVault(address protocol_) external;

    function transferFunds(address token_) external;

    function getProtocolTokens(address protocol_) external;

    function updateAuth(address auth_, bool isAuth_) external;

    function updateRebalancer(address rebalancer_, bool isRebalancer_) external;

    function approve(address[] memory protocols_, address[] memory tokens_, uint256[] memory amounts_) external;

    function revoke(address[] memory protocols_, address[] memory tokens_) external;
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 10000000
  },
  "evmVersion": "paris",
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "metadata": {
    "useLiteralContent": true
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"contract IFluidReserveContract","name":"reserveContract_","type":"address"},{"internalType":"contract IFluidLiquidity","name":"liquidity_","type":"address"},{"internalType":"address","name":"supplyToken_","type":"address"},{"internalType":"address","name":"borrowToken_","type":"address"},{"internalType":"int256","name":"rateBufferKink1_","type":"int256"},{"internalType":"int256","name":"rateBufferKink2_","type":"int256"},{"internalType":"uint256","name":"minUpdateDiff_","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"errorId_","type":"uint256"}],"name":"FluidConfigError","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"supplyRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"oldRateKink1","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newRateKink1","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"oldRateKink2","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newRateKink2","type":"uint256"}],"name":"LogUpdateRate","type":"event"},{"inputs":[],"name":"BORROW_TOKEN","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LIQUIDITY","outputs":[{"internalType":"contract IFluidLiquidity","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_UPDATE_DIFF","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RATE_BUFFER_KINK1","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RATE_BUFFER_KINK2","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RESERVE_CONTRACT","outputs":[{"internalType":"contract IFluidReserveContract","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SUPPLY_TOKEN","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"calcBorrowRates","outputs":[{"internalType":"uint256","name":"rateKink1_","type":"uint256"},{"internalType":"uint256","name":"rateKink2_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"configPercentDiff","outputs":[{"internalType":"uint256","name":"configPercentDiff_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rebalance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"supplyTokenLendingRate","outputs":[{"internalType":"uint256","name":"rate_","type":"uint256"}],"stateMutability":"view","type":"function"}]

6101c06040523480156200001257600080fd5b50604051620017583803806200175883398101604081905262000035916200023c565b866001600160a01b0381166200006857604051636801712d60e11b8152620186bf60048201526024015b60405180910390fd5b866001600160a01b0381166200009757604051636801712d60e11b8152620186bf60048201526024016200005f565b866001600160a01b038116620000c657604051636801712d60e11b8152620186bf60048201526024016200005f565b866001600160a01b038116620000f557604051636801712d60e11b8152620186bf60048201526024016200005f565b84158062000104575061271087135b806200011b575062000118612710620002c3565b87125b8062000128575061271086135b806200013f57506200013c612710620002c3565b86125b156200016457604051636801712d60e11b8152620186c160048201526024016200005f565b505050506001600160a01b03968716608090815295871660a090815294871660c08181529490971660e0818152610140929092526101009384526101209283526040805160208181018b905260078284015282518083038401815260608301845280519082012061016052988101999099526005898801528051808a0390970187529488018552855195870195909520610180528601939093526006858201528151808603909101815293909101905281519101206101a052620002ee565b6001600160a01b03811681146200023957600080fd5b50565b600080600080600080600060e0888a0312156200025857600080fd5b8751620002658162000223565b6020890151909750620002788162000223565b60408901519096506200028b8162000223565b60608901519095506200029e8162000223565b809450506080880151925060a0880151915060c0880151905092959891949750929550565b6000600160ff1b8201620002e757634e487b7160e01b600052601160045260246000fd5b5060000390565b60805160a05160c05160e05161010051610120516101405161016051610180516101a05161136a620003ee600039600081816105f10152818161072c015261089f01526000610379015260006102760152600081816101a7015281816109b701528181610c9f0152610cd40152600081816101f501528181611005015261103b01526000818160d301528181610f660152610f9c01526000818161018001528181610a210152610d410152600061015901526000818161010d015281816102b6015281816103a2015281816106320152818161076c015281816108c501528181610b5a0152610e940152600081816101ce01526104fd015261136a6000f3fe608060405234801561001057600080fd5b50600436106100c95760003560e01c80636449b8d7116100815780637d7c2a1c1161005b5780637d7c2a1c1461021f5780639dc1056614610229578063ee53f65c1461023157600080fd5b80636449b8d7146101c95780636a4bee28146101f057806376a9a0f71461021757600080fd5b80632bd173cd116100b25780632bd173cd146101545780634c90f25c1461017b578063535af56d146101a257600080fd5b80631cb79486146100ce5780632861c7d114610108575b600080fd5b6100f57f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b61012f7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100ff565b61012f7f000000000000000000000000000000000000000000000000000000000000000081565b61012f7f000000000000000000000000000000000000000000000000000000000000000081565b6100f57f000000000000000000000000000000000000000000000000000000000000000081565b61012f7f000000000000000000000000000000000000000000000000000000000000000081565b6100f57f000000000000000000000000000000000000000000000000000000000000000081565b6100f561024e565b6102276104cf565b005b6100f5610704565b610239610869565b604080519283526020830191909152016100ff565b6040517fb5c736e40000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152600090819073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063b5c736e490602401602060405180830381865afa1580156102fd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061032191906110f8565b905066ffffffffffffff600882901c811660ff8084169190911b91608884901c16608084901c9091161b81156104c9576040517fb5c736e40000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063b5c736e490602401602060405180830381865afa1580156103fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061042291906110f8565b9050600064e8d4a51000610444605b84901c67ffffffffffffffff1686611140565b61044e9190611157565b9050600064e8d4a51000610470609b85901c67ffffffffffffffff1686611140565b61047a9190611157565b905061ffff8316601084901c613fff1661049661271085611140565b836104a383612710611192565b6104ad9085611140565b6104b79190611140565b6104c19190611157565b985050505050505b50505090565b6040517f467c9eff0000000000000000000000000000000000000000000000000000000081523360048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063467c9eff906024016020604051808303816000875af115801561055b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061057f91906111a5565b6105bf576040517fd002e25a000000000000000000000000000000000000000000000000000000008152620186c060048201526024015b60405180910390fd5b60006105c961024e565b6040517fb5c736e40000000000000000000000000000000000000000000000000000000081527f0000000000000000000000000000000000000000000000000000000000000000600482015290915060009073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063b5c736e490602401602060405180830381865afa158015610679573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061069d91906110f8565b9050600f811660018190036106bb576106b68383610952565b505050565b806002036106cd576106b68383610c20565b6040517fd002e25a000000000000000000000000000000000000000000000000000000008152620186c360048201526024016105b6565b6040517fb5c736e40000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152600090819073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063b5c736e490602401602060405180830381865afa1580156107b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107d791906110f8565b90506000806107ed6107e761024e565b84610f5d565b9092509050600f8316600181900361081a57602484901c61ffff1661081281856110a1565b955050610862565b806002036106cd5761ffff602485901c811690604486901c1661083d82866110a1565b9650600061084b82866110a1565b905080881161085a578061085c565b875b97505050505b5050505090565b60008061094a61087761024e565b6040517fb5c736e40000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063b5c736e490602401602060405180830381865afa158015610921573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094591906110f8565b610f5d565b915091509091565b61099a6040518060a00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600081526020016000815260200160008152602001600081525090565b602482901c61ffff166109ad8484610f5d565b50606083018190527f0000000000000000000000000000000000000000000000000000000000000000906109e29083906110a1565b1015610a1f576040517fd002e25a000000000000000000000000000000000000000000000000000000008152620186c260048201526024016105b6565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16825261ffff600484901c81166040840152601484901c81166020840152603484901c16608083015260006001604051908082528060200260200182016040528015610afb57816020015b610ae86040518060a00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600081526020016000815260200160008152602001600081525090565b815260200190600190039081610aa05790505b5090508281600081518110610b1257610b126111ce565b60209081029190910101526040517f3fad77fc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690633fad77fc90610b8f9084906004016111fd565b600060405180830381600087803b158015610ba957600080fd5b505af1158015610bbd573d6000803e3d6000fd5b505050606080850151604080518981526020810187905290810191909152600091810182905260808101919091527f24e2edf993a55aa376aad1f221b77e38909f025c6b5010a003b527fc1d111171915060a00160405180910390a15050505050565b610c766040518060e00160405280600073ffffffffffffffffffffffffffffffffffffffff1681526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b61ffff602483901c811690604484901c16610c918585610f5d565b60a0850152608084018190527f000000000000000000000000000000000000000000000000000000000000000090610cca9084906110a1565b108015610d0357507f0000000000000000000000000000000000000000000000000000000000000000610d01828560a001516110a1565b105b15610d3f576040517fd002e25a000000000000000000000000000000000000000000000000000000008152620186c260048201526024016105b6565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16835261ffff600485901c81166060850152601485901c81166020850152603485901c81166040850152605485901c1660c084015260006001604051908082528060200260200182016040528015610e3557816020015b610e226040518060e00160405280600073ffffffffffffffffffffffffffffffffffffffff1681526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b815260200190600190039081610dcc5790505b5090508381600081518110610e4c57610e4c6111ce565b60209081029190910101526040517f9dde597700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690639dde597790610ec9908490600401611281565b600060405180830381600087803b158015610ee357600080fd5b505af1158015610ef7573d6000803e3d6000fd5b50505060808086015160a080880151604080518c8152602081018a90529081019390935260608301879052928201929092527f24e2edf993a55aa376aad1f221b77e38909f025c6b5010a003b527fc1d11117192500160405180910390a1505050505050565b60008080610f8b7f00000000000000000000000000000000000000000000000000000000000000008661130c565b13610f97576000610fc1565b610fc17f00000000000000000000000000000000000000000000000000000000000000008561130c565b915061ffff8211610fd25781610fd6565b61ffff5b915082600f16600103610ffe57603483901c61ffff1680831115610ff8578092505b5061109a565b600061102a7f00000000000000000000000000000000000000000000000000000000000000008661130c565b13611036576000611060565b6110607f00000000000000000000000000000000000000000000000000000000000000008561130c565b905061ffff81116110715780611075565b61ffff5b9050605483901c61ffff168083111561108c578092505b80821115611098578091505b505b9250929050565b60008183036110b2575060006110f2565b818311156110cb576110c48284611192565b90506110d8565b6110d58383611192565b90505b826110e582612710611140565b6110ef9190611157565b90505b92915050565b60006020828403121561110a57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176110f2576110f2611111565b60008261118d577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b818103818111156110f2576110f2611111565b6000602082840312156111b757600080fd5b815180151581146111c757600080fd5b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602080825282518282018190526000919060409081850190868401855b82811015611274578151805173ffffffffffffffffffffffffffffffffffffffff16855286810151878601528581015186860152606080820151908601526080908101519085015260a0909301929085019060010161121a565b5091979650505050505050565b602080825282518282018190526000919060409081850190868401855b82811015611274578151805173ffffffffffffffffffffffffffffffffffffffff16855286810151878601528581015186860152606080820151908601526080808201519086015260a0808201519086015260c0908101519085015260e0909301929085019060010161129e565b808201828112600083128015821682158216171561132c5761132c611111565b50509291505056fea26469706673582212206366a84e57e82bef7a964beeb5fda8d95428ff87b970d6cb1e962d037c65536c64736f6c63430008150033000000000000000000000000264786ef916af64a1db19f513f24a3681734ce9200000000000000000000000052aa899454998be5b000ad077a46bbe360f4e4970000000000000000000000007f39c581f595b53c5cb19bd0b3f8da6c935e2ca0000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee000000000000000000000000000000000000000000000000000000000000009600000000000000000000000000000000000000000000000000000000000000c80000000000000000000000000000000000000000000000000000000000000019

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106100c95760003560e01c80636449b8d7116100815780637d7c2a1c1161005b5780637d7c2a1c1461021f5780639dc1056614610229578063ee53f65c1461023157600080fd5b80636449b8d7146101c95780636a4bee28146101f057806376a9a0f71461021757600080fd5b80632bd173cd116100b25780632bd173cd146101545780634c90f25c1461017b578063535af56d146101a257600080fd5b80631cb79486146100ce5780632861c7d114610108575b600080fd5b6100f57f000000000000000000000000000000000000000000000000000000000000009681565b6040519081526020015b60405180910390f35b61012f7f00000000000000000000000052aa899454998be5b000ad077a46bbe360f4e49781565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100ff565b61012f7f0000000000000000000000007f39c581f595b53c5cb19bd0b3f8da6c935e2ca081565b61012f7f000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b6100f57f000000000000000000000000000000000000000000000000000000000000001981565b61012f7f000000000000000000000000264786ef916af64a1db19f513f24a3681734ce9281565b6100f57f00000000000000000000000000000000000000000000000000000000000000c881565b6100f561024e565b6102276104cf565b005b6100f5610704565b610239610869565b604080519283526020830191909152016100ff565b6040517fb5c736e40000000000000000000000000000000000000000000000000000000081527f94416004645a626907820dc10a83f0e7e82fe5572b44e84e877643ce205ff0ed6004820152600090819073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000052aa899454998be5b000ad077a46bbe360f4e497169063b5c736e490602401602060405180830381865afa1580156102fd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061032191906110f8565b905066ffffffffffffff600882901c811660ff8084169190911b91608884901c16608084901c9091161b81156104c9576040517fb5c736e40000000000000000000000000000000000000000000000000000000081527fc24eaceff5753c99066a839532d708a8661af7a9b01d44d0cd915c53969eb72560048201526000907f00000000000000000000000052aa899454998be5b000ad077a46bbe360f4e49773ffffffffffffffffffffffffffffffffffffffff169063b5c736e490602401602060405180830381865afa1580156103fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061042291906110f8565b9050600064e8d4a51000610444605b84901c67ffffffffffffffff1686611140565b61044e9190611157565b9050600064e8d4a51000610470609b85901c67ffffffffffffffff1686611140565b61047a9190611157565b905061ffff8316601084901c613fff1661049661271085611140565b836104a383612710611192565b6104ad9085611140565b6104b79190611140565b6104c19190611157565b985050505050505b50505090565b6040517f467c9eff0000000000000000000000000000000000000000000000000000000081523360048201527f000000000000000000000000264786ef916af64a1db19f513f24a3681734ce9273ffffffffffffffffffffffffffffffffffffffff169063467c9eff906024016020604051808303816000875af115801561055b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061057f91906111a5565b6105bf576040517fd002e25a000000000000000000000000000000000000000000000000000000008152620186c060048201526024015b60405180910390fd5b60006105c961024e565b6040517fb5c736e40000000000000000000000000000000000000000000000000000000081527fa2e5aefc6e2cbe2917a296f0fd89c5f915c487c803db1d98eccb43f14012d711600482015290915060009073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000052aa899454998be5b000ad077a46bbe360f4e497169063b5c736e490602401602060405180830381865afa158015610679573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061069d91906110f8565b9050600f811660018190036106bb576106b68383610952565b505050565b806002036106cd576106b68383610c20565b6040517fd002e25a000000000000000000000000000000000000000000000000000000008152620186c360048201526024016105b6565b6040517fb5c736e40000000000000000000000000000000000000000000000000000000081527fa2e5aefc6e2cbe2917a296f0fd89c5f915c487c803db1d98eccb43f14012d7116004820152600090819073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000052aa899454998be5b000ad077a46bbe360f4e497169063b5c736e490602401602060405180830381865afa1580156107b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107d791906110f8565b90506000806107ed6107e761024e565b84610f5d565b9092509050600f8316600181900361081a57602484901c61ffff1661081281856110a1565b955050610862565b806002036106cd5761ffff602485901c811690604486901c1661083d82866110a1565b9650600061084b82866110a1565b905080881161085a578061085c565b875b97505050505b5050505090565b60008061094a61087761024e565b6040517fb5c736e40000000000000000000000000000000000000000000000000000000081527fa2e5aefc6e2cbe2917a296f0fd89c5f915c487c803db1d98eccb43f14012d71160048201527f00000000000000000000000052aa899454998be5b000ad077a46bbe360f4e49773ffffffffffffffffffffffffffffffffffffffff169063b5c736e490602401602060405180830381865afa158015610921573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094591906110f8565b610f5d565b915091509091565b61099a6040518060a00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600081526020016000815260200160008152602001600081525090565b602482901c61ffff166109ad8484610f5d565b50606083018190527f0000000000000000000000000000000000000000000000000000000000000019906109e29083906110a1565b1015610a1f576040517fd002e25a000000000000000000000000000000000000000000000000000000008152620186c260048201526024016105b6565b7f000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee73ffffffffffffffffffffffffffffffffffffffff16825261ffff600484901c81166040840152601484901c81166020840152603484901c16608083015260006001604051908082528060200260200182016040528015610afb57816020015b610ae86040518060a00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600081526020016000815260200160008152602001600081525090565b815260200190600190039081610aa05790505b5090508281600081518110610b1257610b126111ce565b60209081029190910101526040517f3fad77fc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000052aa899454998be5b000ad077a46bbe360f4e4971690633fad77fc90610b8f9084906004016111fd565b600060405180830381600087803b158015610ba957600080fd5b505af1158015610bbd573d6000803e3d6000fd5b505050606080850151604080518981526020810187905290810191909152600091810182905260808101919091527f24e2edf993a55aa376aad1f221b77e38909f025c6b5010a003b527fc1d111171915060a00160405180910390a15050505050565b610c766040518060e00160405280600073ffffffffffffffffffffffffffffffffffffffff1681526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b61ffff602483901c811690604484901c16610c918585610f5d565b60a0850152608084018190527f000000000000000000000000000000000000000000000000000000000000001990610cca9084906110a1565b108015610d0357507f0000000000000000000000000000000000000000000000000000000000000019610d01828560a001516110a1565b105b15610d3f576040517fd002e25a000000000000000000000000000000000000000000000000000000008152620186c260048201526024016105b6565b7f000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee73ffffffffffffffffffffffffffffffffffffffff16835261ffff600485901c81166060850152601485901c81166020850152603485901c81166040850152605485901c1660c084015260006001604051908082528060200260200182016040528015610e3557816020015b610e226040518060e00160405280600073ffffffffffffffffffffffffffffffffffffffff1681526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b815260200190600190039081610dcc5790505b5090508381600081518110610e4c57610e4c6111ce565b60209081029190910101526040517f9dde597700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000052aa899454998be5b000ad077a46bbe360f4e4971690639dde597790610ec9908490600401611281565b600060405180830381600087803b158015610ee357600080fd5b505af1158015610ef7573d6000803e3d6000fd5b50505060808086015160a080880151604080518c8152602081018a90529081019390935260608301879052928201929092527f24e2edf993a55aa376aad1f221b77e38909f025c6b5010a003b527fc1d11117192500160405180910390a1505050505050565b60008080610f8b7f00000000000000000000000000000000000000000000000000000000000000968661130c565b13610f97576000610fc1565b610fc17f00000000000000000000000000000000000000000000000000000000000000968561130c565b915061ffff8211610fd25781610fd6565b61ffff5b915082600f16600103610ffe57603483901c61ffff1680831115610ff8578092505b5061109a565b600061102a7f00000000000000000000000000000000000000000000000000000000000000c88661130c565b13611036576000611060565b6110607f00000000000000000000000000000000000000000000000000000000000000c88561130c565b905061ffff81116110715780611075565b61ffff5b9050605483901c61ffff168083111561108c578092505b80821115611098578091505b505b9250929050565b60008183036110b2575060006110f2565b818311156110cb576110c48284611192565b90506110d8565b6110d58383611192565b90505b826110e582612710611140565b6110ef9190611157565b90505b92915050565b60006020828403121561110a57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176110f2576110f2611111565b60008261118d577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b818103818111156110f2576110f2611111565b6000602082840312156111b757600080fd5b815180151581146111c757600080fd5b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602080825282518282018190526000919060409081850190868401855b82811015611274578151805173ffffffffffffffffffffffffffffffffffffffff16855286810151878601528581015186860152606080820151908601526080908101519085015260a0909301929085019060010161121a565b5091979650505050505050565b602080825282518282018190526000919060409081850190868401855b82811015611274578151805173ffffffffffffffffffffffffffffffffffffffff16855286810151878601528581015186860152606080820151908601526080808201519086015260a0808201519086015260c0908101519085015260e0909301929085019060010161129e565b808201828112600083128015821682158216171561132c5761132c611111565b50509291505056fea26469706673582212206366a84e57e82bef7a964beeb5fda8d95428ff87b970d6cb1e962d037c65536c64736f6c63430008150033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000264786ef916af64a1db19f513f24a3681734ce9200000000000000000000000052aa899454998be5b000ad077a46bbe360f4e4970000000000000000000000007f39c581f595b53c5cb19bd0b3f8da6c935e2ca0000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee000000000000000000000000000000000000000000000000000000000000009600000000000000000000000000000000000000000000000000000000000000c80000000000000000000000000000000000000000000000000000000000000019

-----Decoded View---------------
Arg [0] : reserveContract_ (address): 0x264786EF916af64a1DB19F513F24a3681734ce92
Arg [1] : liquidity_ (address): 0x52Aa899454998Be5b000Ad077a46Bbe360F4e497
Arg [2] : supplyToken_ (address): 0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0
Arg [3] : borrowToken_ (address): 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE
Arg [4] : rateBufferKink1_ (int256): 150
Arg [5] : rateBufferKink2_ (int256): 200
Arg [6] : minUpdateDiff_ (uint256): 25

-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 000000000000000000000000264786ef916af64a1db19f513f24a3681734ce92
Arg [1] : 00000000000000000000000052aa899454998be5b000ad077a46bbe360f4e497
Arg [2] : 0000000000000000000000007f39c581f595b53c5cb19bd0b3f8da6c935e2ca0
Arg [3] : 000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000096
Arg [5] : 00000000000000000000000000000000000000000000000000000000000000c8
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000019


Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.