Contract 0xa0C61494842176CE0cDB828542b4C3a842cc29af

Contract Overview

Balance:
0 AVAX
Txn Hash Method
Block
From
To
Value [Txn Fee]
0x614b2fc866a6d7f439091f03e2304c7e503f7e61ab864dd12e49f58ff26d9bf4Set Addresses66003142022-02-26 6:13:47223 days 15 mins ago0x9e97ae5d91da840eed47a5b07fdabbc2bfad8ada IN 0xa0c61494842176ce0cdb828542b4c3a842cc29af0 AVAX0.00967755 25
0x6d78f522a81f2864681385f0ac15523e9ac5532612f92d3be5fc48d0f7692cc7Set Addresses60673062022-02-14 1:30:57235 days 4 hrs ago0x9e97ae5d91da840eed47a5b07fdabbc2bfad8ada IN 0xa0c61494842176ce0cdb828542b4c3a842cc29af0 AVAX0.0028593 45
0x23e47f4a8bc471d7c3c21e67bf30a262333844a183849733e00b93e14fa5e44f0x6080604060665632022-02-14 1:05:34235 days 5 hrs ago0x9e97ae5d91da840eed47a5b07fdabbc2bfad8ada IN  Contract Creation0 AVAX0.18164259 45
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0x2bbad00a8783ea41d6c1cc9cd8f488e9c0bec9d21f513ad357ee5b18c358f02b70986042022-03-10 0:04:43211 days 6 hrs ago 0xa0c61494842176ce0cdb828542b4c3a842cc29af0xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX
0x2bbad00a8783ea41d6c1cc9cd8f488e9c0bec9d21f513ad357ee5b18c358f02b70986042022-03-10 0:04:43211 days 6 hrs ago 0xa0c61494842176ce0cdb828542b4c3a842cc29af0xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX
0x2bbad00a8783ea41d6c1cc9cd8f488e9c0bec9d21f513ad357ee5b18c358f02b70986042022-03-10 0:04:43211 days 6 hrs ago 0xa0c61494842176ce0cdb828542b4c3a842cc29af0xf7d924a8f414a16a54f2cf9a98ac266281239ffb0 AVAX
0x2bbad00a8783ea41d6c1cc9cd8f488e9c0bec9d21f513ad357ee5b18c358f02b70986042022-03-10 0:04:43211 days 6 hrs ago 0xa0c61494842176ce0cdb828542b4c3a842cc29af0x0db336c1ab0cc14972b53caa4f100068731c54aa0 AVAX
0x2bbad00a8783ea41d6c1cc9cd8f488e9c0bec9d21f513ad357ee5b18c358f02b70986042022-03-10 0:04:43211 days 6 hrs ago 0xa0c61494842176ce0cdb828542b4c3a842cc29af0xf7d924a8f414a16a54f2cf9a98ac266281239ffb0 AVAX
0x2bbad00a8783ea41d6c1cc9cd8f488e9c0bec9d21f513ad357ee5b18c358f02b70986042022-03-10 0:04:43211 days 6 hrs ago 0xa0c61494842176ce0cdb828542b4c3a842cc29af0x0db336c1ab0cc14972b53caa4f100068731c54aa0 AVAX
0x2bbad00a8783ea41d6c1cc9cd8f488e9c0bec9d21f513ad357ee5b18c358f02b70986042022-03-10 0:04:43211 days 6 hrs ago 0xa0c61494842176ce0cdb828542b4c3a842cc29af0x9ab04cd8b701e5bb4fdf31378af679d2f4534f8a0 AVAX
0x2bbad00a8783ea41d6c1cc9cd8f488e9c0bec9d21f513ad357ee5b18c358f02b70986042022-03-10 0:04:43211 days 6 hrs ago 0xcb74a8f05537e346ac54c173652e57c96b4339d20xa0c61494842176ce0cdb828542b4c3a842cc29af0 AVAX
0xfc7b08b109d3896a9f7e6d6bd2d9a0b4ff58a18b961ba113745b821d33ac46c970986022022-03-10 0:04:39211 days 6 hrs ago 0xa0c61494842176ce0cdb828542b4c3a842cc29af0xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX
0xfc7b08b109d3896a9f7e6d6bd2d9a0b4ff58a18b961ba113745b821d33ac46c970986022022-03-10 0:04:39211 days 6 hrs ago 0xa0c61494842176ce0cdb828542b4c3a842cc29af0xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX
0xfc7b08b109d3896a9f7e6d6bd2d9a0b4ff58a18b961ba113745b821d33ac46c970986022022-03-10 0:04:39211 days 6 hrs ago 0xa0c61494842176ce0cdb828542b4c3a842cc29af0xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX
0xfc7b08b109d3896a9f7e6d6bd2d9a0b4ff58a18b961ba113745b821d33ac46c970986022022-03-10 0:04:39211 days 6 hrs ago 0xa0c61494842176ce0cdb828542b4c3a842cc29af0xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX
0xfc7b08b109d3896a9f7e6d6bd2d9a0b4ff58a18b961ba113745b821d33ac46c970986022022-03-10 0:04:39211 days 6 hrs ago 0xa0c61494842176ce0cdb828542b4c3a842cc29af0xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX
0xfc7b08b109d3896a9f7e6d6bd2d9a0b4ff58a18b961ba113745b821d33ac46c970986022022-03-10 0:04:39211 days 6 hrs ago 0xa0c61494842176ce0cdb828542b4c3a842cc29af0xf7d924a8f414a16a54f2cf9a98ac266281239ffb0 AVAX
0xfc7b08b109d3896a9f7e6d6bd2d9a0b4ff58a18b961ba113745b821d33ac46c970986022022-03-10 0:04:39211 days 6 hrs ago 0xa0c61494842176ce0cdb828542b4c3a842cc29af0x0db336c1ab0cc14972b53caa4f100068731c54aa0 AVAX
0xfc7b08b109d3896a9f7e6d6bd2d9a0b4ff58a18b961ba113745b821d33ac46c970986022022-03-10 0:04:39211 days 6 hrs ago 0xa0c61494842176ce0cdb828542b4c3a842cc29af0xf7d924a8f414a16a54f2cf9a98ac266281239ffb0 AVAX
0xfc7b08b109d3896a9f7e6d6bd2d9a0b4ff58a18b961ba113745b821d33ac46c970986022022-03-10 0:04:39211 days 6 hrs ago 0xa0c61494842176ce0cdb828542b4c3a842cc29af0x0db336c1ab0cc14972b53caa4f100068731c54aa0 AVAX
0xfc7b08b109d3896a9f7e6d6bd2d9a0b4ff58a18b961ba113745b821d33ac46c970986022022-03-10 0:04:39211 days 6 hrs ago 0xa0c61494842176ce0cdb828542b4c3a842cc29af0x9ab04cd8b701e5bb4fdf31378af679d2f4534f8a0 AVAX
0xfc7b08b109d3896a9f7e6d6bd2d9a0b4ff58a18b961ba113745b821d33ac46c970986022022-03-10 0:04:39211 days 6 hrs ago 0xcb74a8f05537e346ac54c173652e57c96b4339d20xa0c61494842176ce0cdb828542b4c3a842cc29af0 AVAX
0x8938bc6b1ca06ef77b5aaeebe75375db1cad450ad7ffc2a5f62601fa62c2d6a170986012022-03-10 0:04:35211 days 6 hrs ago 0xa0c61494842176ce0cdb828542b4c3a842cc29af0x0db336c1ab0cc14972b53caa4f100068731c54aa0 AVAX
0x8938bc6b1ca06ef77b5aaeebe75375db1cad450ad7ffc2a5f62601fa62c2d6a170986012022-03-10 0:04:35211 days 6 hrs ago 0xa0c61494842176ce0cdb828542b4c3a842cc29af0x6a62e076f10ecd61ca91a456bf86d40fdb8bcc650 AVAX
0x8938bc6b1ca06ef77b5aaeebe75375db1cad450ad7ffc2a5f62601fa62c2d6a170986012022-03-10 0:04:35211 days 6 hrs ago 0xa0c61494842176ce0cdb828542b4c3a842cc29af0x1aa108e2392cd316be9255f78a3673e9f6f654470 AVAX
0x8938bc6b1ca06ef77b5aaeebe75375db1cad450ad7ffc2a5f62601fa62c2d6a170986012022-03-10 0:04:35211 days 6 hrs ago 0xa0c61494842176ce0cdb828542b4c3a842cc29af0x1aa108e2392cd316be9255f78a3673e9f6f654470 AVAX
0x8938bc6b1ca06ef77b5aaeebe75375db1cad450ad7ffc2a5f62601fa62c2d6a170986012022-03-10 0:04:35211 days 6 hrs ago 0xa0c61494842176ce0cdb828542b4c3a842cc29af0x1aa108e2392cd316be9255f78a3673e9f6f654470 AVAX
0x8938bc6b1ca06ef77b5aaeebe75375db1cad450ad7ffc2a5f62601fa62c2d6a170986012022-03-10 0:04:35211 days 6 hrs ago 0xa0c61494842176ce0cdb828542b4c3a842cc29af0x1aa108e2392cd316be9255f78a3673e9f6f654470 AVAX
[ Download CSV Export 
Loading

Similar Match Source Code
Note: This contract matches the deployed ByteCode of the Source Code for Contract 0xa7C7633027B6ec8f8E69Bfa94044ec6F709112c3

Contract Name:
TroveManagerLiquidations

Compiler Version
v0.6.11+commit.5ef660b1

Optimization Enabled:
Yes with 100 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 28 : TroveManagerLiquidations.sol
// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.6.11;

import "./Interfaces/IWAsset.sol";
import "./Dependencies/TroveManagerBase.sol";

/** 
 * TroveManagerLiquidations is derived from TroveManager and has all the functions 
 * related to Liquidations. 
 */

contract TroveManagerLiquidations is TroveManagerBase {

    address yetiFinanceTreasury;

    struct LiquidationValues {
        uint256 entireTroveDebt;
        newColls entireTroveColl;
        newColls collGasCompensation;
        uint256 YUSDGasCompensation;
        uint256 debtToOffset;
        newColls collToSendToSP;
        uint256 debtToRedistribute;
        newColls collToRedistribute;
        newColls collSurplus;
    }

    struct LiquidationTotals {
        uint256 totalVCInSequence;
        uint256 totalDebtInSequence;
        newColls totalCollGasCompensation;
        uint256 totalYUSDGasCompensation;
        uint256 totalDebtToOffset;
        newColls totalCollToSendToSP;
        uint256 totalDebtToRedistribute;
        newColls totalCollToRedistribute;
        newColls totalCollSurplus;
    }

    struct LocalVariables_LiquidationSequence {
        uint256 remainingYUSDInStabPool;
        uint256 i;
        uint256 ICR;
        address user;
        bool backToNormalMode;
        uint256 entireSystemDebt;
        uint256 entireSystemColl;
    }

    struct LocalVariables_OuterLiquidationFunction {
        uint256 YUSDInStabPool;
        bool recoveryModeAtStart;
        uint256 liquidatedDebt;
    }

    struct LocalVariables_InnerSingleLiquidateFunction {
        newColls collToLiquidate;
        uint256 pendingDebtReward;
        newColls pendingCollReward;
    }

    struct LocalVariables_ORVals {
        uint256 debtToOffset;
        newColls collToSendToSP;
        uint256 debtToRedistribute;
        newColls collToRedistribute;
        newColls collSurplus;
    }

    event TroveLiquidated(
        address indexed _borrower,
        uint256 _debt,
        TroveManagerOperation _operation
    );
    event Liquidation(
        uint256 liquidatedAmount,
        uint256 totalYUSDGasCompensation,
        address[] totalCollTokens,
        uint256[] totalCollAmounts,
        address[] totalCollGasCompTokens,
        uint256[] totalCollGasCompAmounts
    );

    function setAddresses(
        address _borrowerOperationsAddress,
        address _activePoolAddress,
        address _defaultPoolAddress,
        address _stabilityPoolAddress,
        address _gasPoolAddress,
        address _collSurplusPoolAddress,
        address _yusdTokenAddress,
        address _sortedTrovesAddress,
        address _yetiTokenAddress,
        address _sYETIAddress,
        address _whitelistAddress,
        address _troveManagerAddress,
        address _yetiFinanceTreasury
    ) external onlyOwner {
        checkContract(_borrowerOperationsAddress);
        checkContract(_activePoolAddress);
        checkContract(_defaultPoolAddress);
        checkContract(_stabilityPoolAddress);
        checkContract(_gasPoolAddress);
        checkContract(_collSurplusPoolAddress);
        checkContract(_yusdTokenAddress);
        checkContract(_sortedTrovesAddress);
        checkContract(_yetiTokenAddress);
        checkContract(_sYETIAddress);
        checkContract(_whitelistAddress);
        checkContract(_troveManagerAddress);
        checkContract(_yetiFinanceTreasury);

        borrowerOperationsAddress = _borrowerOperationsAddress;
        activePool = IActivePool(_activePoolAddress);
        defaultPool = IDefaultPool(_defaultPoolAddress);
        stabilityPoolContract = IStabilityPool(_stabilityPoolAddress);
        whitelist = IWhitelist(_whitelistAddress);
        gasPoolAddress = _gasPoolAddress;
        collSurplusPool = ICollSurplusPool(_collSurplusPoolAddress);
        yusdTokenContract = IYUSDToken(_yusdTokenAddress);
        sortedTroves = ISortedTroves(_sortedTrovesAddress);
        yetiTokenContract = IYETIToken(_yetiTokenAddress);
        sYETIContract = ISYETI(_sYETIAddress);
        troveManager = ITroveManager(_troveManagerAddress);
        troveManagerAddress = _troveManagerAddress;
        yetiFinanceTreasury = _yetiFinanceTreasury;

        emit BorrowerOperationsAddressChanged(_borrowerOperationsAddress);
        emit ActivePoolAddressChanged(_activePoolAddress);
        emit DefaultPoolAddressChanged(_defaultPoolAddress);
        emit StabilityPoolAddressChanged(_stabilityPoolAddress);
        emit GasPoolAddressChanged(_gasPoolAddress);
        emit CollSurplusPoolAddressChanged(_collSurplusPoolAddress);
        emit YUSDTokenAddressChanged(_yusdTokenAddress);
        emit SortedTrovesAddressChanged(_sortedTrovesAddress);
        emit YETITokenAddressChanged(_yetiTokenAddress);
        emit SYETIAddressChanged(_sYETIAddress);

        _renounceOwnership();
    }

    /** 
     * Function for liquidating a list of troves in a single transaction. Will perform as many as it can 
     * and looks at if it is eligible for liquidation based on the current ICR value. 
     */
    function batchLiquidateTroves(address[] memory _troveArray, address _liquidator) public {
        _requireCallerisTroveManager();
        require(_troveArray.length != 0, "TroveManager: Calldata address array must not be empty");

        IActivePool activePoolCached = activePool;
        IDefaultPool defaultPoolCached = defaultPool;
        IStabilityPool stabilityPoolCached = stabilityPoolContract;

        LocalVariables_OuterLiquidationFunction memory vars;
        LiquidationTotals memory totals;

        vars.YUSDInStabPool = stabilityPoolCached.getTotalYUSDDeposits();
        vars.recoveryModeAtStart = _checkRecoveryMode();

        // Perform the appropriate liquidation sequence - tally values and obtain their totals.
        if (vars.recoveryModeAtStart) {
            totals = _getTotalFromBatchLiquidate_RecoveryMode(
                activePoolCached,
                defaultPoolCached,
                vars.YUSDInStabPool,
                _troveArray
            );
        } else {
            //  if !vars.recoveryModeAtStart
            totals = _getTotalsFromBatchLiquidate_NormalMode(
                activePoolCached,
                defaultPoolCached,
                vars.YUSDInStabPool,
                _troveArray
            );
        }

        require(totals.totalDebtInSequence > 0, "TroveManager: nothing to liquidate");
        // Move liquidated Collateral and YUSD to the appropriate pools
        stabilityPoolCached.offset(
            totals.totalDebtToOffset,
            totals.totalCollToSendToSP.tokens,
            totals.totalCollToSendToSP.amounts
        );
        troveManager.redistributeDebtAndColl(
            activePoolCached,
            defaultPoolCached,
            totals.totalDebtToRedistribute,
            totals.totalCollToRedistribute.tokens,
            totals.totalCollToRedistribute.amounts
        );
        if (_CollsIsNonZero(totals.totalCollSurplus)) {
            activePoolCached.sendCollaterals(
                address(collSurplusPool),
                totals.totalCollSurplus.tokens,
                totals.totalCollSurplus.amounts
            );
        }

        // Update system snapshots
        troveManager.updateSystemSnapshots_excludeCollRemainder(
            activePoolCached,
            totals.totalCollGasCompensation.tokens,
            totals.totalCollGasCompensation.amounts
        );

        vars.liquidatedDebt = totals.totalDebtInSequence;

        // merge the colls into one to emit correct event.
        newColls memory sumCollsResult = _sumColls(
            totals.totalCollToSendToSP,
            totals.totalCollToRedistribute
        );
        sumCollsResult = _sumColls(sumCollsResult, totals.totalCollSurplus);

        emit Liquidation(
            vars.liquidatedDebt,
            totals.totalYUSDGasCompensation,
            sumCollsResult.tokens,
            sumCollsResult.amounts,
            totals.totalCollGasCompensation.tokens,
            totals.totalCollGasCompensation.amounts
        );
        // Send gas compensation to caller
        _sendGasCompensation(
            activePoolCached,
            _liquidator,
            totals.totalYUSDGasCompensation,
            totals.totalCollGasCompensation.tokens,
            totals.totalCollGasCompensation.amounts
        );
    }

    /*
     * This function is used when the batch liquidation sequence starts during Recovery Mode. However, it
     * handle the case where the system *leaves* Recovery Mode, part way through the liquidation sequence
     */
    function _getTotalFromBatchLiquidate_RecoveryMode(
        IActivePool _activePool,
        IDefaultPool _defaultPool,
        uint256 _YUSDInStabPool,
        address[] memory _troveArray
    ) internal returns (LiquidationTotals memory totals) {
        LocalVariables_LiquidationSequence memory vars;
        LiquidationValues memory singleLiquidation;

        vars.remainingYUSDInStabPool = _YUSDInStabPool;
        vars.backToNormalMode = false;
        vars.entireSystemDebt = getEntireSystemDebt();
        // get total VC
        vars.entireSystemColl = getEntireSystemColl();

        for (vars.i = 0; vars.i < _troveArray.length; vars.i++) {
            vars.user = _troveArray[vars.i];

            // Skip non-active troves
            Status userStatus = Status(troveManager.getTroveStatus(vars.user));
            if (userStatus != Status.active) {
                continue;
            }
            vars.ICR = troveManager.getCurrentICR(vars.user);

            if (!vars.backToNormalMode) {
                // Skip this trove if ICR is greater than MCR and Stability Pool is empty
                if (vars.ICR >= MCR && vars.remainingYUSDInStabPool == 0) {
                    continue;
                }

                uint256 TCR = LiquityMath._computeCR(vars.entireSystemColl, vars.entireSystemDebt);

                singleLiquidation = _liquidateRecoveryMode(
                    _activePool,
                    _defaultPool,
                    vars.user,
                    vars.ICR,
                    vars.remainingYUSDInStabPool,
                    TCR
                );

                // Update aggregate trackers
                vars.remainingYUSDInStabPool = vars.remainingYUSDInStabPool.sub(
                    singleLiquidation.debtToOffset
                );
                vars.entireSystemDebt = vars.entireSystemDebt.sub(singleLiquidation.debtToOffset);

                uint256 collToSendToSpVc = _getVCColls(singleLiquidation.collToSendToSP);
                uint256 collGasCompensationTotal = _getVCColls(
                    singleLiquidation.collGasCompensation
                );
                uint256 collSurplusTotal = _getVCColls(singleLiquidation.collSurplus);

                vars.entireSystemColl = vars
                    .entireSystemColl
                    .sub(collToSendToSpVc)
                    .sub(collGasCompensationTotal)
                    .sub(collSurplusTotal);

                // Add liquidation values to their respective running totals
                totals = _addLiquidationValuesToTotals(totals, singleLiquidation);

                vars.backToNormalMode = !_checkPotentialRecoveryMode(
                    vars.entireSystemColl,
                    vars.entireSystemDebt
                );
            } else if (vars.backToNormalMode && vars.ICR < MCR) {
                singleLiquidation = _liquidateNormalMode(
                    _activePool,
                    _defaultPool,
                    vars.user,
                    vars.remainingYUSDInStabPool
                );
                vars.remainingYUSDInStabPool = vars.remainingYUSDInStabPool.sub(
                    singleLiquidation.debtToOffset
                );

                // Add liquidation values to their respective running totals
                totals = _addLiquidationValuesToTotals(totals, singleLiquidation);
            } else continue; // In Normal Mode skip troves with ICR >= MCR
        }
    }

    function _getTotalsFromBatchLiquidate_NormalMode(
        IActivePool _activePool,
        IDefaultPool _defaultPool,
        uint256 _YUSDInStabPool,
        address[] memory _troveArray
    ) internal returns (LiquidationTotals memory totals) {
        LocalVariables_LiquidationSequence memory vars;
        LiquidationValues memory singleLiquidation;

        vars.remainingYUSDInStabPool = _YUSDInStabPool;
        for (vars.i = 0; vars.i < _troveArray.length; vars.i++) {
            vars.user = _troveArray[vars.i];
            vars.ICR = troveManager.getCurrentICR(vars.user);
            if (vars.ICR < MCR) {
                singleLiquidation = _liquidateNormalMode(
                    _activePool,
                    _defaultPool,
                    vars.user,
                    vars.remainingYUSDInStabPool
                );
                vars.remainingYUSDInStabPool = vars.remainingYUSDInStabPool.sub(
                    singleLiquidation.debtToOffset
                );

                // Add liquidation values to their respective running totals
                totals = _addLiquidationValuesToTotals(totals, singleLiquidation);
            }
        }
    }

    // Liquidate one trove, in Normal Mode.
    function _liquidateNormalMode(
        IActivePool _activePool,
        IDefaultPool _defaultPool,
        address _borrower,
        uint256 _YUSDInStabPool
    ) internal returns (LiquidationValues memory singleLiquidation) {
        LocalVariables_InnerSingleLiquidateFunction memory vars;

        (
            singleLiquidation.entireTroveDebt,
            singleLiquidation.entireTroveColl.tokens,
            singleLiquidation.entireTroveColl.amounts,
            vars.pendingDebtReward,
            vars.pendingCollReward.tokens,
            vars.pendingCollReward.amounts
        ) = troveManager.getEntireDebtAndColls(_borrower);

        troveManager.movePendingTroveRewardsToActivePool(
            _activePool,
            _defaultPool,
            vars.pendingDebtReward,
            vars.pendingCollReward.tokens,
            vars.pendingCollReward.amounts, 
            _borrower
        );
        troveManager.removeStakeTLR(_borrower);

        singleLiquidation.collGasCompensation = _getCollGasCompensation(
            singleLiquidation.entireTroveColl
        );

        // WAssets sent as liquidation reward will be unstaked and no longer accrue rewards
        _updateWAssetsRewardOwner(singleLiquidation.collGasCompensation, _borrower, address(0));

        singleLiquidation.YUSDGasCompensation = YUSD_GAS_COMPENSATION;

        vars.collToLiquidate.tokens = singleLiquidation.entireTroveColl.tokens;
        vars.collToLiquidate.amounts = new uint256[](vars.collToLiquidate.tokens.length);

        for (uint256 i = 0; i < vars.collToLiquidate.tokens.length; i++) {
            vars.collToLiquidate.amounts[i] = singleLiquidation.entireTroveColl.amounts[i].sub(
                singleLiquidation.collGasCompensation.amounts[i]
            );
        }

        LocalVariables_ORVals memory or_vals = _getOffsetAndRedistributionVals(
            singleLiquidation.entireTroveDebt,
            vars.collToLiquidate,
            _YUSDInStabPool
        );

        newColls memory collsToUpdate = _sumColls(or_vals.collToSendToSP, or_vals.collToRedistribute);
        // rewards for WAssets sent to SP and collToRedistribute will
        // accrue to Yeti Finance Treasury until the assets are claimed
        _updateWAssetsRewardOwner(collsToUpdate, _borrower, yetiFinanceTreasury);

        singleLiquidation = _updateSingleLiquidation(or_vals, singleLiquidation);
        troveManager.closeTroveLiquidation(_borrower);

        if (_CollsIsNonZero(singleLiquidation.collSurplus)) {
            troveManager.collSurplusUpdate(
                _borrower,
                singleLiquidation.collSurplus.tokens,
                singleLiquidation.collSurplus.amounts
            );
        }

        emit TroveLiquidated(
            _borrower,
            singleLiquidation.entireTroveDebt,
            TroveManagerOperation.liquidateInNormalMode
        );
        newColls memory borrowerColls;
        emit TroveUpdated(
            _borrower,
            0,
            borrowerColls.tokens,
            borrowerColls.amounts,
            TroveManagerOperation.liquidateInNormalMode
        );
        return singleLiquidation;
    }


    // Liquidate one trove, in Recovery Mode.
    function _liquidateRecoveryMode(
        IActivePool _activePool,
        IDefaultPool _defaultPool,
        address _borrower,
        uint256 _ICR,
        uint256 _YUSDInStabPool,
        uint256 _TCR
    ) internal returns (LiquidationValues memory singleLiquidation) {
        LocalVariables_InnerSingleLiquidateFunction memory vars;

        if (troveManager.getTroveOwnersCount() <= 1) {
            return singleLiquidation;
        } // don't liquidate if last trove

        (
            singleLiquidation.entireTroveDebt,
            singleLiquidation.entireTroveColl.tokens,
            singleLiquidation.entireTroveColl.amounts,
            vars.pendingDebtReward,
            vars.pendingCollReward.tokens,
            vars.pendingCollReward.amounts
        ) = troveManager.getEntireDebtAndColls(_borrower);

        singleLiquidation.collGasCompensation = _getCollGasCompensation(
            singleLiquidation.entireTroveColl
        );

        // WAssets sent as liquidation reward will be unstaked and no longer accrue rewards
        _updateWAssetsRewardOwner(singleLiquidation.collGasCompensation, _borrower, address(0));

        singleLiquidation.YUSDGasCompensation = YUSD_GAS_COMPENSATION;

        vars.collToLiquidate.tokens = singleLiquidation.entireTroveColl.tokens;
        vars.collToLiquidate.amounts = new uint256[](vars.collToLiquidate.tokens.length);

        for (uint256 i = 0; i < vars.collToLiquidate.tokens.length; i++) {
            vars.collToLiquidate.amounts[i] = singleLiquidation.entireTroveColl.amounts[i].sub(
                singleLiquidation.collGasCompensation.amounts[i]
            );
        }

        // If ICR <= 100%, purely redistribute the Trove across all active Troves
        if (_ICR <= _100pct) {
            troveManager.movePendingTroveRewardsToActivePool(
                _activePool,
                _defaultPool,
                vars.pendingDebtReward,
                vars.pendingCollReward.tokens,
                vars.pendingCollReward.amounts, 
                _borrower
            );
            // troveManager.movePendingTroveRewardsToActivePool(_activePool, _defaultPool, vars.pendingDebtReward, singleLiquidation.entireTroveColl.tokens, singleLiquidation.entireTroveColl.amounts);
            troveManager.removeStakeTLR(_borrower);

            singleLiquidation.debtToOffset = 0;
            newColls memory emptyColls;
            singleLiquidation.collToSendToSP = emptyColls;
            singleLiquidation.debtToRedistribute = singleLiquidation.entireTroveDebt;
            singleLiquidation.collToRedistribute = vars.collToLiquidate;

            // WAsset rewards for collToRedistribute will accrue to
            // Yeti Finance Treasury until the WAssets are claimed by troves
            _updateWAssetsRewardOwner(singleLiquidation.collToRedistribute, _borrower, yetiFinanceTreasury);

            troveManager.closeTroveLiquidation(_borrower);
            emit TroveLiquidated(
                _borrower,
                singleLiquidation.entireTroveDebt,
                TroveManagerOperation.liquidateInRecoveryMode
            );
            newColls memory borrowerColls;// = troveManager.getTroveColls(_borrower);
            emit TroveUpdated(
                _borrower,
                0,
                borrowerColls.tokens,
                borrowerColls.amounts,
                TroveManagerOperation.liquidateInRecoveryMode
            );

            // If 100% < ICR < MCR, offset as much as possible, and redistribute the remainder
            // ICR > 100% is implied by prevoius state. 
        } else if (_ICR < MCR) {

            troveManager.movePendingTroveRewardsToActivePool(
                _activePool,
                _defaultPool,
                vars.pendingDebtReward,
                vars.pendingCollReward.tokens,
                vars.pendingCollReward.amounts, 
                _borrower
            );

            troveManager.removeStakeTLR(_borrower);

            LocalVariables_ORVals memory or_vals = _getOffsetAndRedistributionVals(
                singleLiquidation.entireTroveDebt,
                vars.collToLiquidate,
                _YUSDInStabPool
            );

            newColls memory collsToUpdate = _sumColls(or_vals.collToSendToSP, or_vals.collToRedistribute);
            // rewards for WAssets sent to SP and collToRedistribute will
            // accrue to Yeti Finance Treasury until the assets are claimed
            _updateWAssetsRewardOwner(collsToUpdate, _borrower, yetiFinanceTreasury);

            singleLiquidation = _updateSingleLiquidation(or_vals, singleLiquidation);

            troveManager.closeTroveLiquidation(_borrower);
            emit TroveLiquidated(
                _borrower,
                singleLiquidation.entireTroveDebt,
                TroveManagerOperation.liquidateInRecoveryMode
            );
            newColls memory borrowerColls;// = troveManager.getTroveColls(_borrower);
            emit TroveUpdated(
                _borrower,
                0,
                borrowerColls.tokens,
                borrowerColls.amounts,
                TroveManagerOperation.liquidateInRecoveryMode
            );
            /*
             * If 110% <= ICR < current TCR (accounting for the preceding liquidations in the current sequence)
             * and there is YUSD in the Stability Pool, only offset, with no redistribution,
             * but at a capped rate of 1.1 and only if the whole debt can be liquidated.
             * The remainder due to the capped rate will be claimable as collateral surplus.
             * ICR >= 110% is implied from last else if statement. 
             */
        } else if (
           (_ICR < _TCR) && (singleLiquidation.entireTroveDebt <= _YUSDInStabPool)
        ) {
            troveManager.movePendingTroveRewardsToActivePool(
                _activePool,
                _defaultPool,
                vars.pendingDebtReward,
                vars.pendingCollReward.tokens,
                vars.pendingCollReward.amounts,
                _borrower
            );

            assert(_YUSDInStabPool != 0);

            troveManager.removeStakeTLR(_borrower);

            singleLiquidation = _getCappedOffsetVals(
                singleLiquidation.entireTroveDebt,
                singleLiquidation.entireTroveColl.tokens,
                singleLiquidation.entireTroveColl.amounts,
                MCR
            );

            newColls memory collsToUpdate = _sumColls(
                singleLiquidation.collToSendToSP,
                singleLiquidation.collToRedistribute
            );
            // rewards for WAssets sent to SP and collToRedistribute will
            // accrue to Yeti Finance Treasury until the assets are claimed
            _updateWAssetsRewardOwner(collsToUpdate, _borrower, yetiFinanceTreasury);

            troveManager.closeTroveLiquidation(_borrower);

            emit TroveLiquidated(
                _borrower,
                singleLiquidation.entireTroveDebt,
                TroveManagerOperation.liquidateInRecoveryMode
            );
            newColls memory borrowerColls;
            emit TroveUpdated(
                _borrower,
                0,
                borrowerColls.tokens,
                borrowerColls.amounts,
                TroveManagerOperation.liquidateInRecoveryMode
            );
        } else {
            // if (_ICR >= MCR && ( _ICR >= _TCR || singleLiquidation.entireTroveDebt > _YUSDInStabPool))
            LiquidationValues memory zeroVals;
            return zeroVals;
        }

        if (_CollsIsNonZero(singleLiquidation.collSurplus)) {
            troveManager.collSurplusUpdate(
                _borrower,
                singleLiquidation.collSurplus.tokens,
                singleLiquidation.collSurplus.amounts
            );
        }

        return singleLiquidation;
    }

    function _updateSingleLiquidation(
        LocalVariables_ORVals memory or_vals,
        LiquidationValues memory singleLiquidation
    ) internal pure returns (LiquidationValues memory) {
        singleLiquidation.debtToOffset = or_vals.debtToOffset;
        singleLiquidation.collToSendToSP = or_vals.collToSendToSP;
        singleLiquidation.debtToRedistribute = or_vals.debtToRedistribute;
        singleLiquidation.collToRedistribute = or_vals.collToRedistribute;
        singleLiquidation.collSurplus = or_vals.collSurplus;
        return singleLiquidation;
    }

    /* In a full liquidation, returns the values for a trove's coll and debt to be offset, and coll and debt to be
     * redistributed to active troves. _colls parameters is the _colls to be liquidated (total trove colls minus collateral for gas compensation)
     * collsToRedistribute.tokens and collsToRedistribute.amounts should be the same length
     * and should be the same length as _colls.tokens and _colls.amounts.
     * If there is any colls redistributed to stability pool, collsToSendToSP.tokens and collsToSendToSP.amounts
     * will be length equal to _colls.tokens and _colls.amounts. However, if no colls are redistributed to stability pool (which is the case when _YUSDInStabPool == 0),
     * then collsToSendToSP.tokens and collsToSendToSP.amounts will be empty.
     */
    function _getOffsetAndRedistributionVals(
        uint256 _entireTroveDebt,
        newColls memory _collsToLiquidate,
        uint256 _YUSDInStabPool
    ) internal view returns (LocalVariables_ORVals memory or_vals) {
        or_vals.collToRedistribute.tokens = _collsToLiquidate.tokens;
        or_vals.collToRedistribute.amounts = new uint256[](_collsToLiquidate.tokens.length);

        if (_YUSDInStabPool > 0) {
            /*
             * Offset as much debt & collateral as possible against the Stability Pool, and redistribute the remainder
             * between all active troves.
             *
             *  If the trove's debt is larger than the deposited YUSD in the Stability Pool:
             *
             *  - Offset an amount of the trove's debt equal to the YUSD in the Stability Pool
             *  - Remainder of trove's debt will be redistributed
             *  - Trove collateral can be partitioned into two parts:
             *  - (1) Offsetting Collateral = (debtToOffset / troveDebt) * Collateral
             *  - (2) Redistributed Collateral = Total Collateral - Offsetting Collateral
             *  - The max offsetting collateral that can be sent to the stability pool is an amount of collateral such that
             *  - the stability pool receives 110% of value of the debtToOffset. Any extra Offsetting Collateral is
             *  - sent to the collSurplusPool and can be claimed by the borrower.
             */
            or_vals.collToSendToSP.tokens = _collsToLiquidate.tokens;
            or_vals.collToSendToSP.amounts = new uint256[](_collsToLiquidate.tokens.length);

            or_vals.collSurplus.tokens = _collsToLiquidate.tokens;
            or_vals.collSurplus.amounts = new uint256[](_collsToLiquidate.tokens.length);

            or_vals.debtToOffset = LiquityMath._min(_entireTroveDebt, _YUSDInStabPool);

            or_vals.debtToRedistribute = _entireTroveDebt.sub(or_vals.debtToOffset);

            uint toLiquidateCollValueUSD = _getUSDColls(_collsToLiquidate);

            // collOffsetRatio: max percentage of the collateral that can be sent to the SP as offsetting collateral
            // collOffsetRatio = percentage of the trove's debt that can be offset by the stability pool
            uint256 collOffsetRatio = _100pct.mul(_100pct).mul(or_vals.debtToOffset).div(_entireTroveDebt);

            // SPRatio: percentage of liquidated collateral that needs to be sent to SP in order to give SP depositors
            // $110 of collateral for every 100 YUSD they are using to liquidate.
            uint256 SPRatio = or_vals.debtToOffset.mul(_100pct).mul(_110pct).div(toLiquidateCollValueUSD);

            // But SP ratio is capped at collOffsetRatio:
            SPRatio = LiquityMath._min(collOffsetRatio, SPRatio);

            // if there is extra collateral left in the offset portion of the collateral after
            // giving stability pool holders $110 of collateral for every 100 YUSD that is taken from them,
            // then this is surplus collateral that can be claimed by the borrower
            uint256 collSurplusRatio = collOffsetRatio.sub(SPRatio);

            for (uint256 i = 0; i < _collsToLiquidate.tokens.length; i++) {
                or_vals.collToSendToSP.amounts[i] = _collsToLiquidate.amounts[i].mul(SPRatio).div(
                    _100pct
                ).div(_100pct);

                or_vals.collSurplus.amounts[i] = _collsToLiquidate
                    .amounts[i]
                    .mul(collSurplusRatio)
                    .div(_100pct)
                    .div(_100pct);

                // remaining collateral is redistributed:
                or_vals.collToRedistribute.amounts[i] = _collsToLiquidate
                    .amounts[i]
                    .sub(or_vals.collToSendToSP.amounts[i])
                    .sub(or_vals.collSurplus.amounts[i]);
            }
        } else {
            // all colls are redistributed because no YUSD in stability pool to liquidate
            or_vals.debtToOffset = 0;
            for (uint256 i = 0; i < _collsToLiquidate.tokens.length; i++) {
                or_vals.collToRedistribute.amounts[i] = _collsToLiquidate.amounts[i];
            }
            or_vals.debtToRedistribute = _entireTroveDebt;
        }
    }

    function _addLiquidationValuesToTotals(
        LiquidationTotals memory oldTotals,
        LiquidationValues memory singleLiquidation
    ) internal view returns (LiquidationTotals memory newTotals) {
        // Tally all the values with their respective running totals
        //update one of these
        newTotals.totalCollGasCompensation = _sumColls(
            oldTotals.totalCollGasCompensation,
            singleLiquidation.collGasCompensation
        );
        newTotals.totalYUSDGasCompensation = oldTotals.totalYUSDGasCompensation.add(
            singleLiquidation.YUSDGasCompensation
        );
        newTotals.totalDebtInSequence = oldTotals.totalDebtInSequence.add(
            singleLiquidation.entireTroveDebt
        );
        newTotals.totalDebtToOffset = oldTotals.totalDebtToOffset.add(
            singleLiquidation.debtToOffset
        );
        newTotals.totalCollToSendToSP = _sumColls(
            oldTotals.totalCollToSendToSP,
            singleLiquidation.collToSendToSP
        );
        newTotals.totalDebtToRedistribute = oldTotals.totalDebtToRedistribute.add(
            singleLiquidation.debtToRedistribute
        );
        newTotals.totalCollToRedistribute = _sumColls(
            oldTotals.totalCollToRedistribute,
            singleLiquidation.collToRedistribute
        );
        newTotals.totalCollSurplus = _sumColls(
            oldTotals.totalCollSurplus,
            singleLiquidation.collSurplus
        );

        return newTotals;
    }

    /*
    *  Get its offset coll/debt and Collateral gas comp, and close the trove.
    */
    function _getCappedOffsetVals
    (
        uint _entireTroveDebt,
        address[] memory _troveTokens,
        uint[] memory _troveAmounts,
        uint _MCR
    )
    internal
    view
    returns (LiquidationValues memory singleLiquidation)
    {
        newColls memory _entireTroveColl;
        _entireTroveColl.tokens = _troveTokens;
        _entireTroveColl.amounts = _troveAmounts;

        uint USD_Value_To_Send_To_SP = _MCR.mul(_entireTroveDebt).div(_100pct);
        uint USD_Value_of_Trove_Colls = _getUSDColls(_entireTroveColl);

        uint SPRatio = USD_Value_To_Send_To_SP.mul(_100pct).div(USD_Value_of_Trove_Colls);
        SPRatio = LiquityMath._min(SPRatio, _100pct);


        singleLiquidation.entireTroveDebt = _entireTroveDebt;
        singleLiquidation.entireTroveColl = _entireTroveColl;

        singleLiquidation.YUSDGasCompensation = YUSD_GAS_COMPENSATION;

        singleLiquidation.debtToOffset = _entireTroveDebt;
        singleLiquidation.debtToRedistribute = 0;

        singleLiquidation.collToSendToSP.tokens = _troveTokens;
        singleLiquidation.collToSendToSP.amounts = new uint[](_troveTokens.length);

        singleLiquidation.collSurplus.tokens = _troveTokens;
        singleLiquidation.collSurplus.amounts = new uint[](_troveTokens.length);

        singleLiquidation.collGasCompensation.tokens = _troveTokens;
        singleLiquidation.collGasCompensation.amounts = new uint[](_troveTokens.length);

        for (uint i = 0; i < _troveTokens.length; i++) {
            uint _cappedCollAmount = SPRatio.mul(_troveAmounts[i]).div(_100pct);
            uint _gasComp = _cappedCollAmount.div(PERCENT_DIVISOR);
            uint _toSP = _cappedCollAmount.sub(_gasComp);
            uint _collSurplus = _troveAmounts[i].sub(_cappedCollAmount);

            singleLiquidation.collGasCompensation.amounts[i] = _gasComp;
            singleLiquidation.collToSendToSP.amounts[i] = _toSP;
            singleLiquidation.collSurplus.amounts[i] = _collSurplus;
        }
    }

    function _sendGasCompensation(
        IActivePool _activePool,
        address _liquidator,
        uint256 _YUSD,
        address[] memory _tokens,
        uint256[] memory _amounts
    ) internal {
        if (_YUSD > 0) {
            yusdTokenContract.returnFromPool(gasPoolAddress, _liquidator, _YUSD);
        }

        _activePool.sendCollateralsUnwrap(_liquidator, _tokens, _amounts, false);
    }

    /*
     * Update rewards tracking so future rewards go to Yeti Finance Treasury
     * for the trove's asset that have been liquidated and moved to either the
     * Stability Pool or Default Pool
    */
    function _updateWAssetsRewardOwner(newColls memory _colls, address _borrower, address _newOwner) internal {
        for (uint i = 0; i < _colls.tokens.length; i++) {
            address token = _colls.tokens[i];
            uint amount = _colls.amounts[i];
            if (whitelist.isWrapped(token)) {
                IWAsset(token).updateReward(_borrower, _newOwner, amount);
            }
        }
    }

    function _requireCallerisTroveManager() internal view {
        require(msg.sender == troveManagerAddress);
    }
}

File 2 of 28 : IWAsset.sol
// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.6.11;


// Wrapped Asset
interface IWAsset  {

    function wrap(uint _amount, address _from, address _to, address _rewardOwner) external;

    function unwrapFor(address _for, uint amount) external;

    function updateReward(address from, address to, uint amount) external;

    function claimReward(address _to) external;

    function claimRewardFor(address _for) external;

    function getPendingRewards(address _for) external returns (address[] memory tokens, uint[] memory amounts);

    function endTreasuryReward(uint _amount) external;
}

File 3 of 28 : TroveManagerBase.sol
// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.6.11;

import "../Interfaces/ITroveManager.sol";
import "../Interfaces/IStabilityPool.sol";
import "../Interfaces/ICollSurplusPool.sol";
import "../Interfaces/IYUSDToken.sol";
import "../Interfaces/ISortedTroves.sol";
import "../Interfaces/IYETIToken.sol";
import "../Interfaces/ISYETI.sol";
import "../Interfaces/IActivePool.sol";
import "../Interfaces/IWhitelist.sol";
import "../Interfaces/ITroveManagerLiquidations.sol";
import "../Interfaces/ITroveManagerRedemptions.sol";
import "./LiquityBase.sol";
import "./Ownable.sol";
import "./CheckContract.sol";

/** 
 * Contains shared functionality of TroveManagerLiquidations, TroveManagerRedemptions, and TroveManager. 
 * Keeps addresses to cache, events, structs, status, etc. Also keeps Trove struct. 
 */

contract TroveManagerBase is LiquityBase, Ownable, CheckContract {

    // --- Connected contract declarations ---

    address public borrowerOperationsAddress;

    IStabilityPool stabilityPoolContract;

    ITroveManager public troveManager;

    IYUSDToken yusdTokenContract;

    IYETIToken yetiTokenContract;

    ISYETI sYETIContract;

    ITroveManagerRedemptions troveManagerRedemptions;

    ITroveManagerLiquidations troveManagerLiquidations;

    address gasPoolAddress;

    address public troveManagerAddress;
    address public troveManagerRedemptionsAddress;
    address public troveManagerLiquidationsAddress;

    // A doubly linked list of Troves, sorted by their sorted by their individual collateral ratios
    ISortedTroves public sortedTroves;

    ICollSurplusPool collSurplusPool;

    struct ContractsCache {
        IActivePool activePool;
        IDefaultPool defaultPool;
        IYUSDToken yusdToken;
        ISYETI sYETI;
        ISortedTroves sortedTroves;
        ICollSurplusPool collSurplusPool;
        address gasPoolAddress;
    }

    struct SingleRedemptionValues {
        uint YUSDLot;
        newColls CollLot;
        bool cancelledPartial;
    }

    enum Status {
        nonExistent,
        active,
        closedByOwner,
        closedByLiquidation,
        closedByRedemption
    }

    enum TroveManagerOperation {
        applyPendingRewards,
        liquidateInNormalMode,
        liquidateInRecoveryMode,
        redeemCollateral
    }

    // Store the necessary data for a trove
    struct Trove {
        newColls colls;
        uint debt;
        mapping(address => uint) stakes;
        Status status;
        uint128 arrayIndex;
    }

    event BorrowerOperationsAddressChanged(address _newBorrowerOperationsAddress);
    event YUSDTokenAddressChanged(address _newYUSDTokenAddress);
    event ActivePoolAddressChanged(address _activePoolAddress);
    event DefaultPoolAddressChanged(address _defaultPoolAddress);
    event StabilityPoolAddressChanged(address _stabilityPoolAddress);
    event GasPoolAddressChanged(address _gasPoolAddress);
    event CollSurplusPoolAddressChanged(address _collSurplusPoolAddress);
    event SortedTrovesAddressChanged(address _sortedTrovesAddress);
    event YETITokenAddressChanged(address _yetiTokenAddress);
    event SYETIAddressChanged(address _sYETIAddress);

    event TroveUpdated(address indexed _borrower, uint _debt, address[] _tokens, uint[] _amounts, TroveManagerOperation operation);
}

File 4 of 28 : ITroveManager.sol
// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.6.11;

import "./ILiquityBase.sol";
import "./IStabilityPool.sol";
import "./IYUSDToken.sol";
import "./IYETIToken.sol";
import "./ISYETI.sol";
import "./IActivePool.sol";
import "./IDefaultPool.sol";


// Common interface for the Trove Manager.
interface ITroveManager is ILiquityBase {

    // --- Events ---

    event BorrowerOperationsAddressChanged(address _newBorrowerOperationsAddress);
    event PriceFeedAddressChanged(address _newPriceFeedAddress);
    event YUSDTokenAddressChanged(address _newYUSDTokenAddress);
    event ActivePoolAddressChanged(address _activePoolAddress);
    event DefaultPoolAddressChanged(address _defaultPoolAddress);
    event StabilityPoolAddressChanged(address _stabilityPoolAddress);
    event GasPoolAddressChanged(address _gasPoolAddress);
    event CollSurplusPoolAddressChanged(address _collSurplusPoolAddress);
    event SortedTrovesAddressChanged(address _sortedTrovesAddress);
    event YETITokenAddressChanged(address _yetiTokenAddress);
    event SYETIAddressChanged(address _sYETIAddress);

    event Liquidation(uint liquidatedAmount, uint totalYUSDGasCompensation, 
        address[] totalCollTokens, uint[] totalCollAmounts,
        address[] totalCollGasCompTokens, uint[] totalCollGasCompAmounts);
    event Redemption(uint _attemptedYUSDAmount, uint _actualYUSDAmount, uint YUSDfee, address[] tokens, uint[] amounts);
    event TroveLiquidated(address indexed _borrower, uint _debt, uint _coll, uint8 operation);
    event BaseRateUpdated(uint _baseRate);
    event LastFeeOpTimeUpdated(uint _lastFeeOpTime);
    event TotalStakesUpdated(address token, uint _newTotalStakes);
    event SystemSnapshotsUpdated(uint _totalStakesSnapshot, uint _totalCollateralSnapshot);
    event LTermsUpdated(uint _L_ETH, uint _L_YUSDDebt);
    event TroveSnapshotsUpdated(uint _L_ETH, uint _L_YUSDDebt);
    event TroveIndexUpdated(address _borrower, uint _newIndex);

    // --- Functions ---

    function setAddresses(
        address _borrowerOperationsAddress,
        address _activePoolAddress,
        address _defaultPoolAddress,
        address _stabilityPoolAddress,
        address _gasPoolAddress,
        address _collSurplusPoolAddress,
        address _yusdTokenAddress,
        address _sortedTrovesAddress,
        address _yetiTokenAddress,
        address _sYETIAddress,
        address _whitelistAddress,
        address _troveManagerRedemptionsAddress,
        address _troveManagerLiquidationsAddress
    )
    external;

    function stabilityPool() external view returns (IStabilityPool);
    function yusdToken() external view returns (IYUSDToken);
    function yetiToken() external view returns (IYETIToken);
    function sYETI() external view returns (ISYETI);

    function getTroveOwnersCount() external view returns (uint);

    function getTroveFromTroveOwnersArray(uint _index) external view returns (address);

    function getCurrentICR(address _borrower) external view returns (uint);

    function liquidate(address _borrower) external;

    function batchLiquidateTroves(address[] calldata _troveArray, address _liquidator) external;

    function redeemCollateral(
        uint _YUSDAmount,
        uint _YUSDMaxFee,
        address _firstRedemptionHint,
        address _upperPartialRedemptionHint,
        address _lowerPartialRedemptionHint,
        uint _partialRedemptionHintNICR,
        uint _maxIterations
    ) external;

    function updateStakeAndTotalStakes(address _borrower) external;

    function updateTroveCollTMR(address  _borrower, address[] memory addresses, uint[] memory amounts) external;

    function updateTroveRewardSnapshots(address _borrower) external;

    function addTroveOwnerToArray(address _borrower) external returns (uint index);

    function applyPendingRewards(address _borrower) external;

//    function getPendingETHReward(address _borrower) external view returns (uint);
    function getPendingCollRewards(address _borrower) external view returns (address[] memory, uint[] memory);

    function getPendingYUSDDebtReward(address _borrower) external view returns (uint);

     function hasPendingRewards(address _borrower) external view returns (bool);

//    function getEntireDebtAndColl(address _borrower) external view returns (
//        uint debt,
//        uint coll,
//        uint pendingYUSDDebtReward,
//        uint pendingETHReward
//    );

    function closeTrove(address _borrower) external;

    function removeStake(address _borrower) external;

    function removeStakeTMR(address _borrower) external;
    function updateTroveDebt(address _borrower, uint debt) external;

    function getRedemptionRate() external view returns (uint);
    function getRedemptionRateWithDecay() external view returns (uint);

    function getRedemptionFeeWithDecay(uint _ETHDrawn) external view returns (uint);

    function getBorrowingRate() external view returns (uint);
    function getBorrowingRateWithDecay() external view returns (uint);

    function getBorrowingFee(uint YUSDDebt) external view returns (uint);
    function getBorrowingFeeWithDecay(uint _YUSDDebt) external view returns (uint);

    function decayBaseRateFromBorrowing() external;

    function getTroveStatus(address _borrower) external view returns (uint);

    function isTroveActive(address _borrower) external view returns (bool);

    function getTroveStake(address _borrower, address _token) external view returns (uint);

    function getTotalStake(address _token) external view returns (uint);

    function getTroveDebt(address _borrower) external view returns (uint);

    function getL_Coll(address _token) external view returns (uint);

    function getL_YUSD(address _token) external view returns (uint);

    function getRewardSnapshotColl(address _borrower, address _token) external view returns (uint);

    function getRewardSnapshotYUSD(address _borrower, address _token) external view returns (uint);

    // returns the VC value of a trove
    function getTroveVC(address _borrower) external view returns (uint);

    function getTroveColls(address _borrower) external view returns (address[] memory, uint[] memory);

    function getCurrentTroveState(address _borrower) external view returns (address[] memory, uint[] memory, uint);

    function setTroveStatus(address _borrower, uint num) external;

    function updateTroveColl(address _borrower, address[] memory _tokens, uint[] memory _amounts) external;

    function increaseTroveDebt(address _borrower, uint _debtIncrease) external returns (uint);

    function decreaseTroveDebt(address _borrower, uint _collDecrease) external returns (uint);

    function getTCR() external view returns (uint);

    function checkRecoveryMode() external view returns (bool);

    function closeTroveRedemption(address _borrower) external;

    function closeTroveLiquidation(address _borrower) external;

    function removeStakeTLR(address _borrower) external;

    function updateBaseRate(uint newBaseRate) external;

    function calcDecayedBaseRate() external view returns (uint);

    function redistributeDebtAndColl(IActivePool _activePool, IDefaultPool _defaultPool, uint _debt, address[] memory _tokens, uint[] memory _amounts) external;

    function updateSystemSnapshots_excludeCollRemainder(IActivePool _activePool, address[] memory _tokens, uint[] memory _amounts) external;

    function getEntireDebtAndColls(address _borrower) external view
    returns (uint, address[] memory, uint[] memory, uint, address[] memory, uint[] memory);

    function movePendingTroveRewardsToActivePool(IActivePool _activePool, IDefaultPool _defaultPool, uint _YUSD, address[] memory _tokens, uint[] memory _amounts, address _borrower) external;

    function collSurplusUpdate(address _account, address[] memory _tokens, uint[] memory _amounts) external;

}

File 5 of 28 : IStabilityPool.sol
// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.6.11;

import "./ICollateralReceiver.sol";

/*
 * The Stability Pool holds YUSD tokens deposited by Stability Pool depositors.
 *
 * When a trove is liquidated, then depending on system conditions, some of its YUSD debt gets offset with
 * YUSD in the Stability Pool:  that is, the offset debt evaporates, and an equal amount of YUSD tokens in the Stability Pool is burned.
 *
 * Thus, a liquidation causes each depositor to receive a YUSD loss, in proportion to their deposit as a share of total deposits.
 * They also receive an ETH gain, as the ETH collateral of the liquidated trove is distributed among Stability depositors,
 * in the same proportion.
 *
 * When a liquidation occurs, it depletes every deposit by the same fraction: for example, a liquidation that depletes 40%
 * of the total YUSD in the Stability Pool, depletes 40% of each deposit.
 *
 * A deposit that has experienced a series of liquidations is termed a "compounded deposit": each liquidation depletes the deposit,
 * multiplying it by some factor in range ]0,1[
 *
 * Please see the implementation spec in the proof document, which closely follows on from the compounded deposit / ETH gain derivations:
 * https://github.com/liquity/liquity/blob/master/papers/Scalable_Reward_Distribution_with_Compounding_Stakes.pdf
 *
 * --- YETI ISSUANCE TO STABILITY POOL DEPOSITORS ---
 *
 * An YETI issuance event occurs at every deposit operation, and every liquidation.
 *
 * Each deposit is tagged with the address of the front end through which it was made.
 *
 * All deposits earn a share of the issued YETI in proportion to the deposit as a share of total deposits. The YETI earned
 * by a given deposit, is split between the depositor and the front end through which the deposit was made, based on the front end's kickbackRate.
 *
 * Please see the system Readme for an overview:
 * https://github.com/liquity/dev/blob/main/README.md#yeti-issuance-to-stability-providers
 */
interface IStabilityPool is ICollateralReceiver {

    // --- Events ---
    
    event StabilityPoolETHBalanceUpdated(uint _newBalance);
    event StabilityPoolYUSDBalanceUpdated(uint _newBalance);

    event BorrowerOperationsAddressChanged(address _newBorrowerOperationsAddress);
    event TroveManagerAddressChanged(address _newTroveManagerAddress);
    event ActivePoolAddressChanged(address _newActivePoolAddress);
    event DefaultPoolAddressChanged(address _newDefaultPoolAddress);
    event YUSDTokenAddressChanged(address _newYUSDTokenAddress);
    event SortedTrovesAddressChanged(address _newSortedTrovesAddress);
    event PriceFeedAddressChanged(address _newPriceFeedAddress);
    event CommunityIssuanceAddressChanged(address _newCommunityIssuanceAddress);

    event P_Updated(uint _P);
    event S_Updated(uint _S, uint128 _epoch, uint128 _scale);
    event G_Updated(uint _G, uint128 _epoch, uint128 _scale);
    event EpochUpdated(uint128 _currentEpoch);
    event ScaleUpdated(uint128 _currentScale);

    event FrontEndRegistered(address indexed _frontEnd, uint _kickbackRate);
    event FrontEndTagSet(address indexed _depositor, address indexed _frontEnd);

    event DepositSnapshotUpdated(address indexed _depositor, uint _P, uint _S, uint _G);
    event FrontEndSnapshotUpdated(address indexed _frontEnd, uint _P, uint _G);
    event UserDepositChanged(address indexed _depositor, uint _newDeposit);
    event FrontEndStakeChanged(address indexed _frontEnd, uint _newFrontEndStake, address _depositor);

    event ETHGainWithdrawn(address indexed _depositor, uint _ETH, uint _YUSDLoss);
    event YETIPaidToDepositor(address indexed _depositor, uint _YETI);
    event YETIPaidToFrontEnd(address indexed _frontEnd, uint _YETI);
    event EtherSent(address _to, uint _amount);

    // --- Functions ---

    /*
     * Called only once on init, to set addresses of other Liquity contracts
     * Callable only by owner, renounces ownership at the end
     */
    function setAddresses(
        address _borrowerOperationsAddress,
        address _troveManagerAddress,
        address _activePoolAddress,
        address _yusdTokenAddress,
        address _sortedTrovesAddress,
        address _communityIssuanceAddress,
        address _whitelistAddress,
        address _troveManagerLiquidationsAddress
    )
        external;

    /*
     * Initial checks:
     * - Frontend is registered or zero address
     * - Sender is not a registered frontend
     * - _amount is not zero
     * ---
     * - Triggers a YETI issuance, based on time passed since the last issuance. The YETI issuance is shared between *all* depositors and front ends
     * - Tags the deposit with the provided front end tag param, if it's a new deposit
     * - Sends depositor's accumulated gains (YETI, ETH) to depositor
     * - Sends the tagged front end's accumulated YETI gains to the tagged front end
     * - Increases deposit and tagged front end's stake, and takes new snapshots for each.
     */
    function provideToSP(uint _amount, address _frontEndTag) external;

    /*
     * Initial checks:
     * - _amount is zero or there are no under collateralized troves left in the system
     * - User has a non zero deposit
     * ---
     * - Triggers a YETI issuance, based on time passed since the last issuance. The YETI issuance is shared between *all* depositors and front ends
     * - Removes the deposit's front end tag if it is a full withdrawal
     * - Sends all depositor's accumulated gains (YETI, ETH) to depositor
     * - Sends the tagged front end's accumulated YETI gains to the tagged front end
     * - Decreases deposit and tagged front end's stake, and takes new snapshots for each.
     *
     * If _amount > userDeposit, the user withdraws all of their compounded deposit.
     */
    function withdrawFromSP(uint _amount) external;


    /*
     * Initial checks:
     * - Frontend (sender) not already registered
     * - User (sender) has no deposit
     * - _kickbackRate is in the range [0, 100%]
     * ---
     * Front end makes a one-time selection of kickback rate upon registering
     */
    function registerFrontEnd(uint _kickbackRate) external;

    /*
     * Initial checks:
     * - Caller is TroveManager
     * ---
     * Cancels out the specified debt against the YUSD contained in the Stability Pool (as far as possible)
     * and transfers the Trove's ETH collateral from ActivePool to StabilityPool.
     * Only called by liquidation functions in the TroveManager.
     */
    function offset(uint _debt, address[] memory _assets, uint[] memory _amountsAdded) external;

//    /*
//     * Returns the total amount of ETH held by the pool, accounted in an internal variable instead of `balance`,
//     * to exclude edge cases like ETH received from a self-destruct.
//     */
//    function getETH() external view returns (uint);
    
     //*
//     * Calculates and returns the total gains a depositor has accumulated 
//     */
    function  getDepositorGains(address _depositor) external view returns (address[] memory assets, uint[] memory amounts);


    /*
     * Returns the total amount of VC held by the pool, accounted for by multipliying the
     * internal balances of collaterals by the price that is found at the time getVC() is called.
     */
    function getVC() external view returns (uint);

    /*
     * Returns YUSD held in the pool. Changes when users deposit/withdraw, and when Trove debt is offset.
     */
    function getTotalYUSDDeposits() external view returns (uint);

    /*
     * Calculate the YETI gain earned by a deposit since its last snapshots were taken.
     * If not tagged with a front end, the depositor gets a 100% cut of what their deposit earned.
     * Otherwise, their cut of the deposit's earnings is equal to the kickbackRate, set by the front end through
     * which they made their deposit.
     */
    function getDepositorYETIGain(address _depositor) external view returns (uint);

    /*
     * Return the YETI gain earned by the front end.
     */
    function getFrontEndYETIGain(address _frontEnd) external view returns (uint);

    /*
     * Return the user's compounded deposit.
     */
    function getCompoundedYUSDDeposit(address _depositor) external view returns (uint);

    /*
     * Return the front end's compounded stake.
     *
     * The front end's compounded stake is equal to the sum of its depositors' compounded deposits.
     */
    function getCompoundedFrontEndStake(address _frontEnd) external view returns (uint);

    /*
     * Add collateral type to totalColl 
     */
    function addCollateralType(address _collateral) external;

    function getDepositSnapshotS(address depositor, address collateral) external view returns (uint);

    function getCollateral(address _collateral) external view returns (uint);

    function getAllCollateral() external view returns (address[] memory, uint256[] memory);

}

File 6 of 28 : ICollSurplusPool.sol
// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.6.11;

import "../Dependencies/YetiCustomBase.sol";
import "./ICollateralReceiver.sol";


interface ICollSurplusPool is ICollateralReceiver {

    // --- Events ---
    
    event BorrowerOperationsAddressChanged(address _newBorrowerOperationsAddress);
    event TroveManagerAddressChanged(address _newTroveManagerAddress);
    event ActivePoolAddressChanged(address _newActivePoolAddress);

    event CollBalanceUpdated(address indexed _account);
    event CollateralSent(address _to);

    // --- Contract setters ---

    function setAddresses(
        address _borrowerOperationsAddress,
        address _troveManagerAddress,
        address _troveManagerRedemptionsAddress,
        address _activePoolAddress,
        address _whitelistAddress
    ) external;

    function getCollVC() external view returns (uint);

    function getAmountClaimable(address _account, address _collateral) external view returns (uint);

    function getCollateral(address _collateral) external view returns (uint);

    function getAllCollateral() external view returns (address[] memory, uint256[] memory);

    function accountSurplus(address _account, address[] memory _tokens, uint[] memory _amounts) external;

    function claimColl(address _account) external;

    function addCollateralType(address _collateral) external;
}

File 7 of 28 : IYUSDToken.sol
// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.6.11;

import "../Interfaces/IERC20.sol";
import "../Interfaces/IERC2612.sol";

interface IYUSDToken is IERC20, IERC2612 {
    
    // --- Events ---

    event TroveManagerAddressChanged(address _troveManagerAddress);
    event StabilityPoolAddressChanged(address _newStabilityPoolAddress);
    event BorrowerOperationsAddressChanged(address _newBorrowerOperationsAddress);

    event YUSDTokenBalanceUpdated(address _user, uint _amount);

    // --- Functions ---

    function mint(address _account, uint256 _amount) external;

    function burn(address _account, uint256 _amount) external;

    function sendToPool(address _sender,  address poolAddress, uint256 _amount) external;

    function returnFromPool(address poolAddress, address user, uint256 _amount ) external;
}

File 8 of 28 : ISortedTroves.sol
// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.6.11;

// Common interface for the SortedTroves Doubly Linked List.
interface ISortedTroves {

    // --- Events ---
    
    event SortedTrovesAddressChanged(address _sortedDoublyLLAddress);
    event BorrowerOperationsAddressChanged(address _borrowerOperationsAddress);
    event NodeAdded(address _id, uint _NICR);
    event NodeRemoved(address _id);

    // --- Functions ---
    
    function setParams(uint256 _size, address _TroveManagerAddress, address _borrowerOperationsAddress, address _troveManagerRedemptionsAddress) external;

    function insert(address _id, uint256 _ICR, address _prevId, address _nextId) external;

    function remove(address _id) external;

    function reInsert(address _id, uint256 _newICR, address _prevId, address _nextId) external;

    function contains(address _id) external view returns (bool);

    function isFull() external view returns (bool);

    function isEmpty() external view returns (bool);

    function getSize() external view returns (uint256);

    function getMaxSize() external view returns (uint256);

    function getFirst() external view returns (address);

    function getLast() external view returns (address);

    function getNext(address _id) external view returns (address);

    function getPrev(address _id) external view returns (address);

    function getOldICR(address _id) external view returns (uint256);

    function validInsertPosition(uint256 _ICR, address _prevId, address _nextId) external view returns (bool);

    function findInsertPosition(uint256 _ICR, address _prevId, address _nextId) external view returns (address, address);
}

File 9 of 28 : IYETIToken.sol
// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.6.11;

import "./IERC20.sol";
import "./IERC2612.sol";

interface IYETIToken is IERC20, IERC2612 {

    function sendToSYETI(address _sender, uint256 _amount) external;

    function getDeploymentStartTime() external view returns (uint256);

}

File 10 of 28 : ISYETI.sol
// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.6.11;

interface ISYETI {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);
    function increaseAllowance(address spender, uint256 addedValue) external returns (bool);
    function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);

    function name() external view returns (string memory);
    function symbol() external view returns (string memory);
    function decimals() external view returns (uint8);

    function mint(uint256 amount) external returns (bool);
    function burn(address to, uint256 shares) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

File 11 of 28 : IActivePool.sol
// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.6.11;

import "./IPool.sol";

    
interface IActivePool is IPool {
    // --- Events ---
    event BorrowerOperationsAddressChanged(address _newBorrowerOperationsAddress);
    event TroveManagerAddressChanged(address _newTroveManagerAddress);
    event ActivePoolYUSDDebtUpdated(uint _YUSDDebt);
    event ActivePoolCollateralBalanceUpdated(address _collateral, uint _amount);

    // --- Functions ---
    
    function sendCollaterals(address _to, address[] memory _tokens, uint[] memory _amounts) external returns (bool);
    function sendCollateralsUnwrap(
        address _to,
        address[] memory _tokens,
        uint[] memory _amounts,
        bool _collectRewards) external returns (bool);
    function getCollateralVC(address collateralAddress) external view returns (uint);
    function addCollateralType(address _collateral) external;
}

File 12 of 28 : IWhitelist.sol
// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.6.11;


interface IWhitelist {
    function getValidCollateral() view external returns (address[] memory);

    function setAddresses(
        address _activePoolAddress,
        address _defaultPoolAddress,
        address _stabilityPoolAddress,
        address _collSurplusPoolAddress, 
        address _borrowerOperationsAddress
    ) external;

    function isValidRouter(address _router) external view returns (bool);
    function getOracle(address _collateral) view external returns (address);
    function getRatio(address _collateral) view external returns (uint256);
    function getIsActive(address _collateral) view external returns (bool);
    function getPriceCurve(address _collateral) external view returns (address);
    function getDecimals(address _collateral) external view returns (uint256);
    function getFee(address _collateral, uint _collateralVCInput, uint256 _collateralVCBalancePost, uint256 _totalVCBalancePre, uint256 _totalVCBalancePost) external view returns (uint256 fee);
    function getFeeAndUpdate(address _collateral, uint _collateralVCInput, uint256 _collateralVCBalancePost, uint256 _totalVCBalancePre, uint256 _totalVCBalancePost) external returns (uint256 fee);
    function getIndex(address _collateral) external view returns (uint256);
    function isWrapped(address _collateral) external view returns (bool);
    function setDefaultRouter(address _collateral, address _router) external;

    function getValueVC(address _collateral, uint _amount) view external returns (uint);
    function getValueUSD(address _collateral, uint _amount) view external returns (uint256);
    function getDefaultRouterAddress(address _collateral) external view returns (address);
}

File 13 of 28 : ITroveManagerLiquidations.sol
// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.6.11;


interface ITroveManagerLiquidations {
    function batchLiquidateTroves(address[] memory _troveArray, address _liquidator) external;
}

File 14 of 28 : ITroveManagerRedemptions.sol
// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.6.11;

interface ITroveManagerRedemptions {
    function redeemCollateral(
        uint _YUSDamount,
        uint _YUSDMaxFee,
        address _firstRedemptionHint,
        address _upperPartialRedemptionHint,
        address _lowerPartialRedemptionHint,
        uint _partialRedemptionHintNICR,
        uint _maxIterations,
        // uint _maxFeePercentage,
        address _redeemSender
    )
    external;
}

File 15 of 28 : LiquityBase.sol
// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.6.11;

import "./LiquityMath.sol";
import "../Interfaces/IActivePool.sol";
import "../Interfaces/IDefaultPool.sol";
import "../Interfaces/ILiquityBase.sol";
import "../Interfaces/IWhitelist.sol";
import "./YetiCustomBase.sol";


/* 
* Base contract for TroveManager, BorrowerOperations and StabilityPool. Contains global system constants and
* common functions. 
*/
contract LiquityBase is ILiquityBase, YetiCustomBase {

    uint constant public _100pct = 1000000000000000000; // 1e18 == 100%

    uint constant public _110pct = 1100000000000000000; // 1.1e18 == 110%

    // Minimum collateral ratio for individual troves
    uint constant public MCR = 1100000000000000000; // 110%

    // Critical system collateral ratio. If the system's total collateral ratio (TCR) falls below the CCR, Recovery Mode is triggered.
    uint constant public CCR = 1500000000000000000; // 150%

    // Amount of YUSD to be locked in gas pool on opening troves
    uint constant public YUSD_GAS_COMPENSATION = 200e18;

    // Minimum amount of net YUSD debt a must have
    uint constant public MIN_NET_DEBT = 1800e18;
    // uint constant public MIN_NET_DEBT = 0; 

    uint constant public PERCENT_DIVISOR = 200; // dividing by 200 yields 0.5%

    uint constant public BORROWING_FEE_FLOOR = DECIMAL_PRECISION / 1000 * 5; // 0.5%
    uint constant public REDEMPTION_FEE_FLOOR = DECIMAL_PRECISION / 1000 * 5; // 0.5%

    IActivePool public activePool;

    IDefaultPool public defaultPool;

    // --- Gas compensation functions ---

    // Returns the composite debt (drawn debt + gas compensation) of a trove, for the purpose of ICR calculation
    function _getCompositeDebt(uint _debt) internal pure returns (uint) {
        return _debt.add(YUSD_GAS_COMPENSATION);
    }


    function _getNetDebt(uint _debt) internal pure returns (uint) {
        return _debt.sub(YUSD_GAS_COMPENSATION);
    }


    // Return the amount of collateral to be drawn from a trove's collateral and sent as gas compensation.
    function _getCollGasCompensation(newColls memory _coll) internal pure returns (newColls memory) {
        require(_coll.tokens.length == _coll.amounts.length, "_getCollGasCompensation(): Collateral length mismatch");

        uint[] memory amounts = new uint[](_coll.tokens.length);
        for (uint i = 0; i < _coll.tokens.length; i++) {
            amounts[i] = _coll.amounts[i] / PERCENT_DIVISOR;
        }
        return newColls(_coll.tokens, amounts);
    }

    // Return the system's Total Virtual Coin Balance
    // Virtual Coins are a way to keep track of the system collateralization given
    // the collateral ratios of each collateral type
    function getEntireSystemColl() public view returns (uint entireSystemColl) {
        uint activeColl = activePool.getVC();
        uint liquidatedColl = defaultPool.getVC();

        return activeColl.add(liquidatedColl);
    }


    function getEntireSystemDebt() public override view returns (uint entireSystemDebt) {
        uint activeDebt = activePool.getYUSDDebt();
        uint closedDebt = defaultPool.getYUSDDebt();

        return activeDebt.add(closedDebt);
    }


    function _getICRColls(newColls memory _colls, uint _debt) internal view returns (uint ICR) {
        uint totalVC = _getVCColls(_colls);
        ICR = LiquityMath._computeCR(totalVC, _debt);
        return ICR;
    }


    function _getVC(address[] memory _tokens, uint[] memory _amounts) internal view returns (uint totalVC) {
        require(_tokens.length == _amounts.length, "Not same length");
        for (uint i = 0; i < _tokens.length; i++) {
            uint tokenVC = whitelist.getValueVC(_tokens[i], _amounts[i]);
            totalVC = totalVC.add(tokenVC);
        }
        return totalVC;
    }


    function _getVCColls(newColls memory _colls) internal view returns (uint VC) {
        for (uint i = 0; i < _colls.tokens.length; i++) {
            uint valueVC = whitelist.getValueVC(_colls.tokens[i], _colls.amounts[i]);
            VC = VC.add(valueVC);
        }
        return VC;
    }


    function _getUSDColls(newColls memory _colls) internal view returns (uint USDValue) {
        for (uint i = 0; i < _colls.tokens.length; i++) {
            uint valueUSD = whitelist.getValueUSD(_colls.tokens[i], _colls.amounts[i]);
            USDValue = USDValue.add(valueUSD);
        }
        return USDValue;
    }


    function _getTCR() internal view returns (uint TCR) {
        uint entireSystemColl = getEntireSystemColl();
        uint entireSystemDebt = getEntireSystemDebt();
        
        TCR = LiquityMath._computeCR(entireSystemColl, entireSystemDebt);
        return TCR;
    }


    function _checkRecoveryMode() internal view returns (bool) {
        uint TCR = _getTCR();

        return TCR < CCR;
    }

    // fee and amount are denominated in dollar
    function _requireUserAcceptsFee(uint _fee, uint _amount, uint _maxFeePercentage) internal pure {
        uint feePercentage = _fee.mul(DECIMAL_PRECISION).div(_amount);
        require(feePercentage <= _maxFeePercentage, "Fee exceeded provided maximum");
    }


    // get Colls struct for the given tokens and amounts
    function _getColls(address[] memory tokens, uint[] memory amounts) internal view returns (newColls memory coll) {
        require(tokens.length == amounts.length);
        coll.tokens = tokens;
        for (uint i = 0; i < tokens.length; i++) {
            coll.amounts[whitelist.getIndex(tokens[i])] = amounts[i];
        }
        return coll;
    }


    // checks coll has a nonzero balance of at least one token in coll.tokens
    function _CollsIsNonZero(newColls memory coll) internal pure returns (bool) {
        for (uint i = 0; i < coll.tokens.length; i++) {
            if (coll.amounts[i] > 0) {
                return true;
            }
        }
        return false;
    }


    function _sendColl(address _to, newColls memory _coll) internal returns (bool) {
        for (uint i = 0; i < _coll.tokens.length; i++) {
            IERC20 token = IERC20(_coll.tokens[i]);
            if (!token.transfer(_to, _coll.amounts[i])) {
                return false;
            }
        }
        return true;
    }


    // Check whether or not the system *would be* in Recovery Mode, given the entire system coll and debt.
    // returns true if the system would be in recovery mode and false if not
    function _checkPotentialRecoveryMode(uint _entireSystemColl, uint _entireSystemDebt)
    internal
    pure
    returns (bool)
    {
        uint TCR = LiquityMath._computeCR(_entireSystemColl, _entireSystemDebt);

        return TCR < CCR;
    }



}

File 16 of 28 : Ownable.sol
// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.6.11;

/**
 * Based on OpenZeppelin's Ownable contract:
 * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol
 *
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
contract Ownable {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor () internal {
        _owner = msg.sender;
        emit OwnershipTransferred(address(0), msg.sender);
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(isOwner(), "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Returns true if the caller is the current owner.
     */
    function isOwner() public view returns (bool) {
        return msg.sender == _owner;
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     *
     * NOTE: This function is not safe, as it doesn’t check owner is calling it.
     * Make sure you check it before calling it.
     */
    function _renounceOwnership() internal {
        emit OwnershipTransferred(_owner, address(0));
        _owner = address(0);
    }
}

File 17 of 28 : CheckContract.sol
// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.6.11;


contract CheckContract {
    /**
     * Check that the account is an already deployed non-destroyed contract.
     * See: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Address.sol#L12
     */
    function checkContract(address _account) internal view {
        require(_account != address(0), "Account cannot be zero address");

        uint256 size;
        // solhint-disable-next-line no-inline-assembly
        assembly { size := extcodesize(_account) }
        require(size > 0, "Account code size cannot be zero");
    }
}

File 18 of 28 : ILiquityBase.sol
// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.6.11;

import "./IPriceFeed.sol";


interface ILiquityBase {

    function getEntireSystemDebt() external view returns (uint entireSystemDebt);
}

File 19 of 28 : IDefaultPool.sol
// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.6.11;

import "./IPool.sol";

interface IDefaultPool is IPool {
    // --- Events ---
    event TroveManagerAddressChanged(address _newTroveManagerAddress);
    event DefaultPoolYUSDDebtUpdated(uint _YUSDDebt);
    event DefaultPoolETHBalanceUpdated(uint _ETH);

    // --- Functions ---
    
    function sendCollsToActivePool(address[] memory _collaterals, uint[] memory _amounts, address _borrower) external;
    function addCollateralType(address _collateral) external;
    function getCollateralVC(address collateralAddress) external view returns (uint);
}

File 20 of 28 : IPriceFeed.sol
// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.6.11;

interface IPriceFeed {

    // --- Events ---
    event LastGoodPriceUpdated(uint _lastGoodPrice);

    // --- Function ---
    // function fetchPrice() external returns (uint);

    function fetchPrice_v() view external returns (uint);
}

File 21 of 28 : ICollateralReceiver.sol
// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.6.11;

interface ICollateralReceiver {
    function receiveCollateral(address[] memory _tokens, uint[] memory _amounts) external;
}

File 22 of 28 : IERC20.sol
// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.6.11;

/**
 * Based on the OpenZeppelin IER20 interface:
 * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol
 *
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);
    function increaseAllowance(address spender, uint256 addedValue) external returns (bool);
    function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);

    function name() external view returns (string memory);
    function symbol() external view returns (string memory);
    function decimals() external view returns (uint8);
    
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

File 23 of 28 : IERC2612.sol
// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.6.11;

/**
 * @dev Interface of the ERC2612 standard as defined in the EIP.
 *
 * Adds the {permit} method, which can be used to change one's
 * {IERC20-allowance} without having to send a transaction, by signing a
 * message. This allows users to spend tokens without having to hold Ether.
 *
 * See https://eips.ethereum.org/EIPS/eip-2612.
 * 
 * Code adapted from https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2237/
 */
interface IERC2612 {
    /**
     * @dev Sets `amount` as the allowance of `spender` over `owner`'s tokens,
     * given `owner`'s signed approval.
     *
     * IMPORTANT: The same issues {IERC20-approve} has related to transaction
     * ordering also apply here.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     * - `deadline` must be a timestamp in the future.
     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
     * over the EIP712-formatted function arguments.
     * - the signature must use ``owner``'s current nonce (see {nonces}).
     *
     * For more information on the signature format, see the
     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
     * section].
     */
    function permit(address owner, address spender, uint256 amount, 
                    uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;
    
    /**
     * @dev Returns the current ERC2612 nonce for `owner`. This value must be
     * included whenever a signature is generated for {permit}.
     *
     * Every successful call to {permit} increases `owner`'s nonce by one. This
     * prevents a signature from being used multiple times.
     *
     * `owner` can limit the time a Permit is valid for by setting `deadline` to 
     * a value in the near future. The deadline argument can be set to uint(-1) to 
     * create Permits that effectively never expire.
     */
    function nonces(address owner) external view returns (uint256);
    
    function version() external view returns (string memory);
    function permitTypeHash() external view returns (bytes32);
    function domainSeparator() external view returns (bytes32);
}

File 24 of 28 : IPool.sol
// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.6.11;

import "./ICollateralReceiver.sol";

// Common interface for the Pools.
interface IPool is ICollateralReceiver {
    
    // --- Events ---
    
    event ETHBalanceUpdated(uint _newBalance);
    event YUSDBalanceUpdated(uint _newBalance);
    event ActivePoolAddressChanged(address _newActivePoolAddress);
    event DefaultPoolAddressChanged(address _newDefaultPoolAddress);
    event StabilityPoolAddressChanged(address _newStabilityPoolAddress);
    event WhitelistAddressChanged(address _newWhitelistAddress);
    event EtherSent(address _to, uint _amount);
    event CollateralSent(address _collateral, address _to, uint _amount);

    // --- Functions ---

    function getVC() external view returns (uint);

    function getCollateral(address collateralAddress) external view returns (uint);

    function getAllCollateral() external view returns (address[] memory, uint256[] memory);

    function getYUSDDebt() external view returns (uint);

    function increaseYUSDDebt(uint _amount) external;

    function decreaseYUSDDebt(uint _amount) external;

}

File 25 of 28 : YetiCustomBase.sol
// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.6.11;

import "./BaseMath.sol";
import "./SafeMath.sol";
import "../Interfaces/IERC20.sol";
import "../Interfaces/IWhitelist.sol";


contract YetiCustomBase is BaseMath {
    using SafeMath for uint256;

    IWhitelist whitelist;

    struct newColls {
        // tokens and amounts should be the same length
        address[] tokens;
        uint256[] amounts;
    }

    // Collateral math

    // gets the sum of _coll1 and _coll2
    function _sumColls(newColls memory _coll1, newColls memory _coll2)
        internal
        view
        returns (newColls memory finalColls)
    {
        newColls memory coll3;

        coll3.tokens = whitelist.getValidCollateral();
        coll3.amounts = new uint256[](coll3.tokens.length);

        uint256 n = 0;
        for (uint256 i = 0; i < _coll1.tokens.length; i++) {
            uint256 tokenIndex = whitelist.getIndex(_coll1.tokens[i]);
            if (_coll1.amounts[i] > 0) {
                n++;
                coll3.amounts[tokenIndex] = _coll1.amounts[i];
            }
        }

        for (uint256 i = 0; i < _coll2.tokens.length; i++) {
            uint256 tokenIndex = whitelist.getIndex(_coll2.tokens[i]);
            if (_coll2.amounts[i] > 0) {
                if (coll3.amounts[tokenIndex] == 0) {
                    n++;
                }
                coll3.amounts[tokenIndex] = coll3.amounts[tokenIndex].add(_coll2.amounts[i]);
            }
        }

        address[] memory sumTokens = new address[](n);
        uint256[] memory sumAmounts = new uint256[](n);
        uint256 j = 0;

        // should only find n amounts over 0
        for (uint256 i = 0; i < coll3.tokens.length; i++) {
            if (coll3.amounts[i] > 0) {
                sumTokens[j] = coll3.tokens[i];
                sumAmounts[j] = coll3.amounts[i];
                j++;
            }
        }
        finalColls.tokens = sumTokens;
        finalColls.amounts = sumAmounts;
    }


    // gets the sum of coll1 with tokens and amounts
    function _sumColls(
        newColls memory _coll1,
        address[] memory tokens,
        uint256[] memory amounts
    ) internal view returns (newColls memory) {
        newColls memory coll2 = newColls(tokens, amounts);
        return _sumColls(_coll1, coll2);
    }


    function _sumColls(
        address[] memory tokens1,
        uint256[] memory amounts1,
        address[] memory tokens2,
        uint256[] memory amounts2
    ) internal view returns (newColls memory) {
        newColls memory coll1 = newColls(tokens1, amounts1);
        return _sumColls(coll1, tokens2, amounts2);
    }


    // Function for summing colls when coll1 includes all the tokens in the whitelist
    // Used in active, default, stability, and surplus pools
    // assumes _coll1.tokens = all whitelisted tokens
    function _leftSumColls(
        newColls memory _coll1,
        address[] memory _tokens,
        uint256[] memory _amounts
    ) internal view returns (uint[] memory) {
        uint[] memory sumAmounts = _getArrayCopy(_coll1.amounts);

        // assumes that sumAmounts length = whitelist tokens length.
        for (uint256 i = 0; i < _tokens.length; i++) {
            uint tokenIndex = whitelist.getIndex(_tokens[i]);
            sumAmounts[tokenIndex] = sumAmounts[tokenIndex].add(_amounts[i]);
        }

        return sumAmounts;
    }


    // Function for summing colls when one list is all tokens. Used in active, default, stability, and surplus pools
    function _leftSubColls(newColls memory _coll1, address[] memory _subTokens, uint[] memory _subAmounts)
        internal
        view
        returns (uint[] memory)
    {
        uint[] memory diffAmounts = _getArrayCopy(_coll1.amounts);

        //assumes that coll1.tokens = whitelist tokens. Keeps all of coll1's tokens, and subtracts coll2's amounts
        for (uint256 i = 0; i < _subTokens.length; i++) {
            uint256 tokenIndex = whitelist.getIndex(_subTokens[i]);
            diffAmounts[tokenIndex] = diffAmounts[tokenIndex].sub(_subAmounts[i]);
        }
        return diffAmounts;
    }
    

    // Returns _coll1 minus _tokens and _amounts
    // will error if _tokens include a token not in _coll1.tokens
    function _subColls(newColls memory _coll1, address[] memory _tokens, uint[] memory _amounts)
        internal
        view
        returns (newColls memory finalColls)
    {
        require(_tokens.length == _amounts.length, "Sub Colls invalid input");

        newColls memory coll3;
        coll3.tokens = whitelist.getValidCollateral();
        coll3.amounts = new uint256[](coll3.tokens.length);
        uint256 n = 0;

        for (uint256 i = 0; i < _coll1.tokens.length; i++) {
            if (_coll1.amounts[i] > 0) {
                uint256 tokenIndex = whitelist.getIndex(_coll1.tokens[i]);
                coll3.amounts[tokenIndex] = _coll1.amounts[i];
                n++;
            }
        }

        for (uint256 i = 0; i < _tokens.length; i++) {
            uint256 tokenIndex = whitelist.getIndex(_tokens[i]);
            require(coll3.amounts[tokenIndex] >= _amounts[i], "illegal sub");
            coll3.amounts[tokenIndex] = coll3.amounts[tokenIndex].sub(_amounts[i]);
            if (coll3.amounts[tokenIndex] == 0) {
                n--;
            }
        }

        address[] memory diffTokens = new address[](n);
        uint256[] memory diffAmounts = new uint256[](n);
        uint256 j = 0;

        for (uint256 i = 0; i < coll3.tokens.length; i++) {
            if (coll3.amounts[i] > 0) {
                diffTokens[j] = coll3.tokens[i];
                diffAmounts[j] = coll3.amounts[i];
                j++;
            }
        }
        finalColls.tokens = diffTokens;
        finalColls.amounts = diffAmounts;
    }

    function _getArrayCopy(uint[] memory _arr) internal pure returns (uint[] memory){
        uint[] memory copy = new uint[](_arr.length);
        for (uint i = 0; i < _arr.length; i++) {
            copy[i] = _arr[i];
        }
        return copy;
    }
}

File 26 of 28 : BaseMath.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.6.11;


contract BaseMath {
    uint constant public DECIMAL_PRECISION = 1e18;
}

File 27 of 28 : SafeMath.sol
// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.6.11;

/**
 * Based on OpenZeppelin's SafeMath:
 * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/math/SafeMath.sol
 *
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     * - Subtraction cannot overflow.
     *
     * _Available since v2.4.0._
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     *
     * _Available since v2.4.0._
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        // Solidity only automatically asserts when dividing by 0
        require(b > 0, errorMessage);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return mod(a, b, "SafeMath: modulo by zero");
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts with custom message when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     *
     * _Available since v2.4.0._
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }
}

File 28 of 28 : LiquityMath.sol
// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.6.11;

import "./SafeMath.sol";

library LiquityMath {
    using SafeMath for uint;

    uint internal constant DECIMAL_PRECISION = 1e18;

    function _min(uint _a, uint _b) internal pure returns (uint) {
        return (_a < _b) ? _a : _b;
    }

    function _max(uint _a, uint _b) internal pure returns (uint) {
        return (_a >= _b) ? _a : _b;
    }

    /* 
    * Multiply two decimal numbers and use normal rounding rules:
    * -round product up if 19'th mantissa digit >= 5
    * -round product down if 19'th mantissa digit < 5
    *
    * Used only inside the exponentiation, _decPow().
    */
    function decMul(uint x, uint y) internal pure returns (uint decProd) {
        uint prod_xy = x.mul(y);

        decProd = prod_xy.add(DECIMAL_PRECISION / 2).div(DECIMAL_PRECISION);
    }

    /* 
    * _decPow: Exponentiation function for 18-digit decimal base, and integer exponent n.
    * 
    * Uses the efficient "exponentiation by squaring" algorithm. O(log(n)) complexity. 
    * 
    * Called by two functions that represent time in units of minutes:
    * 1) TroveManager._calcDecayedBaseRate
    * 2) CommunityIssuance._getCumulativeIssuanceFraction 
    * 
    * The exponent is capped to avoid reverting due to overflow. The cap 525600000 equals
    * "minutes in 1000 years": 60 * 24 * 365 * 1000
    * 
    * If a period of > 1000 years is ever used as an exponent in either of the above functions, the result will be
    * negligibly different from just passing the cap, since: 
    *
    * In function 1), the decayed base rate will be 0 for 1000 years or > 1000 years
    * In function 2), the difference in tokens issued at 1000 years and any time > 1000 years, will be negligible
    */
    function _decPow(uint _base, uint _minutes) internal pure returns (uint) {
       
        if (_minutes > 525600000) {_minutes = 525600000;}  // cap to avoid overflow
    
        if (_minutes == 0) {return DECIMAL_PRECISION;}

        uint y = DECIMAL_PRECISION;
        uint x = _base;
        uint n = _minutes;

        // Exponentiation-by-squaring
        while (n > 1) {
            if (n % 2 == 0) {
                x = decMul(x, x);
                n = n.div(2);
            } else { // if (n % 2 != 0)
                y = decMul(x, y);
                x = decMul(x, x);
                n = (n.sub(1)).div(2);
            }
        }

        return decMul(x, y);
  }

    function _getAbsoluteDifference(uint _a, uint _b) internal pure returns (uint) {
        return (_a >= _b) ? _a.sub(_b) : _b.sub(_a);
    }

    //  _coll should be the amount of VC and _debt is debt of YUSD\
    // new collateral ratio is 10**18 times the collateral ratio. (150% => 1.5e18)
    function _computeCR(uint _coll, uint _debt) internal pure returns (uint) {
        if (_debt > 0) {
            uint newCollRatio = _coll.mul(10**18).div(_debt);
            return newCollRatio;
        }
        // Return the maximal value for uint256 if the Trove has a debt of 0. Represents "infinite" CR.
        else { // if (_debt == 0)
            return 2**256 - 1; 
        }
    }

}

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

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_activePoolAddress","type":"address"}],"name":"ActivePoolAddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_newBorrowerOperationsAddress","type":"address"}],"name":"BorrowerOperationsAddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_collSurplusPoolAddress","type":"address"}],"name":"CollSurplusPoolAddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_defaultPoolAddress","type":"address"}],"name":"DefaultPoolAddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_gasPoolAddress","type":"address"}],"name":"GasPoolAddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"liquidatedAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalYUSDGasCompensation","type":"uint256"},{"indexed":false,"internalType":"address[]","name":"totalCollTokens","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"totalCollAmounts","type":"uint256[]"},{"indexed":false,"internalType":"address[]","name":"totalCollGasCompTokens","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"totalCollGasCompAmounts","type":"uint256[]"}],"name":"Liquidation","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_sYETIAddress","type":"address"}],"name":"SYETIAddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_sortedTrovesAddress","type":"address"}],"name":"SortedTrovesAddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_stabilityPoolAddress","type":"address"}],"name":"StabilityPoolAddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_borrower","type":"address"},{"indexed":false,"internalType":"uint256","name":"_debt","type":"uint256"},{"indexed":false,"internalType":"enum TroveManagerBase.TroveManagerOperation","name":"_operation","type":"uint8"}],"name":"TroveLiquidated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_borrower","type":"address"},{"indexed":false,"internalType":"uint256","name":"_debt","type":"uint256"},{"indexed":false,"internalType":"address[]","name":"_tokens","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"_amounts","type":"uint256[]"},{"indexed":false,"internalType":"enum TroveManagerBase.TroveManagerOperation","name":"operation","type":"uint8"}],"name":"TroveUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_yetiTokenAddress","type":"address"}],"name":"YETITokenAddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_newYUSDTokenAddress","type":"address"}],"name":"YUSDTokenAddressChanged","type":"event"},{"inputs":[],"name":"BORROWING_FEE_FLOOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CCR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DECIMAL_PRECISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MCR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_NET_DEBT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERCENT_DIVISOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REDEMPTION_FEE_FLOOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"YUSD_GAS_COMPENSATION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_100pct","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_110pct","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"activePool","outputs":[{"internalType":"contract IActivePool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_troveArray","type":"address[]"},{"internalType":"address","name":"_liquidator","type":"address"}],"name":"batchLiquidateTroves","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"borrowerOperationsAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"defaultPool","outputs":[{"internalType":"contract IDefaultPool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getEntireSystemColl","outputs":[{"internalType":"uint256","name":"entireSystemColl","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getEntireSystemDebt","outputs":[{"internalType":"uint256","name":"entireSystemDebt","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_borrowerOperationsAddress","type":"address"},{"internalType":"address","name":"_activePoolAddress","type":"address"},{"internalType":"address","name":"_defaultPoolAddress","type":"address"},{"internalType":"address","name":"_stabilityPoolAddress","type":"address"},{"internalType":"address","name":"_gasPoolAddress","type":"address"},{"internalType":"address","name":"_collSurplusPoolAddress","type":"address"},{"internalType":"address","name":"_yusdTokenAddress","type":"address"},{"internalType":"address","name":"_sortedTrovesAddress","type":"address"},{"internalType":"address","name":"_yetiTokenAddress","type":"address"},{"internalType":"address","name":"_sYETIAddress","type":"address"},{"internalType":"address","name":"_whitelistAddress","type":"address"},{"internalType":"address","name":"_troveManagerAddress","type":"address"},{"internalType":"address","name":"_yetiFinanceTreasury","type":"address"}],"name":"setAddresses","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sortedTroves","outputs":[{"internalType":"contract ISortedTroves","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"troveManager","outputs":[{"internalType":"contract ITroveManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"troveManagerAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"troveManagerLiquidationsAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"troveManagerRedemptionsAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

608060405234801561001057600080fd5b50600380546001600160a01b031916339081179091556040516000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a361479f806100606000396000f3fe608060405234801561001057600080fd5b50600436106101585760003560e01c8063795d26c3116100c3578063ae9187541161007c578063ae9187541461021f578063b7f8cf9b14610227578063db5e73211461022f578063e369e4ab146102bf578063f5f468ed1461036b578063f92d34331461019b57610158565b8063795d26c3146101e35780637f7dde4a146101eb578063887105d3146101f35780638da5cb5b146101fb5780638f32d59b14610203578063a20baee6146101db57610158565b80634870dd9a116101155780634870dd9a146101bb578063499f99d9146101c35780635733d58f146101cb5780635a4d28bb146101d357806372fe25aa146101db578063794e5724146101a357610158565b806316a81f311461015d5780631bf435551461018157806328d28b5b1461019b578063308e9647146101a35780633cc74225146101ab5780633d83908a146101b3575b600080fd5b610165610373565b604080516001600160a01b039092168252519081900360200190f35b610189610382565b60408051918252519081900360200190f35b61018961038f565b61018961039a565b6101656103a6565b6101656103b5565b6101896103c4565b6101896103c9565b6101896103d6565b6101656103e2565b6101896103f1565b6101896103fd565b61016561050a565b610189610519565b6101656105e1565b61020b6105f0565b604080519115158252519081900360200190f35b610165610601565b610165610610565b6102bd60048036036101a081101561024657600080fd5b506001600160a01b038135811691602081013582169160408201358116916060810135821691608082013581169160a081013582169160c082013581169160e0810135821691610100820135811691610120810135821691610140820135811691610160810135821691610180909101351661061f565b005b6102bd600480360360408110156102d557600080fd5b810190602081018135600160201b8111156102ef57600080fd5b82018360208201111561030157600080fd5b803590602001918460208302840111600160201b8311171561032257600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550505090356001600160a01b03169150610b8a9050565b6101656112f6565b600f546001600160a01b031681565b686194049f30f720000081565b6611c37937e0800081565b670f43fc2c04ee000081565b6002546001600160a01b031681565b6006546001600160a01b031681565b60c881565b680ad78ebc5ac620000081565b6714d1120d7b16000081565b600d546001600160a01b031681565b670de0b6b3a764000081565b600080600160009054906101000a90046001600160a01b03166001600160a01b0316638df709926040518163ffffffff1660e01b815260040160206040518083038186803b15801561044e57600080fd5b505afa158015610462573d6000803e3d6000fd5b505050506040513d602081101561047857600080fd5b5051600254604080516346fb84c960e11b815290519293506000926001600160a01b0390921691638df7099291600480820192602092909190829003018186803b1580156104c557600080fd5b505afa1580156104d9573d6000803e3d6000fd5b505050506040513d60208110156104ef57600080fd5b50519050610503828263ffffffff61130516565b9250505090565b6001546001600160a01b031681565b600080600160009054906101000a90046001600160a01b03166001600160a01b03166301d40b636040518163ffffffff1660e01b815260040160206040518083038186803b15801561056a57600080fd5b505afa15801561057e573d6000803e3d6000fd5b505050506040513d602081101561059457600080fd5b5051600254604080516301d40b6360e01b815290519293506000926001600160a01b03909216916301d40b6391600480820192602092909190829003018186803b1580156104c557600080fd5b6003546001600160a01b031690565b6003546001600160a01b0316331490565b6010546001600160a01b031681565b6004546001600160a01b031681565b6106276105f0565b610678576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6106818d611368565b61068a8c611368565b6106938b611368565b61069c8a611368565b6106a589611368565b6106ae88611368565b6106b787611368565b6106c086611368565b6106c985611368565b6106d284611368565b6106db83611368565b6106e482611368565b6106ed81611368565b8c600460006101000a8154816001600160a01b0302191690836001600160a01b031602179055508b600160006101000a8154816001600160a01b0302191690836001600160a01b031602179055508a600260006101000a8154816001600160a01b0302191690836001600160a01b0316021790555089600560006101000a8154816001600160a01b0302191690836001600160a01b03160217905550826000806101000a8154816001600160a01b0302191690836001600160a01b0316021790555088600c60006101000a8154816001600160a01b0302191690836001600160a01b0316021790555087601160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555086600760006101000a8154816001600160a01b0302191690836001600160a01b0316021790555085601060006101000a8154816001600160a01b0302191690836001600160a01b0316021790555084600860006101000a8154816001600160a01b0302191690836001600160a01b0316021790555083600960006101000a8154816001600160a01b0302191690836001600160a01b0316021790555081600660006101000a8154816001600160a01b0302191690836001600160a01b0316021790555081600d60006101000a8154816001600160a01b0302191690836001600160a01b0316021790555080601260006101000a8154816001600160a01b0302191690836001600160a01b031602179055507f3ca631ffcd2a9b5d9ae18543fc82f58eb4ca33af9e6ab01b7a8e95331e6ed9858d60405180826001600160a01b03166001600160a01b0316815260200191505060405180910390a1604080516001600160a01b038e16815290517f78f058b189175430c48dc02699e3a0031ea4ff781536dc2fab847de4babdd8829181900360200190a1604080516001600160a01b038d16815290517f5ee0cae2f063ed938bb55046f6a932fb6ae792bf43624806bb90abe68a50be9b9181900360200190a1604080516001600160a01b038c16815290517f82966d27eea39b038ee0fa30cd16532bb24f6e65d31cb58fb227aa5766cdcc7f9181900360200190a1604080516001600160a01b038b16815290517fcfb07d791fcafc032b35837b50eb84b74df518cf4cc287e8084f47630fa70fa09181900360200190a1604080516001600160a01b038a16815290517fe67f36a6e961157d6eff83b91f3af5a62131ceb6f04954ef74f51c1c05e7f88d9181900360200190a1604080516001600160a01b038916815290517fc3cd2681391697b6aa2901e9d80dd9dd3218bb54e24e0817c566fa568adeba369181900360200190a1604080516001600160a01b038816815290517f65f4cf077bc01e4742eb5ad98326f6e95b63548ea24b17f8d5e823111fe788009181900360200190a1604080516001600160a01b038716815290517f449ef232e1f38887f74a15dce9059e717b689423d5270f46e1d478e4bbd1c91e9181900360200190a1604080516001600160a01b038616815290517f2ea605b72d3979601397bc2b968c2390809927edefe7ec75779d5325fb0ba0799181900360200190a1610b7b61141b565b50505050505050505050505050565b610b92611465565b8151610bcf5760405162461bcd60e51b81526004018080602001828103825260368152602001806146dd6036913960400191505060405180910390fd5b6001546002546005546001600160a01b03928316929182169116610bf161452a565b610bf961454d565b826001600160a01b031663a6db9b236040518163ffffffff1660e01b815260040160206040518083038186803b158015610c3257600080fd5b505afa158015610c46573d6000803e3d6000fd5b505050506040513d6020811015610c5c57600080fd5b50518252610c6861147e565b1580156020840152610c8b57610c84858584600001518a611499565b9050610c9e565b610c9b858584600001518a6117e4565b90505b6000816020015111610ce15760405162461bcd60e51b81526004018080602001828103825260228152602001806147486022913960400191505060405180910390fd5b608081015160a0820151805160209182015160405163768cc57560e01b8152600481018581526060602483019081528451606484015284516001600160a01b038b169763768cc57597909695946044810192608490910191808801910280838360005b83811015610d5c578181015183820152602001610d44565b50505050905001838103825284818151815260200191508051906020019060200280838360005b83811015610d9b578181015183820152602001610d83565b5050505090500195505050505050600060405180830381600087803b158015610dc357600080fd5b505af1158015610dd7573d6000803e3d6000fd5b505060065460c084015160e085015180516020918201516040516338d3db5160e21b81526001600160a01b038d8116600483019081528d821660248401526044830187905260a060648401908152855160a4850152855192909816995063e34f6d4498508e978e979691939092608482019260c490920191808801910280838360005b83811015610e72578181015183820152602001610e5a565b50505050905001838103825284818151815260200191508051906020019060200280838360005b83811015610eb1578181015183820152602001610e99565b50505050905001975050505050505050600060405180830381600087803b158015610edb57600080fd5b505af1158015610eef573d6000803e3d6000fd5b50505050610f0181610100015161190e565b1561101c57601154610100820151805160209182015160405163d0d8c20d60e01b81526001600160a01b0394851660048201818152606060248401908152855160648501528551978d169763d0d8c20d9793969594929391926044810192608490910191818801910280838360005b83811015610f88578181015183820152602001610f70565b50505050905001838103825284818151815260200191508051906020019060200280838360005b83811015610fc7578181015183820152602001610faf565b5050505090500195505050505050602060405180830381600087803b158015610fef57600080fd5b505af1158015611003573d6000803e3d6000fd5b505050506040513d602081101561101957600080fd5b50505b60065460408083015180516020918201519251630e1f182560e41b81526001600160a01b038a811660048301908152606060248401908152845160648501528451929097169663e1f18250968d969094929391926044810192608490910191808801910280838360005b8381101561109e578181015183820152602001611086565b50505050905001838103825284818151815260200191508051906020019060200280838360005b838110156110dd5781810151838201526020016110c5565b5050505090500195505050505050600060405180830381600087803b15801561110557600080fd5b505af1158015611119573d6000803e3d6000fd5b505050602082015160408401525061112f6145b0565b6111418260a001518360e00151611959565b905061115281836101000151611959565b90507ff9c8e708c82ad9ab70e0c58ca02ae4dceef6c9546eacbeb0b7ac025be81c460a83604001518360600151836000015184602001518660400151600001518760400151602001516040518087815260200186815260200180602001806020018060200180602001858103855289818151815260200191508051906020019060200280838360005b838110156111f35781810151838201526020016111db565b50505050905001858103845288818151815260200191508051906020019060200280838360005b8381101561123257818101518382015260200161121a565b50505050905001858103835287818151815260200191508051906020019060200280838360005b83811015611271578181015183820152602001611259565b50505050905001858103825286818151815260200191508051906020019060200280838360005b838110156112b0578181015183820152602001611298565b505050509050019a505050505050505050505060405180910390a16112ec86888460600151856040015160000151866040015160200151611e74565b5050505050505050565b600e546001600160a01b031681565b60008282018381101561135f576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b90505b92915050565b6001600160a01b0381166113c3576040805162461bcd60e51b815260206004820152601e60248201527f4163636f756e742063616e6e6f74206265207a65726f20616464726573730000604482015290519081900360640190fd5b803b80611417576040805162461bcd60e51b815260206004820181905260248201527f4163636f756e7420636f64652073697a652063616e6e6f74206265207a65726f604482015290519081900360640190fd5b5050565b6003546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600380546001600160a01b0319169055565b600d546001600160a01b0316331461147c57600080fd5b565b600080611489612017565b6714d1120d7b1600001191505090565b6114a161454d565b6114a96145ca565b6114b1614612565b848252600060808301526114c36103fd565b60a08301526114d0610519565b60c0830152600060208301525b8351826020015110156117da57838260200151815181106114fa57fe5b6020908102919091018101516001600160a01b0390811660608501819052600654604080516321e3780160e01b815260048101939093525160009491909316926321e37801926024808201939291829003018186803b15801561155c57600080fd5b505afa158015611570573d6000803e3d6000fd5b505050506040513d602081101561158657600080fd5b5051600481111561159357fe5b905060018160048111156115a357fe5b146115ae57506117ca565b6006546060840151604080516327fb7d8960e01b81526001600160a01b039283166004820152905191909216916327fb7d89916024808301926020929190829003018186803b15801561160057600080fd5b505afa158015611614573d6000803e3d6000fd5b505050506040513d602081101561162a57600080fd5b50516040840152608083015161176057670f43fc2c04ee000083604001511015801561165557508251155b1561166057506117ca565b60006116748460c001518560a00151612036565b905061169089898660600151876040015188600001518661207a565b608081015185519194506116aa919063ffffffff612fab16565b8452608083015160a08501516116c59163ffffffff612fab16565b8460a001818152505060006116dd8460a00151612fed565b905060006116ee8560400151612fed565b90506000611700866101000151612fed565b905061172d8161172184611721878c60c00151612fab90919063ffffffff16565b9063ffffffff612fab16565b60c088015261173c88876130dc565b97506117508760c001518860a001516131c5565b156080880152506117c892505050565b8260800151801561177c5750670f43fc2c04ee00008360400151105b156117c2576117958888856060015186600001516131e4565b608081015184519193506117af919063ffffffff612fab16565b83526117bb84836130dc565b93506117c8565b506117ca565b505b60208201805160010190526114dd565b5050949350505050565b6117ec61454d565b6117f46145ca565b6117fc614612565b848252600060208301525b8351826020015110156117da578382602001518151811061182457fe5b6020908102919091018101516001600160a01b0390811660608501819052600654604080516327fb7d8960e01b81526004810193909352519216926327fb7d8992602480840193829003018186803b15801561187f57600080fd5b505afa158015611893573d6000803e3d6000fd5b505050506040513d60208110156118a957600080fd5b505160408301819052670f43fc2c04ee000011156118fe576118d58787846060015185600001516131e4565b608081015183519192506118ef919063ffffffff612fab16565b82526118fb83826130dc565b92505b6020820180516001019052611807565b6000805b82515181101561194e5760008360200151828151811061192e57fe5b60200260200101511115611946576001915050611954565b600101611912565b50600090505b919050565b6119616145b0565b6119696145b0565b6000805460408051634eb5750560e11b815290516001600160a01b0390921692639d6aea0a92600480840193829003018186803b1580156119a957600080fd5b505afa1580156119bd573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260208110156119e657600080fd5b8101908080516040519392919084600160201b821115611a0557600080fd5b908301906020820185811115611a1a57600080fd5b82518660208202830111600160201b82111715611a3657600080fd5b82525081516020918201928201910280838360005b83811015611a63578181015183820152602001611a4b565b505050509190910160405250505081835250516001600160401b0381118015611a8b57600080fd5b50604051908082528060200260200182016040528015611ab5578160200160208202803683370190505b5060208201526000805b855151811015611bd25760008054875180516001600160a01b039092169163b31610db919085908110611aee57fe5b60200260200101516040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015611b3c57600080fd5b505afa158015611b50573d6000803e3d6000fd5b505050506040513d6020811015611b6657600080fd5b50516020880151805191925060009184908110611b7f57fe5b60200260200101511115611bc9576020870151805160019094019383908110611ba457fe5b602002602001015184602001518281518110611bbc57fe5b6020026020010181815250505b50600101611abf565b5060005b845151811015611d325760008054865180516001600160a01b039092169163b31610db919085908110611c0557fe5b60200260200101516040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015611c5357600080fd5b505afa158015611c67573d6000803e3d6000fd5b505050506040513d6020811015611c7d57600080fd5b50516020870151805191925060009184908110611c9657fe5b60200260200101511115611d295783602001518181518110611cb457fe5b602002602001015160001415611ccb576001909201915b611d0c86602001518381518110611cde57fe5b602002602001015185602001518381518110611cf657fe5b602002602001015161130590919063ffffffff16565b84602001518281518110611d1c57fe5b6020026020010181815250505b50600101611bd6565b506060816001600160401b0381118015611d4b57600080fd5b50604051908082528060200260200182016040528015611d75578160200160208202803683370190505b5090506060826001600160401b0381118015611d9057600080fd5b50604051908082528060200260200182016040528015611dba578160200160208202803683370190505b5090506000805b855151811015611e6157600086602001518281518110611ddd57fe5b60200260200101511115611e59578551805182908110611df957fe5b6020026020010151848381518110611e0d57fe5b6001600160a01b03909216602092830291909101820152860151805182908110611e3357fe5b6020026020010151838381518110611e4757fe5b60209081029190910101526001909101905b600101611dc1565b5050908452602084015250909392505050565b8215611ef357600754600c5460408051631062c15f60e11b81526001600160a01b039283166004820152878316602482015260448101879052905191909216916320c582be91606480830192600092919082900301818387803b158015611eda57600080fd5b505af1158015611eee573d6000803e3d6000fd5b505050505b846001600160a01b031663ab471ec585848460006040518563ffffffff1660e01b815260040180856001600160a01b03166001600160a01b03168152602001806020018060200184151515158152602001838103835286818151815260200191508051906020019060200280838360005b83811015611f7c578181015183820152602001611f64565b50505050905001838103825285818151815260200191508051906020019060200280838360005b83811015611fbb578181015183820152602001611fa3565b505050509050019650505050505050602060405180830381600087803b158015611fe457600080fd5b505af1158015611ff8573d6000803e3d6000fd5b505050506040513d602081101561200e57600080fd5b50505050505050565b600080612022610519565b9050600061202e6103fd565b905061050382825b600081156120715760006120688361205c86670de0b6b3a764000063ffffffff613a1d16565b9063ffffffff613a7616565b91506113629050565b50600019611362565b612082614612565b61208a61463a565b600654604080516324f77f7760e11b815290516001926001600160a01b0316916349eefeee916004808301926020929190829003018186803b1580156120cf57600080fd5b505afa1580156120e3573d6000803e3d6000fd5b505050506040513d60208110156120f957600080fd5b5051116121065750612fa1565b60065460408051630956f86160e11b81526001600160a01b038981166004830152915191909216916312adf0c2916024808301926000929190829003018186803b15801561215357600080fd5b505afa158015612167573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260c081101561219057600080fd5b815160208301805160405192949293830192919084600160201b8211156121b657600080fd5b9083019060208201858111156121cb57600080fd5b82518660208202830111600160201b821117156121e757600080fd5b82525081516020918201928201910280838360005b838110156122145781810151838201526020016121fc565b5050505090500160405260200180516040519392919084600160201b82111561223c57600080fd5b90830190602082018581111561225157600080fd5b82518660208202830111600160201b8211171561226d57600080fd5b82525081516020918201928201910280838360005b8381101561229a578181015183820152602001612282565b505050509050016040526020018051906020019092919080516040519392919084600160201b8211156122cc57600080fd5b9083019060208201858111156122e157600080fd5b82518660208202830111600160201b821117156122fd57600080fd5b82525081516020918201928201910280838360005b8381101561232a578181015183820152602001612312565b5050505090500160405260200180516040519392919084600160201b82111561235257600080fd5b90830190602082018581111561236757600080fd5b82518660208202830111600160201b8211171561238357600080fd5b82525081516020918201928201910280838360005b838110156123b0578181015183820152602001612398565b505050509190910160409081526020808e018051928e015180830198909852979096528b8601979097525050505082019290925291909152908352516123f590613ab8565b6040830181905261240890876000613bb3565b680ad78ebc5ac62000006060830152602082015151815152805151516001600160401b038111801561243957600080fd5b50604051908082528060200260200182016040528015612463578160200160208202803683370190505b5081516020015260005b815151518110156124e6576124c1836040015160200151828151811061248f57fe5b602002602001015184602001516020015183815181106124ab57fe5b6020026020010151612fab90919063ffffffff16565b8251602001518051839081106124d357fe5b602090810291909101015260010161246d565b50670de0b6b3a7640000851161288057600660009054906101000a90046001600160a01b03166001600160a01b0316637837eeeb898984602001518560400151600001518660400151602001518c6040518763ffffffff1660e01b815260040180876001600160a01b03166001600160a01b03168152602001866001600160a01b03166001600160a01b031681526020018581526020018060200180602001846001600160a01b03166001600160a01b03168152602001838103835286818151815260200191508051906020019060200280838360005b838110156125d55781810151838201526020016125bd565b50505050905001838103825285818151815260200191508051906020019060200280838360005b838110156126145781810151838201526020016125fc565b5050505090500198505050505050505050600060405180830381600087803b15801561263f57600080fd5b505af1158015612653573d6000803e3d6000fd5b505060065460408051630bce3bf960e41b81526001600160a01b038b81166004830152915191909216935063bce3bf909250602480830192600092919082900301818387803b1580156126a557600080fd5b505af11580156126b9573d6000803e3d6000fd5b505060006080850152506126cd90506145b0565b60a08301819052825160c0840152815160e084018190526012546126fc919089906001600160a01b0316613bb3565b600654604080516322962f6560e01b81526001600160a01b038a81166004830152915191909216916322962f6591602480830192600092919082900301818387803b15801561274a57600080fd5b505af115801561275e573d6000803e3d6000fd5b50508451604080519182526002602083015280516001600160a01b038c16945060008051602061469d8339815191529350918290030190a261279e6145b0565b876001600160a01b03166000805160206146bd83398151915260008360000151846020015160026040518085815260200180602001806020018460038111156127e357fe5b60ff168152602001838103835286818151815260200191508051906020019060200280838360005b8381101561282357818101518382015260200161280b565b50505050905001838103825285818151815260200191508051906020019060200280838360005b8381101561286257818101518382015260200161284a565b50505050905001965050505050505060405180910390a25050612e89565b670f43fc2c04ee0000851015612c3757600660009054906101000a90046001600160a01b03166001600160a01b0316637837eeeb898984602001518560400151600001518660400151602001518c6040518763ffffffff1660e01b815260040180876001600160a01b03166001600160a01b03168152602001866001600160a01b03166001600160a01b031681526020018581526020018060200180602001846001600160a01b03166001600160a01b03168152602001838103835286818151815260200191508051906020019060200280838360005b8381101561296f578181015183820152602001612957565b50505050905001838103825285818151815260200191508051906020019060200280838360005b838110156129ae578181015183820152602001612996565b5050505090500198505050505050505050600060405180830381600087803b1580156129d957600080fd5b505af11580156129ed573d6000803e3d6000fd5b505060065460408051630bce3bf960e41b81526001600160a01b038b81166004830152915191909216935063bce3bf909250602480830192600092919082900301818387803b158015612a3f57600080fd5b505af1158015612a53573d6000803e3d6000fd5b50505050612a5f614661565b82518251612a6e919087613cf7565b9050612a786145b0565b612a8a82602001518360600151611959565b601254909150612aa69082908a906001600160a01b0316613bb3565b612ab08285614053565b600654604080516322962f6560e01b81526001600160a01b038c8116600483015291519397509116916322962f659160248082019260009290919082900301818387803b158015612b0057600080fd5b505af1158015612b14573d6000803e3d6000fd5b50508551604080519182526002602083015280516001600160a01b038d16945060008051602061469d8339815191529350918290030190a2612b546145b0565b886001600160a01b03166000805160206146bd8339815191526000836000015184602001516002604051808581526020018060200180602001846003811115612b9957fe5b60ff168152602001838103835286818151815260200191508051906020019060200280838360005b83811015612bd9578181015183820152602001612bc1565b50505050905001838103825285818151815260200191508051906020019060200280838360005b83811015612c18578181015183820152602001612c00565b50505050905001965050505050505060405180910390a2505050612e89565b8285108015612c47575081518410155b15612e7857600660009054906101000a90046001600160a01b03166001600160a01b0316637837eeeb898984602001518560400151600001518660400151602001518c6040518763ffffffff1660e01b815260040180876001600160a01b03166001600160a01b03168152602001866001600160a01b03166001600160a01b031681526020018581526020018060200180602001846001600160a01b03166001600160a01b03168152602001838103835286818151815260200191508051906020019060200280838360005b83811015612d2b578181015183820152602001612d13565b50505050905001838103825285818151815260200191508051906020019060200280838360005b83811015612d6a578181015183820152602001612d52565b5050505090500198505050505050505050600060405180830381600087803b158015612d9557600080fd5b505af1158015612da9573d6000803e3d6000fd5b505050508360001415612db857fe5b60065460408051630bce3bf960e41b81526001600160a01b0389811660048301529151919092169163bce3bf9091602480830192600092919082900301818387803b158015612e0657600080fd5b505af1158015612e1a573d6000803e3d6000fd5b505083516020808601518051910151612e40945091925090670f43fc2c04ee0000614092565b9150612e4a6145b0565b612e5c8360a001518460e00151611959565b6012549091506126fc90829089906001600160a01b0316613bb3565b612e80614612565b9150612fa19050565b612e9782610100015161190e565b15612f9f5760065461010083015180516020918201516040516396755e5560e01b81526001600160a01b038b81166004830190815260606024840190815285516064850152855192909716966396755e55968e969594929391926044810192608490910191808801910280838360005b83811015612f1f578181015183820152602001612f07565b50505050905001838103825284818151815260200191508051906020019060200280838360005b83811015612f5e578181015183820152602001612f46565b5050505090500195505050505050600060405180830381600087803b158015612f8657600080fd5b505af1158015612f9a573d6000803e3d6000fd5b505050505b505b9695505050505050565b600061135f83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525061432f565b6000805b8251518110156130d65760008054845180516001600160a01b0390921691632e2b1a8891908590811061302057fe5b60200260200101518660200151858151811061303857fe5b60200260200101516040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b031681526020018281526020019250505060206040518083038186803b15801561308d57600080fd5b505afa1580156130a1573d6000803e3d6000fd5b505050506040513d60208110156130b757600080fd5b505190506130cb838263ffffffff61130516565b925050600101612ff1565b50919050565b6130e461454d565b6130f683604001518360400151611959565b6040820152606080830151908401516131149163ffffffff61130516565b60608201528151602084015161312f9163ffffffff61130516565b60208201526080808301519084015161314d9163ffffffff61130516565b608082015260a080840151908301516131669190611959565b60a082015260c080830151908401516131849163ffffffff61130516565b60c082015260e0808401519083015161319d9190611959565b8160e001819052506131b9836101000151836101000151611959565b61010082015292915050565b6000806131d28484612036565b6714d1120d7b16000011949350505050565b6131ec614612565b6131f461463a565b60065460408051630956f86160e11b81526001600160a01b038781166004830152915191909216916312adf0c2916024808301926000929190829003018186803b15801561324157600080fd5b505afa158015613255573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260c081101561327e57600080fd5b815160208301805160405192949293830192919084600160201b8211156132a457600080fd5b9083019060208201858111156132b957600080fd5b82518660208202830111600160201b821117156132d557600080fd5b82525081516020918201928201910280838360005b838110156133025781810151838201526020016132ea565b5050505090500160405260200180516040519392919084600160201b82111561332a57600080fd5b90830190602082018581111561333f57600080fd5b82518660208202830111600160201b8211171561335b57600080fd5b82525081516020918201928201910280838360005b83811015613388578181015183820152602001613370565b505050509050016040526020018051906020019092919080516040519392919084600160201b8211156133ba57600080fd5b9083019060208201858111156133cf57600080fd5b82518660208202830111600160201b821117156133eb57600080fd5b82525081516020918201928201910280838360005b83811015613418578181015183820152602001613400565b5050505090500160405260200180516040519392919084600160201b82111561344057600080fd5b90830190602082018581111561345557600080fd5b82518660208202830111600160201b8211171561347157600080fd5b82525081516020918201928201910280838360005b8381101561349e578181015183820152602001613486565b505050509190910160409081526020808e01518d8301805180840199909952989097528c81019889528681019990995298909452505050948752600654915190518051908401519451637837eeeb60e01b81526001600160a01b038d8116600483019081528d82166024840152604483018590528c821660a484015260c060648401908152845160c48501528451929096169850637837eeeb978f978f9791948f94608482019260e490920191888101910280838360005b8381101561356e578181015183820152602001613556565b50505050905001838103825285818151815260200191508051906020019060200280838360005b838110156135ad578181015183820152602001613595565b5050505090500198505050505050505050600060405180830381600087803b1580156135d857600080fd5b505af11580156135ec573d6000803e3d6000fd5b505060065460408051630bce3bf960e41b81526001600160a01b038981166004830152915191909216935063bce3bf909250602480830192600092919082900301818387803b15801561363e57600080fd5b505af1158015613652573d6000803e3d6000fd5b505050506136638260200151613ab8565b6040830181905261367690856000613bb3565b680ad78ebc5ac62000006060830152602082015151815152805151516001600160401b03811180156136a757600080fd5b506040519080825280602002602001820160405280156136d1578160200160208202803683370190505b5081516020015260005b81515151811015613722576136fd836040015160200151828151811061248f57fe5b82516020015180518390811061370f57fe5b60209081029190910101526001016136db565b5061372b614661565b8251825161373a919086613cf7565b90506137446145b0565b61375682602001518360600151611959565b60125490915061377290829088906001600160a01b0316613bb3565b61377c8285614053565b600654604080516322962f6560e01b81526001600160a01b038a8116600483015291519397509116916322962f659160248082019260009290919082900301818387803b1580156137cc57600080fd5b505af11580156137e0573d6000803e3d6000fd5b505050506137f284610100015161190e565b156138fa5760065461010085015180516020918201516040516396755e5560e01b81526001600160a01b038b81166004830190815260606024840190815285516064850152855192909716966396755e55968e969594929391926044810192608490910191808801910280838360005b8381101561387a578181015183820152602001613862565b50505050905001838103825284818151815260200191508051906020019060200280838360005b838110156138b95781810151838201526020016138a1565b5050505090500195505050505050600060405180830381600087803b1580156138e157600080fd5b505af11580156138f5573d6000803e3d6000fd5b505050505b8351604080519182526001602083015280516001600160a01b0389169260008051602061469d83398151915292908290030190a26139366145b0565b866001600160a01b03166000805160206146bd833981519152600083600001518460200151600160405180858152602001806020018060200184600381111561397b57fe5b60ff168152602001838103835286818151815260200191508051906020019060200280838360005b838110156139bb5781810151838201526020016139a3565b50505050905001838103825285818151815260200191508051906020019060200280838360005b838110156139fa5781810151838201526020016139e2565b50505050905001965050505050505060405180910390a250505050949350505050565b600082613a2c57506000611362565b82820282848281613a3957fe5b041461135f5760405162461bcd60e51b815260040180806020018281038252602181526020018061467c6021913960400191505060405180910390fd5b600061135f83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506143c6565b613ac06145b0565b60208201515182515114613b055760405162461bcd60e51b81526004018080602001828103825260358152602001806147136035913960400191505060405180910390fd5b8151516060906001600160401b0381118015613b2057600080fd5b50604051908082528060200260200182016040528015613b4a578160200160208202803683370190505b50905060005b835151811015613b9b5760c884602001518281518110613b6c57fe5b602002602001015181613b7b57fe5b04828281518110613b8857fe5b6020908102919091010152600101613b50565b50604080518082019091529251835260208301525090565b60005b835151811015613cf157600084600001518281518110613bd257fe5b60200260200101519050600085602001518381518110613bee57fe5b602090810291909101810151600054604080516324af709f60e11b81526001600160a01b038781166004830152915193955091169263495ee13e92602480840193829003018186803b158015613c4357600080fd5b505afa158015613c57573d6000803e3d6000fd5b505050506040513d6020811015613c6d57600080fd5b505115613ce7576040805163164746fd60e11b81526001600160a01b038781166004830152868116602483015260448201849052915191841691632c8e8dfa9160648082019260009290919082900301818387803b158015613cce57600080fd5b505af1158015613ce2573d6000803e3d6000fd5b505050505b5050600101613bb6565b50505050565b613cff614661565b82516060820151528251516001600160401b0381118015613d1f57600080fd5b50604051908082528060200260200182016040528015613d49578160200160208202803683370190505b506060820151602001528115613ff45782516020820151528251516001600160401b0381118015613d7957600080fd5b50604051908082528060200260200182016040528015613da3578160200160208202803683370190505b50602080830151015282516080820151528251516001600160401b0381118015613dcc57600080fd5b50604051908082528060200260200182016040528015613df6578160200160208202803683370190505b50608082015160200152613e0a848361442b565b808252613e1e90859063ffffffff612fab16565b60408201526000613e2e84614441565b90506000613e658661205c8560000151613e59670de0b6b3a764000080613a1d90919063ffffffff16565b9063ffffffff613a1d16565b90506000613e988361205c670f43fc2c04ee0000613e59670de0b6b3a76400008960000151613a1d90919063ffffffff16565b9050613ea4828261442b565b90506000613eb8838363ffffffff612fab16565b905060005b875151811015613fea57613f09670de0b6b3a764000061205c670de0b6b3a764000061205c878d602001518781518110613ef357fe5b6020026020010151613a1d90919063ffffffff16565b8660200151602001518281518110613f1d57fe5b602002602001018181525050613f55670de0b6b3a764000061205c670de0b6b3a764000061205c868d602001518781518110613ef357fe5b8660800151602001518281518110613f6957fe5b602002602001018181525050613fc38660800151602001518281518110613f8c57fe5b60200260200101516117218860200151602001518481518110613fab57fe5b60200260200101518b6020015185815181106124ab57fe5b8660600151602001518281518110613fd757fe5b6020908102919091010152600101613ebd565b505050505061404c565b60008082525b835151811015614043578360200151818151811061401457fe5b6020026020010151826060015160200151828151811061403057fe5b6020908102919091010152600101613ffa565b50604081018490525b9392505050565b61405b614612565b508151608082810191909152602083015160a0830152604083015160c0830152606083015160e08301529091015161010082015290565b61409a614612565b6140a26145b0565b8481526020810184905260006140ca670de0b6b3a764000061205c868a63ffffffff613a1d16565b905060006140d783614441565b905060006140f78261205c85670de0b6b3a764000063ffffffff613a1d16565b905061410b81670de0b6b3a764000061442b565b89865260208601859052680ad78ebc5ac62000006060870152608086018a9052600060c087015260a086015189905288519091506001600160401b038111801561415457600080fd5b5060405190808252806020026020018201604052801561417e578160200160208202803683370190505b5060a08601516020015261010085015188905287516001600160401b03811180156141a857600080fd5b506040519080825280602002602001820160405280156141d2578160200160208202803683370190505b5061010086015160200152604085015188905287516001600160401b03811180156141fc57600080fd5b50604051908082528060200260200182016040528015614226578160200160208202803683370190505b5060408601516020015260005b8851811015614322576000614270670de0b6b3a764000061205c8b858151811061425957fe5b602002602001015186613a1d90919063ffffffff16565b905060006142858260c863ffffffff613a7616565b90506000614299838363ffffffff612fab16565b905060006142ad848d87815181106124ab57fe5b9050828a604001516020015186815181106142c457fe5b602002602001018181525050818a60a001516020015186815181106142e557fe5b602002602001018181525050808a610100015160200151868151811061430757fe5b60209081029190910101525050600190920191506142339050565b5050505050949350505050565b600081848411156143be5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561438357818101518382015260200161436b565b50505050905090810190601f1680156143b05780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600081836144155760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561438357818101518382015260200161436b565b50600083858161442157fe5b0495945050505050565b600081831061443a578161135f565b5090919050565b6000805b8251518110156130d65760008054845180516001600160a01b039092169163cacabd2791908590811061447457fe5b60200260200101518660200151858151811061448c57fe5b60200260200101516040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b031681526020018281526020019250505060206040518083038186803b1580156144e157600080fd5b505afa1580156144f5573d6000803e3d6000fd5b505050506040513d602081101561450b57600080fd5b5051905061451f838263ffffffff61130516565b925050600101614445565b604051806060016040528060008152602001600015158152602001600081525090565b604051806101200160405280600081526020016000815260200161456f6145b0565b8152602001600081526020016000815260200161458a6145b0565b81526020016000815260200161459e6145b0565b81526020016145ab6145b0565b905290565b604051806040016040528060608152602001606081525090565b6040518060e0016040528060008152602001600081526020016000815260200160006001600160a01b0316815260200160001515815260200160008152602001600081525090565b6040518061012001604052806000815260200161462d6145b0565b815260200161456f6145b0565b604051806060016040528061464d6145b0565b8152602001600081526020016145ab6145b0565b6040518060a001604052806000815260200161458a6145b056fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77679aef5b8c9f79ba6e1427981d7b06db55d0eadf337f8ed36e4ba5395a9111a398c96bbf8d2aa6be678259387225d169084fca483ed9598bde8ea258036bcacf54726f76654d616e616765723a2043616c6c646174612061646472657373206172726179206d757374206e6f7420626520656d7074795f676574436f6c6c476173436f6d70656e736174696f6e28293a20436f6c6c61746572616c206c656e677468206d69736d6174636854726f76654d616e616765723a206e6f7468696e6720746f206c6971756964617465a2646970667358221220feb1318e8b95d940fd870f4d604685db20e65a109272bd356553ce5ba224f12a64736f6c634300060b0033

Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading