Contract 0xcB74A8F05537e346AC54c173652e57c96b4339d2

Contract Overview

Balance:
0 AVAX
Txn Hash Method
Block
From
To
Value [Txn Fee]
0x2bbad00a8783ea41d6c1cc9cd8f488e9c0bec9d21f513ad357ee5b18c358f02bBatch Liquidate ...70986042022-03-10 0:04:43211 days 5 hrs ago0x756536561b373d185a880dfc863614a1bef34a9c IN 0xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX0.01525162531.25
0xfc7b08b109d3896a9f7e6d6bd2d9a0b4ff58a18b961ba113745b821d33ac46c9Batch Liquidate ...70986022022-03-10 0:04:39211 days 5 hrs ago0x756536561b373d185a880dfc863614a1bef34a9c IN 0xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX0.0169931562531.25
0x8938bc6b1ca06ef77b5aaeebe75375db1cad450ad7ffc2a5f62601fa62c2d6a1Batch Liquidate ...70986012022-03-10 0:04:35211 days 5 hrs ago0x756536561b373d185a880dfc863614a1bef34a9c IN 0xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX0.0574060937531.25
0x471a12f122e2267a0a7432718d7e5614b37e501dfc029796186e8c00796a2571Batch Liquidate ...70986002022-03-10 0:04:34211 days 5 hrs ago0x756536561b373d185a880dfc863614a1bef34a9c IN 0xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX0.1005777812531.25
0x00505be2f114d3d53f2614a44253f0c2d720cde2181a649402292f593213d7f2Batch Liquidate ...70964652022-03-09 22:52:55211 days 6 hrs ago0x756536561b373d185a880dfc863614a1bef34a9c IN 0xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX0.0169927812531.25
0x47ac532ad6af797749cc25c90e372a8bb9a4b8ee6d4c99ecbada1b2833f1b224Batch Liquidate ...70964642022-03-09 22:52:53211 days 6 hrs ago0x756536561b373d185a880dfc863614a1bef34a9c IN 0xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX0.0169931562531.25
0xf029dc5143c9b524c7db9d00f257b8269d9d8574b6bbaa185b868e7025da54d4Batch Liquidate ...70964632022-03-09 22:52:49211 days 6 hrs ago0x756536561b373d185a880dfc863614a1bef34a9c IN 0xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX0.1110047812531.25
0xc818cc0b74361204a8a1c57525b3880d8f86280eb405c5d4f5a5381675981a85Batch Liquidate ...70964622022-03-09 22:52:48211 days 6 hrs ago0x756536561b373d185a880dfc863614a1bef34a9c IN 0xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX0.1020986562531.25
0x2375f6ee34f80c1a81ed1cbe9a365e71b092abd97b229dcb3c4c46f966bd12c6Batch Liquidate ...70942752022-03-09 21:39:04211 days 7 hrs ago0x756536561b373d185a880dfc863614a1bef34a9c IN 0xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX0.01525231.25
0xffb3db1a3aa461ce6eff5bbfd7d51b6cfcc3374447c73e064d19f9d677e3dfb2Batch Liquidate ...70942742022-03-09 21:39:01211 days 7 hrs ago0x756536561b373d185a880dfc863614a1bef34a9c IN 0xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX0.1118337531.25
0xdd4c55ea9f7cab774d6191e3caa8ac54a3c37f9a452e7f5a0c67f9bb5fc51bbfBatch Liquidate ...70937422022-03-09 21:21:10211 days 8 hrs ago0x756536561b373d185a880dfc863614a1bef34a9c IN 0xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX0.01525231.25
0x086aca8ce0285b10d3423b6e7170721c9ed97009704f71acae5f325345911179Batch Liquidate ...70937412022-03-09 21:21:08211 days 8 hrs ago0x756536561b373d185a880dfc863614a1bef34a9c IN 0xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX0.099059812531.25
0x560640dd5943f797eb10f79daaa7b72219d728d66916ae03c72ec339b1e39830Batch Liquidate ...70931912022-03-09 21:02:39211 days 8 hrs ago0x756536561b373d185a880dfc863614a1bef34a9c IN 0xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX0.01583237531.25
0xfbed5dea86d139dd9548a7d5c0c242b351e3ca7a85882475768a0211de00d6bdBatch Liquidate ...70931892022-03-09 21:02:34211 days 8 hrs ago0x756536561b373d185a880dfc863614a1bef34a9c IN 0xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX0.1121445937531.25
0xa708bbac3cf19937349b40f4d256f3279f8ab905b7ffe58ddd65fa564070f0a4Batch Liquidate ...70929792022-03-09 20:55:32211 days 8 hrs ago0x756536561b373d185a880dfc863614a1bef34a9c IN 0xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX0.01467162531.25
0xfcef90cd4bc05767b9a8a0ce78dae4f6a0b7d34090a5521b5cf89de38ed02779Batch Liquidate ...70929782022-03-09 20:55:29211 days 8 hrs ago0x756536561b373d185a880dfc863614a1bef34a9c IN 0xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX0.078728562531.25
0x35e8853be25800c622e5a874ddda0f0e8a6bad9451f81488c920d597ef1c7306Batch Liquidate ...70926592022-03-09 20:44:42211 days 8 hrs ago0x756536561b373d185a880dfc863614a1bef34a9c IN 0xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX0.01525231.25
0x4efb49bdd6dc28c38196d1ab2b5367b6f9c99eab0edc62fcd249e488b154fb1eBatch Liquidate ...70926572022-03-09 20:44:38211 days 8 hrs ago0x756536561b373d185a880dfc863614a1bef34a9c IN 0xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX0.105797937531.25
0x497ecba3a0aa3f9929964326f4d286c5a901f39a72c924575895f7f98b17e4e5Batch Liquidate ...70924972022-03-09 20:39:09211 days 8 hrs ago0x756536561b373d185a880dfc863614a1bef34a9c IN 0xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX0.01525231.25
0xec092cb3a3d8bcc0f34a97d7f9f4d229e7802f402a20f35647b19d0b98fd0eb7Batch Liquidate ...70924962022-03-09 20:39:06211 days 8 hrs ago0x756536561b373d185a880dfc863614a1bef34a9c IN 0xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX0.0700462187531.25
0xbcf33d36f4b0d15212776f797334d152a579b3fb7e283ef371d5538b81fee7c7Batch Liquidate ...70924292022-03-09 20:36:37211 days 8 hrs ago0x756536561b373d185a880dfc863614a1bef34a9c IN 0xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX0.01525231.25
0x62522467d1052160e6705935ff3bdecdbafc475539ce4653356ff193661b6b40Batch Liquidate ...70924252022-03-09 20:36:29211 days 8 hrs ago0x756536561b373d185a880dfc863614a1bef34a9c IN 0xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX0.0671047187531.25
0xbafc82dc8222c831603f6066a73ff1c5357020416112f8d0beea8a11fd24a1c6Batch Liquidate ...70921842022-03-09 20:28:03211 days 9 hrs ago0x756536561b373d185a880dfc863614a1bef34a9c IN 0xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX0.01467162531.25
0x9b18e1b9a89389637e5a26d9a16d9b7b6c01170c770a113df89d6dc1b8ed6e64Batch Liquidate ...70921822022-03-09 20:27:59211 days 9 hrs ago0x756536561b373d185a880dfc863614a1bef34a9c IN 0xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX0.037760562531.25
0xd7043a131b832e718d9d23c8b397c28a104698c4dcb9250a7e955508d5936026Batch Liquidate ...70919682022-03-09 20:20:40211 days 9 hrs ago0x756536561b373d185a880dfc863614a1bef34a9c IN 0xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX0.01525231.25
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0x3c4624cb91fc6f8bae4030590fba93fbe2f5e5b80ad725acb28b79187e03f61596634452022-05-14 7:02:46145 days 22 hrs ago 0x6387c0e385196fecb43d5fe37ebe9777b790a8820xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX
0x3c4624cb91fc6f8bae4030590fba93fbe2f5e5b80ad725acb28b79187e03f61596634452022-05-14 7:02:46145 days 22 hrs ago 0x6387c0e385196fecb43d5fe37ebe9777b790a8820xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX
0x3c4624cb91fc6f8bae4030590fba93fbe2f5e5b80ad725acb28b79187e03f61596634452022-05-14 7:02:46145 days 22 hrs ago 0x6387c0e385196fecb43d5fe37ebe9777b790a8820xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX
0xccd13f15844fd0091db949f11344d83aa664a273a042d7ccec8f2319c3db4e0296634452022-05-14 7:02:46145 days 22 hrs ago 0x6387c0e385196fecb43d5fe37ebe9777b790a8820xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX
0xccd13f15844fd0091db949f11344d83aa664a273a042d7ccec8f2319c3db4e0296634452022-05-14 7:02:46145 days 22 hrs ago 0x6387c0e385196fecb43d5fe37ebe9777b790a8820xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX
0xccd13f15844fd0091db949f11344d83aa664a273a042d7ccec8f2319c3db4e0296634452022-05-14 7:02:46145 days 22 hrs ago 0x6387c0e385196fecb43d5fe37ebe9777b790a8820xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX
0xccd13f15844fd0091db949f11344d83aa664a273a042d7ccec8f2319c3db4e0296634452022-05-14 7:02:46145 days 22 hrs ago 0x6387c0e385196fecb43d5fe37ebe9777b790a8820xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX
0xccd13f15844fd0091db949f11344d83aa664a273a042d7ccec8f2319c3db4e0296634452022-05-14 7:02:46145 days 22 hrs ago 0x6387c0e385196fecb43d5fe37ebe9777b790a8820xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX
0xccd13f15844fd0091db949f11344d83aa664a273a042d7ccec8f2319c3db4e0296634452022-05-14 7:02:46145 days 22 hrs ago 0x6387c0e385196fecb43d5fe37ebe9777b790a8820xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX
0xccd13f15844fd0091db949f11344d83aa664a273a042d7ccec8f2319c3db4e0296634452022-05-14 7:02:46145 days 22 hrs ago 0x6387c0e385196fecb43d5fe37ebe9777b790a8820xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX
0x979cbb37f982c099c873212b8e5bafac2b8afb00626bfa4f7ed5bdfe3b7a50f296634452022-05-14 7:02:46145 days 22 hrs ago 0x6387c0e385196fecb43d5fe37ebe9777b790a8820xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX
0x979cbb37f982c099c873212b8e5bafac2b8afb00626bfa4f7ed5bdfe3b7a50f296634452022-05-14 7:02:46145 days 22 hrs ago 0x6387c0e385196fecb43d5fe37ebe9777b790a8820xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX
0x979cbb37f982c099c873212b8e5bafac2b8afb00626bfa4f7ed5bdfe3b7a50f296634452022-05-14 7:02:46145 days 22 hrs ago 0x6387c0e385196fecb43d5fe37ebe9777b790a8820xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX
0x979cbb37f982c099c873212b8e5bafac2b8afb00626bfa4f7ed5bdfe3b7a50f296634452022-05-14 7:02:46145 days 22 hrs ago 0x6387c0e385196fecb43d5fe37ebe9777b790a8820xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX
0x979cbb37f982c099c873212b8e5bafac2b8afb00626bfa4f7ed5bdfe3b7a50f296634452022-05-14 7:02:46145 days 22 hrs ago 0x6387c0e385196fecb43d5fe37ebe9777b790a8820xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX
0x979cbb37f982c099c873212b8e5bafac2b8afb00626bfa4f7ed5bdfe3b7a50f296634452022-05-14 7:02:46145 days 22 hrs ago 0x6387c0e385196fecb43d5fe37ebe9777b790a8820xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX
0x979cbb37f982c099c873212b8e5bafac2b8afb00626bfa4f7ed5bdfe3b7a50f296634452022-05-14 7:02:46145 days 22 hrs ago 0x6387c0e385196fecb43d5fe37ebe9777b790a8820xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX
0xc3438baa64c13ebca481b2121dcf1ef1a9c6c32813f136997be611d51da25cd196634452022-05-14 7:02:46145 days 22 hrs ago 0x6387c0e385196fecb43d5fe37ebe9777b790a8820xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX
0xc3438baa64c13ebca481b2121dcf1ef1a9c6c32813f136997be611d51da25cd196634452022-05-14 7:02:46145 days 22 hrs ago 0x6387c0e385196fecb43d5fe37ebe9777b790a8820xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX
0xc3438baa64c13ebca481b2121dcf1ef1a9c6c32813f136997be611d51da25cd196634452022-05-14 7:02:46145 days 22 hrs ago 0x6387c0e385196fecb43d5fe37ebe9777b790a8820xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX
0xc3438baa64c13ebca481b2121dcf1ef1a9c6c32813f136997be611d51da25cd196634452022-05-14 7:02:46145 days 22 hrs ago 0x6387c0e385196fecb43d5fe37ebe9777b790a8820xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX
0xc3438baa64c13ebca481b2121dcf1ef1a9c6c32813f136997be611d51da25cd196634452022-05-14 7:02:46145 days 22 hrs ago 0x6387c0e385196fecb43d5fe37ebe9777b790a8820xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX
0xc3438baa64c13ebca481b2121dcf1ef1a9c6c32813f136997be611d51da25cd196634452022-05-14 7:02:46145 days 22 hrs ago 0x6387c0e385196fecb43d5fe37ebe9777b790a8820xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX
0xc3438baa64c13ebca481b2121dcf1ef1a9c6c32813f136997be611d51da25cd196634452022-05-14 7:02:46145 days 22 hrs ago 0x6387c0e385196fecb43d5fe37ebe9777b790a8820xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX
0x236c2394818a20f30c1ceabbb09e9ed711999d98665a31b98315827d3ac5150896634452022-05-14 7:02:46145 days 22 hrs ago 0x6387c0e385196fecb43d5fe37ebe9777b790a8820xcb74a8f05537e346ac54c173652e57c96b4339d20 AVAX
[ Download CSV Export 
Loading

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

Contract Name:
TroveManager

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 27 : TroveManager.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/IWhitelist.sol";
import "./Interfaces/ITroveManagerLiquidations.sol";
import "./Interfaces/ITroveManagerRedemptions.sol";
import "./Dependencies/TroveManagerBase.sol";
import "./Interfaces/IERC20.sol";

/** 
 * Trove Manager is the contract which deals with the state of a user's trove. It has all the 
 * external functions for liquidations, redemptions, as well as functions called by 
 * BorrowerOperations function calls. 
 */

contract TroveManager is TroveManagerBase, ITroveManager {
    string constant public NAME = "TroveManager";

    // --- Data structures ---

    uint constant public SECONDS_IN_ONE_MINUTE = 60;

    /*
     * Half-life of 12h. 12h = 720 min
     * (1/2) = d^720 => d = (1/2)^(1/720)
     */
    uint constant public MINUTE_DECAY_FACTOR = 999037758833783000;
    uint constant public MAX_BORROWING_FEE = DECIMAL_PRECISION / 100 * 5; // 5%

    // During bootsrap period redemptions are not allowed
    uint constant public BOOTSTRAP_PERIOD = 14 days;

    uint public baseRate;

    // The timestamp of the latest fee operation (redemption or new YUSD issuance)
    uint public lastFeeOperationTime;


    mapping (address => Trove) Troves;

    // uint public totalStakes;
    mapping (address => uint) public totalStakes;

    // Snapshot of the value of totalStakes, taken immediately after the latest liquidation
    mapping (address => uint) public totalStakesSnapshot;

    // Snapshot of the total collateral across the ActivePool and DefaultPool, immediately after the latest liquidation.
    mapping (address => uint) public totalCollateralSnapshot;

    /*
    * L_Coll and L_YUSDDebt track the sums of accumulated liquidation rewards per unit staked. Each collateral type has 
    * its own L_Coll and L_YUSDDebt.
    * During its lifetime, each stake earns:
    *
    * A Collateral gain of ( stake * [L_Coll[coll] - L_Coll[coll](0)] )
    * A YUSDDebt increase  of ( stake * [L_YUSDDebt - L_YUSDDebt(0)] )
    *
    * Where L_Coll[coll](0) and L_YUSDDebt(0) are snapshots of L_Coll[coll] and L_YUSDDebt for the active Trove taken at the instant the stake was made
    */
    mapping (address => uint) private L_Coll;
    mapping (address => uint) public L_YUSDDebt;

    // Map addresses with active troves to their RewardSnapshot
    mapping (address => RewardSnapshot) rewardSnapshots;

    // Object containing the reward snapshots for a given active trove
    struct RewardSnapshot {
        mapping(address => uint) CollRewards;
        mapping(address => uint) YUSDDebts;
    }

    // Array of all active trove addresses - used to to compute an approximate hint off-chain, for the sorted list insertion
    address[] private TroveOwners;

    // Error trackers for the trove redistribution calculation
    mapping (address => uint) public lastCollError_Redistribution;
    mapping (address => uint) public lastYUSDDebtError_Redistribution;

    /*
    * --- Variable container structs for liquidations ---
    *
    * These structs are used to hold, return and assign variables inside the liquidation functions,
    * in order to avoid the error: "CompilerError: Stack too deep".
    **/

    // --- Events ---

    event BaseRateUpdated(uint _baseRate);
    event LastFeeOpTimeUpdated(uint _lastFeeOpTime);
    event TotalStakesUpdated(address token, uint _newTotalStakes);
    event SystemSnapshotsUpdated(uint _unix);

    event Liquidation(uint liquidatedAmount, uint totalYUSDGasCompensation, 
        address[] totalCollTokens, uint[] totalCollAmounts,
        address[] totalCollGasCompTokens, uint[] totalCollGasCompAmounts);

    event LTermsUpdated(address _Coll_Address, uint _L_Coll, uint _L_YUSDDebt);
    event TroveSnapshotsUpdated(uint _unix);
    event TroveIndexUpdated(address _borrower, uint _newIndex);
    event TroveUpdated(address indexed _borrower, uint _debt, address[] _tokens, uint[] _amounts, TroveManagerOperation operation);

    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
    override
    onlyOwner
    {
        checkContract(_borrowerOperationsAddress);
        checkContract(_activePoolAddress);
        checkContract(_defaultPoolAddress);
        checkContract(_stabilityPoolAddress);
        checkContract(_gasPoolAddress);
        checkContract(_collSurplusPoolAddress);
        checkContract(_yusdTokenAddress);
        checkContract(_sortedTrovesAddress);
        checkContract(_yetiTokenAddress);
        checkContract(_sYETIAddress);
        checkContract(_whitelistAddress);
        checkContract(_troveManagerRedemptionsAddress);
        checkContract(_troveManagerLiquidationsAddress);

        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);

        troveManagerRedemptionsAddress = _troveManagerRedemptionsAddress;
        troveManagerLiquidationsAddress = _troveManagerLiquidationsAddress;
        troveManagerRedemptions = ITroveManagerRedemptions(_troveManagerRedemptionsAddress);
        troveManagerLiquidations = ITroveManagerLiquidations(_troveManagerLiquidationsAddress);
        _renounceOwnership();
    }

    // --- Getters ---

    function getTroveOwnersCount() public view override returns (uint) {
        return TroveOwners.length;
    }

    function getTroveFromTroveOwnersArray(uint _index) external view override returns (address) {
        return TroveOwners[_index];
    }

    // --- Trove Liquidation functions ---

    // Single liquidation function. Closes the trove if its ICR is lower than the minimum collateral ratio.
    function liquidate(address _borrower) external override {
        _requireTroveIsActive(_borrower);

        address[] memory borrowers = new address[](1);
        borrowers[0] = _borrower;
        batchLiquidateTroves(borrowers, msg.sender);
    }

    /*
    * Attempt to liquidate a custom list of troves provided by the caller.
    */
    function batchLiquidateTroves(address[] memory _troveArray, address _liquidator) public override {
        troveManagerLiquidations.batchLiquidateTroves(_troveArray, _liquidator);
    }


    // --- Liquidation helper functions ---

    /*
    * This function is called only by TroveManagerLiquidations.sol during a liquidation in recovery mode where
    * the trove has TCR > ICR >= MCR. In this case, the liquidation occurs. 110% of the debt in
    * collateral is sent to the stability pool and any surplus is sent to the collateral surplus pool
    */
    function collSurplusUpdate(address _account, address[] memory _tokens, uint[] memory _amounts) external override {
        _requireCallerIsTML();
        collSurplusPool.accountSurplus(_account, _tokens, _amounts);
    }

    // Move a Trove's pending debt and collateral rewards from distributions, from the Default Pool to the Active Pool
    function movePendingTroveRewardsToActivePool(IActivePool _activePool, IDefaultPool _defaultPool, uint _YUSD, address[] memory _tokens, uint[] memory _amounts, address _borrower) external override {
        _requireCallerIsTML();
        _movePendingTroveRewardsToActivePool(_activePool, _defaultPool, _YUSD, _tokens, _amounts, _borrower);
    }

    function _movePendingTroveRewardsToActivePool(IActivePool _activePool, IDefaultPool _defaultPool, uint _YUSD, address[] memory _tokens, uint[] memory _amounts, address _borrower) internal {
        _defaultPool.decreaseYUSDDebt(_YUSD);
        _activePool.increaseYUSDDebt(_YUSD);
        _defaultPool.sendCollsToActivePool(_tokens, _amounts, _borrower);
    }

    // Update position of given trove
    function _updateTrove(address _borrower, address _lowerHint, address _upperHint) internal {
        (uint debt, address[] memory tokens, uint[] memory amounts, , , ) = getEntireDebtAndColls(_borrower);

        newColls memory troveColl;
        troveColl.tokens = tokens;
        troveColl.amounts = amounts;

        uint ICR = _getICRColls(troveColl, debt);
        sortedTroves.reInsert(_borrower, ICR, _lowerHint, _upperHint);
    }

    // Update position for a set of troves using latest price data. This can be called by anyone.
    // Yeti Finance will also be running a bot to assist with keeping the list from becoming
    // too stale.
    function updateTroves(address[] memory _borrowers, address[] memory _lowerHints, address[] memory _upperHints) external {
        require(_borrowers.length == _lowerHints.length);
        require(_lowerHints.length == _upperHints.length);

        for (uint i = 0; i < _lowerHints.length; i++) {
            _updateTrove(_borrowers[i], _lowerHints[i], _upperHints[i]);
        }
    }

    /* Send _YUSDamount YUSD to the system and redeem the corresponding amount of collateral from as many Troves as are needed to fill the redemption
    * request.  Applies pending rewards to a Trove before reducing its debt and coll.
    *
    * Note that if _amount is very large, this function can run out of gas, specially if traversed troves are small. This can be easily avoided by
    * splitting the total _amount in appropriate chunks and calling the function multiple times.
    *
    * Param `_maxIterations` can also be provided, so the loop through Troves is capped (if it’s zero, it will be ignored).This makes it easier to
    * avoid OOG for the frontend, as only knowing approximately the average cost of an iteration is enough, without needing to know the “topology”
    * of the trove list. It also avoids the need to set the cap in stone in the contract, nor doing gas calculations, as both gas price and opcode
    * costs can vary.
    *
    * All Troves that are redeemed from -- with the likely exception of the last one -- will end up with no debt left, therefore they will be closed.
    * If the last Trove does have some remaining debt, it has a finite ICR, and the reinsertion could be anywhere in the list, therefore it requires a hint.
    * A frontend should use getRedemptionHints() to calculate what the ICR of this Trove will be after redemption, and pass a hint for its position
    * in the sortedTroves list along with the ICR value that the hint was found for.
    *
    * If another transaction modifies the list between calling getRedemptionHints() and passing the hints to redeemCollateral(), it
    * is very likely that the last (partially) redeemed Trove would end up with a different ICR than what the hint is for. In this case the
    * redemption will stop after the last completely redeemed Trove and the sender will keep the remaining YUSD amount, which they can attempt
    * to redeem later.
    */
    function redeemCollateral(
        uint _YUSDamount,
        uint _YUSDMaxFee,
        address _firstRedemptionHint,
        address _upperPartialRedemptionHint,
        address _lowerPartialRedemptionHint,
        uint _partialRedemptionHintICR,
        uint _maxIterations
    )
    external
    override
    {
        troveManagerRedemptions.redeemCollateral(
            _YUSDamount,
            _YUSDMaxFee,
            _firstRedemptionHint,
            _upperPartialRedemptionHint,
            _lowerPartialRedemptionHint,
            _partialRedemptionHintICR,
            _maxIterations,
            msg.sender);
    }

    // --- Helper functions ---

    // Return the current collateral ratio (ICR) of a given Trove.
    // Takes a trove's pending coll and debt rewards from redistributions into account.
    function getCurrentICR(address _borrower) public view override returns (uint) {
        (newColls memory colls, uint currentYUSDDebt) = _getCurrentTroveState(_borrower);

        uint ICR = _getICRColls(colls, currentYUSDDebt);
        return ICR;
    }

    // Gets current trove state as colls and debt. 
    function _getCurrentTroveState(address _borrower) internal view
    returns (newColls memory colls, uint YUSDdebt) {
        newColls memory pendingCollReward = _getPendingCollRewards(_borrower);
        uint pendingYUSDDebtReward = getPendingYUSDDebtReward(_borrower);
        
        uint currentYUSDDebt = Troves[_borrower].debt.add(pendingYUSDDebtReward);
        newColls memory currentColls = _sumColls(Troves[_borrower].colls, pendingCollReward);
        
        return (currentColls, currentYUSDDebt);
    }

    // Add the borrowers's coll and debt rewards earned from redistributions, to their Trove
    function applyPendingRewards(address _borrower) external override {
        _requireCallerIsBOorTMR();
        return _applyPendingRewards(activePool, defaultPool, _borrower);
    }

    // Add the borrowers's coll and debt rewards earned from redistributions, to their Trove
    function _applyPendingRewards(IActivePool _activePool, IDefaultPool _defaultPool, address _borrower) internal {
        if (hasPendingRewards(_borrower)) {
            _requireTroveIsActive(_borrower);

            // Compute pending collateral rewards
            newColls memory pendingCollReward = _getPendingCollRewards(_borrower);
            uint pendingYUSDDebtReward = getPendingYUSDDebtReward(_borrower);

            // Apply pending rewards to trove's state
            Troves[_borrower].colls = _sumColls(Troves[_borrower].colls, pendingCollReward);
            Troves[_borrower].debt = Troves[_borrower].debt.add(pendingYUSDDebtReward);

            _updateTroveRewardSnapshots(_borrower);

            // Transfer from DefaultPool to ActivePool
            _movePendingTroveRewardsToActivePool(_activePool, _defaultPool, pendingYUSDDebtReward, pendingCollReward.tokens, pendingCollReward.amounts, _borrower);

            emit TroveUpdated(
                _borrower,
                Troves[_borrower].debt,
                Troves[_borrower].colls.tokens,
                Troves[_borrower].colls.amounts,
                TroveManagerOperation.applyPendingRewards
            );
        }
    }

    // Update borrower's snapshots of L_Coll and L_YUSDDebt to reflect the current values
    function updateTroveRewardSnapshots(address _borrower) external override {
        _requireCallerIsBorrowerOperations();
        _updateTroveRewardSnapshots(_borrower);
    }

    function _updateTroveRewardSnapshots(address _borrower) internal {
        address[] memory allColls = whitelist.getValidCollateral();
        for (uint i = 0; i < allColls.length; i++) {
            address asset = allColls[i];
            rewardSnapshots[_borrower].CollRewards[asset] = L_Coll[asset];
            rewardSnapshots[_borrower].YUSDDebts[asset] = L_YUSDDebt[asset];
        }
        emit TroveSnapshotsUpdated(block.timestamp);
    }

    // Get the borrower's pending accumulated Coll rewards, earned by their stake
    // Returned tokens and amounts are the length of whitelist.getValidCollateral();;
    function getPendingCollRewards(address _borrower) override external view returns (address[] memory, uint[] memory) {
        newColls memory pendingCollRewards = _getPendingCollRewards(_borrower);
        return (pendingCollRewards.tokens, pendingCollRewards.amounts);
    }

    // Get the borrower's pending accumulated Coll rewards, earned by their stake
    // pendingCollRewards.token and pendingCollRewards.amounts are the length of whitelist.getValidCollateral();
    function _getPendingCollRewards(address _borrower) internal view returns (newColls memory pendingCollRewards) {
        if (Troves[_borrower].status != Status.active) {
            newColls memory emptyColls;
            return emptyColls;
        }

        address[] memory allColls = whitelist.getValidCollateral();
        pendingCollRewards.amounts = new uint[](allColls.length);
        pendingCollRewards.tokens = allColls;
        for (uint i = 0; i < allColls.length; i++ ) {
            address coll = allColls[i];
            uint snapshotCollReward = rewardSnapshots[_borrower].CollRewards[coll];
            uint rewardPerUnitStaked = L_Coll[coll].sub(snapshotCollReward);
            if ( rewardPerUnitStaked == 0) {
                pendingCollRewards.amounts[i] = 0;
                continue; }

            uint stake = Troves[_borrower].stakes[coll];
            uint dec = IERC20(coll).decimals();
            uint assetCollReward = stake.mul(rewardPerUnitStaked).div(10 ** dec);
            pendingCollRewards.amounts[i] = assetCollReward; // i is correct index here
        }
        return pendingCollRewards;
    }

    // Get the borrower's pending accumulated YUSD reward, earned by their stake
    function getPendingYUSDDebtReward(address _borrower) public view override returns (uint pendingYUSDDebtReward) {
        if (Troves[_borrower].status != Status.active) {
            return 0;
        }
        address[] memory allColls = whitelist.getValidCollateral();

        for (uint i = 0; i < allColls.length; i++ ) {
            address coll = allColls[i];
            uint snapshotYUSDDebt = rewardSnapshots[_borrower].YUSDDebts[coll];
            uint rewardPerUnitStaked = L_YUSDDebt[allColls[i]].sub(snapshotYUSDDebt);
            if ( rewardPerUnitStaked == 0) { continue; }

            uint stake =  Troves[_borrower].stakes[coll];

            uint assetYUSDDebtReward = stake.mul(rewardPerUnitStaked).div(DECIMAL_PRECISION);
            pendingYUSDDebtReward = pendingYUSDDebtReward.add(assetYUSDDebtReward);
        }

        return pendingYUSDDebtReward;
    }

    function hasPendingRewards(address _borrower) public view override returns (bool) {
        /*
        * A Trove has pending rewards if its snapshot is less than the current rewards per-unit-staked sum:
        * this indicates that rewards have occured since the snapshot was made, and the user therefore has
        * pending rewards
        */
        if (Troves[_borrower].status != Status.active) {return false;}
        address[] memory assets =  Troves[_borrower].colls.tokens;
        for (uint i = 0; i < assets.length; i++) {
            address token = assets[i];
            if (rewardSnapshots[_borrower].CollRewards[token] < L_Coll[token]) {
                return true;
            }
        }
        return false;
    }

    // Returns debt, collsTokens, collsAmounts, pendingYUSDDebtReward, pendingRewardTokens, pendingRewardAmouns
    function getEntireDebtAndColls(
        address _borrower
    )
    public
    view override
    returns (uint, address[] memory, uint[] memory, uint, address[] memory, uint[] memory)
    {
        uint debt = Troves[_borrower].debt;
        newColls memory colls = Troves[_borrower].colls;

        uint pendingYUSDDebtReward = getPendingYUSDDebtReward(_borrower);
        newColls memory pendingCollReward = _getPendingCollRewards(_borrower);

        debt = debt.add(pendingYUSDDebtReward);

        // add in pending rewards to colls
        colls = _sumColls(colls, pendingCollReward);

        return (debt, colls.tokens, colls.amounts, pendingYUSDDebtReward, pendingCollReward.tokens, pendingCollReward.amounts);
    }

    // Borrower operations remove stake sum. 
    function removeStake(address _borrower) external override {
        _requireCallerIsBorrowerOperations();
        return _removeStake(_borrower);
    }

    // Remove borrower's stake from the totalStakes sum, and set their stake to 0
    function _removeStake(address _borrower) internal {
        address[] memory borrowerColls = Troves[_borrower].colls.tokens;
        for (uint i = 0; i < borrowerColls.length; i++) {
            address coll = borrowerColls[i];
            uint stake = Troves[_borrower].stakes[coll];
            totalStakes[coll] = totalStakes[coll].sub(stake);
            Troves[_borrower].stakes[coll] = 0;
        }
    }

    // Update borrower's stake based on their latest collateral value
    // computed at time function is called based on current price of collateral
    function updateStakeAndTotalStakes(address _borrower) external override {
        _requireCallerIsBOorTMR();
        _updateStakeAndTotalStakes(_borrower);
    }

    function _updateStakeAndTotalStakes(address _borrower) internal {
        for (uint i = 0; i < Troves[_borrower].colls.tokens.length; i++) {
            address token = Troves[_borrower].colls.tokens[i];
            uint amount = Troves[_borrower].colls.amounts[i];

            uint newStake = _computeNewStake(token, amount);
            uint oldStake = Troves[_borrower].stakes[token];

            Troves[_borrower].stakes[token] = newStake;
            totalStakes[token] = totalStakes[token].sub(oldStake).add(newStake);

            emit TotalStakesUpdated(token, totalStakes[token]);
        }
    }

    // Calculate a new stake based on the snapshots of the totalStakes and totalCollateral taken at the last liquidation
    function _computeNewStake(address token, uint _coll) internal view returns (uint) {
        uint stake;
        if (totalCollateralSnapshot[token] == 0) {
            stake = _coll;
        } else {
            /*
            * The following assert() holds true because:
            * - The system always contains >= 1 trove
            * - When we close or liquidate a trove, we redistribute the pending rewards, so if all troves were closed/liquidated,
            * rewards would’ve been emptied and totalCollateralSnapshot would be zero too.
            */
            assert(totalStakesSnapshot[token] > 0);
            stake = _coll.mul(totalStakesSnapshot[token]).div(totalCollateralSnapshot[token]);
        }
        return stake;
    }

    function redistributeDebtAndColl(IActivePool _activePool, IDefaultPool _defaultPool, uint _debt, address[] memory _tokens, uint[] memory _amounts) external override {
        _requireCallerIsTML();
        require(_tokens.length == _amounts.length, "TM: len tokens amounts");
        if (_debt == 0) { return; }
        /*
        * Add distributed coll and debt rewards-per-unit-staked to the running totals. Division uses a "feedback"
        * error correction, to keep the cumulative error low in the running totals L_Coll and L_YUSDDebt:
        *
        * 1) Form numerators which compensate for the floor division errors that occurred the last time this
        * function was called.
        * 2) Calculate "per-unit-staked" ratios.
        * 3) Multiply each ratio back by its denominator, to reveal the current floor division error.
        * 4) Store these errors for use in the next correction when this function is called.
        * 5) Note: static analysis tools complain about this "division before multiplication", however, it is intended.
        */
        uint totalCollateralVC = _getVC(_tokens, _amounts); // total collateral value in VC terms

        for (uint i = 0; i < _tokens.length; i++) {
            address token = _tokens[i];
            uint amount = _amounts[i];
            // Prorate debt per collateral by dividing each collateral value by cumulative collateral value and multiply by outstanding debt
            uint collateralVC = whitelist.getValueVC(token, amount);
            uint proratedDebtForCollateral = collateralVC.mul(_debt).div(totalCollateralVC);
            uint dec = IERC20(token).decimals();
            uint CollNumerator = amount.mul(10 ** dec).add(lastCollError_Redistribution[token]);
            uint YUSDDebtNumerator = proratedDebtForCollateral.mul(DECIMAL_PRECISION).add(lastYUSDDebtError_Redistribution[token]);
            if (totalStakes[token] > 0) {
                // Get the per-unit-staked terms
                uint CollRewardPerUnitStaked = CollNumerator.div(totalStakes[token]);
                uint YUSDDebtRewardPerUnitStaked = YUSDDebtNumerator.div(totalStakes[token].mul(10 ** (18 - dec)));

                lastCollError_Redistribution[token] = CollNumerator.sub(CollRewardPerUnitStaked.mul(totalStakes[token]));
                lastYUSDDebtError_Redistribution[token] = YUSDDebtNumerator.sub(YUSDDebtRewardPerUnitStaked.mul(totalStakes[token].mul(10 ** (18 - dec))));

                // Add per-unit-staked terms to the running totals
                L_Coll[token] = L_Coll[token].add(CollRewardPerUnitStaked);
                L_YUSDDebt[token] = L_YUSDDebt[token].add(YUSDDebtRewardPerUnitStaked);
                emit LTermsUpdated(token, L_Coll[token], L_YUSDDebt[token]);
            }
        }

        // Transfer coll and debt from ActivePool to DefaultPool
        _activePool.decreaseYUSDDebt(_debt);
        _defaultPool.increaseYUSDDebt(_debt);
        _activePool.sendCollaterals(address(_defaultPool), _tokens, _amounts);
    }

    function closeTrove(address _borrower) external override {
        _requireCallerIsBorrowerOperations();
        return _closeTrove(_borrower, Status.closedByOwner);
    }

    function closeTroveLiquidation(address _borrower) external override {
        _requireCallerIsTML();
        return _closeTrove(_borrower, Status.closedByLiquidation);
    }

    function closeTroveRedemption(address _borrower) external override {
        _requireCallerIsTMR();
        return _closeTrove(_borrower, Status.closedByRedemption);
    }

    function _closeTrove(address _borrower, Status closedStatus) internal {
        assert(closedStatus != Status.nonExistent && closedStatus != Status.active);

        uint TroveOwnersArrayLength = TroveOwners.length;
        _requireMoreThanOneTroveInSystem(TroveOwnersArrayLength);
        newColls memory emptyColls;

        Troves[_borrower].status = closedStatus;
        Troves[_borrower].colls = emptyColls;
        Troves[_borrower].debt = 0;

        address[] memory allColls = whitelist.getValidCollateral();
        for (uint i = 0; i < allColls.length; i++) {
            rewardSnapshots[_borrower].CollRewards[allColls[i]] = 0;
            rewardSnapshots[_borrower].YUSDDebts[allColls[i]] = 0;
        }

        _removeTroveOwner(_borrower, TroveOwnersArrayLength);
        sortedTroves.remove(_borrower);
    }

    /*
    * Updates snapshots of system total stakes and total collateral, excluding a given collateral remainder from the calculation.
    * Used in a liquidation sequence.
    *
    * The calculation excludes a portion of collateral that is in the ActivePool:
    *
    * the total Coll gas compensation from the liquidation sequence
    *
    * The Coll as compensation must be excluded as it is always sent out at the very end of the liquidation sequence.
    */
    function updateSystemSnapshots_excludeCollRemainder(IActivePool _activePool, address[] memory _tokens, uint[] memory _amounts) external override {
        _requireCallerIsTML();
        for (uint i = 0; i < _tokens.length; i++) {
            address token = _tokens[i];
            totalStakesSnapshot[token] = totalStakes[token];

            uint _tokenRemainder = _amounts[i];
            uint activeColl = _activePool.getCollateral(token);
            uint liquidatedColl = defaultPool.getCollateral(token);
            totalCollateralSnapshot[token] = activeColl.sub(_tokenRemainder).add(liquidatedColl);
        }
        emit SystemSnapshotsUpdated(block.timestamp);
    }

    // Push the owner's address to the Trove owners list, and record the corresponding array index on the Trove struct
    function addTroveOwnerToArray(address _borrower) external override returns (uint index) {
        _requireCallerIsBorrowerOperations();
        return _addTroveOwnerToArray(_borrower);
    }

    function _addTroveOwnerToArray(address _borrower) internal returns (uint128 index) {
        /* Max array size is 2**128 - 1, i.e. ~3e30 troves. No risk of overflow, since troves have minimum YUSD
        debt of liquidation reserve plus MIN_NET_DEBT. 3e30 YUSD dwarfs the value of all wealth in the world ( which is < 1e15 USD). */
        // Push the Troveowner to the array
        TroveOwners.push(_borrower);

        // Record the index of the new Troveowner on their Trove struct
        index = uint128(TroveOwners.length.sub(1));
        Troves[_borrower].arrayIndex = index;
        return index;
    }

    /*
    * Remove a Trove owner from the TroveOwners array, not preserving array order. Removing owner 'B' does the following:
    * [A B C D E] => [A E C D], and updates E's Trove struct to point to its new array index.
    */
    function _removeTroveOwner(address _borrower, uint TroveOwnersArrayLength) internal {
        Status troveStatus = Troves[_borrower].status;
        // It’s set in caller function `_closeTrove`
        assert(troveStatus != Status.nonExistent && troveStatus != Status.active);

        uint128 index = Troves[_borrower].arrayIndex;
        uint length = TroveOwnersArrayLength;
        uint idxLast = length.sub(1);

        assert(index <= idxLast);

        address addressToMove = TroveOwners[idxLast];

        TroveOwners[index] = addressToMove;
        Troves[addressToMove].arrayIndex = index;
        emit TroveIndexUpdated(addressToMove, index);

        TroveOwners.pop();
    }

    // --- Recovery Mode and TCR functions ---

    function getTCR() external view override returns (uint) {
        return _getTCR();
    }

    function checkRecoveryMode() external view override returns (bool) {
        return _checkRecoveryMode();
    }


    // --- Redemption fee functions ---

    function updateBaseRate(uint newBaseRate) external override {
        _requireCallerIsTMR();
        assert(newBaseRate > 0);
        baseRate = newBaseRate;
        emit BaseRateUpdated(newBaseRate);
        _updateLastFeeOpTime();
    }

    function getRedemptionRate() public view override returns (uint) {
        return _calcRedemptionRate(baseRate);
    }

    function getRedemptionRateWithDecay() public view override returns (uint) {
        return _calcRedemptionRate(calcDecayedBaseRate());
    }

    function _calcRedemptionRate(uint _baseRate) internal pure returns (uint) {
        return LiquityMath._min(
            REDEMPTION_FEE_FLOOR.add(_baseRate),
            DECIMAL_PRECISION // cap at a maximum of 100%
        );
    }

    function _getRedemptionFee(uint _YUSDRedeemed) internal view returns (uint) {
        return _calcRedemptionFee(getRedemptionRate(), _YUSDRedeemed);
    }

    function getRedemptionFeeWithDecay(uint _YUSDRedeemed) external view override returns (uint) {
        return _calcRedemptionFee(getRedemptionRateWithDecay(), _YUSDRedeemed);
    }

    function _calcRedemptionFee(uint _redemptionRate, uint _YUSDRedeemed) internal pure returns (uint) {
        uint redemptionFee = _redemptionRate.mul(_YUSDRedeemed).div(DECIMAL_PRECISION);
        require(redemptionFee < _YUSDRedeemed, "TM:Fee>returned colls");
        return redemptionFee;
    }


    // --- Borrowing fee functions ---

    function getBorrowingRate() public view override returns (uint) {
        return _calcBorrowingRate(baseRate);
    }

    function getBorrowingRateWithDecay() public view override returns (uint) {
        return _calcBorrowingRate(calcDecayedBaseRate());
    }

    function _calcBorrowingRate(uint _baseRate) internal pure returns (uint) {
        return LiquityMath._min(
            BORROWING_FEE_FLOOR.add(_baseRate),
            MAX_BORROWING_FEE
        );
    }

    function getBorrowingFee(uint _YUSDDebt) external view override returns (uint) {
        return _calcBorrowingFee(getBorrowingRate(), _YUSDDebt);
    }

    function getBorrowingFeeWithDecay(uint _YUSDDebt) external view override returns (uint) {
        return _calcBorrowingFee(getBorrowingRateWithDecay(), _YUSDDebt);
    }

    function _calcBorrowingFee(uint _borrowingRate, uint _YUSDDebt) internal pure returns (uint) {
        return _borrowingRate.mul(_YUSDDebt).div(DECIMAL_PRECISION);
    }


    // Updates the baseRate state variable based on time elapsed since the last redemption or YUSD borrowing operation.
    function decayBaseRateFromBorrowing() external override {
        _requireCallerIsBorrowerOperations();

        uint decayedBaseRate = calcDecayedBaseRate();
        assert(decayedBaseRate <= DECIMAL_PRECISION);  // The baseRate can decay to 0

        baseRate = decayedBaseRate;
        emit BaseRateUpdated(decayedBaseRate);

        _updateLastFeeOpTime();
    }


    // --- Internal fee functions ---

    // Update the last fee operation time only if time passed >= decay interval. This prevents base rate griefing.
    function _updateLastFeeOpTime() internal {
        uint timePassed = block.timestamp.sub(lastFeeOperationTime);

        if (timePassed >= SECONDS_IN_ONE_MINUTE) {
            lastFeeOperationTime = block.timestamp;
            emit LastFeeOpTimeUpdated(block.timestamp);
        }
    }

    function calcDecayedBaseRate() public view override returns (uint) {
        uint minutesPassed = _minutesPassedSinceLastFeeOp();
        uint decayFactor = LiquityMath._decPow(MINUTE_DECAY_FACTOR, minutesPassed);

        return baseRate.mul(decayFactor).div(DECIMAL_PRECISION);
    }

    function _minutesPassedSinceLastFeeOp() internal view returns (uint) {
        return (block.timestamp.sub(lastFeeOperationTime)).div(SECONDS_IN_ONE_MINUTE);
    }

    // --- 'require' wrapper functions ---

    function _requireCallerIsBorrowerOperations() internal view {
        require(msg.sender == borrowerOperationsAddress, "TM: must be called by BO");
    }

    function _requireCallerIsBOorTMR() internal view {
        require(msg.sender == borrowerOperationsAddress || msg.sender == troveManagerRedemptionsAddress,
            "TM: Invalid Caller");
    }

    function _requireCallerIsTMR() internal view {
        require(msg.sender == troveManagerRedemptionsAddress,
            "TM: must be called by TMR");
    }

    function _requireCallerIsTML() internal view {
        require(msg.sender == troveManagerLiquidationsAddress,
            "TM: must be called by TML");
    }

    function _requireTroveIsActive(address _borrower) internal view {
        require(Troves[_borrower].status == Status.active, "TM: trove must exist");
    }

    function _requireMoreThanOneTroveInSystem(uint TroveOwnersArrayLength) internal view {
        require (TroveOwnersArrayLength > 1 && sortedTroves.getSize() > 1, "TM: last trove");
    }

    // --- Trove property getters ---

    function getTroveStatus(address _borrower) external view override returns (uint) {
        return uint(Troves[_borrower].status);
    }

    function isTroveActive(address _borrower) external view override returns (bool) {
        return Troves[_borrower].status == Status.active;
    }

    function getTroveStake(address _borrower, address _token) external view override returns (uint) {
        return Troves[_borrower].stakes[_token];
    }

    function getTroveDebt(address _borrower) external view override returns (uint) {
        return Troves[_borrower].debt;
    }

    // -- Trove Manager State Variable Getters -- 

    function getTotalStake(address _token) external view override returns (uint) {
        return totalStakes[_token];
    }

    function getL_Coll(address _token) external view override returns (uint) {
        return L_Coll[_token];
    }

    function getL_YUSD(address _token) external view override returns (uint) {
        return L_YUSDDebt[_token];
    }

    function getRewardSnapshotColl(address _borrower, address _token) external view override returns (uint) {
        return rewardSnapshots[_borrower].CollRewards[_token];
    }

    function getRewardSnapshotYUSD(address _borrower, address _token) external view override returns (uint) {
        return rewardSnapshots[_borrower].YUSDDebts[_token];
    }

    // recomputes VC given current prices and returns it
    function getTroveVC(address _borrower) external view override returns (uint) {
        return _getVCColls(Troves[_borrower].colls);
    }

    function getTroveColls(address _borrower) external view override returns (address[] memory, uint[] memory) {
        return (Troves[_borrower].colls.tokens, Troves[_borrower].colls.amounts);
    }

    function getCurrentTroveState(address _borrower) external override view returns (address[] memory, uint[] memory, uint) {
        (newColls memory colls, uint currentYUSDDebt) = _getCurrentTroveState(_borrower);
        return (colls.tokens, colls.amounts, currentYUSDDebt);
    }

    // --- Called by TroveManagerRedemptions Only ---


    function updateTroveDebt(address _borrower, uint debt) external override {
        _requireCallerIsTMR();
        Troves[_borrower].debt = debt;
    }

    function updateTroveCollTMR(address  _borrower, address[] memory addresses, uint[] memory amounts) external override {
        _requireCallerIsTMR();
        (Troves[_borrower].colls.tokens, Troves[_borrower].colls.amounts) = (addresses, amounts);
    }

    function removeStakeTMR(address _borrower) external override {
        _requireCallerIsTMR();
        _removeStake(_borrower);
    }

    // --- Called by TroverManagerLiquidations Only ---

    function removeStakeTLR(address _borrower) external override {
        _requireCallerIsTML();
        _removeStake(_borrower);
    }

    // --- Trove property setters, called by BorrowerOperations ---

    function setTroveStatus(address _borrower, uint _num) external override {
        _requireCallerIsBorrowerOperations();
        Troves[_borrower].status = Status(_num);
    }

    function updateTroveColl(address _borrower, address[] memory _tokens, uint[] memory _amounts) external override {
        _requireCallerIsBorrowerOperations();
        require(_tokens.length == _amounts.length);
        Troves[_borrower].colls.tokens = _tokens;
        Troves[_borrower].colls.amounts = _amounts;
    }

    function increaseTroveDebt(address _borrower, uint _debtIncrease) external override returns (uint) {
        _requireCallerIsBorrowerOperations();
        uint newDebt = Troves[_borrower].debt.add(_debtIncrease);
        Troves[_borrower].debt = newDebt;
        return newDebt;
    }

    function decreaseTroveDebt(address _borrower, uint _debtDecrease) external override returns (uint) {
        _requireCallerIsBorrowerOperations();
        uint newDebt = Troves[_borrower].debt.sub(_debtDecrease);
        Troves[_borrower].debt = newDebt;
        return newDebt;
    }

    // --- contract getters ---

    function stabilityPool() external view override returns (IStabilityPool) {
        return stabilityPoolContract;
    }

    function yusdToken() external view override returns (IYUSDToken) {
        return yusdTokenContract;
    }

    function yetiToken() external view override returns (IYETIToken) {
        return yetiTokenContract;
    }

    function sYETI() external view override returns (ISYETI) {
        return sYETIContract;
    }
 }

File 2 of 27 : 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 3 of 27 : 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 4 of 27 : 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 5 of 27 : 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 6 of 27 : 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 7 of 27 : 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 8 of 27 : 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 9 of 27 : 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 10 of 27 : ITroveManagerLiquidations.sol
// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.6.11;


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

File 11 of 27 : 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 12 of 27 : 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 13 of 27 : 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 14 of 27 : ILiquityBase.sol
// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.6.11;

import "./IPriceFeed.sol";


interface ILiquityBase {

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

File 15 of 27 : 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 16 of 27 : 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 17 of 27 : 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 18 of 27 : ICollateralReceiver.sol
// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.6.11;

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

File 19 of 27 : 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 20 of 27 : 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 21 of 27 : 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 22 of 27 : BaseMath.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.6.11;


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

File 23 of 27 : 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 24 of 27 : 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 25 of 27 : 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 26 of 27 : 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 27 of 27 : 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":"uint256","name":"_baseRate","type":"uint256"}],"name":"BaseRateUpdated","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":"address","name":"_Coll_Address","type":"address"},{"indexed":false,"internalType":"uint256","name":"_L_Coll","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_L_YUSDDebt","type":"uint256"}],"name":"LTermsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_L_ETH","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_L_YUSDDebt","type":"uint256"}],"name":"LTermsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_lastFeeOpTime","type":"uint256"}],"name":"LastFeeOpTimeUpdated","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":"_newPriceFeedAddress","type":"address"}],"name":"PriceFeedAddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_attemptedYUSDAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_actualYUSDAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"YUSDfee","type":"uint256"},{"indexed":false,"internalType":"address[]","name":"tokens","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"Redemption","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":false,"internalType":"uint256","name":"_unix","type":"uint256"}],"name":"SystemSnapshotsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_totalStakesSnapshot","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_totalCollateralSnapshot","type":"uint256"}],"name":"SystemSnapshotsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"_newTotalStakes","type":"uint256"}],"name":"TotalStakesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_borrower","type":"address"},{"indexed":false,"internalType":"uint256","name":"_newIndex","type":"uint256"}],"name":"TroveIndexUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_borrower","type":"address"},{"indexed":false,"internalType":"uint256","name":"_debt","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_coll","type":"uint256"},{"indexed":false,"internalType":"uint8","name":"operation","type":"uint8"}],"name":"TroveLiquidated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_unix","type":"uint256"}],"name":"TroveSnapshotsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_L_ETH","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_L_YUSDDebt","type":"uint256"}],"name":"TroveSnapshotsUpdated","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":"BOOTSTRAP_PERIOD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"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":[{"internalType":"address","name":"","type":"address"}],"name":"L_YUSDDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_BORROWING_FEE","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":"MINUTE_DECAY_FACTOR","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":"NAME","outputs":[{"internalType":"string","name":"","type":"string"}],"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":"SECONDS_IN_ONE_MINUTE","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":"_borrower","type":"address"}],"name":"addTroveOwnerToArray","outputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"}],"name":"applyPendingRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"baseRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"calcDecayedBaseRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"checkRecoveryMode","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"}],"name":"closeTrove","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"}],"name":"closeTroveLiquidation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"}],"name":"closeTroveRedemption","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"address[]","name":"_tokens","type":"address[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"}],"name":"collSurplusUpdate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decayBaseRateFromBorrowing","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"},{"internalType":"uint256","name":"_debtDecrease","type":"uint256"}],"name":"decreaseTroveDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"defaultPool","outputs":[{"internalType":"contract IDefaultPool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_YUSDDebt","type":"uint256"}],"name":"getBorrowingFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_YUSDDebt","type":"uint256"}],"name":"getBorrowingFeeWithDecay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBorrowingRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBorrowingRateWithDecay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"}],"name":"getCurrentICR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"}],"name":"getCurrentTroveState","outputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"}],"name":"getEntireDebtAndColls","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"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":[{"internalType":"address","name":"_token","type":"address"}],"name":"getL_Coll","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"getL_YUSD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"}],"name":"getPendingCollRewards","outputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"}],"name":"getPendingYUSDDebtReward","outputs":[{"internalType":"uint256","name":"pendingYUSDDebtReward","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_YUSDRedeemed","type":"uint256"}],"name":"getRedemptionFeeWithDecay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRedemptionRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRedemptionRateWithDecay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"},{"internalType":"address","name":"_token","type":"address"}],"name":"getRewardSnapshotColl","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"},{"internalType":"address","name":"_token","type":"address"}],"name":"getRewardSnapshotYUSD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTCR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"getTotalStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"}],"name":"getTroveColls","outputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"}],"name":"getTroveDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"getTroveFromTroveOwnersArray","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTroveOwnersCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"},{"internalType":"address","name":"_token","type":"address"}],"name":"getTroveStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"}],"name":"getTroveStatus","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"}],"name":"getTroveVC","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"}],"name":"hasPendingRewards","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"},{"internalType":"uint256","name":"_debtIncrease","type":"uint256"}],"name":"increaseTroveDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"}],"name":"isTroveActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lastCollError_Redistribution","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastFeeOperationTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lastYUSDDebtError_Redistribution","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"}],"name":"liquidate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IActivePool","name":"_activePool","type":"address"},{"internalType":"contract IDefaultPool","name":"_defaultPool","type":"address"},{"internalType":"uint256","name":"_YUSD","type":"uint256"},{"internalType":"address[]","name":"_tokens","type":"address[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"},{"internalType":"address","name":"_borrower","type":"address"}],"name":"movePendingTroveRewardsToActivePool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_YUSDamount","type":"uint256"},{"internalType":"uint256","name":"_YUSDMaxFee","type":"uint256"},{"internalType":"address","name":"_firstRedemptionHint","type":"address"},{"internalType":"address","name":"_upperPartialRedemptionHint","type":"address"},{"internalType":"address","name":"_lowerPartialRedemptionHint","type":"address"},{"internalType":"uint256","name":"_partialRedemptionHintICR","type":"uint256"},{"internalType":"uint256","name":"_maxIterations","type":"uint256"}],"name":"redeemCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IActivePool","name":"_activePool","type":"address"},{"internalType":"contract IDefaultPool","name":"_defaultPool","type":"address"},{"internalType":"uint256","name":"_debt","type":"uint256"},{"internalType":"address[]","name":"_tokens","type":"address[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"}],"name":"redistributeDebtAndColl","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"}],"name":"removeStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"}],"name":"removeStakeTLR","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"}],"name":"removeStakeTMR","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sYETI","outputs":[{"internalType":"contract ISYETI","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":"_troveManagerRedemptionsAddress","type":"address"},{"internalType":"address","name":"_troveManagerLiquidationsAddress","type":"address"}],"name":"setAddresses","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"},{"internalType":"uint256","name":"_num","type":"uint256"}],"name":"setTroveStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sortedTroves","outputs":[{"internalType":"contract ISortedTroves","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stabilityPool","outputs":[{"internalType":"contract IStabilityPool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"totalCollateralSnapshot","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"totalStakes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"totalStakesSnapshot","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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"},{"inputs":[{"internalType":"uint256","name":"newBaseRate","type":"uint256"}],"name":"updateBaseRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"}],"name":"updateStakeAndTotalStakes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IActivePool","name":"_activePool","type":"address"},{"internalType":"address[]","name":"_tokens","type":"address[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"}],"name":"updateSystemSnapshots_excludeCollRemainder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"},{"internalType":"address[]","name":"_tokens","type":"address[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"}],"name":"updateTroveColl","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"},{"internalType":"address[]","name":"addresses","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"updateTroveCollTMR","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"},{"internalType":"uint256","name":"debt","type":"uint256"}],"name":"updateTroveDebt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"}],"name":"updateTroveRewardSnapshots","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_borrowers","type":"address[]"},{"internalType":"address[]","name":"_lowerHints","type":"address[]"},{"internalType":"address[]","name":"_upperHints","type":"address[]"}],"name":"updateTroves","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"yetiToken","outputs":[{"internalType":"contract IYETIToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"yusdToken","outputs":[{"internalType":"contract IYUSDToken","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

608060405234801561001057600080fd5b50600380546001600160a01b031916339081179091556040516000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3615e9280620000616000396000f3fe608060405234801561001057600080fd5b50600436106105255760003560e01c8063794e5724116102af578063c550c36211610172578063de665835116100d9578063e369e4ab11610092578063e369e4ab1461196c578063f36b242514611a18578063f5f468ed14611a20578063f92d343314610990578063fe2ba84814611a28578063fefa753d14611a4e57610525565b8063de6658351461167c578063de6c20fd146116a2578063df349ed5146116aa578063e1f18250146116d0578063e2ac77b014611803578063e34f6d441461182957610525565b8063d5b356351161012b578063d5b356351461153a578063d66a255314611557578063d9a724441461157d578063db5e73211461159a578063dbebddce14611628578063dc3fe76f1461164e57610525565b8063c550c36214611492578063c6179445146114b8578063c7b55481146114de578063cbd138ae146114e6578063cde047991461150c578063d380a37c1461153257610525565b8063a20baee611610216578063b7f8cf9b116101cf578063b7f8cf9b14611400578063ba6e79f714611408578063bce3bf9014611436578063bd5ef3f91461145c578063c35bc55014611482578063c52861f21461148a57610525565b8063a20baee614610f37578063a264539214611345578063a3f4df7e1461134d578063ae918754146113ca578063af3700dc146113d2578063b620115d146113f857610525565b80638e201a14116102685780638e201a14146110d35780638f32d59b1461119257806396755e551461119a57806399723784146112cd5780639976cf45146112f35780639cbf39791461131f57610525565b8063794e5724146109c6578063795d26c31461108d5780637f7dde4a1461109557806382fe3eb91461109d578063887105d3146110c35780638da5cb5b146110cb57610525565b806335a058b4116103f75780634e9de6351161035e5780635dba4c4a116103175780635dba4c4a14610f0257806361ec893d14610f0a578063631203b014610f1257806366ca4a2114610f2f57806372fe25aa14610f375780637837eeeb14610f3f57610525565b80634e9de63514610d5d57806350953b6214610e90578063568bcbb214610ebe5780635733d58f14610ec65780635a4d28bb14610ece5780635d6b480f14610ed657610525565b806343a124fa116103b057806343a124fa14610d185780634597997814610d20578063477d66cf14610d285780634870dd9a14610d45578063499f99d914610d4d57806349eefeee14610d5557610525565b806335a058b414610a3d578063371e45ba14610b035780633735aa2014610b295780633bc8913e14610b635780633cc7422514610d085780633d83908a14610d1057610525565b80631f68f20a1161049b5780632b11551a116104545780632b11551a146109985780632f865568146109a0578063308e9647146109c657806331bafd9b146109ce578063328e1404146109fa578063330283aa14610a2057610525565b80631f68f20a1461090e57806321e378011461091657806322962f651461093c578063240926691461096257806327fb7d891461096a57806328d28b5b1461099057610525565b806315d549f1116104ed57806315d549f11461075957806316a81f311461077f5780631843bf881461078757806318f2817a146108ba5780631bf43555146108e05780631e7ff8f6146108e857610525565b8063048c661d1461052a5780630b0765571461054e57806312610e921461057657806312adf0c2146105b457806313312d591461070b575b600080fd5b610532611a74565b604080516001600160a01b039092168252519081900360200190f35b6105746004803603602081101561056457600080fd5b50356001600160a01b0316611a84565b005b6105a26004803603604081101561058c57600080fd5b506001600160a01b038135169060200135611aac565b60408051918252519081900360200190f35b6105da600480360360208110156105ca57600080fd5b50356001600160a01b0316611b0a565b604051808781526020018060200180602001868152602001806020018060200185810385528a818151815260200191508051906020019060200280838360005b8381101561063257818101518382015260200161061a565b50505050905001858103845289818151815260200191508051906020019060200280838360005b83811015610671578181015183820152602001610659565b50505050905001858103835287818151815260200191508051906020019060200280838360005b838110156106b0578181015183820152602001610698565b50505050905001858103825286818151815260200191508051906020019060200280838360005b838110156106ef5781810151838201526020016106d7565b505050509050019a505050505050505050505060405180910390f35b610574600480360360e081101561072157600080fd5b508035906020810135906001600160a01b03604082013581169160608101358216916080820135169060a08101359060c00135611c70565b6105a26004803603602081101561076f57600080fd5b50356001600160a01b0316611d12565b610532611d36565b6105746004803603606081101561079d57600080fd5b6001600160a01b038235169190810190604081016020820135600160201b8111156107c757600080fd5b8201836020820111156107d957600080fd5b803590602001918460208302840111600160201b831117156107fa57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b81111561084957600080fd5b82018360208201111561085b57600080fd5b803590602001918460208302840111600160201b8311171561087c57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550611d45945050505050565b610574600480360360208110156108d057600080fd5b50356001600160a01b0316611d9c565b6105a2611dad565b6105a2600480360360208110156108fe57600080fd5b50356001600160a01b0316611dba565b6105a2611dd5565b6105a26004803603602081101561092c57600080fd5b50356001600160a01b0316611ddb565b6105746004803603602081101561095257600080fd5b50356001600160a01b0316611e06565b6105a2611e19565b6105a26004803603602081101561098057600080fd5b50356001600160a01b0316611e2c565b6105a2611e5a565b6105a2611e6b565b610574600480360360208110156109b657600080fd5b50356001600160a01b0316611e7d565b6105a2611ee4565b610574600480360360408110156109e457600080fd5b506001600160a01b038135169060200135611ef0565b6105a260048036036020811015610a1057600080fd5b50356001600160a01b0316611f17565b61057460048036036020811015610a3657600080fd5b5035611f29565b610a6360048036036020811015610a5357600080fd5b50356001600160a01b0316611f7b565b604051808060200180602001848152602001838103835286818151815260200191508051906020019060200280838360005b83811015610aad578181015183820152602001610a95565b50505050905001838103825285818151815260200191508051906020019060200280838360005b83811015610aec578181015183820152602001610ad4565b505050509050019550505050505060405180910390f35b6105a260048036036020811015610b1957600080fd5b50356001600160a01b0316611fa9565b610b4f60048036036020811015610b3f57600080fd5b50356001600160a01b0316612243565b604080519115158252519081900360200190f35b61057460048036036060811015610b7957600080fd5b810190602081018135600160201b811115610b9357600080fd5b820183602082011115610ba557600080fd5b803590602001918460208302840111600160201b83111715610bc657600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b811115610c1557600080fd5b820183602082011115610c2757600080fd5b803590602001918460208302840111600160201b83111715610c4857600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b811115610c9757600080fd5b820183602082011115610ca957600080fd5b803590602001918460208302840111600160201b83111715610cca57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550612279945050505050565b6105326122f3565b610532612302565b610b4f612311565b6105a261231b565b6105a260048036036020811015610d3e57600080fd5b5035612366565b6105a2612379565b6105a261237e565b6105a261238b565b61057460048036036060811015610d7357600080fd5b6001600160a01b038235169190810190604081016020820135600160201b811115610d9d57600080fd5b820183602082011115610daf57600080fd5b803590602001918460208302840111600160201b83111715610dd057600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b811115610e1f57600080fd5b820183602082011115610e3157600080fd5b803590602001918460208302840111600160201b83111715610e5257600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550612391945050505050565b6105a260048036036040811015610ea657600080fd5b506001600160a01b0381358116916020013516612400565b61053261242f565b6105a261243e565b61053261244a565b61057460048036036040811015610eec57600080fd5b506001600160a01b038135169060200135612459565b6105746124ac565b6105a26124d2565b6105a260048036036020811015610f2857600080fd5b50356124d7565b6105a26124e4565b6105a26124f6565b610574600480360360c0811015610f5557600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b811115610f8f57600080fd5b820183602082011115610fa157600080fd5b803590602001918460208302840111600160201b83111715610fc257600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b81111561101157600080fd5b82018360208201111561102357600080fd5b803590602001918460208302840111600160201b8311171561104457600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550505090356001600160a01b031691506125029050565b6105a2612518565b61053261261e565b610574600480360360208110156110b357600080fd5b50356001600160a01b031661262d565b6105a261263e565b610532612706565b6110f9600480360360208110156110e957600080fd5b50356001600160a01b0316612715565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b8381101561113d578181015183820152602001611125565b50505050905001838103825284818151815260200191508051906020019060200280838360005b8381101561117c578181015183820152602001611164565b5050505090500194505050505060405180910390f35b610b4f61273c565b610574600480360360608110156111b057600080fd5b6001600160a01b038235169190810190604081016020820135600160201b8111156111da57600080fd5b8201836020820111156111ec57600080fd5b803590602001918460208302840111600160201b8311171561120d57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b81111561125c57600080fd5b82018360208201111561126e57600080fd5b803590602001918460208302840111600160201b8311171561128f57600080fd5b91908080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525092955061274d945050505050565b6110f9600480360360208110156112e357600080fd5b50356001600160a01b0316612850565b6105a26004803603604081101561130957600080fd5b506001600160a01b038135169060200135612924565b6105a26004803603602081101561133557600080fd5b50356001600160a01b031661295a565b61053261296c565b61135561297b565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561138f578181015183820152602001611377565b50505050905090810190601f1680156113bc5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6105326129a3565b6105a2600480360360208110156113e857600080fd5b50356001600160a01b03166129b2565b6105a26129c4565b6105326129ce565b6105a26004803603604081101561141e57600080fd5b506001600160a01b03813581169160200135166129dd565b6105746004803603602081101561144c57600080fd5b50356001600160a01b0316612a08565b6105746004803603602081101561147257600080fd5b50356001600160a01b0316612a19565b6105a2612a2c565b6105a2612a33565b610574600480360360208110156114a857600080fd5b50356001600160a01b0316612a45565b6105a2600480360360208110156114ce57600080fd5b50356001600160a01b0316612a4d565b6105a2612b27565b610574600480360360208110156114fc57600080fd5b50356001600160a01b0316612b33565b6105a26004803603602081101561152257600080fd5b50356001600160a01b0316612b46565b6105a2612b61565b6105a26004803603602081101561155057600080fd5b5035612b67565b6105a26004803603602081101561156d57600080fd5b50356001600160a01b0316612b7a565b6105326004803603602081101561159357600080fd5b5035612b98565b61057460048036036101a08110156115b157600080fd5b506001600160a01b038135811691602081013582169160408201358116916060810135821691608082013581169160a081013582169160c082013581169160e08101358216916101008201358116916101208101358216916101408201358116916101608101358216916101809091013516612bc2565b6105a26004803603602081101561163e57600080fd5b50356001600160a01b0316612eef565b6105a26004803603604081101561166457600080fd5b506001600160a01b0381358116916020013516612f01565b6105a26004803603602081101561169257600080fd5b50356001600160a01b0316612f30565b610532612f42565b6105a2600480360360208110156116c057600080fd5b50356001600160a01b0316612f51565b610574600480360360608110156116e657600080fd5b6001600160a01b038235169190810190604081016020820135600160201b81111561171057600080fd5b82018360208201111561172257600080fd5b803590602001918460208302840111600160201b8311171561174357600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b81111561179257600080fd5b8201836020820111156117a457600080fd5b803590602001918460208302840111600160201b831117156117c557600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550612f63945050505050565b610b4f6004803603602081101561181957600080fd5b50356001600160a01b0316613157565b610574600480360360a081101561183f57600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b81111561187957600080fd5b82018360208201111561188b57600080fd5b803590602001918460208302840111600160201b831117156118ac57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b8111156118fb57600080fd5b82018360208201111561190d57600080fd5b803590602001918460208302840111600160201b8311171561192e57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550613285945050505050565b6105746004803603604081101561198257600080fd5b810190602081018135600160201b81111561199c57600080fd5b8201836020820111156119ae57600080fd5b803590602001918460208302840111600160201b831117156119cf57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550505090356001600160a01b0316915061388d9050565b6105a2613930565b61053261393d565b61057460048036036020811015611a3e57600080fd5b50356001600160a01b031661394c565b6105a260048036036020811015611a6457600080fd5b50356001600160a01b0316613954565b6005546001600160a01b03165b90565b611a8c61396f565b600154600254611aa9916001600160a01b039081169116836139da565b50565b6000611ab6613ca2565b6001600160a01b038316600090815260146020526040812060020154611ae2908463ffffffff613cfc16565b6001600160a01b03851660009081526014602052604090206002018190559150505b92915050565b6001600160a01b0381166000908152601460205260408120600201546060908190839082908190611b39615d37565b6001600160a01b0389166000908152601460209081526040918290208251815460609381028201840185529381018481529093919284928491840182828015611bab57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611b8d575b5050505050815260200160018201805480602002602001604051908101604052809291908181526020018280548015611c0357602002820191906000526020600020905b815481526020019060010190808311611bef575b50505050508152505090506000611c198a611fa9565b9050611c23615d37565b611c2c8b613d45565b9050611c3e848363ffffffff61405316565b9350611c4a83826140ad565b805160209182015183519390920151959d909c50909a5091985096509194509092505050565b600a546040805163c2f6202d60e01b8152600481018a9052602481018990526001600160a01b0388811660448301528781166064830152868116608483015260a4820186905260c482018590523360e48301529151919092169163c2f6202d9161010480830192600092919082900301818387803b158015611cf157600080fd5b505af1158015611d05573d6000803e3d6000fd5b5050505050505050505050565b6000611d1c613ca2565b611d25826145cb565b6001600160801b031690505b919050565b600f546001600160a01b031681565b611d4d614665565b6001600160a01b038316600090815260146020908152604082208351859385939091611d8191600185019190860190615d51565b50508251611d9491906020850190615d9c565b505050505050565b611da461396f565b611aa9816146c0565b686194049f30f720000081565b6001600160a01b031660009081526015602052604090205490565b60125481565b6001600160a01b038116600090815260146020526040812060049081015460ff1690811115611b0457fe5b611e0e61480f565b611aa981600361486a565b6064670de0b6b3a76400005b0460050281565b6000611e36615d37565b6000611e4184614b93565b915091506000611e518383614cdd565b95945050505050565b6103e8670de0b6b3a7640000611e25565b6000611e78601254614cfd565b905090565b611e8681614d33565b604080516001808252818301909252606091602080830190803683370190505090508181600081518110611eb657fe5b60200260200101906001600160a01b031690816001600160a01b031681525050611ee0813361388d565b5050565b670f43fc2c04ee000081565b611ef8614665565b6001600160a01b03909116600090815260146020526040902060020155565b601c6020526000908152604090205481565b611f31614665565b60008111611f3b57fe5b60128190556040805182815290517fc454ee9b76c52f782a256af821b857ca6e125d1e3333bcede402fec2bed9600c9181900360200190a1611aa9614da9565b6060806000611f88615d37565b6000611f9386614b93565b8151602090920151919891975095509350505050565b600060016001600160a01b038316600090815260146020526040902060049081015460ff1690811115611fd857fe5b14611fe557506000611d31565b6000805460408051634eb5750560e11b815290516060936001600160a01b0390931692639d6aea0a9260048082019391829003018186803b15801561202957600080fd5b505afa15801561203d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561206657600080fd5b8101908080516040519392919084600160201b82111561208557600080fd5b90830190602082018581111561209a57600080fd5b82518660208202830111600160201b821117156120b657600080fd5b82525081516020918201928201910280838360005b838110156120e35781810151838201526020016120cb565b50505050905001604052505050905060008090505b815181101561223c57600082828151811061210f57fe5b602002602001015190506000601a6000876001600160a01b03166001600160a01b031681526020019081526020016000206001016000836001600160a01b03166001600160a01b0316815260200190815260200160002054905060006121b6826019600088888151811061217f57fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054613cfc90919063ffffffff16565b9050806121c557505050612234565b6001600160a01b038088166000908152601460209081526040808320938716835260039093019052908120549061221a670de0b6b3a764000061220e848663ffffffff614e0516565b9063ffffffff614e5e16565b905061222c888263ffffffff61405316565b975050505050505b6001016120f8565b5050919050565b600060016001600160a01b038316600090815260146020526040902060049081015460ff169081111561227257fe5b1492915050565b815183511461228757600080fd5b805182511461229557600080fd5b60005b82518110156122ed576122e58482815181106122b057fe5b60200260200101518483815181106122c457fe5b60200260200101518484815181106122d857fe5b6020026020010151614ea0565b600101612298565b50505050565b6002546001600160a01b031681565b6006546001600160a01b031681565b6000611e78614f5e565b600080612326614f79565b9050600061233c670ddd4b8c6c7d70d883614f95565b905061235f670de0b6b3a764000061220e83601254614e0590919063ffffffff16565b9250505090565b6000611b046123736124e4565b8361504a565b60c881565b680ad78ebc5ac620000081565b601b5490565b612399613ca2565b80518251146123a757600080fd5b6001600160a01b038316600090815260146020908152604090912083516123d092850190615d9c565b506001600160a01b038316600090815260146020908152604090912082516122ed92600190920191840190615d51565b6001600160a01b039182166000908152601a602090815260408083209390941682526001909201909152205490565b6007546001600160a01b031690565b6714d1120d7b16000081565b600d546001600160a01b031681565b612461613ca2565b80600481111561246d57fe5b6001600160a01b038316600090815260146020526040902060049081018054909160ff199091169060019084908111156124a357fe5b02179055505050565b6124b4613ca2565b60006124be61231b565b9050670de0b6b3a7640000811115611f3b57fe5b603c81565b6000611b04612373613930565b6000611e786124f161231b565b615068565b670de0b6b3a764000081565b61250a61480f565b611d9486868686868661508f565b600080600160009054906101000a90046001600160a01b03166001600160a01b0316638df709926040518163ffffffff1660e01b815260040160206040518083038186803b15801561256957600080fd5b505afa15801561257d573d6000803e3d6000fd5b505050506040513d602081101561259357600080fd5b5051600254604080516346fb84c960e11b815290519293506000926001600160a01b0390921691638df7099291600480820192602092909190829003018186803b1580156125e057600080fd5b505afa1580156125f4573d6000803e3d6000fd5b505050506040513d602081101561260a57600080fd5b5051905061235f828263ffffffff61405316565b6001546001600160a01b031681565b612635613ca2565b611aa981615242565b600080600160009054906101000a90046001600160a01b03166001600160a01b03166301d40b636040518163ffffffff1660e01b815260040160206040518083038186803b15801561268f57600080fd5b505afa1580156126a3573d6000803e3d6000fd5b505050506040513d60208110156126b957600080fd5b5051600254604080516301d40b6360e01b815290519293506000926001600160a01b03909216916301d40b6391600480820192602092909190829003018186803b1580156125e057600080fd5b6003546001600160a01b031690565b606080612720615d37565b61272984613d45565b8051602090910151909350915050915091565b6003546001600160a01b0316331490565b61275561480f565b6011546040516304f7e4f160e51b81526001600160a01b03858116600483019081526060602484019081528651606485015286519290941693639efc9e2093889388938893909290916044820191608401906020808801910280838360005b838110156127cc5781810151838201526020016127b4565b50505050905001838103825284818151815260200191508051906020019060200280838360005b8381101561280b5781810151838201526020016127f3565b5050505090500195505050505050600060405180830381600087803b15801561283357600080fd5b505af1158015612847573d6000803e3d6000fd5b50505050505050565b6001600160a01b03811660009081526014602090815260409182902080548351818402810184019094528084526060938493600184019284918301828280156128c257602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116128a4575b505050505091508080548060200260200160405190810160405280929190818152602001828054801561291457602002820191906000526020600020905b815481526020019060010190808311612900575b5050505050905091509150915091565b600061292e613ca2565b6001600160a01b038316600090815260146020526040812060020154611ae2908463ffffffff61405316565b601d6020526000908152604090205481565b6009546001600160a01b031690565b6040518060400160405280600c81526020016b2a3937bb32a6b0b730b3b2b960a11b81525081565b6010546001600160a01b031681565b60166020526000908152604090205481565b6000611e78615406565b6004546001600160a01b031681565b6001600160a01b039182166000908152601a6020908152604080832093909416825291909152205490565b612a1061480f565b611aa981615429565b612a21614665565b611aa981600461486a565b6212750081565b6000611e78612a4061231b565b614cfd565b612a10614665565b6001600160a01b0381166000908152601460209081526040808320815181546060948102820185018452928101838152611b049491938492849190840182828015612ac157602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612aa3575b5050505050815260200160018201805480602002602001604051908101604052809291908181526020018280548015612b1957602002820191906000526020600020905b815481526020019060010190808311612b05575b50505050508152505061554b565b670ddd4b8c6c7d70d881565b612b3b613ca2565b611aa981600261486a565b6001600160a01b031660009081526019602052604090205490565b60135481565b6000611b04612b74612a33565b8361563a565b6001600160a01b031660009081526014602052604090206002015490565b6000601b8281548110612ba757fe5b6000918252602090912001546001600160a01b031692915050565b612bca61273c565b612c1b576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b612c248d6156a7565b612c2d8c6156a7565b612c368b6156a7565b612c3f8a6156a7565b612c48896156a7565b612c51886156a7565b612c5a876156a7565b612c63866156a7565b612c6c856156a7565b612c75846156a7565b612c7e836156a7565b612c87826156a7565b612c90816156a7565b8c600460006101000a8154816001600160a01b0302191690836001600160a01b031602179055508b600160006101000a8154816001600160a01b0302191690836001600160a01b031602179055508a600260006101000a8154816001600160a01b0302191690836001600160a01b0316021790555089600560006101000a8154816001600160a01b0302191690836001600160a01b03160217905550826000806101000a8154816001600160a01b0302191690836001600160a01b0316021790555088600c60006101000a8154816001600160a01b0302191690836001600160a01b0316021790555087601160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555086600760006101000a8154816001600160a01b0302191690836001600160a01b0316021790555085601060006101000a8154816001600160a01b0302191690836001600160a01b0316021790555084600860006101000a8154816001600160a01b0302191690836001600160a01b0316021790555083600960006101000a8154816001600160a01b0302191690836001600160a01b0316021790555081600e60006101000a8154816001600160a01b0302191690836001600160a01b0316021790555080600f60006101000a8154816001600160a01b0302191690836001600160a01b0316021790555081600a60006101000a8154816001600160a01b0302191690836001600160a01b0316021790555080600b60006101000a8154816001600160a01b0302191690836001600160a01b03160217905550612ee0615756565b50505050505050505050505050565b60196020526000908152604090205481565b6001600160a01b0391821660009081526014602090815260408083209390941682526003909201909152205490565b60176020526000908152604090205481565b6008546001600160a01b031690565b60156020526000908152604090205481565b612f6b61480f565b60005b825181101561311e576000838281518110612f8557fe5b6020908102919091018101516001600160a01b03811660009081526015835260408082205460169094528120929092558451909250849084908110612fc657fe5b602002602001015190506000866001600160a01b0316639b56d6c9846040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561302857600080fd5b505afa15801561303c573d6000803e3d6000fd5b505050506040513d602081101561305257600080fd5b505160025460408051639b56d6c960e01b81526001600160a01b03878116600483015291519394506000939190921691639b56d6c9916024808301926020929190829003018186803b1580156130a757600080fd5b505afa1580156130bb573d6000803e3d6000fd5b505050506040513d60208110156130d157600080fd5b505190506130f5816130e9848663ffffffff613cfc16565b9063ffffffff61405316565b6001600160a01b0394909416600090815260176020526040902093909355505050600101612f6e565b506040805142815290517f523f4c1c183d46bec16040588c9c0aee1cbce44d14a4499539c18ef5761b6c3d9181900360200190a1505050565b600060016001600160a01b038316600090815260146020526040902060049081015460ff169081111561318657fe5b1461319357506000611d31565b6001600160a01b0382166000908152601460209081526040918290208054835181840281018401909452808452606093928301828280156131fd57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116131df575b50939450600093505050505b815181101561327b57600082828151811061322057fe5b6020908102919091018101516001600160a01b03808216600081815260188552604080822054938b168252601a8652808220928252919094529092205490925010156132725760019350505050611d31565b50600101613209565b5060009392505050565b61328d61480f565b80518251146132dc576040805162461bcd60e51b8152602060048201526016602482015275544d3a206c656e20746f6b656e7320616d6f756e747360501b604482015290519081900360640190fd5b826132e657613886565b60006132f283836157a0565b905060005b83518110156136b757600084828151811061330e57fe5b60200260200101519050600084838151811061332657fe5b60209081029190910181015160008054604080516305c5635160e31b81526001600160a01b0388811660048301526024820186905291519496509294911692632e2b1a88926044808201939291829003018186803b15801561338757600080fd5b505afa15801561339b573d6000803e3d6000fd5b505050506040513d60208110156133b157600080fd5b5051905060006133cb8661220e848c63ffffffff614e0516565b90506000846001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561340857600080fd5b505afa15801561341c573d6000803e3d6000fd5b505050506040513d602081101561343257600080fd5b50516001600160a01b0386166000908152601c602052604081205460ff90921692509061346d906130e987600a86900a63ffffffff614e0516565b6001600160a01b0387166000908152601d6020526040812054919250906134a6906130e986670de0b6b3a764000063ffffffff614e0516565b6001600160a01b038816600090815260156020526040902054909150156136a4576001600160a01b0387166000908152601560205260408120546134f190849063ffffffff614e5e16565b6001600160a01b0389166000908152601560205260408120549192509061353690613529906012889003600a0a63ffffffff614e0516565b849063ffffffff614e5e16565b6001600160a01b038a166000908152601560205260409020549091506135749061356790849063ffffffff614e0516565b859063ffffffff613cfc16565b6001600160a01b038a166000908152601c60209081526040808320939093556015905220546135d2906135c5906135b8906012899003600a0a63ffffffff614e0516565b839063ffffffff614e0516565b849063ffffffff613cfc16565b6001600160a01b038a166000908152601d6020908152604080832093909355601890522054613607908363ffffffff61405316565b6001600160a01b038a1660009081526018602090815260408083209390935560199052205461363c908263ffffffff61405316565b6001600160a01b038a16600081815260196020818152604080842086905560188252928390205491815282519384528301528181019290925290517f6f63d00bdf85957664165c9e20900aabd5a17378cb5c0955ce760e48a6ae48c79181900360600190a150505b5050600190950194506132f79350505050565b50856001600160a01b031663e7b1d678856040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b1580156136fe57600080fd5b505af1158015613712573d6000803e3d6000fd5b50505050846001600160a01b031663420429ca856040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561375c57600080fd5b505af1158015613770573d6000803e3d6000fd5b50505050856001600160a01b031663d0d8c20d8685856040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b031681526020018060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156137f15781810151838201526020016137d9565b50505050905001838103825284818151815260200191508051906020019060200280838360005b83811015613830578181015183820152602001613818565b5050505090500195505050505050602060405180830381600087803b15801561385857600080fd5b505af115801561386c573d6000803e3d6000fd5b505050506040513d602081101561388257600080fd5b5050505b5050505050565b600b546040805163e369e4ab60e01b81526001600160a01b0384811660248301526004820192835285516044830152855193169263e369e4ab92869286928291606401906020808701910280838360005b838110156138f65781810151838201526020016138de565b505050509050019350505050600060405180830381600087803b15801561391c57600080fd5b505af1158015611d94573d6000803e3d6000fd5b6000611e78601254615068565b600e546001600160a01b031681565b612a10613ca2565b6001600160a01b031660009081526018602052604090205490565b6004546001600160a01b03163314806139925750600e546001600160a01b031633145b6139d8576040805162461bcd60e51b81526020600482015260126024820152712a269d1024b73b30b634b21021b0b63632b960711b604482015290519081900360640190fd5b565b6139e381613157565b15613c9d576139f181614d33565b6139f9615d37565b613a0282613d45565b90506000613a0f83611fa9565b6001600160a01b038416600090815260146020908152604091829020825181546060938102820184018552938101848152949550613aef949093919284928491840182828015613a8857602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311613a6a575b5050505050815260200160018201805480602002602001604051908101604052809291908181526020018280548015613ae057602002820191906000526020600020905b815481526020019060010190808311613acc575b505050505081525050836140ad565b6001600160a01b0384166000908152601460209081526040909120825180519192613b1f92849290910190615d9c565b506020828101518051613b389260018501920190615d51565b5050506001600160a01b038316600090815260146020526040902060020154613b67908263ffffffff61405316565b6001600160a01b038416600090815260146020526040902060020155613b8c83615242565b613ba2858583856000015186602001518861508f565b6001600160a01b03831660008181526014602090815260408083206002810154825181815260608101869052608094810185815283549582018690527f98c96bbf8d2aa6be678259387225d169084fca483ed9598bde8ea258036bcacf969295939460018601949083019060a084019087908015613c4957602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311613c2b575b50508381038252858181548152602001915080548015613c8857602002820191906000526020600020905b815481526020019060010190808311613c74575b5050965050505050505060405180910390a250505b505050565b6004546001600160a01b031633146139d8576040805162461bcd60e51b8152602060048201526018602482015277544d3a206d7573742062652063616c6c656420627920424f60401b604482015290519081900360640190fd5b6000613d3e83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506158d3565b9392505050565b613d4d615d37565b60016001600160a01b038316600090815260146020526040902060049081015460ff1690811115613d7a57fe5b14613d8e57613d87615d37565b9050611d31565b6000805460408051634eb5750560e11b815290516060936001600160a01b0390931692639d6aea0a9260048082019391829003018186803b158015613dd257600080fd5b505afa158015613de6573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015613e0f57600080fd5b8101908080516040519392919084600160201b821115613e2e57600080fd5b908301906020820185811115613e4357600080fd5b82518660208202830111600160201b82111715613e5f57600080fd5b82525081516020918201928201910280838360005b83811015613e8c578181015183820152602001613e74565b505050509050016040525050509050805167ffffffffffffffff81118015613eb357600080fd5b50604051908082528060200260200182016040528015613edd578160200160208202803683370190505b50602083015280825260005b815181101561223c576000828281518110613f0057fe5b6020908102919091018101516001600160a01b038088166000908152601a8452604080822092841682529184528181205460189094529081205491935090613f4e908363ffffffff613cfc16565b905080613f7b57600086602001518581518110613f6757fe5b60200260200101818152505050505061404b565b6001600160a01b0380881660009081526014602090815260408083209387168084526003909401825280832054815163313ce56760e01b8152915190949263313ce5679260048082019391829003018186803b158015613fda57600080fd5b505afa158015613fee573d6000803e3d6000fd5b505050506040513d602081101561400457600080fd5b505160ff1690506000614025600a83900a61220e858763ffffffff614e0516565b9050808960200151888151811061403857fe5b6020026020010181815250505050505050505b600101613ee9565b600082820183811015613d3e576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6140b5615d37565b6140bd615d37565b6000805460408051634eb5750560e11b815290516001600160a01b0390921692639d6aea0a92600480840193829003018186803b1580156140fd57600080fd5b505afa158015614111573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561413a57600080fd5b8101908080516040519392919084600160201b82111561415957600080fd5b90830190602082018581111561416e57600080fd5b82518660208202830111600160201b8211171561418a57600080fd5b82525081516020918201928201910280838360005b838110156141b757818101518382015260200161419f565b5050505091909101604052505050818352505167ffffffffffffffff811180156141e057600080fd5b5060405190808252806020026020018201604052801561420a578160200160208202803683370190505b5060208201526000805b8551518110156143275760008054875180516001600160a01b039092169163b31610db91908590811061424357fe5b60200260200101516040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561429157600080fd5b505afa1580156142a5573d6000803e3d6000fd5b505050506040513d60208110156142bb57600080fd5b505160208801518051919250600091849081106142d457fe5b6020026020010151111561431e5760208701518051600190940193839081106142f957fe5b60200260200101518460200151828151811061431157fe5b6020026020010181815250505b50600101614214565b5060005b8451518110156144875760008054865180516001600160a01b039092169163b31610db91908590811061435a57fe5b60200260200101516040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156143a857600080fd5b505afa1580156143bc573d6000803e3d6000fd5b505050506040513d60208110156143d257600080fd5b505160208701518051919250600091849081106143eb57fe5b6020026020010151111561447e578360200151818151811061440957fe5b602002602001015160001415614420576001909201915b6144618660200151838151811061443357fe5b60200260200101518560200151838151811061444b57fe5b602002602001015161405390919063ffffffff16565b8460200151828151811061447157fe5b6020026020010181815250505b5060010161432b565b5060608167ffffffffffffffff811180156144a157600080fd5b506040519080825280602002602001820160405280156144cb578160200160208202803683370190505b50905060608267ffffffffffffffff811180156144e757600080fd5b50604051908082528060200260200182016040528015614511578160200160208202803683370190505b5090506000805b8551518110156145b85760008660200151828151811061453457fe5b602002602001015111156145b057855180518290811061455057fe5b602002602001015184838151811061456457fe5b6001600160a01b0390921660209283029190910182015286015180518290811061458a57fe5b602002602001015183838151811061459e57fe5b60209081029190910101526001909101905b600101614518565b5050908452602084015250909392505050565b601b80546001808201835560008381527f3ad8aa4f87544323a9d1e5dd902f40c356527a7955687113db5f9a85ad579dc190920180546001600160a01b0319166001600160a01b038616179055915490916146269190613cfc565b6001600160a01b039290921660009081526014602052604090206004018054610100600160881b0319166101006001600160801b038516021790555090565b600e546001600160a01b031633146139d8576040805162461bcd60e51b81526020600482015260196024820152782a269d1036bab9ba1031329031b0b63632b210313c902a26a960391b604482015290519081900360640190fd5b60005b6001600160a01b038216600090815260146020526040902054811015611ee0576001600160a01b038216600090815260146020526040812080548390811061470757fe5b60009182526020808320909101546001600160a01b0386811684526014909252604083206001018054929091169350908490811061474157fe5b90600052602060002001549050600061475a838361596a565b6001600160a01b038681166000908152601460209081526040808320938816835260039093018152828220805490859055601590915291902054919250906147a89083906130e99084613cfc565b6001600160a01b038516600081815260156020908152604091829020849055815192835282019290925281517fd5630907014190fb9340da1cf427c96f094dabfbf73d25506e4b0cda9e3a4ca0929181900390910190a15050600190920191506146c39050565b600f546001600160a01b031633146139d8576040805162461bcd60e51b815260206004820152601960248201527815134e881b5d5cdd0818994818d85b1b195908189e48151353603a1b604482015290519081900360640190fd5b600081600481111561487857fe5b141580156148925750600181600481111561488f57fe5b14155b61489857fe5b601b546148a4816159ea565b6148ac615d37565b6001600160a01b038416600090815260146020526040902060049081018054859260ff199091169060019084908111156148e257fe5b02179055506001600160a01b0384166000908152601460209081526040909120825180518493614916928492910190615d9c565b50602082810151805161492f9260018501920190615d51565b5050506001600160a01b0380851660009081526014602052604080822060020182905581548151634eb5750560e11b815291516060949190911692639d6aea0a9260048082019391829003018186803b15801561498b57600080fd5b505afa15801561499f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260208110156149c857600080fd5b8101908080516040519392919084600160201b8211156149e757600080fd5b9083019060208201858111156149fc57600080fd5b82518660208202830111600160201b82111715614a1857600080fd5b82525081516020918201928201910280838360005b83811015614a45578181015183820152602001614a2d565b50505050905001604052505050905060008090505b8151811015614b1b576001600160a01b0386166000908152601a6020526040812083518290859085908110614a8b57fe5b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020819055506000601a6000886001600160a01b03166001600160a01b031681526020019081526020016000206001016000848481518110614aef57fe5b6020908102919091018101516001600160a01b0316825281019190915260400160002055600101614a5a565b50614b268584615aaa565b60105460408051631484968760e11b81526001600160a01b038881166004830152915191909216916329092d0e91602480830192600092919082900301818387803b158015614b7457600080fd5b505af1158015614b88573d6000803e3d6000fd5b505050505050505050565b614b9b615d37565b6000614ba5615d37565b614bae84613d45565b90506000614bbb85611fa9565b6001600160a01b03861660009081526014602052604081206002015491925090614beb908363ffffffff61405316565b9050614bf5615d37565b6001600160a01b038716600090815260146020908152604091829020825181546060938102820184018552938101848152614cd094919384928491840182828015614c6957602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311614c4b575b5050505050815260200160018201805480602002602001604051908101604052809291908181526020018280548015614cc157602002820191906000526020600020905b815481526020019060010190808311614cad575b505050505081525050856140ad565b9550909350505050915091565b600080614ce98461554b565b9050614cf58184615c51565b949350505050565b6000611b04614d25836103e8670de0b6b3a76400005b0460050261405390919063ffffffff16565b670de0b6b3a7640000615c89565b60016001600160a01b038216600090815260146020526040902060049081015460ff1690811115614d6057fe5b14611aa9576040805162461bcd60e51b815260206004820152601460248201527315134e881d1c9bdd99481b5d5cdd08195e1a5cdd60621b604482015290519081900360640190fd5b6000614dc060135442613cfc90919063ffffffff16565b9050603c8110611aa95742601381905560408051918252517f860f8d2f0c74dd487e89e2883e3b25b8159ce1e1b3433a291cba7b82c508f3bc9181900360200190a150565b600082614e1457506000611b04565b82820282848281614e2157fe5b0414613d3e5760405162461bcd60e51b8152600401808060200182810382526021815260200180615e3c6021913960400191505060405180910390fd5b6000613d3e83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250615c9f565b6000606080614eae86611b0a565b505050925092509250614ebf615d37565b828152602081018290526000614ed58286614cdd565b6010546040805163015f109360e51b81526001600160a01b038c81166004830152602482018590528b811660448301528a811660648301529151939450911691632be212609160848082019260009290919082900301818387803b158015614f3c57600080fd5b505af1158015614f50573d6000803e3d6000fd5b505050505050505050505050565b600080614f69615406565b6714d1120d7b1600001191505090565b6000611e78603c61220e60135442613cfc90919063ffffffff16565b6000631f540500821115614fab57631f54050091505b81614fbf5750670de0b6b3a7640000611b04565b670de0b6b3a764000083835b6001811115615036576002810661500057614fe68283615d04565b9150614ff981600263ffffffff614e5e16565b9050615031565b61500a8284615d04565b92506150168283615d04565b915061502e600261220e83600163ffffffff613cfc16565b90505b614fcb565b6150408284615d04565b9695505050505050565b6000613d3e670de0b6b3a764000061220e858563ffffffff614e0516565b6000611b04615082836103e8670de0b6b3a7640000614d13565b66b1a2bc2ec50000615c89565b846001600160a01b031663e7b1d678856040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b1580156150d557600080fd5b505af11580156150e9573d6000803e3d6000fd5b50505050856001600160a01b031663420429ca856040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561513357600080fd5b505af1158015615147573d6000803e3d6000fd5b5050604051630c39994b60e31b81526001600160a01b038481166044830152606060048301908152875160648401528751918a1694506361ccca5893508792879287929182916024820191608401906020808901910280838360005b838110156151bb5781810151838201526020016151a3565b50505050905001838103825285818151815260200191508051906020019060200280838360005b838110156151fa5781810151838201526020016151e2565b5050505090500195505050505050600060405180830381600087803b15801561522257600080fd5b505af1158015615236573d6000803e3d6000fd5b50505050505050505050565b6000805460408051634eb5750560e11b815290516060936001600160a01b0390931692639d6aea0a9260048082019391829003018186803b15801561528657600080fd5b505afa15801561529a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260208110156152c357600080fd5b8101908080516040519392919084600160201b8211156152e257600080fd5b9083019060208201858111156152f757600080fd5b82518660208202830111600160201b8211171561531357600080fd5b82525081516020918201928201910280838360005b83811015615340578181015183820152602001615328565b50505050905001604052505050905060008090505b81518110156153ce57600082828151811061536c57fe5b6020908102919091018101516001600160a01b039081166000818152601884526040808220549389168252601a855280822092825282855280822093909355601984528281205460019283019094529190912091909155919091019050615355565b506040805142815290517f82bbdd533bb4dbd06fe175bb28e15f2391ffb6124331ff8f7066153c385baacb9181900360200190a15050565b60008061541161263e565b9050600061541d612518565b905061235f8282615c51565b6001600160a01b03811660009081526014602090815260409182902080548351818402810184019094528084526060939283018282801561549357602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311615475575b50939450600093505050505b8151811015613c9d5760008282815181106154b657fe5b6020908102919091018101516001600160a01b0380871660009081526014845260408082209284168252600390920184528181205460159094522054909250615505908263ffffffff613cfc16565b6001600160a01b0392831660008181526015602090815260408083209490945594881681526014855282812091815260039091019093528220919091555060010161549f565b6000805b8251518110156156345760008054845180516001600160a01b0390921691632e2b1a8891908590811061557e57fe5b60200260200101518660200151858151811061559657fe5b60200260200101516040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b031681526020018281526020019250505060206040518083038186803b1580156155eb57600080fd5b505afa1580156155ff573d6000803e3d6000fd5b505050506040513d602081101561561557600080fd5b50519050615629838263ffffffff61405316565b92505060010161554f565b50919050565b600080615659670de0b6b3a764000061220e868663ffffffff614e0516565b9050828110613d3e576040805162461bcd60e51b8152602060048201526015602482015274544d3a4665653e72657475726e656420636f6c6c7360581b604482015290519081900360640190fd5b6001600160a01b038116615702576040805162461bcd60e51b815260206004820152601e60248201527f4163636f756e742063616e6e6f74206265207a65726f20616464726573730000604482015290519081900360640190fd5b803b80611ee0576040805162461bcd60e51b815260206004820181905260248201527f4163636f756e7420636f64652073697a652063616e6e6f74206265207a65726f604482015290519081900360640190fd5b6003546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600380546001600160a01b0319169055565b600081518351146157ea576040805162461bcd60e51b815260206004820152600f60248201526e09cdee840e6c2daca40d8cadccee8d608b1b604482015290519081900360640190fd5b60005b83518110156158cc576000805485516001600160a01b0390911690632e2b1a889087908590811061581a57fe5b602002602001015186858151811061582e57fe5b60200260200101516040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b031681526020018281526020019250505060206040518083038186803b15801561588357600080fd5b505afa158015615897573d6000803e3d6000fd5b505050506040513d60208110156158ad57600080fd5b505190506158c1838263ffffffff61405316565b9250506001016157ed565b5092915050565b600081848411156159625760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561592757818101518382015260200161590f565b50505050905090810190601f1680156159545780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6001600160a01b0382166000908152601760205260408120548190615990575081613d3e565b6001600160a01b0384166000908152601660205260409020546159af57fe5b6001600160a01b038416600090815260176020908152604080832054601690925290912054614cf5919061220e90869063ffffffff614e0516565b600181118015615a6857506010546040805163de8fa43160e01b815290516001926001600160a01b03169163de8fa431916004808301926020929190829003018186803b158015615a3a57600080fd5b505afa158015615a4e573d6000803e3d6000fd5b505050506040513d6020811015615a6457600080fd5b5051115b611aa9576040805162461bcd60e51b815260206004820152600e60248201526d544d3a206c6173742074726f766560901b604482015290519081900360640190fd5b6001600160a01b03821660009081526014602052604081206004015460ff1690816004811115615ad657fe5b14158015615af057506001816004811115615aed57fe5b14155b615af657fe5b6001600160a01b03831660009081526014602052604081206004015461010090046001600160801b0316908390615b2e826001613cfc565b905080836001600160801b03161115615b4357fe5b6000601b8281548110615b5257fe5b600091825260209091200154601b80546001600160a01b03909216925082916001600160801b038716908110615b8457fe5b600091825260208083209190910180546001600160a01b0319166001600160a01b03948516179055918316808252601483526040918290206004018054610100600160881b0319166101006001600160801b038a169081029190911790915582519182529281019290925280517f02b04ae5f7be9ca7c103293a2aa15f3c339d15d6eda53b721fef7b0e609c831a9281900390910190a1601b805480615c2657fe5b600082815260209020810160001990810180546001600160a01b031916905501905550505050505050565b60008115615c80576000615c778361220e86670de0b6b3a764000063ffffffff614e0516565b9150611b049050565b50600019611b04565b6000818310615c985781613d3e565b5090919050565b60008183615cee5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561592757818101518382015260200161590f565b506000838581615cfa57fe5b0495945050505050565b600080615d17848463ffffffff614e0516565b9050614cf5670de0b6b3a764000061220e836706f05b59d3b20000614053565b604051806040016040528060608152602001606081525090565b828054828255906000526020600020908101928215615d8c579160200282015b82811115615d8c578251825591602001919060010190615d71565b50615d98929150615dfd565b5090565b828054828255906000526020600020908101928215615df1579160200282015b82811115615df157825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190615dbc565b50615d98929150615e17565b611a8191905b80821115615d985760008155600101615e03565b611a8191905b80821115615d985780546001600160a01b0319168155600101615e1d56fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a26469706673582212203d45b3769312319278d38fb6f401f91112a76e373f40bb924461490cc733fdcf64736f6c634300060b0033

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