Contract

0xA9DF16C778673f1D8f0dA13B1C3FdBAb840Af692

Overview

S Balance

Sonic LogoSonic LogoSonic Logo0 S

S Value

-

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To

There are no matching entries

1 Internal Transaction found.

Latest 1 internal transaction

Parent Transaction Hash Block From To
4343382024-12-15 7:51:5420 days ago1734249114  Contract Creation0 S
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
FluidVaultTicksBranchesResolver

Compiler Version
v0.8.21+commit.d9974bed

Optimization Enabled:
Yes with 10000000 runs

Other Settings:
paris EvmVersion
File 1 of 10 : main.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.21;

import { TickMath } from "../../../libraries/tickMath.sol";
import { BigMathMinified } from "../../../libraries/bigMathMinified.sol";
import { IFluidVaultResolver } from "../vault/iVaultResolver.sol";
import { IFluidVault } from "../../../protocols/vault/interfaces/iVault.sol";

import { Structs } from "./structs.sol";
import { Variables } from "./variables.sol";

/// @notice Fluid Vault protocol ticks & branches resolver for all vault types.
contract FluidVaultTicksBranchesResolver is Variables, Structs {
    /// @notice thrown if an input param address is zero
    error FluidVaultTicksBranchesResolver__AddressZero();

    /// @notice constructor sets the immutable vault resolver address
    constructor(IFluidVaultResolver vaultResolver_) Variables(vaultResolver_) {
        if (address(vaultResolver_) == address(0)) {
            revert FluidVaultTicksBranchesResolver__AddressZero();
        }
    }

    function getTicksDebt(
        address vault_,
        int fromTick_,
        uint totalTicks_
    ) public view returns (TickDebt[] memory ticksDebt_, int toTick_) {
        int topTick_ = _tickHelper(((VAULT_RESOLVER.getVaultVariablesRaw(vault_) >> 2) & X20));

        fromTick_ = topTick_ < fromTick_ ? topTick_ : fromTick_;
        if (fromTick_ > type(int).min) {
            // if fromTick_ == tpye(int).min means top tick is not set, meaning no positions exist
            int startMapId_ = fromTick_ < 0 ? ((fromTick_ + 1) / 256) - 1 : fromTick_ / 256;
            // Removing all other after fromTick
            uint tickHasDebt_;
            {
                uint tickHasDebtRaw_ = VAULT_RESOLVER.getTickHasDebtRaw(vault_, startMapId_);

                uint bitsToRemove_ = uint(-fromTick_ + (startMapId_ * 256 + 255));
                tickHasDebt_ = (tickHasDebtRaw_ << bitsToRemove_) >> bitsToRemove_;
            }

            // Adding 1 here as toTick_ is inclusive in the data so if totalTicks_ = 400 then it'll only check 400
            toTick_ = fromTick_ - int(totalTicks_) + 1;

            uint count_ = _countTicksWithDebt(vault_, toTick_, startMapId_, tickHasDebt_);

            (, , uint vaultSupplyExchangePrice_, uint vaultBorrowExchangePrice_) = IFluidVault(vault_)
                .updateExchangePrices(VAULT_RESOLVER.getVaultVariables2Raw(vault_));

            ticksDebt_ = _populateTicksDebt(
                vault_,
                toTick_,
                startMapId_,
                tickHasDebt_,
                count_,
                vaultSupplyExchangePrice_,
                vaultBorrowExchangePrice_
            );
        }
    }

    function getMultipleVaultsTicksDebt(
        address[] memory vaults_,
        int[] memory fromTicks_,
        uint[] memory totalTicks_
    ) public view returns (VaultsTickDebt[] memory vaultsTickDebt_) {
        uint length_ = vaults_.length;

        vaultsTickDebt_ = new VaultsTickDebt[](length_);
        for (uint i = 0; i < length_; i++) {
            (vaultsTickDebt_[i].tickDebt, vaultsTickDebt_[i].toTick) = getTicksDebt(
                vaults_[i],
                fromTicks_[i],
                totalTicks_[i]
            );
        }
    }

    function getAllVaultsTicksDebt(uint totalTicks_) public view returns (VaultsTickDebt[] memory vaultsTickDebt_) {
        address[] memory vaults_ = VAULT_RESOLVER.getAllVaultsAddresses();
        uint length_ = vaults_.length;

        vaultsTickDebt_ = new VaultsTickDebt[](length_);
        for (uint i = 0; i < length_; i++) {
            (vaultsTickDebt_[i].tickDebt, vaultsTickDebt_[i].toTick) = getTicksDebt(
                vaults_[i],
                type(int).max,
                totalTicks_
            );
        }
    }

    function getBranchesDebt(
        address vault_,
        uint fromBranchId_,
        uint toBranchId_
    ) public view returns (BranchDebt[] memory branchesDebt_) {
        uint vaultVariables_ = VAULT_RESOLVER.getVaultVariablesRaw(vault_);
        uint totalBranch_ = (vaultVariables_ >> 52) & X30;
        toBranchId_ = (toBranchId_ == 0 ? 1 : toBranchId_);
        fromBranchId_ = (totalBranch_ < fromBranchId_ ? totalBranch_ : fromBranchId_);

        require(fromBranchId_ >= toBranchId_, "fromBranchId_ must be greater than or equal to toBranchId_");

        branchesDebt_ = new BranchDebt[](fromBranchId_ - toBranchId_ + 1);

        uint index_;

        for (uint i = fromBranchId_; i >= toBranchId_; i--) {
            branchesDebt_[index_++] = _getBranchDebt(vault_, vaultVariables_, i);
        }
    }

    function getMultipleVaultsBranchesDebt(
        address[] memory vaults_,
        uint[] memory fromBranchIds_,
        uint[] memory toBranchIds_
    ) external view returns (BranchesDebt[] memory branchesDebt_) {
        uint length_ = vaults_.length;

        branchesDebt_ = new BranchesDebt[](length_);
        for (uint i = 0; i < length_; i++) {
            branchesDebt_[i].branchDebt = getBranchesDebt(vaults_[i], fromBranchIds_[i], toBranchIds_[i]);
        }
    }

    function getAllVaultsBranchesDebt() external view returns (BranchesDebt[] memory branchesDebt_) {
        address[] memory vaults_ = VAULT_RESOLVER.getAllVaultsAddresses();
        uint length_ = vaults_.length;

        branchesDebt_ = new BranchesDebt[](length_);
        for (uint i = 0; i < length_; i++) {
            branchesDebt_[i].branchDebt = getBranchesDebt(vaults_[i], type(uint).max, 0);
        }
    }

    function _populateTicksDebt(
        address vault_,
        int toTick_,
        int mapId_,
        uint tickHasDebt_,
        uint count_,
        uint vaultSupplyExchangePrice_,
        uint vaultBorrowExchangePrice_
    ) internal view returns (TickDebt[] memory ticksDebt_) {
        ticksDebt_ = new TickDebt[](count_);

        count_ = 0; // reuse var for loop index counter
        int nextTick_;
        uint tickExistingRawDebt_;
        uint ratio_;
        uint collateralRaw_;

        while (true) {
            while (tickHasDebt_ > 0) {
                {
                    uint msb_ = BigMathMinified.mostSignificantBit(tickHasDebt_);
                    // removing next tick from tickHasDebt
                    tickHasDebt_ = (tickHasDebt_ << (257 - msb_)) >> (257 - msb_);
                    nextTick_ = mapId_ * 256 + int(msb_ - 1);
                }
                if (nextTick_ < toTick_) {
                    return ticksDebt_;
                }
                tickExistingRawDebt_ = (VAULT_RESOLVER.getTickDataRaw(vault_, nextTick_) >> 25) & X64;
                tickExistingRawDebt_ = (tickExistingRawDebt_ >> 8) << (tickExistingRawDebt_ & X8);
                ratio_ = TickMath.getRatioAtTick(nextTick_);
                collateralRaw_ = (tickExistingRawDebt_ * (1 << 96)) / ratio_;
                ticksDebt_[count_++] = TickDebt({
                    debtRaw: tickExistingRawDebt_,
                    collateralRaw: collateralRaw_,
                    debtNormal: (tickExistingRawDebt_ * vaultBorrowExchangePrice_) / 1e12,
                    collateralNormal: (collateralRaw_ * vaultSupplyExchangePrice_) / 1e12,
                    ratio: ratio_,
                    tick: nextTick_
                });
            }

            if (--mapId_ == -129) {
                break;
            }

            tickHasDebt_ = VAULT_RESOLVER.getTickHasDebtRaw(vault_, mapId_);
        }
    }

    function _tickHelper(uint tickRaw_) internal pure returns (int tick) {
        require(tickRaw_ < X20, "invalid-number");
        if (tickRaw_ > 0) {
            tick = tickRaw_ & 1 == 1 ? int((tickRaw_ >> 1) & X19) : -int((tickRaw_ >> 1) & X19);
        } else {
            tick = type(int).min;
        }
    }

    function _countTicksWithDebt(
        address vault_,
        int toTick_,
        int mapId_,
        uint tickHasDebt_
    ) internal view returns (uint count_) {
        uint msb_;
        int nextTick_;
        while (true) {
            while (tickHasDebt_ > 0) {
                msb_ = BigMathMinified.mostSignificantBit(tickHasDebt_);
                // removing next tick from tickHasDebt
                tickHasDebt_ = (tickHasDebt_ << (257 - msb_)) >> (257 - msb_);
                nextTick_ = mapId_ * 256 + int(msb_ - 1);
                if (nextTick_ < toTick_) {
                    return count_;
                }
                count_++;
            }

            if (--mapId_ == -129) {
                break;
            }
            tickHasDebt_ = VAULT_RESOLVER.getTickHasDebtRaw(vault_, mapId_);
        }
        return count_;
    }

    function _getBranchDebt(
        address vault_,
        uint vaultVariables_,
        uint branchId_
    ) internal view returns (BranchDebt memory) {
        uint currentBranchData_ = VAULT_RESOLVER.getBranchDataRaw(vault_, branchId_);

        int minimaTick_ = _tickHelper((currentBranchData_ >> 2) & X20);
        uint status_ = currentBranchData_ & 3;

        if (status_ == 0) {
            // not liquidated status == 0
            // only current branch can be non-liquidated branch
            return _getActiveBranchDebt(vaultVariables_, currentBranchData_, branchId_, status_);
        } else if (status_ == 1) {
            // liquidated status == 1
            return _getLiquidatedBranchDebt(vault_, currentBranchData_, branchId_, status_, minimaTick_);
        } else {
            // merged status == 2
            // absorbed status == 3
            return _getClosedOrMergedBranchDebt(currentBranchData_, branchId_, status_);
        }
    }

    function _getActiveBranchDebt(
        uint vaultVariables_,
        uint currentBranchData_,
        uint branchId_,
        uint status_
    ) internal pure returns (BranchDebt memory branchDebt_) {
        int topTick_ = _tickHelper((vaultVariables_ >> 2) & X20);

        uint ratio_ = topTick_ > type(int).min ? TickMath.getRatioAtTick(topTick_) : 0;

        branchDebt_ = BranchDebt({
            debtRaw: 0,
            collateralRaw: 0,
            debtNormal: 0,
            collateralNormal: 0,
            branchId: branchId_,
            status: status_, // active status
            tick: topTick_, // as branch is not liquidated, just returning topTick for now, as whenever liquidation starts it'll start from topTick
            partials: 0,
            ratio: ratio_,
            debtFactor: (currentBranchData_ >> 116) & X50,
            baseBranchId: ((currentBranchData_ >> 166) & X30),
            baseBranchTick: _tickHelper((currentBranchData_ >> 196) & X20) // if == type(int).min, then current branch is master branch
        });
    }

    function _getClosedOrMergedBranchDebt(
        uint currentBranchData_,
        uint branchId_,
        uint status_
    ) internal pure returns (BranchDebt memory branchDebt_) {
        int baseBranchTick_ = _tickHelper((currentBranchData_ >> 196) & X20);
        uint ratio_ = baseBranchTick_ > type(int).min ? TickMath.getRatioAtTick(baseBranchTick_) : 0;

        branchDebt_ = BranchDebt({
            debtRaw: 0,
            collateralRaw: 0,
            debtNormal: 0,
            collateralNormal: 0,
            branchId: branchId_,
            status: status_,
            tick: baseBranchTick_, // as branch is merged/closed, so adding baseBranchTick_ as this is where it went out of existance
            partials: 0,
            ratio: ratio_,
            debtFactor: (currentBranchData_ >> 116) & X50,
            baseBranchId: ((currentBranchData_ >> 166) & X30),
            baseBranchTick: baseBranchTick_ // if == type(int).min, then current branch is master branch
        });
    }

    function _getLiquidatedBranchDebt(
        address vault_,
        uint currentBranchData_,
        uint branchId_,
        uint status_,
        int minimaTick_
    ) internal view returns (BranchDebt memory branchDebt_) {
        uint debtLiquidity_ = BigMathMinified.fromBigNumber((currentBranchData_ >> 52) & X64, 8, X8);
        (uint collateralRaw_, uint ratio_) = _getCollateralRaw(currentBranchData_, debtLiquidity_, minimaTick_);

        (, , uint256 vaultSupplyExchangePrice_, uint256 vaultBorrowExchangePrice_) = IFluidVault(vault_)
            .updateExchangePrices(VAULT_RESOLVER.getVaultVariables2Raw(vault_));

        branchDebt_ = BranchDebt({
            debtRaw: debtLiquidity_,
            collateralRaw: collateralRaw_,
            debtNormal: (debtLiquidity_ * vaultBorrowExchangePrice_) / 1e12,
            collateralNormal: (collateralRaw_ * vaultSupplyExchangePrice_) / 1e12,
            branchId: branchId_,
            status: status_,
            tick: minimaTick_, // as branch is merged/closed, so adding baseBranchTick_ as this is where it went out of existance
            partials: 0,
            ratio: ratio_,
            debtFactor: (currentBranchData_ >> 116) & X50,
            baseBranchId: ((currentBranchData_ >> 166) & X30),
            baseBranchTick: _tickHelper((currentBranchData_ >> 196) & X20) // if == type(int).min, then current branch is master branch
        });
    }

    function _getCollateralRaw(
        uint currentBranchData_,
        uint debtLiquidity_,
        int minimaTick_
    ) internal pure returns (uint collateralRaw_, uint ratio_) {
        ratio_ = TickMath.getRatioAtTick(int24(minimaTick_));
        uint ratioOneLess_ = (ratio_ * 10000) / 10015;
        uint length_ = ratio_ - ratioOneLess_;
        uint partials_ = (currentBranchData_ >> 22) & X30;
        uint currentRatio_ = ratioOneLess_ + ((length_ * partials_) / X30);
        collateralRaw_ = (debtLiquidity_ * TickMath.ZERO_TICK_SCALED_RATIO) / currentRatio_;
    }
}

File 2 of 10 : bigMathMinified.sol
// 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)
            }
        }
    }
}

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

/// @title library that calculates number "tick" and "ratioX96" from this: ratioX96 = (1.0015^tick) * 2^96
/// @notice this library is used in Fluid Vault protocol for optimiziation.
/// @dev "tick" supports between -32767 and 32767. "ratioX96" supports between 37075072 and 169307877264527972847801929085841449095838922544595
library TickMath {
    /// The minimum tick that can be passed in getRatioAtTick. 1.0015**-32767
    int24 internal constant MIN_TICK = -32767;
    /// The maximum tick that can be passed in getRatioAtTick. 1.0015**32767
    int24 internal constant MAX_TICK = 32767;

    uint256 internal constant FACTOR00 = 0x100000000000000000000000000000000;
    uint256 internal constant FACTOR01 = 0xff9dd7de423466c20352b1246ce4856f; // 2^128/1.0015**1 = 339772707859149738855091969477551883631
    uint256 internal constant FACTOR02 = 0xff3bd55f4488ad277531fa1c725a66d0; // 2^128/1.0015**2 = 339263812140938331358054887146831636176
    uint256 internal constant FACTOR03 = 0xfe78410fd6498b73cb96a6917f853259; // 2^128/1.0015**4 = 338248306163758188337119769319392490073
    uint256 internal constant FACTOR04 = 0xfcf2d9987c9be178ad5bfeffaa123273; // 2^128/1.0015**8 = 336226404141693512316971918999264834163
    uint256 internal constant FACTOR05 = 0xf9ef02c4529258b057769680fc6601b3; // 2^128/1.0015**16 = 332218786018727629051611634067491389875
    uint256 internal constant FACTOR06 = 0xf402d288133a85a17784a411f7aba082; // 2^128/1.0015**32 = 324346285652234375371948336458280706178
    uint256 internal constant FACTOR07 = 0xe895615b5beb6386553757b0352bda90; // 2^128/1.0015**64 = 309156521885964218294057947947195947664
    uint256 internal constant FACTOR08 = 0xd34f17a00ffa00a8309940a15930391a; // 2^128/1.0015**128 = 280877777739312896540849703637713172762 
    uint256 internal constant FACTOR09 = 0xae6b7961714e20548d88ea5123f9a0ff; // 2^128/1.0015**256 = 231843708922198649176471782639349113087
    uint256 internal constant FACTOR10 = 0x76d6461f27082d74e0feed3b388c0ca1; // 2^128/1.0015**512 = 157961477267171621126394973980180876449
    uint256 internal constant FACTOR11 = 0x372a3bfe0745d8b6b19d985d9a8b85bb; // 2^128/1.0015**1024 = 73326833024599564193373530205717235131
    uint256 internal constant FACTOR12 = 0x0be32cbee48979763cf7247dd7bb539d; // 2^128/1.0015**2048 = 15801066890623697521348224657638773661
    uint256 internal constant FACTOR13 = 0x8d4f70c9ff4924dac37612d1e2921e;   // 2^128/1.0015**4096 = 733725103481409245883800626999235102
    uint256 internal constant FACTOR14 = 0x4e009ae5519380809a02ca7aec77;     // 2^128/1.0015**8192 = 1582075887005588088019997442108535
    uint256 internal constant FACTOR15 = 0x17c45e641b6e95dee056ff10;         // 2^128/1.0015**16384 = 7355550435635883087458926352

    /// The minimum value that can be returned from getRatioAtTick. Equivalent to getRatioAtTick(MIN_TICK). ~ Equivalent to `(1 << 96) * (1.0015**-32767)`
    uint256 internal constant MIN_RATIOX96 = 37075072;
    /// The maximum value that can be returned from getRatioAtTick. Equivalent to getRatioAtTick(MAX_TICK).
    /// ~ Equivalent to `(1 << 96) * (1.0015**32767)`, rounding etc. leading to minor difference
    uint256 internal constant MAX_RATIOX96 = 169307877264527972847801929085841449095838922544595;

    uint256 internal constant ZERO_TICK_SCALED_RATIO = 0x1000000000000000000000000; // 1 << 96 // 79228162514264337593543950336
    uint256 internal constant _1E26 = 1e26;

    /// @notice ratioX96 = (1.0015^tick) * 2^96
    /// @dev Throws if |tick| > max tick
    /// @param tick The input tick for the above formula
    /// @return ratioX96 ratio = (debt amount/collateral amount)
    function getRatioAtTick(int tick) internal pure returns (uint256 ratioX96) {
        assembly {
            let absTick_ := sub(xor(tick, sar(255, tick)), sar(255, tick))

            if gt(absTick_, MAX_TICK) {
                revert(0, 0)
            }
            let factor_ := FACTOR00
            if and(absTick_, 0x1) {
                factor_ := FACTOR01
            }
            if and(absTick_, 0x2) {
                factor_ := shr(128, mul(factor_, FACTOR02))
            }
            if and(absTick_, 0x4) {
                factor_ := shr(128, mul(factor_, FACTOR03))
            }
            if and(absTick_, 0x8) {
                factor_ := shr(128, mul(factor_, FACTOR04))
            }
            if and(absTick_, 0x10) {
                factor_ := shr(128, mul(factor_, FACTOR05))
            }
            if and(absTick_, 0x20) {
                factor_ := shr(128, mul(factor_, FACTOR06))
            }
            if and(absTick_, 0x40) {
                factor_ := shr(128, mul(factor_, FACTOR07))
            }
            if and(absTick_, 0x80) {
                factor_ := shr(128, mul(factor_, FACTOR08))
            }
            if and(absTick_, 0x100) {
                factor_ := shr(128, mul(factor_, FACTOR09))
            }
            if and(absTick_, 0x200) {
                factor_ := shr(128, mul(factor_, FACTOR10))
            }
            if and(absTick_, 0x400) {
                factor_ := shr(128, mul(factor_, FACTOR11))
            }
            if and(absTick_, 0x800) {
                factor_ := shr(128, mul(factor_, FACTOR12))
            }
            if and(absTick_, 0x1000) {
                factor_ := shr(128, mul(factor_, FACTOR13))
            }
            if and(absTick_, 0x2000) {
                factor_ := shr(128, mul(factor_, FACTOR14))
            }
            if and(absTick_, 0x4000) {
                factor_ := shr(128, mul(factor_, FACTOR15))
            }

            let precision_ := 0
            if iszero(and(tick, 0x8000000000000000000000000000000000000000000000000000000000000000)) {
                factor_ := div(0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, factor_)
                // we round up in the division so getTickAtRatio of the output price is always consistent
                if mod(factor_, 0x100000000) {
                    precision_ := 1
                }
            }
            ratioX96 := add(shr(32, factor_), precision_)
        }
    }

    /// @notice ratioX96 = (1.0015^tick) * 2^96
    /// @dev Throws if ratioX96 > max ratio || ratioX96 < min ratio
    /// @param ratioX96 The input ratio; ratio = (debt amount/collateral amount)
    /// @return tick The output tick for the above formula. Returns in round down form. if tick is 123.23 then 123, if tick is -123.23 then returns -124
    /// @return perfectRatioX96 perfect ratio for the above tick
    function getTickAtRatio(uint256 ratioX96) internal pure returns (int tick, uint perfectRatioX96) {
        assembly {
            if or(gt(ratioX96, MAX_RATIOX96), lt(ratioX96, MIN_RATIOX96)) {
                revert(0, 0)
            }

            let cond := lt(ratioX96, ZERO_TICK_SCALED_RATIO)
            let factor_

            if iszero(cond) {
                // if ratioX96 >= ZERO_TICK_SCALED_RATIO
                factor_ := div(mul(ratioX96, _1E26), ZERO_TICK_SCALED_RATIO)
            }
            if cond {
                // ratioX96 < ZERO_TICK_SCALED_RATIO
                factor_ := div(mul(ZERO_TICK_SCALED_RATIO, _1E26), ratioX96)
            }

            // put in https://www.wolframalpha.com/ whole equation: (1.0015^tick) * 2^96 * 10^26 / 79228162514264337593543950336

            // for tick = 16384
            // ratioX96 = (1.0015^16384) * 2^96 = 3665252098134783297721995888537077351735
            // 3665252098134783297721995888537077351735 * 10^26 / 79228162514264337593543950336 =
            // 4626198540796508716348404308345255985.06131964639489434655721
            if iszero(lt(factor_, 4626198540796508716348404308345255985)) {
                tick := or(tick, 0x4000)
                factor_ := div(mul(factor_, _1E26), 4626198540796508716348404308345255985)
            }
            // for tick = 8192
            // ratioX96 = (1.0015^8192) * 2^96 = 17040868196391020479062776466509865
            // 17040868196391020479062776466509865 * 10^26 / 79228162514264337593543950336 =
            // 21508599537851153911767490449162.3037648642153898377655505172
            if iszero(lt(factor_, 21508599537851153911767490449162)) {
                tick := or(tick, 0x2000)
                factor_ := div(mul(factor_, _1E26), 21508599537851153911767490449162)
            }
            // for tick = 4096
            // ratioX96 = (1.0015^4096) * 2^96 = 36743933851015821532611831851150
            // 36743933851015821532611831851150 * 10^26 / 79228162514264337593543950336 =
            // 46377364670549310883002866648.9777607649742626173648716941385
            if iszero(lt(factor_, 46377364670549310883002866649)) {
                tick := or(tick, 0x1000)
                factor_ := div(mul(factor_, _1E26), 46377364670549310883002866649)
            }
            // for tick = 2048
            // ratioX96 = (1.0015^2048) * 2^96 = 1706210527034005899209104452335
            // 1706210527034005899209104452335 * 10^26 / 79228162514264337593543950336 =
            // 2153540449365864845468344760.06357108484096046743300420319322
            if iszero(lt(factor_, 2153540449365864845468344760)) {
                tick := or(tick, 0x800)
                factor_ := div(mul(factor_, _1E26), 2153540449365864845468344760)
            }
            // for tick = 1024
            // ratioX96 = (1.0015^1024) * 2^96 = 367668226692760093024536487236
            // 367668226692760093024536487236 * 10^26 / 79228162514264337593543950336 =
            // 464062544207767844008185024.950588990554136265212906454481127
            if iszero(lt(factor_, 464062544207767844008185025)) {
                tick := or(tick, 0x400)
                factor_ := div(mul(factor_, _1E26), 464062544207767844008185025)
            }
            // for tick = 512
            // ratioX96 = (1.0015^512) * 2^96 = 170674186729409605620119663668
            // 170674186729409605620119663668 * 10^26 / 79228162514264337593543950336 =
            // 215421109505955298802281577.031879604792139232258508172947569
            if iszero(lt(factor_, 215421109505955298802281577)) {
                tick := or(tick, 0x200)
                factor_ := div(mul(factor_, _1E26), 215421109505955298802281577)
            }
            // for tick = 256
            // ratioX96 = (1.0015^256) * 2^96 = 116285004205991934861656513301
            // 116285004205991934861656513301 * 10^26 / 79228162514264337593543950336 =
            // 146772309890508740607270614.667650899656438875541505058062410
            if iszero(lt(factor_, 146772309890508740607270615)) {
                tick := or(tick, 0x100)
                factor_ := div(mul(factor_, _1E26), 146772309890508740607270615)
            }
            // for tick = 128
            // ratioX96 = (1.0015^128) * 2^96 = 95984619659632141743747099590
            // 95984619659632141743747099590 * 10^26 / 79228162514264337593543950336 =
            // 121149622323187099817270416.157248837742741760456796835775887
            if iszero(lt(factor_, 121149622323187099817270416)) {
                tick := or(tick, 0x80)
                factor_ := div(mul(factor_, _1E26), 121149622323187099817270416)
            }
            // for tick = 64
            // ratioX96 = (1.0015^64) * 2^96 = 87204845308406958006717891124
            // 87204845308406958006717891124 * 10^26 / 79228162514264337593543950336 =
            // 110067989135437147685980801.568068573422377364214113968609839
            if iszero(lt(factor_, 110067989135437147685980801)) {
                tick := or(tick, 0x40)
                factor_ := div(mul(factor_, _1E26), 110067989135437147685980801)
            }
            // for tick = 32
            // ratioX96 = (1.0015^32) * 2^96 = 83120873769022354029916374475
            // 83120873769022354029916374475 * 10^26 / 79228162514264337593543950336 =
            // 104913292358707887270979599.831816586773651266562785765558183
            if iszero(lt(factor_, 104913292358707887270979600)) {
                tick := or(tick, 0x20)
                factor_ := div(mul(factor_, _1E26), 104913292358707887270979600)
            }
            // for tick = 16
            // ratioX96 = (1.0015^16) * 2^96 = 81151180492336368327184716176
            // 81151180492336368327184716176 * 10^26 / 79228162514264337593543950336 =
            // 102427189924701091191840927.762844039579442328381455567932128
            if iszero(lt(factor_, 102427189924701091191840928)) {
                tick := or(tick, 0x10)
                factor_ := div(mul(factor_, _1E26), 102427189924701091191840928)
            }
            // for tick = 8
            // ratioX96 = (1.0015^8) * 2^96 = 80183906840906820640659903620
            // 80183906840906820640659903620 * 10^26 / 79228162514264337593543950336 =
            // 101206318935480056907421312.890625
            if iszero(lt(factor_, 101206318935480056907421313)) {
                tick := or(tick, 0x8)
                factor_ := div(mul(factor_, _1E26), 101206318935480056907421313)
            }
            // for tick = 4
            // ratioX96 = (1.0015^4) * 2^96 = 79704602139525152702959747603
            // 79704602139525152702959747603 * 10^26 / 79228162514264337593543950336 =
            // 100601351350506250000000000
            if iszero(lt(factor_, 100601351350506250000000000)) {
                tick := or(tick, 0x4)
                factor_ := div(mul(factor_, _1E26), 100601351350506250000000000)
            }
            // for tick = 2
            // ratioX96 = (1.0015^2) * 2^96 = 79466025265172787701084167660
            // 79466025265172787701084167660 * 10^26 / 79228162514264337593543950336 =
            // 100300225000000000000000000
            if iszero(lt(factor_, 100300225000000000000000000)) {
                tick := or(tick, 0x2)
                factor_ := div(mul(factor_, _1E26), 100300225000000000000000000)
            }
            // for tick = 1
            // ratioX96 = (1.0015^1) * 2^96 = 79347004758035734099934266261
            // 79347004758035734099934266261 * 10^26 / 79228162514264337593543950336 =
            // 100150000000000000000000000
            if iszero(lt(factor_, 100150000000000000000000000)) {
                tick := or(tick, 0x1)
                factor_ := div(mul(factor_, _1E26), 100150000000000000000000000)
            }
            if iszero(cond) {
                // if ratioX96 >= ZERO_TICK_SCALED_RATIO
                perfectRatioX96 := div(mul(ratioX96, _1E26), factor_)
            }
            if cond {
                // ratioX96 < ZERO_TICK_SCALED_RATIO
                tick := not(tick)
                perfectRatioX96 := div(mul(ratioX96, factor_), 100150000000000000000000000)
            }
            // perfect ratio should always be <= ratioX96
            // not sure if it can ever be bigger but better to have extra checks
            if gt(perfectRatioX96, ratioX96) {
                revert(0, 0)
            }
        }
    }
}

File 4 of 10 : 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;
    }
}

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

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

abstract contract Structs {
    struct RateData {
        uint256 version;
        AdminModuleStructs.RateDataV1Params rateDataV1;
        AdminModuleStructs.RateDataV2Params rateDataV2;
    }

    struct OverallTokenData {
        uint256 borrowRate;
        uint256 supplyRate;
        uint256 fee; // revenue fee
        uint256 lastStoredUtilization;
        uint256 storageUpdateThreshold;
        uint256 lastUpdateTimestamp;
        uint256 supplyExchangePrice;
        uint256 borrowExchangePrice;
        uint256 supplyRawInterest;
        uint256 supplyInterestFree;
        uint256 borrowRawInterest;
        uint256 borrowInterestFree;
        uint256 totalSupply;
        uint256 totalBorrow;
        uint256 revenue;
        uint256 maxUtilization; // maximum allowed utilization
        RateData rateData;
    }

    // amounts are always in normal (for withInterest already multiplied with exchange price)
    struct UserSupplyData {
        bool modeWithInterest; // true if mode = with interest, false = without interest
        uint256 supply; // user supply amount
        // the withdrawal limit (e.g. if 10% is the limit, and 100M is supplied, it would be 90M)
        uint256 withdrawalLimit;
        uint256 lastUpdateTimestamp;
        uint256 expandPercent; // withdrawal limit expand percent in 1e2
        uint256 expandDuration; // withdrawal limit expand duration in seconds
        uint256 baseWithdrawalLimit;
        // the current actual max withdrawable amount (e.g. if 10% is the limit, and 100M is supplied, it would be 10M)
        uint256 withdrawableUntilLimit;
        uint256 withdrawable; // actual currently withdrawable amount (supply - withdrawal Limit) & considering balance
    }

    // amounts are always in normal (for withInterest already multiplied with exchange price)
    struct UserBorrowData {
        bool modeWithInterest; // true if mode = with interest, false = without interest
        uint256 borrow; // user borrow amount
        uint256 borrowLimit;
        uint256 lastUpdateTimestamp;
        uint256 expandPercent;
        uint256 expandDuration;
        uint256 baseBorrowLimit;
        uint256 maxBorrowLimit;
        uint256 borrowableUntilLimit; // borrowable amount until any borrow limit (incl. max utilization limit)
        uint256 borrowable; // actual currently borrowable amount (borrow limit - already borrowed) & considering balance, max utilization
        uint256 borrowLimitUtilization; // borrow limit for `maxUtilization`
    }
}

File 6 of 10 : iVaultResolver.sol
//SPDX-License-Identifier: MIT
pragma solidity 0.8.21;

import { Structs } from "./structs.sol";

interface IFluidVaultResolver {
    function vaultByNftId(uint nftId_) external view returns (address vault_);

    function positionByNftId(
        uint nftId_
    ) external view returns (Structs.UserPosition memory userPosition_, Structs.VaultEntireData memory vaultData_);

    function getVaultVariablesRaw(address vault_) external view returns (uint);

    function getVaultVariables2Raw(address vault_) external view returns (uint);

    function getTickHasDebtRaw(address vault_, int key_) external view returns (uint);

    function getTickDataRaw(address vault_, int tick_) external view returns (uint);

    function getBranchDataRaw(address vault_, uint branch_) external view returns (uint);

    function getPositionDataRaw(address vault_, uint positionId_) external view returns (uint);

    function getAllVaultsAddresses() external view returns (address[] memory vaults_);

    function getVaultLiquidation(
        address vault_,
        uint tokenInAmt_
    ) external returns (Structs.LiquidationStruct memory liquidationData_);

    function getVaultEntireData(address vault_) external view returns (Structs.VaultEntireData memory vaultData_);
}

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

import { IFluidVault } from "../../../protocols/vault/interfaces/iVault.sol";
import { Structs as FluidLiquidityResolverStructs } from "../liquidity/structs.sol";

// @dev Amounts are always in token amount for normal col / normal debt or in
// shares for Dex smart col / smart debt.
contract Structs {
    struct Configs {
        // can be supplyRate instead if Vault Type is smart col. in that case if 1st bit == 1 then positive else negative
        uint16 supplyRateMagnifier;
        // can be borrowRate instead if Vault Type is smart debt. in that case if 1st bit == 1 then positive else negative
        uint16 borrowRateMagnifier;
        uint16 collateralFactor;
        uint16 liquidationThreshold;
        uint16 liquidationMaxLimit;
        uint16 withdrawalGap;
        uint16 liquidationPenalty;
        uint16 borrowFee;
        address oracle;
        // Oracle price is always debt per col, i.e. amount of debt for 1 col.
        // In case of Dex this price can be used to resolve shares values w.r.t. token0 or token1:
        // - T2: debt token per 1 col share
        // - T3: debt shares per 1 col token
        // - T4: debt shares per 1 col share
        uint oraclePriceOperate;
        uint oraclePriceLiquidate;
        address rebalancer;
        uint lastUpdateTimestamp;
    }

    struct ExchangePricesAndRates {
        uint lastStoredLiquiditySupplyExchangePrice; // 0 in case of smart col
        uint lastStoredLiquidityBorrowExchangePrice; // 0 in case of smart debt
        uint lastStoredVaultSupplyExchangePrice;
        uint lastStoredVaultBorrowExchangePrice;
        uint liquiditySupplyExchangePrice; // set to 1e12 in case of smart col
        uint liquidityBorrowExchangePrice; // set to 1e12 in case of smart debt
        uint vaultSupplyExchangePrice;
        uint vaultBorrowExchangePrice;
        uint supplyRateLiquidity; // set to 0 in case of smart col. Must get per token through DexEntireData
        uint borrowRateLiquidity; // set to 0 in case of smart debt. Must get per token through DexEntireData
        // supplyRateVault or borrowRateVault:
        // - when normal col / debt: rate at liquidity + diff rewards or fee through magnifier (rewardsOrFeeRate below)
        // - when smart col / debt: rewards or fee rate at the vault itself. always == rewardsOrFeeRate below.
        // to get the full rates for vault when smart col / debt, combine with data from DexResolver:
        // - rateAtLiquidity for token0 or token1 (DexResolver)
        // - the rewards or fee rate at the vault (VaultResolver)
        // - the Dex APR (currently off-chain compiled through tracking swap events at the DEX)
        int supplyRateVault; // can be negative in case of smart col (meaning pay to supply)
        int borrowRateVault; // can be negative in case of smart debt (meaning get paid to borrow)
        // rewardsOrFeeRateSupply: rewards or fee rate in percent 1e2 precision (1% = 100, 100% = 10000).
        // positive rewards, negative fee.
        // for smart col vaults: supplyRateVault == supplyRateLiquidity.
        // for normal col vaults: relative percent to supplyRateLiquidity, e.g.:
        // when rewards: supplyRateLiquidity = 4%, rewardsOrFeeRateSupply = 20%, supplyRateVault = 4.8%.
        // when fee: supplyRateLiquidity = 4%, rewardsOrFeeRateSupply = -30%, supplyRateVault = 2.8%.
        int rewardsOrFeeRateSupply;
        // rewardsOrFeeRateBorrow: rewards or fee rate in percent 1e2 precision (1% = 100, 100% = 10000).
        // negative rewards, positive fee.
        // for smart debt vaults: borrowRateVault == borrowRateLiquidity.
        // for normal debt vaults: relative percent to borrowRateLiquidity, e.g.:
        // when rewards: borrowRateLiquidity = 4%, rewardsOrFeeRateBorrow = -20%, borrowRateVault = 3.2%.
        // when fee: borrowRateLiquidity = 4%, rewardsOrFeeRateBorrow = 30%, borrowRateVault = 5.2%.
        int rewardsOrFeeRateBorrow;
    }

    struct TotalSupplyAndBorrow {
        uint totalSupplyVault;
        uint totalBorrowVault;
        uint totalSupplyLiquidityOrDex;
        uint totalBorrowLiquidityOrDex;
        uint absorbedSupply;
        uint absorbedBorrow;
    }

    struct LimitsAndAvailability {
        // in case of DEX: withdrawable / borrowable amount of vault at DEX, BUT there could be that DEX can not withdraw
        // that much at Liquidity! So for DEX this must be combined with returned data in DexResolver.
        uint withdrawLimit;
        uint withdrawableUntilLimit;
        uint withdrawable;
        uint borrowLimit;
        uint borrowableUntilLimit; // borrowable amount until any borrow limit (incl. max utilization limit)
        uint borrowable; // actual currently borrowable amount (borrow limit - already borrowed) & considering balance, max utilization
        uint borrowLimitUtilization; // borrow limit for `maxUtilization` config at Liquidity
        uint minimumBorrowing;
    }

    struct CurrentBranchState {
        uint status; // if 0 then not liquidated, if 1 then liquidated, if 2 then merged, if 3 then closed
        int minimaTick;
        uint debtFactor;
        uint partials;
        uint debtLiquidity;
        uint baseBranchId;
        int baseBranchMinima;
    }

    struct VaultState {
        uint totalPositions;
        int topTick;
        uint currentBranch;
        uint totalBranch;
        uint totalBorrow;
        uint totalSupply;
        CurrentBranchState currentBranchState;
    }

    struct VaultEntireData {
        address vault;
        bool isSmartCol; // true if col token is a Fluid Dex
        bool isSmartDebt; // true if debt token is a Fluid Dex
        IFluidVault.ConstantViews constantVariables;
        Configs configs;
        ExchangePricesAndRates exchangePricesAndRates;
        TotalSupplyAndBorrow totalSupplyAndBorrow;
        LimitsAndAvailability limitsAndAvailability;
        VaultState vaultState;
        // liquidity related data such as supply amount, limits, expansion etc.
        // Also set for Dex, limits are in shares and same things apply as noted for LimitsAndAvailability above!
        FluidLiquidityResolverStructs.UserSupplyData liquidityUserSupplyData;
        // liquidity related data such as borrow amount, limits, expansion etc.
        // Also set for Dex, limits are in shares and same things apply as noted for LimitsAndAvailability above!
        FluidLiquidityResolverStructs.UserBorrowData liquidityUserBorrowData;
    }

    struct UserPosition {
        uint nftId;
        address owner;
        bool isLiquidated;
        bool isSupplyPosition; // if true that means borrowing is 0
        int tick;
        uint tickId;
        uint beforeSupply;
        uint beforeBorrow;
        uint beforeDustBorrow;
        uint supply;
        uint borrow;
        uint dustBorrow;
    }

    /// @dev liquidation related data
    /// @param vault address of vault
    /// @param token0In address of token in
    /// @param token0Out address of token out
    /// @param token1In address of token in (if smart debt)
    /// @param token1Out address of token out (if smart col)
    /// @param inAmt (without absorb liquidity) minimum of available liquidation
    /// @param outAmt (without absorb liquidity) expected token out, collateral to withdraw
    /// @param inAmtWithAbsorb (absorb liquidity included) minimum of available liquidation. In most cases it'll be same as inAmt but sometimes can be bigger.
    /// @param outAmtWithAbsorb (absorb liquidity included) expected token out, collateral to withdraw. In most cases it'll be same as outAmt but sometimes can be bigger.
    /// @param absorbAvailable true if absorb is available
    /// @dev Liquidity in with absirb will always be >= without asborb. Sometimes without asborb can provide better swaps,
    ///      sometimes with absirb can provide better swaps. But available in with absirb will always be >= One
    struct LiquidationStruct {
        address vault;
        address token0In;
        address token0Out;
        address token1In;
        address token1Out;
        // amounts in case of smart debt are in shares, otherwise token amounts.
        // smart col can not be liquidated so to exchange inAmt always use DexResolver DexState.tokenPerDebtShare
        // and tokenPerColShare for outAmt when Vault is smart col.
        uint inAmt;
        uint outAmt;
        uint inAmtWithAbsorb;
        uint outAmtWithAbsorb;
        bool absorbAvailable;
    }

    struct AbsorbStruct {
        address vault;
        bool absorbAvailable;
    }
}

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

contract Structs {
    struct TickDebt {
        uint256 debtRaw;
        uint256 collateralRaw;
        uint256 debtNormal; // debtRaw * exchange price
        uint256 collateralNormal; // collateralRaw * exchange price
        uint256 ratio;
        int256 tick;
    }

    struct VaultsTickDebt {
        TickDebt[] tickDebt;
        int toTick;
    }

    struct BranchDebt {
        uint256 debtRaw;
        uint256 collateralRaw;
        uint256 debtNormal; // debtRaw * exchange price
        uint256 collateralNormal; // collateralRaw * exchange price
        uint256 branchId;
        uint256 status; // if 0 then not liquidated, if 1 then liquidated, if 2 then merged, if 3 then closed
        int256 tick;
        uint256 partials;
        uint256 ratio;
        uint debtFactor; // debt factor or connection factor
        uint baseBranchId;
        int baseBranchTick;
    }

    struct BranchesDebt {
        BranchDebt[] branchDebt;
    }
}

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

import { IFluidVaultResolver } from "../vault/iVaultResolver.sol";

contract Variables {
    IFluidVaultResolver public immutable VAULT_RESOLVER;

    uint internal constant X8 = 0xff;
    uint internal constant X19 = 0x7ffff;
    uint internal constant X20 = 0xfffff;
    uint internal constant X30 = 0x3fffffff;
    uint internal constant X50 = 0x3ffffffffffff;
    uint internal constant X64 = 0xffffffffffffffff;

    constructor(IFluidVaultResolver vaultResolver_) {
        VAULT_RESOLVER = vaultResolver_;
    }
}

File 10 of 10 : iVault.sol
//SPDX-License-Identifier: MIT
pragma solidity 0.8.21;

/// @notice common Fluid vaults interface, some methods only available for vaults > T1 (type, simulateLiquidate, rebalance is different)
interface IFluidVault {
    /// @notice returns the vault id
    function VAULT_ID() external view returns (uint256);

    /// @notice returns the vault id
    function TYPE() external view returns (uint256);

    /// @notice reads uint256 data `result_` from storage at a bytes32 storage `slot_` key.
    function readFromStorage(bytes32 slot_) external view returns (uint256 result_);

    struct Tokens {
        address token0;
        address token1;
    }

    struct ConstantViews {
        address liquidity;
        address factory;
        address operateImplementation;
        address adminImplementation;
        address secondaryImplementation;
        address deployer; // address which deploys oracle
        address supply; // either liquidity layer or DEX protocol
        address borrow; // either liquidity layer or DEX protocol
        Tokens supplyToken; // if smart collateral then address of token0 & token1 else just supply token address at token0 and token1 as empty
        Tokens borrowToken; // if smart debt then address of token0 & token1 else just borrow token address at token0 and token1 as empty
        uint256 vaultId;
        uint256 vaultType;
        bytes32 supplyExchangePriceSlot; // if smart collateral then slot is from DEX protocol else from liquidity layer
        bytes32 borrowExchangePriceSlot; // if smart debt then slot is from DEX protocol else from liquidity layer
        bytes32 userSupplySlot; // if smart collateral then slot is from DEX protocol else from liquidity layer
        bytes32 userBorrowSlot; // if smart debt then slot is from DEX protocol else from liquidity layer
    }

    /// @notice returns all Vault constants
    function constantsView() external view returns (ConstantViews memory constantsView_);

    /// @notice fetches the latest user position after a liquidation
    function fetchLatestPosition(
        int256 positionTick_,
        uint256 positionTickId_,
        uint256 positionRawDebt_,
        uint256 tickData_
    )
        external
        view
        returns (
            int256, // tick
            uint256, // raw debt
            uint256, // raw collateral
            uint256, // branchID_
            uint256 // branchData_
        );

    /// @notice calculates the updated vault exchange prices
    function updateExchangePrices(
        uint256 vaultVariables2_
    )
        external
        view
        returns (
            uint256 liqSupplyExPrice_,
            uint256 liqBorrowExPrice_,
            uint256 vaultSupplyExPrice_,
            uint256 vaultBorrowExPrice_
        );

    /// @notice calculates the updated vault exchange prices and writes them to storage
    function updateExchangePricesOnStorage()
        external
        returns (
            uint256 liqSupplyExPrice_,
            uint256 liqBorrowExPrice_,
            uint256 vaultSupplyExPrice_,
            uint256 vaultBorrowExPrice_
        );

    /// @notice returns the liquidity contract address
    function LIQUIDITY() external view returns (address);

    error FluidLiquidateResult(uint256 colLiquidated, uint256 debtLiquidated);

    function rebalance(
        int colToken0MinMax_,
        int colToken1MinMax_,
        int debtToken0MinMax_,
        int debtToken1MinMax_
    ) external payable returns (int supplyAmt_, int borrowAmt_);

    /// @notice reverts with FluidLiquidateResult
    function simulateLiquidate(uint debtAmt_, bool absorb_) 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

[{"inputs":[{"internalType":"contract IFluidVaultResolver","name":"vaultResolver_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"FluidVaultTicksBranchesResolver__AddressZero","type":"error"},{"inputs":[],"name":"VAULT_RESOLVER","outputs":[{"internalType":"contract IFluidVaultResolver","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllVaultsBranchesDebt","outputs":[{"components":[{"components":[{"internalType":"uint256","name":"debtRaw","type":"uint256"},{"internalType":"uint256","name":"collateralRaw","type":"uint256"},{"internalType":"uint256","name":"debtNormal","type":"uint256"},{"internalType":"uint256","name":"collateralNormal","type":"uint256"},{"internalType":"uint256","name":"branchId","type":"uint256"},{"internalType":"uint256","name":"status","type":"uint256"},{"internalType":"int256","name":"tick","type":"int256"},{"internalType":"uint256","name":"partials","type":"uint256"},{"internalType":"uint256","name":"ratio","type":"uint256"},{"internalType":"uint256","name":"debtFactor","type":"uint256"},{"internalType":"uint256","name":"baseBranchId","type":"uint256"},{"internalType":"int256","name":"baseBranchTick","type":"int256"}],"internalType":"struct Structs.BranchDebt[]","name":"branchDebt","type":"tuple[]"}],"internalType":"struct Structs.BranchesDebt[]","name":"branchesDebt_","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"totalTicks_","type":"uint256"}],"name":"getAllVaultsTicksDebt","outputs":[{"components":[{"components":[{"internalType":"uint256","name":"debtRaw","type":"uint256"},{"internalType":"uint256","name":"collateralRaw","type":"uint256"},{"internalType":"uint256","name":"debtNormal","type":"uint256"},{"internalType":"uint256","name":"collateralNormal","type":"uint256"},{"internalType":"uint256","name":"ratio","type":"uint256"},{"internalType":"int256","name":"tick","type":"int256"}],"internalType":"struct Structs.TickDebt[]","name":"tickDebt","type":"tuple[]"},{"internalType":"int256","name":"toTick","type":"int256"}],"internalType":"struct Structs.VaultsTickDebt[]","name":"vaultsTickDebt_","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"vault_","type":"address"},{"internalType":"uint256","name":"fromBranchId_","type":"uint256"},{"internalType":"uint256","name":"toBranchId_","type":"uint256"}],"name":"getBranchesDebt","outputs":[{"components":[{"internalType":"uint256","name":"debtRaw","type":"uint256"},{"internalType":"uint256","name":"collateralRaw","type":"uint256"},{"internalType":"uint256","name":"debtNormal","type":"uint256"},{"internalType":"uint256","name":"collateralNormal","type":"uint256"},{"internalType":"uint256","name":"branchId","type":"uint256"},{"internalType":"uint256","name":"status","type":"uint256"},{"internalType":"int256","name":"tick","type":"int256"},{"internalType":"uint256","name":"partials","type":"uint256"},{"internalType":"uint256","name":"ratio","type":"uint256"},{"internalType":"uint256","name":"debtFactor","type":"uint256"},{"internalType":"uint256","name":"baseBranchId","type":"uint256"},{"internalType":"int256","name":"baseBranchTick","type":"int256"}],"internalType":"struct Structs.BranchDebt[]","name":"branchesDebt_","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"vaults_","type":"address[]"},{"internalType":"uint256[]","name":"fromBranchIds_","type":"uint256[]"},{"internalType":"uint256[]","name":"toBranchIds_","type":"uint256[]"}],"name":"getMultipleVaultsBranchesDebt","outputs":[{"components":[{"components":[{"internalType":"uint256","name":"debtRaw","type":"uint256"},{"internalType":"uint256","name":"collateralRaw","type":"uint256"},{"internalType":"uint256","name":"debtNormal","type":"uint256"},{"internalType":"uint256","name":"collateralNormal","type":"uint256"},{"internalType":"uint256","name":"branchId","type":"uint256"},{"internalType":"uint256","name":"status","type":"uint256"},{"internalType":"int256","name":"tick","type":"int256"},{"internalType":"uint256","name":"partials","type":"uint256"},{"internalType":"uint256","name":"ratio","type":"uint256"},{"internalType":"uint256","name":"debtFactor","type":"uint256"},{"internalType":"uint256","name":"baseBranchId","type":"uint256"},{"internalType":"int256","name":"baseBranchTick","type":"int256"}],"internalType":"struct Structs.BranchDebt[]","name":"branchDebt","type":"tuple[]"}],"internalType":"struct Structs.BranchesDebt[]","name":"branchesDebt_","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"vaults_","type":"address[]"},{"internalType":"int256[]","name":"fromTicks_","type":"int256[]"},{"internalType":"uint256[]","name":"totalTicks_","type":"uint256[]"}],"name":"getMultipleVaultsTicksDebt","outputs":[{"components":[{"components":[{"internalType":"uint256","name":"debtRaw","type":"uint256"},{"internalType":"uint256","name":"collateralRaw","type":"uint256"},{"internalType":"uint256","name":"debtNormal","type":"uint256"},{"internalType":"uint256","name":"collateralNormal","type":"uint256"},{"internalType":"uint256","name":"ratio","type":"uint256"},{"internalType":"int256","name":"tick","type":"int256"}],"internalType":"struct Structs.TickDebt[]","name":"tickDebt","type":"tuple[]"},{"internalType":"int256","name":"toTick","type":"int256"}],"internalType":"struct Structs.VaultsTickDebt[]","name":"vaultsTickDebt_","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"vault_","type":"address"},{"internalType":"int256","name":"fromTick_","type":"int256"},{"internalType":"uint256","name":"totalTicks_","type":"uint256"}],"name":"getTicksDebt","outputs":[{"components":[{"internalType":"uint256","name":"debtRaw","type":"uint256"},{"internalType":"uint256","name":"collateralRaw","type":"uint256"},{"internalType":"uint256","name":"debtNormal","type":"uint256"},{"internalType":"uint256","name":"collateralNormal","type":"uint256"},{"internalType":"uint256","name":"ratio","type":"uint256"},{"internalType":"int256","name":"tick","type":"int256"}],"internalType":"struct Structs.TickDebt[]","name":"ticksDebt_","type":"tuple[]"},{"internalType":"int256","name":"toTick_","type":"int256"}],"stateMutability":"view","type":"function"}]

60a06040523480156200001157600080fd5b50604051620027d0380380620027d0833981016040819052620000349162000068565b6001600160a01b038116608081905262000061576040516365b1d2ef60e11b815260040160405180910390fd5b506200009a565b6000602082840312156200007b57600080fd5b81516001600160a01b03811681146200009357600080fd5b9392505050565b6080516126ce620001026000396000818160e40152818161029d015281816104b6015281816105f5015281816107160152818161094501528181610b9b01528181610ef8015281816110c90152818161127f015281816113b401526119bc01526126ce6000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c80637f3e2b481161005b5780637f3e2b48146100df578063a12a377a1461012b578063d17ac4a81461014b578063f2c8e5421461016b57600080fd5b80633009c6ba146100825780636791522f146100ab5780637cec0866146100be575b600080fd5b610095610090366004611ea9565b610173565b6040516100a29190611f85565b60405180910390f35b6100956100b936600461207b565b610297565b6100d16100cc366004612094565b61045d565b6040516100a29291906120c9565b6101067f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100a2565b61013e610139366004612147565b610808565b6040516100a29190612268565b61015e610159366004612094565b6108fa565b6040516100a291906122f0565b61013e610b95565b82516060908067ffffffffffffffff81111561019157610191611d13565b6040519080825280602002602001820160405280156101d757816020015b6040805180820190915260608152600060208201528152602001906001900390816101af5790505b50915060005b8181101561028e5761023b8682815181106101fa576101fa612303565b602002602001015186838151811061021457610214612303565b602002602001015186848151811061022e5761022e612303565b602002602001015161045d565b84838151811061024d5761024d612303565b602002602001015160000185848151811061026a5761026a612303565b6020908102919091018101510191909152528061028681612361565b9150506101dd565b50509392505050565b606060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a8d9f4936040518163ffffffff1660e01b8152600401600060405180830381865afa158015610306573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261034c9190810190612399565b80519091508067ffffffffffffffff81111561036a5761036a611d13565b6040519080825280602002602001820160405280156103b057816020015b6040805180820190915260608152600060208201528152602001906001900390816103885790505b50925060005b81811015610455576104028382815181106103d3576103d3612303565b60200260200101517f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8761045d565b85838151811061041457610414612303565b602002602001015160000186848151811061043157610431612303565b6020908102919091018101510191909152528061044d81612361565b9150506103b6565b505050919050565b6040517f03e883e000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152606091600091829161052991620fffff916002917f000000000000000000000000000000000000000000000000000000000000000016906303e883e090602401602060405180830381865afa1580156104fd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105219190612428565b901c16610d31565b9050848112610538578461053a565b805b94507f80000000000000000000000000000000000000000000000000000000000000008513156107ff57600080861261057e5761057961010087612470565b6105a1565b600161010061058d88836124d8565b6105979190612470565b6105a19190612500565b6040517fa8bc069300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff89811660048301526024820183905291925060009182917f00000000000000000000000000000000000000000000000000000000000000009091169063a8bc069390604401602060405180830381865afa15801561063e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106629190612428565b9050600061067284610100612527565b61067d9060ff6124d8565b6106868a612573565b61069091906124d8565b91821b90911c91506106a490508688612500565b6106af9060016124d8565b935060006106bf89868585610dff565b6040517feb1db01800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff808c1660048301819052929350600092839290916309f0d8cb917f00000000000000000000000000000000000000000000000000000000000000009091169063eb1db01890602401602060405180830381865afa15801561075f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107839190612428565b6040518263ffffffff1660e01b81526004016107a191815260200190565b608060405180830381865afa1580156107be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107e291906125ab565b9350935050506107f78b888787878787610f75565b975050505050505b50935093915050565b82516060908067ffffffffffffffff81111561082657610826611d13565b60405190808252806020026020018201604052801561086657816020015b6040805160208101909152606081528152602001906001900390816108445790505b50915060005b8181101561028e576108ca86828151811061088957610889612303565b60200260200101518683815181106108a3576108a3612303565b60200260200101518684815181106108bd576108bd612303565b60200260200101516108fa565b8382815181106108dc576108dc612303565b602090810291909101015152806108f281612361565b91505061086c565b6040517f03e883e000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301526060916000917f000000000000000000000000000000000000000000000000000000000000000016906303e883e090602401602060405180830381865afa15801561098c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109b09190612428565b9050603481901c633fffffff1683156109c957836109cc565b60015b93508481106109db57846109dd565b805b945083851015610a74576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f66726f6d4272616e636849645f206d757374206265206772656174657220746860448201527f616e206f7220657175616c20746f20746f4272616e636849645f00000000000060648201526084015b60405180910390fd5b610a7e84866125e1565b610a899060016125f4565b67ffffffffffffffff811115610aa157610aa1611d13565b604051908082528060200260200182016040528015610b3657816020015b610b236040518061018001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b815260200190600190039081610abf5790505b5092506000855b858110610b8a57610b4f888583611301565b8583610b5a81612361565b945081518110610b6c57610b6c612303565b60200260200101819052508080610b8290612607565b915050610b3d565b505050509392505050565b606060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a8d9f4936040518163ffffffff1660e01b8152600401600060405180830381865afa158015610c04573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610c4a9190810190612399565b80519091508067ffffffffffffffff811115610c6857610c68611d13565b604051908082528060200260200182016040528015610ca857816020015b604080516020810190915260608152815260200190600190039081610c865790505b50925060005b81811015610d2b57610cfb838281518110610ccb57610ccb612303565b60200260200101517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60006108fa565b848281518110610d0d57610d0d612303565b60209081029190910101515280610d2381612361565b915050610cae565b50505090565b6000620fffff8210610d9f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f696e76616c69642d6e756d6265720000000000000000000000000000000000006044820152606401610a6b565b8115610dd85781600116600114610dc757610dc2600183901c6207ffff16612573565b610dd2565b6207ffff600183901c165b92915050565b507f8000000000000000000000000000000000000000000000000000000000000000919050565b60008060005b8315610e7a57610e1484611483565b9150610e22826101016125e1565b610e2e836101016125e1565b9490941b90931c92610e416001836125e1565b610e4d86610100612527565b610e5791906124d8565b905085811215610e68575050610f6d565b82610e7281612361565b935050610e05565b610e838561263c565b94507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f8514610f6a576040517fa8bc069300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152602482018790527f0000000000000000000000000000000000000000000000000000000000000000169063a8bc069390604401602060405180830381865afa158015610f3f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f639190612428565b9350610e05565b50505b949350505050565b60608367ffffffffffffffff811115610f9057610f90611d13565b604051908082528060200260200182016040528015610ffa57816020015b610fe76040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b815260200190600190039081610fae5790505b509050600093506000806000805b88156112015760006110198a611483565b9050611027816101016125e1565b611033826101016125e1565b9a909a1b90991c986110466001826125e1565b6110528c610100612527565b61105c91906124d8565b9450508a84121561107057505050506112f6565b6040517f168a11c200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8d811660048301526024820186905267ffffffffffffffff916019917f0000000000000000000000000000000000000000000000000000000000000000169063168a11c290604401602060405180830381865afa158015611110573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111349190612428565b901c16600881901c60ff9091161b925061114d84611539565b915081611167846c0100000000000000000000000061266d565b6111719190612684565b90506040518060c0016040528084815260200182815260200164e8d4a51000888661119c919061266d565b6111a69190612684565b815260200164e8d4a510006111bb8a8561266d565b6111c59190612684565b81526020810184905260400185905285896111df81612361565b9a50815181106111f1576111f1612303565b6020026020010181905250611008565b61120a8a61263c565b99507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f8a146112f1576040517fa8bc069300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8d81166004830152602482018c90527f0000000000000000000000000000000000000000000000000000000000000000169063a8bc069390604401602060405180830381865afa1580156112c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112ea9190612428565b9850611008565b505050505b979650505050505050565b6113656040518061018001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6040517fbf518f5f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018490526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bf518f5f90604401602060405180830381865afa1580156113fd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114219190612428565b90506000611437620fffff600284901c16610d31565b905060038216600081900361145c576114528684878461179b565b935050505061147c565b806001036114715761145287848784866118d9565b611452838683611b49565b9392505050565b6000816fffffffffffffffffffffffffffffffff8311156114a55760809150811c5b67ffffffffffffffff8111156114bd576040918201911c5b63ffffffff8111156114d1576020918201911c5b61ffff8111156114e3576010918201911c5b60ff8111156114f4576008918201911c5b600f811115611505576004918201911c5b6003811115611516576002918201911c5b6001811115611526576001820191505b8015611533576001820191505b50919050565b600060ff82901d80831803617fff81111561155357600080fd5b700100000000000000000000000000000000600182161561158157506fff9dd7de423466c20352b1246ce4856f5b60028216156115a0576fff3bd55f4488ad277531fa1c725a66d00260801c5b60048216156115bf576ffe78410fd6498b73cb96a6917f8532590260801c5b60088216156115de576ffcf2d9987c9be178ad5bfeffaa1232730260801c5b60108216156115fd576ff9ef02c4529258b057769680fc6601b30260801c5b602082161561161c576ff402d288133a85a17784a411f7aba0820260801c5b604082161561163b576fe895615b5beb6386553757b0352bda900260801c5b608082161561165a576fd34f17a00ffa00a8309940a15930391a0260801c5b61010082161561167a576fae6b7961714e20548d88ea5123f9a0ff0260801c5b61020082161561169a576f76d6461f27082d74e0feed3b388c0ca10260801c5b6104008216156116ba576f372a3bfe0745d8b6b19d985d9a8b85bb0260801c5b6108008216156116da576f0be32cbee48979763cf7247dd7bb539d0260801c5b6110008216156116f9576e8d4f70c9ff4924dac37612d1e2921e0260801c5b612000821615611717576d4e009ae5519380809a02ca7aec770260801c5b614000821615611733576b17c45e641b6e95dee056ff100260801c5b600091507f80000000000000000000000000000000000000000000000000000000000000008416611791577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0463ffffffff81161561179157600191505b60201c0192915050565b6117ff6040518061018001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6000611813620fffff600288901c16610d31565b905060007f8000000000000000000000000000000000000000000000000000000000000000821361184557600061184e565b61184e82611539565b905060405180610180016040528060008152602001600081526020016000815260200160008152602001868152602001858152602001838152602001600081526020018281526020016603ffffffffffff607489901c168152602001633fffffff60a689901c1681526020016118cc620fffff60c48a901c16610d31565b9052979650505050505050565b61193d6040518061018001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b603c85901c66ffffffffffffff16603486901c60ff161b600080611962888487611c77565b6040517feb1db01800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff808d1660048301819052939550919350600092839290916309f0d8cb917f0000000000000000000000000000000000000000000000000000000000000000169063eb1db01890602401602060405180830381865afa158015611a03573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a279190612428565b6040518263ffffffff1660e01b8152600401611a4591815260200190565b608060405180830381865afa158015611a62573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a8691906125ab565b93509350505060405180610180016040528086815260200185815260200164e8d4a510008388611ab6919061266d565b611ac09190612684565b815260200164e8d4a51000611ad5858861266d565b611adf9190612684565b81526020018a8152602001898152602001888152602001600081526020018481526020016603ffffffffffff60748d901c168152602001633fffffff60a68d901c168152602001611b38620fffff60c48e901c16610d31565b90529b9a5050505050505050505050565b611bad6040518061018001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6000611bc1620fffff60c487901c16610d31565b905060007f80000000000000000000000000000000000000000000000000000000000000008213611bf3576000611bfc565b611bfc82611539565b905060405180610180016040528060008152602001600081526020016000815260200160008152602001868152602001858152602001838152602001600081526020018281526020016603ffffffffffff607489901c168152602001633fffffff60a689901c16815260200183815250925050509392505050565b600080611c868360020b611539565b9050600061271f611c998361271061266d565b611ca39190612684565b90506000611cb182846125e1565b9050633fffffff601688901c811690600090611ccd838561266d565b611cd79190612684565b611ce190856125f4565b905080611cfb6c010000000000000000000000008a61266d565b611d059190612684565b955050505050935093915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611d8957611d89611d13565b604052919050565b600067ffffffffffffffff821115611dab57611dab611d13565b5060051b60200190565b73ffffffffffffffffffffffffffffffffffffffff81168114611dd757600080fd5b50565b600082601f830112611deb57600080fd5b81356020611e00611dfb83611d91565b611d42565b82815260059290921b84018101918181019086841115611e1f57600080fd5b8286015b84811015611e43578035611e3681611db5565b8352918301918301611e23565b509695505050505050565b600082601f830112611e5f57600080fd5b81356020611e6f611dfb83611d91565b82815260059290921b84018101918181019086841115611e8e57600080fd5b8286015b84811015611e435780358352918301918301611e92565b600080600060608486031215611ebe57600080fd5b833567ffffffffffffffff80821115611ed657600080fd5b611ee287838801611dda565b9450602091508186013581811115611ef957600080fd5b8601601f81018813611f0a57600080fd5b8035611f18611dfb82611d91565b81815260059190911b8201840190848101908a831115611f3757600080fd5b928501925b82841015611f5557833582529285019290850190611f3c565b96505050506040860135915080821115611f6e57600080fd5b50611f7b86828701611e4e565b9150509250925092565b60006020808301818452808551808352604092508286019150828160051b8701018488016000805b8481101561206c578984037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0018652825180518886528051898701819052908a0190849060608801905b8083101561204d578351805183526020808201519084015260408082015190840152606080820151908401526080808201519084015260a0908101519083015260c0820191508c84019350600183019250611ff7565b50928b0151968b01969096525095880195935091870191600101611fad565b50919998505050505050505050565b60006020828403121561208d57600080fd5b5035919050565b6000806000606084860312156120a957600080fd5b83356120b481611db5565b95602085013595506040909401359392505050565b604080825283519082018190526000906020906060840190828701845b82811015612138578151805185526020808201519086015260408082015190860152606080820151908601526080808201519086015260a0908101519085015260c084019350908401906001016120e6565b50505092019290925292915050565b60008060006060848603121561215c57600080fd5b833567ffffffffffffffff8082111561217457600080fd5b61218087838801611dda565b9450602086013591508082111561219657600080fd5b6121a287838801611e4e565b93506040860135915080821115611f6e57600080fd5b600081518084526020808501945080840160005b8381101561225d57815180518852838101518489015260408082015190890152606080820151908901526080808201519089015260a0808201519089015260c0808201519089015260e08082015190890152610100808201519089015261012080820151908901526101408082015190890152610160908101519088015261018090960195908201906001016121cc565b509495945050505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b828110156122e3577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184528151518686526122d0878701826121b8565b955050928501929085019060010161228f565b5092979650505050505050565b60208152600061147c60208301846121b8565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361239257612392612332565b5060010190565b600060208083850312156123ac57600080fd5b825167ffffffffffffffff8111156123c357600080fd5b8301601f810185136123d457600080fd5b80516123e2611dfb82611d91565b81815260059190911b8201830190838101908783111561240157600080fd5b928401925b828410156112f657835161241981611db5565b82529284019290840190612406565b60006020828403121561243a57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261247f5761247f612441565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f8000000000000000000000000000000000000000000000000000000000000000831416156124d3576124d3612332565b500590565b80820182811260008312801582168215821617156124f8576124f8612332565b505092915050565b818103600083128015838313168383128216171561252057612520612332565b5092915050565b808202600082127f80000000000000000000000000000000000000000000000000000000000000008414161561255f5761255f612332565b8181058314821517610dd257610dd2612332565b60007f800000000000000000000000000000000000000000000000000000000000000082036125a4576125a4612332565b5060000390565b600080600080608085870312156125c157600080fd5b505082516020840151604085015160609095015191969095509092509050565b81810381811115610dd257610dd2612332565b80820180821115610dd257610dd2612332565b60008161261657612616612332565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b60007f8000000000000000000000000000000000000000000000000000000000000000820361261657612616612332565b8082028115828204841417610dd257610dd2612332565b60008261269357612693612441565b50049056fea26469706673582212208701324d348fcb8b848363e1d0ed7d2920058c437e7fe09f90f34c3262e5b2fc64736f6c63430008150033000000000000000000000000d6c90a7b61f3e0ac04e2f4b0359ab0ac09035507

Deployed Bytecode

0x608060405234801561001057600080fd5b506004361061007d5760003560e01c80637f3e2b481161005b5780637f3e2b48146100df578063a12a377a1461012b578063d17ac4a81461014b578063f2c8e5421461016b57600080fd5b80633009c6ba146100825780636791522f146100ab5780637cec0866146100be575b600080fd5b610095610090366004611ea9565b610173565b6040516100a29190611f85565b60405180910390f35b6100956100b936600461207b565b610297565b6100d16100cc366004612094565b61045d565b6040516100a29291906120c9565b6101067f000000000000000000000000d6c90a7b61f3e0ac04e2f4b0359ab0ac0903550781565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100a2565b61013e610139366004612147565b610808565b6040516100a29190612268565b61015e610159366004612094565b6108fa565b6040516100a291906122f0565b61013e610b95565b82516060908067ffffffffffffffff81111561019157610191611d13565b6040519080825280602002602001820160405280156101d757816020015b6040805180820190915260608152600060208201528152602001906001900390816101af5790505b50915060005b8181101561028e5761023b8682815181106101fa576101fa612303565b602002602001015186838151811061021457610214612303565b602002602001015186848151811061022e5761022e612303565b602002602001015161045d565b84838151811061024d5761024d612303565b602002602001015160000185848151811061026a5761026a612303565b6020908102919091018101510191909152528061028681612361565b9150506101dd565b50509392505050565b606060007f000000000000000000000000d6c90a7b61f3e0ac04e2f4b0359ab0ac0903550773ffffffffffffffffffffffffffffffffffffffff1663a8d9f4936040518163ffffffff1660e01b8152600401600060405180830381865afa158015610306573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261034c9190810190612399565b80519091508067ffffffffffffffff81111561036a5761036a611d13565b6040519080825280602002602001820160405280156103b057816020015b6040805180820190915260608152600060208201528152602001906001900390816103885790505b50925060005b81811015610455576104028382815181106103d3576103d3612303565b60200260200101517f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8761045d565b85838151811061041457610414612303565b602002602001015160000186848151811061043157610431612303565b6020908102919091018101510191909152528061044d81612361565b9150506103b6565b505050919050565b6040517f03e883e000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152606091600091829161052991620fffff916002917f000000000000000000000000d6c90a7b61f3e0ac04e2f4b0359ab0ac0903550716906303e883e090602401602060405180830381865afa1580156104fd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105219190612428565b901c16610d31565b9050848112610538578461053a565b805b94507f80000000000000000000000000000000000000000000000000000000000000008513156107ff57600080861261057e5761057961010087612470565b6105a1565b600161010061058d88836124d8565b6105979190612470565b6105a19190612500565b6040517fa8bc069300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff89811660048301526024820183905291925060009182917f000000000000000000000000d6c90a7b61f3e0ac04e2f4b0359ab0ac090355079091169063a8bc069390604401602060405180830381865afa15801561063e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106629190612428565b9050600061067284610100612527565b61067d9060ff6124d8565b6106868a612573565b61069091906124d8565b91821b90911c91506106a490508688612500565b6106af9060016124d8565b935060006106bf89868585610dff565b6040517feb1db01800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff808c1660048301819052929350600092839290916309f0d8cb917f000000000000000000000000d6c90a7b61f3e0ac04e2f4b0359ab0ac090355079091169063eb1db01890602401602060405180830381865afa15801561075f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107839190612428565b6040518263ffffffff1660e01b81526004016107a191815260200190565b608060405180830381865afa1580156107be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107e291906125ab565b9350935050506107f78b888787878787610f75565b975050505050505b50935093915050565b82516060908067ffffffffffffffff81111561082657610826611d13565b60405190808252806020026020018201604052801561086657816020015b6040805160208101909152606081528152602001906001900390816108445790505b50915060005b8181101561028e576108ca86828151811061088957610889612303565b60200260200101518683815181106108a3576108a3612303565b60200260200101518684815181106108bd576108bd612303565b60200260200101516108fa565b8382815181106108dc576108dc612303565b602090810291909101015152806108f281612361565b91505061086c565b6040517f03e883e000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301526060916000917f000000000000000000000000d6c90a7b61f3e0ac04e2f4b0359ab0ac0903550716906303e883e090602401602060405180830381865afa15801561098c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109b09190612428565b9050603481901c633fffffff1683156109c957836109cc565b60015b93508481106109db57846109dd565b805b945083851015610a74576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f66726f6d4272616e636849645f206d757374206265206772656174657220746860448201527f616e206f7220657175616c20746f20746f4272616e636849645f00000000000060648201526084015b60405180910390fd5b610a7e84866125e1565b610a899060016125f4565b67ffffffffffffffff811115610aa157610aa1611d13565b604051908082528060200260200182016040528015610b3657816020015b610b236040518061018001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b815260200190600190039081610abf5790505b5092506000855b858110610b8a57610b4f888583611301565b8583610b5a81612361565b945081518110610b6c57610b6c612303565b60200260200101819052508080610b8290612607565b915050610b3d565b505050509392505050565b606060007f000000000000000000000000d6c90a7b61f3e0ac04e2f4b0359ab0ac0903550773ffffffffffffffffffffffffffffffffffffffff1663a8d9f4936040518163ffffffff1660e01b8152600401600060405180830381865afa158015610c04573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610c4a9190810190612399565b80519091508067ffffffffffffffff811115610c6857610c68611d13565b604051908082528060200260200182016040528015610ca857816020015b604080516020810190915260608152815260200190600190039081610c865790505b50925060005b81811015610d2b57610cfb838281518110610ccb57610ccb612303565b60200260200101517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60006108fa565b848281518110610d0d57610d0d612303565b60209081029190910101515280610d2381612361565b915050610cae565b50505090565b6000620fffff8210610d9f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f696e76616c69642d6e756d6265720000000000000000000000000000000000006044820152606401610a6b565b8115610dd85781600116600114610dc757610dc2600183901c6207ffff16612573565b610dd2565b6207ffff600183901c165b92915050565b507f8000000000000000000000000000000000000000000000000000000000000000919050565b60008060005b8315610e7a57610e1484611483565b9150610e22826101016125e1565b610e2e836101016125e1565b9490941b90931c92610e416001836125e1565b610e4d86610100612527565b610e5791906124d8565b905085811215610e68575050610f6d565b82610e7281612361565b935050610e05565b610e838561263c565b94507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f8514610f6a576040517fa8bc069300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152602482018790527f000000000000000000000000d6c90a7b61f3e0ac04e2f4b0359ab0ac09035507169063a8bc069390604401602060405180830381865afa158015610f3f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f639190612428565b9350610e05565b50505b949350505050565b60608367ffffffffffffffff811115610f9057610f90611d13565b604051908082528060200260200182016040528015610ffa57816020015b610fe76040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b815260200190600190039081610fae5790505b509050600093506000806000805b88156112015760006110198a611483565b9050611027816101016125e1565b611033826101016125e1565b9a909a1b90991c986110466001826125e1565b6110528c610100612527565b61105c91906124d8565b9450508a84121561107057505050506112f6565b6040517f168a11c200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8d811660048301526024820186905267ffffffffffffffff916019917f000000000000000000000000d6c90a7b61f3e0ac04e2f4b0359ab0ac09035507169063168a11c290604401602060405180830381865afa158015611110573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111349190612428565b901c16600881901c60ff9091161b925061114d84611539565b915081611167846c0100000000000000000000000061266d565b6111719190612684565b90506040518060c0016040528084815260200182815260200164e8d4a51000888661119c919061266d565b6111a69190612684565b815260200164e8d4a510006111bb8a8561266d565b6111c59190612684565b81526020810184905260400185905285896111df81612361565b9a50815181106111f1576111f1612303565b6020026020010181905250611008565b61120a8a61263c565b99507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f8a146112f1576040517fa8bc069300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8d81166004830152602482018c90527f000000000000000000000000d6c90a7b61f3e0ac04e2f4b0359ab0ac09035507169063a8bc069390604401602060405180830381865afa1580156112c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112ea9190612428565b9850611008565b505050505b979650505050505050565b6113656040518061018001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6040517fbf518f5f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018490526000917f000000000000000000000000d6c90a7b61f3e0ac04e2f4b0359ab0ac090355079091169063bf518f5f90604401602060405180830381865afa1580156113fd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114219190612428565b90506000611437620fffff600284901c16610d31565b905060038216600081900361145c576114528684878461179b565b935050505061147c565b806001036114715761145287848784866118d9565b611452838683611b49565b9392505050565b6000816fffffffffffffffffffffffffffffffff8311156114a55760809150811c5b67ffffffffffffffff8111156114bd576040918201911c5b63ffffffff8111156114d1576020918201911c5b61ffff8111156114e3576010918201911c5b60ff8111156114f4576008918201911c5b600f811115611505576004918201911c5b6003811115611516576002918201911c5b6001811115611526576001820191505b8015611533576001820191505b50919050565b600060ff82901d80831803617fff81111561155357600080fd5b700100000000000000000000000000000000600182161561158157506fff9dd7de423466c20352b1246ce4856f5b60028216156115a0576fff3bd55f4488ad277531fa1c725a66d00260801c5b60048216156115bf576ffe78410fd6498b73cb96a6917f8532590260801c5b60088216156115de576ffcf2d9987c9be178ad5bfeffaa1232730260801c5b60108216156115fd576ff9ef02c4529258b057769680fc6601b30260801c5b602082161561161c576ff402d288133a85a17784a411f7aba0820260801c5b604082161561163b576fe895615b5beb6386553757b0352bda900260801c5b608082161561165a576fd34f17a00ffa00a8309940a15930391a0260801c5b61010082161561167a576fae6b7961714e20548d88ea5123f9a0ff0260801c5b61020082161561169a576f76d6461f27082d74e0feed3b388c0ca10260801c5b6104008216156116ba576f372a3bfe0745d8b6b19d985d9a8b85bb0260801c5b6108008216156116da576f0be32cbee48979763cf7247dd7bb539d0260801c5b6110008216156116f9576e8d4f70c9ff4924dac37612d1e2921e0260801c5b612000821615611717576d4e009ae5519380809a02ca7aec770260801c5b614000821615611733576b17c45e641b6e95dee056ff100260801c5b600091507f80000000000000000000000000000000000000000000000000000000000000008416611791577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0463ffffffff81161561179157600191505b60201c0192915050565b6117ff6040518061018001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6000611813620fffff600288901c16610d31565b905060007f8000000000000000000000000000000000000000000000000000000000000000821361184557600061184e565b61184e82611539565b905060405180610180016040528060008152602001600081526020016000815260200160008152602001868152602001858152602001838152602001600081526020018281526020016603ffffffffffff607489901c168152602001633fffffff60a689901c1681526020016118cc620fffff60c48a901c16610d31565b9052979650505050505050565b61193d6040518061018001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b603c85901c66ffffffffffffff16603486901c60ff161b600080611962888487611c77565b6040517feb1db01800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff808d1660048301819052939550919350600092839290916309f0d8cb917f000000000000000000000000d6c90a7b61f3e0ac04e2f4b0359ab0ac09035507169063eb1db01890602401602060405180830381865afa158015611a03573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a279190612428565b6040518263ffffffff1660e01b8152600401611a4591815260200190565b608060405180830381865afa158015611a62573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a8691906125ab565b93509350505060405180610180016040528086815260200185815260200164e8d4a510008388611ab6919061266d565b611ac09190612684565b815260200164e8d4a51000611ad5858861266d565b611adf9190612684565b81526020018a8152602001898152602001888152602001600081526020018481526020016603ffffffffffff60748d901c168152602001633fffffff60a68d901c168152602001611b38620fffff60c48e901c16610d31565b90529b9a5050505050505050505050565b611bad6040518061018001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6000611bc1620fffff60c487901c16610d31565b905060007f80000000000000000000000000000000000000000000000000000000000000008213611bf3576000611bfc565b611bfc82611539565b905060405180610180016040528060008152602001600081526020016000815260200160008152602001868152602001858152602001838152602001600081526020018281526020016603ffffffffffff607489901c168152602001633fffffff60a689901c16815260200183815250925050509392505050565b600080611c868360020b611539565b9050600061271f611c998361271061266d565b611ca39190612684565b90506000611cb182846125e1565b9050633fffffff601688901c811690600090611ccd838561266d565b611cd79190612684565b611ce190856125f4565b905080611cfb6c010000000000000000000000008a61266d565b611d059190612684565b955050505050935093915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611d8957611d89611d13565b604052919050565b600067ffffffffffffffff821115611dab57611dab611d13565b5060051b60200190565b73ffffffffffffffffffffffffffffffffffffffff81168114611dd757600080fd5b50565b600082601f830112611deb57600080fd5b81356020611e00611dfb83611d91565b611d42565b82815260059290921b84018101918181019086841115611e1f57600080fd5b8286015b84811015611e43578035611e3681611db5565b8352918301918301611e23565b509695505050505050565b600082601f830112611e5f57600080fd5b81356020611e6f611dfb83611d91565b82815260059290921b84018101918181019086841115611e8e57600080fd5b8286015b84811015611e435780358352918301918301611e92565b600080600060608486031215611ebe57600080fd5b833567ffffffffffffffff80821115611ed657600080fd5b611ee287838801611dda565b9450602091508186013581811115611ef957600080fd5b8601601f81018813611f0a57600080fd5b8035611f18611dfb82611d91565b81815260059190911b8201840190848101908a831115611f3757600080fd5b928501925b82841015611f5557833582529285019290850190611f3c565b96505050506040860135915080821115611f6e57600080fd5b50611f7b86828701611e4e565b9150509250925092565b60006020808301818452808551808352604092508286019150828160051b8701018488016000805b8481101561206c578984037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0018652825180518886528051898701819052908a0190849060608801905b8083101561204d578351805183526020808201519084015260408082015190840152606080820151908401526080808201519084015260a0908101519083015260c0820191508c84019350600183019250611ff7565b50928b0151968b01969096525095880195935091870191600101611fad565b50919998505050505050505050565b60006020828403121561208d57600080fd5b5035919050565b6000806000606084860312156120a957600080fd5b83356120b481611db5565b95602085013595506040909401359392505050565b604080825283519082018190526000906020906060840190828701845b82811015612138578151805185526020808201519086015260408082015190860152606080820151908601526080808201519086015260a0908101519085015260c084019350908401906001016120e6565b50505092019290925292915050565b60008060006060848603121561215c57600080fd5b833567ffffffffffffffff8082111561217457600080fd5b61218087838801611dda565b9450602086013591508082111561219657600080fd5b6121a287838801611e4e565b93506040860135915080821115611f6e57600080fd5b600081518084526020808501945080840160005b8381101561225d57815180518852838101518489015260408082015190890152606080820151908901526080808201519089015260a0808201519089015260c0808201519089015260e08082015190890152610100808201519089015261012080820151908901526101408082015190890152610160908101519088015261018090960195908201906001016121cc565b509495945050505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b828110156122e3577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184528151518686526122d0878701826121b8565b955050928501929085019060010161228f565b5092979650505050505050565b60208152600061147c60208301846121b8565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361239257612392612332565b5060010190565b600060208083850312156123ac57600080fd5b825167ffffffffffffffff8111156123c357600080fd5b8301601f810185136123d457600080fd5b80516123e2611dfb82611d91565b81815260059190911b8201830190838101908783111561240157600080fd5b928401925b828410156112f657835161241981611db5565b82529284019290840190612406565b60006020828403121561243a57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261247f5761247f612441565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f8000000000000000000000000000000000000000000000000000000000000000831416156124d3576124d3612332565b500590565b80820182811260008312801582168215821617156124f8576124f8612332565b505092915050565b818103600083128015838313168383128216171561252057612520612332565b5092915050565b808202600082127f80000000000000000000000000000000000000000000000000000000000000008414161561255f5761255f612332565b8181058314821517610dd257610dd2612332565b60007f800000000000000000000000000000000000000000000000000000000000000082036125a4576125a4612332565b5060000390565b600080600080608085870312156125c157600080fd5b505082516020840151604085015160609095015191969095509092509050565b81810381811115610dd257610dd2612332565b80820180821115610dd257610dd2612332565b60008161261657612616612332565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b60007f8000000000000000000000000000000000000000000000000000000000000000820361261657612616612332565b8082028115828204841417610dd257610dd2612332565b60008261269357612693612441565b50049056fea26469706673582212208701324d348fcb8b848363e1d0ed7d2920058c437e7fe09f90f34c3262e5b2fc64736f6c63430008150033

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

000000000000000000000000d6c90a7b61f3e0ac04e2f4b0359ab0ac09035507

-----Decoded View---------------
Arg [0] : vaultResolver_ (address): 0xd6C90A7B61F3e0Ac04e2F4B0359aB0ac09035507

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000d6c90a7b61f3e0ac04e2f4b0359ab0ac09035507


Block Transaction Gas Used Reward
view all blocks produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
[ 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.