ETH Price: $3,468.56 (+1.99%)

Contract

0xfED77055B40d63DCf17ab250FFD6948FBFF57B82
 

Overview

ETH Balance

13 wei

Eth Value

Less Than $0.01 (@ $3,468.56/ETH)

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Liquidate Unclos...127208412021-06-28 6:08:551276 days ago1624860535IN
Synthetix: EtherCollateral sUSD Trial
0 ETH0.0040094412
Close Loan127203722021-06-28 4:27:081276 days ago1624854428IN
Synthetix: EtherCollateral sUSD Trial
0 ETH0.0036066112.4
Close Loan126816072021-06-22 3:27:351282 days ago1624332455IN
Synthetix: EtherCollateral sUSD Trial
0 ETH0.0135176932
Withdraw Collate...126815892021-06-22 3:21:101282 days ago1624332070IN
Synthetix: EtherCollateral sUSD Trial
0 ETH0.0091268832
Repay Loan126815742021-06-22 3:17:381282 days ago1624331858IN
Synthetix: EtherCollateral sUSD Trial
0 ETH0.012025432
Withdraw Collate...126808742021-06-22 0:44:501282 days ago1624322690IN
Synthetix: EtherCollateral sUSD Trial
0 ETH0.0176833362
Repay Loan126808182021-06-22 0:32:281282 days ago1624321948IN
Synthetix: EtherCollateral sUSD Trial
0 ETH0.034197891
Close Loan126807942021-06-22 0:27:491282 days ago1624321669IN
Synthetix: EtherCollateral sUSD Trial
0 ETH0.0368093587
Close Loan126807782021-06-22 0:24:421282 days ago1624321482IN
Synthetix: EtherCollateral sUSD Trial
0 ETH0.0414506698
Close Loan126787122021-06-21 16:29:191282 days ago1624292959IN
Synthetix: EtherCollateral sUSD Trial
0 ETH0.010383231
Close Loan126745882021-06-21 0:49:111283 days ago1624236551IN
Synthetix: EtherCollateral sUSD Trial
0 ETH0.0033481810
Close Loan126745682021-06-21 0:46:111283 days ago1624236371IN
Synthetix: EtherCollateral sUSD Trial
0 ETH0.002342737
Close Loan126732092021-06-20 19:55:291283 days ago1624218929IN
Synthetix: EtherCollateral sUSD Trial
0 ETH0.009374428
Close Loan126627472021-06-19 4:45:291285 days ago1624077929IN
Synthetix: EtherCollateral sUSD Trial
0 ETH0.0031994811
Close Loan126621362021-06-19 2:25:511285 days ago1624069551IN
Synthetix: EtherCollateral sUSD Trial
0 ETH0.0044116211
Close Loan126584062021-06-18 12:32:101285 days ago1624019530IN
Synthetix: EtherCollateral sUSD Trial
0 ETH0.0053568916
Close Loan126495102021-06-17 3:28:281287 days ago1623900508IN
Synthetix: EtherCollateral sUSD Trial
0 ETH0.0068089917
Close Loan126289562021-06-13 22:59:341290 days ago1623625174IN
Synthetix: EtherCollateral sUSD Trial
0 ETH0.0037177811.1
Close Loan126191102021-06-12 10:26:011292 days ago1623493561IN
Synthetix: EtherCollateral sUSD Trial
0 ETH0.0035696310
Close Loan126190622021-06-12 10:15:121292 days ago1623492912IN
Synthetix: EtherCollateral sUSD Trial
0 ETH0.003494459.8
Close Loan126175482021-06-12 4:22:191292 days ago1623471739IN
Synthetix: EtherCollateral sUSD Trial
0 ETH0.003367828.4
Close Loan126080872021-06-10 17:22:051293 days ago1623345725IN
Synthetix: EtherCollateral sUSD Trial
0 ETH0.0049697812.4
Close Loan126047082021-06-10 4:53:101294 days ago1623300790IN
Synthetix: EtherCollateral sUSD Trial
0 ETH0.0029086210
Close Loan125895432021-06-07 20:24:551296 days ago1623097495IN
Synthetix: EtherCollateral sUSD Trial
0 ETH0.0046391113
Close Loan125788772021-06-06 4:53:481298 days ago1622955228IN
Synthetix: EtherCollateral sUSD Trial
0 ETH0.0031674210.89
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block
From
To
127208412021-06-28 6:08:551276 days ago1624860535
Synthetix: EtherCollateral sUSD Trial
0.00010424 ETH
127208412021-06-28 6:08:551276 days ago1624860535
Synthetix: EtherCollateral sUSD Trial
0.00000575 ETH
127207522021-06-28 5:46:441276 days ago1624859204
Synthetix: EtherCollateral sUSD Trial
0.94425816 ETH
127207522021-06-28 5:46:441276 days ago1624859204
Synthetix: EtherCollateral sUSD Trial
0.05574183 ETH
127207522021-06-28 5:46:441276 days ago1624859204
Synthetix: EtherCollateral sUSD Trial
0.54346195 ETH
127207522021-06-28 5:46:441276 days ago1624859204
Synthetix: EtherCollateral sUSD Trial
0.07820714 ETH
127207522021-06-28 5:46:441276 days ago1624859204
Synthetix: EtherCollateral sUSD Trial
0.7719653 ETH
127207522021-06-28 5:46:441276 days ago1624859204
Synthetix: EtherCollateral sUSD Trial
0.11144301 ETH
127207522021-06-28 5:46:441276 days ago1624859204
Synthetix: EtherCollateral sUSD Trial
0.40902014 ETH
127207522021-06-28 5:46:441276 days ago1624859204
Synthetix: EtherCollateral sUSD Trial
0.59097985 ETH
127207522021-06-28 5:46:441276 days ago1624859204
Synthetix: EtherCollateral sUSD Trial
6.31343623 ETH
127207522021-06-28 5:46:441276 days ago1624859204
Synthetix: EtherCollateral sUSD Trial
0.68656376 ETH
127207522021-06-28 5:46:441276 days ago1624859204
Synthetix: EtherCollateral sUSD Trial
0.99197534 ETH
127207522021-06-28 5:46:441276 days ago1624859204
Synthetix: EtherCollateral sUSD Trial
0.85802465 ETH
127207522021-06-28 5:46:441276 days ago1624859204
Synthetix: EtherCollateral sUSD Trial
0.96357373 ETH
127207522021-06-28 5:46:441276 days ago1624859204
Synthetix: EtherCollateral sUSD Trial
0.5574183 ETH
127207522021-06-28 5:46:441276 days ago1624859204
Synthetix: EtherCollateral sUSD Trial
0.79086156 ETH
127207522021-06-28 5:46:441276 days ago1624859204
Synthetix: EtherCollateral sUSD Trial
1.08214641 ETH
127207522021-06-28 5:46:441276 days ago1624859204
Synthetix: EtherCollateral sUSD Trial
5.77298009 ETH
127207522021-06-28 5:46:441276 days ago1624859204
Synthetix: EtherCollateral sUSD Trial
3.34450982 ETH
127207522021-06-28 5:46:441276 days ago1624859204
Synthetix: EtherCollateral sUSD Trial
6.99547102 ETH
127207522021-06-28 5:46:441276 days ago1624859204
Synthetix: EtherCollateral sUSD Trial
8.36988087 ETH
127207522021-06-28 5:46:441276 days ago1624859204
Synthetix: EtherCollateral sUSD Trial
8.12327136 ETH
127207522021-06-28 5:46:441276 days ago1624859204
Synthetix: EtherCollateral sUSD Trial
0.87672863 ETH
127207522021-06-28 5:46:441276 days ago1624859204
Synthetix: EtherCollateral sUSD Trial
8.88483965 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
EtherCollateralsUSD

Compiler Version
v0.5.16+commit.9c3226ce

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2020-09-24
*/

/*
   ____            __   __        __   _
  / __/__ __ ___  / /_ / /  ___  / /_ (_)__ __
 _\ \ / // // _ \/ __// _ \/ -_)/ __// / \ \ /
/___/ \_, //_//_/\__//_//_/\__/ \__//_/ /_\_\
     /___/

* Synthetix: EtherCollateralsUSD.sol
*
* Latest source (may be newer): https://github.com/Synthetixio/synthetix/blob/master/contracts/EtherCollateralsUSD.sol
* Docs: https://docs.synthetix.io/contracts/EtherCollateralsUSD
*
* Contract Dependencies: 
*	- IAddressResolver
*	- IEtherCollateralsUSD
*	- MixinResolver
*	- Owned
*	- Pausable
*	- ReentrancyGuard
* Libraries: 
*	- SafeDecimalMath
*	- SafeMath
*
* MIT License
* ===========
*
* Copyright (c) 2020 Synthetix
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
*/



pragma solidity ^0.5.16;


// https://docs.synthetix.io/contracts/Owned
contract Owned {
    address public owner;
    address public nominatedOwner;

    constructor(address _owner) public {
        require(_owner != address(0), "Owner address cannot be 0");
        owner = _owner;
        emit OwnerChanged(address(0), _owner);
    }

    function nominateNewOwner(address _owner) external onlyOwner {
        nominatedOwner = _owner;
        emit OwnerNominated(_owner);
    }

    function acceptOwnership() external {
        require(msg.sender == nominatedOwner, "You must be nominated before you can accept ownership");
        emit OwnerChanged(owner, nominatedOwner);
        owner = nominatedOwner;
        nominatedOwner = address(0);
    }

    modifier onlyOwner {
        _onlyOwner();
        _;
    }

    function _onlyOwner() private view {
        require(msg.sender == owner, "Only the contract owner may perform this action");
    }

    event OwnerNominated(address newOwner);
    event OwnerChanged(address oldOwner, address newOwner);
}


// Inheritance


// https://docs.synthetix.io/contracts/Pausable
contract Pausable is Owned {
    uint public lastPauseTime;
    bool public paused;

    constructor() internal {
        // This contract is abstract, and thus cannot be instantiated directly
        require(owner != address(0), "Owner must be set");
        // Paused will be false, and lastPauseTime will be 0 upon initialisation
    }

    /**
     * @notice Change the paused state of the contract
     * @dev Only the contract owner may call this.
     */
    function setPaused(bool _paused) external onlyOwner {
        // Ensure we're actually changing the state before we do anything
        if (_paused == paused) {
            return;
        }

        // Set our paused state.
        paused = _paused;

        // If applicable, set the last pause time.
        if (paused) {
            lastPauseTime = now;
        }

        // Let everyone know that our pause state has changed.
        emit PauseChanged(paused);
    }

    event PauseChanged(bool isPaused);

    modifier notPaused {
        require(!paused, "This action cannot be performed while the contract is paused");
        _;
    }
}


/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the `nonReentrant` modifier
 * available, which can be aplied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 */
contract ReentrancyGuard {
    /// @dev counter to allow mutex lock with only one SSTORE operation
    uint256 private _guardCounter;

    constructor () internal {
        // The counter starts at one to prevent changing it from zero to a non-zero
        // value, which is a more expensive operation.
        _guardCounter = 1;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and make it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _guardCounter += 1;
        uint256 localCounter = _guardCounter;
        _;
        require(localCounter == _guardCounter, "ReentrancyGuard: reentrant call");
    }
}


interface IAddressResolver {
    function getAddress(bytes32 name) external view returns (address);

    function getSynth(bytes32 key) external view returns (address);

    function requireAndGetAddress(bytes32 name, string calldata reason) external view returns (address);
}


interface ISynth {
    // Views
    function currencyKey() external view returns (bytes32);

    function transferableSynths(address account) external view returns (uint);

    // Mutative functions
    function transferAndSettle(address to, uint value) external returns (bool);

    function transferFromAndSettle(
        address from,
        address to,
        uint value
    ) external returns (bool);

    // Restricted: used internally to Synthetix
    function burn(address account, uint amount) external;

    function issue(address account, uint amount) external;
}


interface IIssuer {
    // Views
    function anySynthOrSNXRateIsInvalid() external view returns (bool anyRateInvalid);

    function availableCurrencyKeys() external view returns (bytes32[] memory);

    function availableSynthCount() external view returns (uint);

    function availableSynths(uint index) external view returns (ISynth);

    function canBurnSynths(address account) external view returns (bool);

    function collateral(address account) external view returns (uint);

    function collateralisationRatio(address issuer) external view returns (uint);

    function collateralisationRatioAndAnyRatesInvalid(address _issuer)
        external
        view
        returns (uint cratio, bool anyRateIsInvalid);

    function debtBalanceOf(address issuer, bytes32 currencyKey) external view returns (uint debtBalance);

    function issuanceRatio() external view returns (uint);

    function lastIssueEvent(address account) external view returns (uint);

    function maxIssuableSynths(address issuer) external view returns (uint maxIssuable);

    function minimumStakeTime() external view returns (uint);

    function remainingIssuableSynths(address issuer)
        external
        view
        returns (
            uint maxIssuable,
            uint alreadyIssued,
            uint totalSystemDebt
        );

    function synths(bytes32 currencyKey) external view returns (ISynth);

    function synthsByAddress(address synthAddress) external view returns (bytes32);

    function totalIssuedSynths(bytes32 currencyKey, bool excludeEtherCollateral) external view returns (uint);

    function transferableSynthetixAndAnyRateIsInvalid(address account, uint balance)
        external
        view
        returns (uint transferable, bool anyRateIsInvalid);

    // Restricted: used internally to Synthetix
    function issueSynths(address from, uint amount) external;

    function issueSynthsOnBehalf(
        address issueFor,
        address from,
        uint amount
    ) external;

    function issueMaxSynths(address from) external;

    function issueMaxSynthsOnBehalf(address issueFor, address from) external;

    function burnSynths(address from, uint amount) external;

    function burnSynthsOnBehalf(
        address burnForAddress,
        address from,
        uint amount
    ) external;

    function burnSynthsToTarget(address from) external;

    function burnSynthsToTargetOnBehalf(address burnForAddress, address from) external;

    function liquidateDelinquentAccount(
        address account,
        uint susdAmount,
        address liquidator
    ) external returns (uint totalRedeemed, uint amountToLiquidate);
}


// Inheritance


// https://docs.synthetix.io/contracts/AddressResolver
contract AddressResolver is Owned, IAddressResolver {
    mapping(bytes32 => address) public repository;

    constructor(address _owner) public Owned(_owner) {}

    /* ========== MUTATIVE FUNCTIONS ========== */

    function importAddresses(bytes32[] calldata names, address[] calldata destinations) external onlyOwner {
        require(names.length == destinations.length, "Input lengths must match");

        for (uint i = 0; i < names.length; i++) {
            repository[names[i]] = destinations[i];
        }
    }

    /* ========== VIEWS ========== */

    function getAddress(bytes32 name) external view returns (address) {
        return repository[name];
    }

    function requireAndGetAddress(bytes32 name, string calldata reason) external view returns (address) {
        address _foundAddress = repository[name];
        require(_foundAddress != address(0), reason);
        return _foundAddress;
    }

    function getSynth(bytes32 key) external view returns (address) {
        IIssuer issuer = IIssuer(repository["Issuer"]);
        require(address(issuer) != address(0), "Cannot find Issuer address");
        return address(issuer.synths(key));
    }
}


// Inheritance


// Internal references


// https://docs.synthetix.io/contracts/MixinResolver
contract MixinResolver is Owned {
    AddressResolver public resolver;

    mapping(bytes32 => address) private addressCache;

    bytes32[] public resolverAddressesRequired;

    uint public constant MAX_ADDRESSES_FROM_RESOLVER = 24;

    constructor(address _resolver, bytes32[MAX_ADDRESSES_FROM_RESOLVER] memory _addressesToCache) internal {
        // This contract is abstract, and thus cannot be instantiated directly
        require(owner != address(0), "Owner must be set");

        for (uint i = 0; i < _addressesToCache.length; i++) {
            if (_addressesToCache[i] != bytes32(0)) {
                resolverAddressesRequired.push(_addressesToCache[i]);
            } else {
                // End early once an empty item is found - assumes there are no empty slots in
                // _addressesToCache
                break;
            }
        }
        resolver = AddressResolver(_resolver);
        // Do not sync the cache as addresses may not be in the resolver yet
    }

    /* ========== SETTERS ========== */
    function setResolverAndSyncCache(AddressResolver _resolver) external onlyOwner {
        resolver = _resolver;

        for (uint i = 0; i < resolverAddressesRequired.length; i++) {
            bytes32 name = resolverAddressesRequired[i];
            // Note: can only be invoked once the resolver has all the targets needed added
            addressCache[name] = resolver.requireAndGetAddress(name, "Resolver missing target");
        }
    }

    /* ========== VIEWS ========== */

    function requireAndGetAddress(bytes32 name, string memory reason) internal view returns (address) {
        address _foundAddress = addressCache[name];
        require(_foundAddress != address(0), reason);
        return _foundAddress;
    }

    // Note: this could be made external in a utility contract if addressCache was made public
    // (used for deployment)
    function isResolverCached(AddressResolver _resolver) external view returns (bool) {
        if (resolver != _resolver) {
            return false;
        }

        // otherwise, check everything
        for (uint i = 0; i < resolverAddressesRequired.length; i++) {
            bytes32 name = resolverAddressesRequired[i];
            // false if our cache is invalid or if the resolver doesn't have the required address
            if (resolver.getAddress(name) != addressCache[name] || addressCache[name] == address(0)) {
                return false;
            }
        }

        return true;
    }

    // Note: can be made external into a utility contract (used for deployment)
    function getResolverAddressesRequired()
        external
        view
        returns (bytes32[MAX_ADDRESSES_FROM_RESOLVER] memory addressesRequired)
    {
        for (uint i = 0; i < resolverAddressesRequired.length; i++) {
            addressesRequired[i] = resolverAddressesRequired[i];
        }
    }

    /* ========== INTERNAL FUNCTIONS ========== */
    function appendToAddressCache(bytes32 name) internal {
        resolverAddressesRequired.push(name);
        require(resolverAddressesRequired.length < MAX_ADDRESSES_FROM_RESOLVER, "Max resolver cache size met");
        // Because this is designed to be called internally in constructors, we don't
        // check the address exists already in the resolver
        addressCache[name] = resolver.getAddress(name);
    }
}


interface IEtherCollateralsUSD {
    // Views
    function totalIssuedSynths() external view returns (uint256);

    function totalLoansCreated() external view returns (uint256);

    function totalOpenLoanCount() external view returns (uint256);

    // Mutative functions
    function openLoan(uint256 _loanAmount) external payable returns (uint256 loanID);

    function closeLoan(uint256 loanID) external;

    function liquidateUnclosedLoan(address _loanCreatorsAddress, uint256 _loanID) external;

    function depositCollateral(address account, uint256 loanID) external payable;

    function withdrawCollateral(uint256 loanID, uint256 withdrawAmount) external;

    function repayLoan(
        address _loanCreatorsAddress,
        uint256 _loanID,
        uint256 _repayAmount
    ) external;
}


/**
 * @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) {
        require(b <= a, "SafeMath: subtraction overflow");
        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-solidity/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) {
        // Solidity only automatically asserts when dividing by 0
        require(b > 0, "SafeMath: division by zero");
        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) {
        require(b != 0, "SafeMath: modulo by zero");
        return a % b;
    }
}


// Libraries


// https://docs.synthetix.io/contracts/SafeDecimalMath
library SafeDecimalMath {
    using SafeMath for uint;

    /* Number of decimal places in the representations. */
    uint8 public constant decimals = 18;
    uint8 public constant highPrecisionDecimals = 27;

    /* The number representing 1.0. */
    uint public constant UNIT = 10**uint(decimals);

    /* The number representing 1.0 for higher fidelity numbers. */
    uint public constant PRECISE_UNIT = 10**uint(highPrecisionDecimals);
    uint private constant UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR = 10**uint(highPrecisionDecimals - decimals);

    /**
     * @return Provides an interface to UNIT.
     */
    function unit() external pure returns (uint) {
        return UNIT;
    }

    /**
     * @return Provides an interface to PRECISE_UNIT.
     */
    function preciseUnit() external pure returns (uint) {
        return PRECISE_UNIT;
    }

    /**
     * @return The result of multiplying x and y, interpreting the operands as fixed-point
     * decimals.
     *
     * @dev A unit factor is divided out after the product of x and y is evaluated,
     * so that product must be less than 2**256. As this is an integer division,
     * the internal division always rounds down. This helps save on gas. Rounding
     * is more expensive on gas.
     */
    function multiplyDecimal(uint x, uint y) internal pure returns (uint) {
        /* Divide by UNIT to remove the extra factor introduced by the product. */
        return x.mul(y) / UNIT;
    }

    /**
     * @return The result of safely multiplying x and y, interpreting the operands
     * as fixed-point decimals of the specified precision unit.
     *
     * @dev The operands should be in the form of a the specified unit factor which will be
     * divided out after the product of x and y is evaluated, so that product must be
     * less than 2**256.
     *
     * Unlike multiplyDecimal, this function rounds the result to the nearest increment.
     * Rounding is useful when you need to retain fidelity for small decimal numbers
     * (eg. small fractions or percentages).
     */
    function _multiplyDecimalRound(
        uint x,
        uint y,
        uint precisionUnit
    ) private pure returns (uint) {
        /* Divide by UNIT to remove the extra factor introduced by the product. */
        uint quotientTimesTen = x.mul(y) / (precisionUnit / 10);

        if (quotientTimesTen % 10 >= 5) {
            quotientTimesTen += 10;
        }

        return quotientTimesTen / 10;
    }

    /**
     * @return The result of safely multiplying x and y, interpreting the operands
     * as fixed-point decimals of a precise unit.
     *
     * @dev The operands should be in the precise unit factor which will be
     * divided out after the product of x and y is evaluated, so that product must be
     * less than 2**256.
     *
     * Unlike multiplyDecimal, this function rounds the result to the nearest increment.
     * Rounding is useful when you need to retain fidelity for small decimal numbers
     * (eg. small fractions or percentages).
     */
    function multiplyDecimalRoundPrecise(uint x, uint y) internal pure returns (uint) {
        return _multiplyDecimalRound(x, y, PRECISE_UNIT);
    }

    /**
     * @return The result of safely multiplying x and y, interpreting the operands
     * as fixed-point decimals of a standard unit.
     *
     * @dev The operands should be in the standard unit factor which will be
     * divided out after the product of x and y is evaluated, so that product must be
     * less than 2**256.
     *
     * Unlike multiplyDecimal, this function rounds the result to the nearest increment.
     * Rounding is useful when you need to retain fidelity for small decimal numbers
     * (eg. small fractions or percentages).
     */
    function multiplyDecimalRound(uint x, uint y) internal pure returns (uint) {
        return _multiplyDecimalRound(x, y, UNIT);
    }

    /**
     * @return The result of safely dividing x and y. The return value is a high
     * precision decimal.
     *
     * @dev y is divided after the product of x and the standard precision unit
     * is evaluated, so the product of x and UNIT must be less than 2**256. As
     * this is an integer division, the result is always rounded down.
     * This helps save on gas. Rounding is more expensive on gas.
     */
    function divideDecimal(uint x, uint y) internal pure returns (uint) {
        /* Reintroduce the UNIT factor that will be divided out by y. */
        return x.mul(UNIT).div(y);
    }

    /**
     * @return The result of safely dividing x and y. The return value is as a rounded
     * decimal in the precision unit specified in the parameter.
     *
     * @dev y is divided after the product of x and the specified precision unit
     * is evaluated, so the product of x and the specified precision unit must
     * be less than 2**256. The result is rounded to the nearest increment.
     */
    function _divideDecimalRound(
        uint x,
        uint y,
        uint precisionUnit
    ) private pure returns (uint) {
        uint resultTimesTen = x.mul(precisionUnit * 10).div(y);

        if (resultTimesTen % 10 >= 5) {
            resultTimesTen += 10;
        }

        return resultTimesTen / 10;
    }

    /**
     * @return The result of safely dividing x and y. The return value is as a rounded
     * standard precision decimal.
     *
     * @dev y is divided after the product of x and the standard precision unit
     * is evaluated, so the product of x and the standard precision unit must
     * be less than 2**256. The result is rounded to the nearest increment.
     */
    function divideDecimalRound(uint x, uint y) internal pure returns (uint) {
        return _divideDecimalRound(x, y, UNIT);
    }

    /**
     * @return The result of safely dividing x and y. The return value is as a rounded
     * high precision decimal.
     *
     * @dev y is divided after the product of x and the high precision unit
     * is evaluated, so the product of x and the high precision unit must
     * be less than 2**256. The result is rounded to the nearest increment.
     */
    function divideDecimalRoundPrecise(uint x, uint y) internal pure returns (uint) {
        return _divideDecimalRound(x, y, PRECISE_UNIT);
    }

    /**
     * @dev Convert a standard decimal representation to a high precision one.
     */
    function decimalToPreciseDecimal(uint i) internal pure returns (uint) {
        return i.mul(UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR);
    }

    /**
     * @dev Convert a high precision decimal to a standard decimal representation.
     */
    function preciseDecimalToDecimal(uint i) internal pure returns (uint) {
        uint quotientTimesTen = i / (UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR / 10);

        if (quotientTimesTen % 10 >= 5) {
            quotientTimesTen += 10;
        }

        return quotientTimesTen / 10;
    }
}


interface ISystemStatus {
    struct Status {
        bool canSuspend;
        bool canResume;
    }

    struct Suspension {
        bool suspended;
        // reason is an integer code,
        // 0 => no reason, 1 => upgrading, 2+ => defined by system usage
        uint248 reason;
    }

    // Views
    function accessControl(bytes32 section, address account) external view returns (bool canSuspend, bool canResume);

    function requireSystemActive() external view;

    function requireIssuanceActive() external view;

    function requireExchangeActive() external view;

    function requireSynthActive(bytes32 currencyKey) external view;

    function requireSynthsActive(bytes32 sourceCurrencyKey, bytes32 destinationCurrencyKey) external view;

    function synthSuspension(bytes32 currencyKey) external view returns (bool suspended, uint248 reason);

    // Restricted functions
    function suspendSynth(bytes32 currencyKey, uint256 reason) external;

    function updateAccessControl(
        bytes32 section,
        address account,
        bool canSuspend,
        bool canResume
    ) external;
}


interface IFeePool {
    // Views

    // solhint-disable-next-line func-name-mixedcase
    function FEE_ADDRESS() external view returns (address);

    function feesAvailable(address account) external view returns (uint, uint);

    function feePeriodDuration() external view returns (uint);

    function isFeesClaimable(address account) external view returns (bool);

    function targetThreshold() external view returns (uint);

    function totalFeesAvailable() external view returns (uint);

    function totalRewardsAvailable() external view returns (uint);

    // Mutative Functions
    function claimFees() external returns (bool);

    function claimOnBehalf(address claimingForAddress) external returns (bool);

    function closeCurrentFeePeriod() external;

    // Restricted: used internally to Synthetix
    function appendAccountIssuanceRecord(
        address account,
        uint lockedAmount,
        uint debtEntryIndex
    ) external;

    function recordFeePaid(uint sUSDAmount) external;

    function setRewardsToDistribute(uint amount) external;
}


interface IERC20 {
    // ERC20 Optional Views
    function name() external view returns (string memory);

    function symbol() external view returns (string memory);

    function decimals() external view returns (uint8);

    // Views
    function totalSupply() external view returns (uint);

    function balanceOf(address owner) external view returns (uint);

    function allowance(address owner, address spender) external view returns (uint);

    // Mutative functions
    function transfer(address to, uint value) external returns (bool);

    function approve(address spender, uint value) external returns (bool);

    function transferFrom(
        address from,
        address to,
        uint value
    ) external returns (bool);

    // Events
    event Transfer(address indexed from, address indexed to, uint value);

    event Approval(address indexed owner, address indexed spender, uint value);
}


// https://docs.synthetix.io/contracts/source/interfaces/IExchangeRates
interface IExchangeRates {
    // Structs
    struct RateAndUpdatedTime {
        uint216 rate;
        uint40 time;
    }

    struct InversePricing {
        uint entryPoint;
        uint upperLimit;
        uint lowerLimit;
        bool frozenAtUpperLimit;
        bool frozenAtLowerLimit;
    }

    // Views
    function aggregators(bytes32 currencyKey) external view returns (address);

    function aggregatorWarningFlags() external view returns (address);

    function anyRateIsInvalid(bytes32[] calldata currencyKeys) external view returns (bool);

    function canFreezeRate(bytes32 currencyKey) external view returns (bool);

    function currentRoundForRate(bytes32 currencyKey) external view returns (uint);

    function currenciesUsingAggregator(address aggregator) external view returns (bytes32[] memory);

    function effectiveValue(
        bytes32 sourceCurrencyKey,
        uint sourceAmount,
        bytes32 destinationCurrencyKey
    ) external view returns (uint value);

    function effectiveValueAndRates(
        bytes32 sourceCurrencyKey,
        uint sourceAmount,
        bytes32 destinationCurrencyKey
    )
        external
        view
        returns (
            uint value,
            uint sourceRate,
            uint destinationRate
        );

    function effectiveValueAtRound(
        bytes32 sourceCurrencyKey,
        uint sourceAmount,
        bytes32 destinationCurrencyKey,
        uint roundIdForSrc,
        uint roundIdForDest
    ) external view returns (uint value);

    function getCurrentRoundId(bytes32 currencyKey) external view returns (uint);

    function getLastRoundIdBeforeElapsedSecs(
        bytes32 currencyKey,
        uint startingRoundId,
        uint startingTimestamp,
        uint timediff
    ) external view returns (uint);

    function inversePricing(bytes32 currencyKey)
        external
        view
        returns (
            uint entryPoint,
            uint upperLimit,
            uint lowerLimit,
            bool frozenAtUpperLimit,
            bool frozenAtLowerLimit
        );

    function lastRateUpdateTimes(bytes32 currencyKey) external view returns (uint256);

    function oracle() external view returns (address);

    function rateAndTimestampAtRound(bytes32 currencyKey, uint roundId) external view returns (uint rate, uint time);

    function rateAndUpdatedTime(bytes32 currencyKey) external view returns (uint rate, uint time);

    function rateForCurrency(bytes32 currencyKey) external view returns (uint);

    function rateIsFlagged(bytes32 currencyKey) external view returns (bool);

    function rateIsFrozen(bytes32 currencyKey) external view returns (bool);

    function rateIsInvalid(bytes32 currencyKey) external view returns (bool);

    function rateIsStale(bytes32 currencyKey) external view returns (bool);

    function rateStalePeriod() external view returns (uint);

    function ratesAndUpdatedTimeForCurrencyLastNRounds(bytes32 currencyKey, uint numRounds)
        external
        view
        returns (uint[] memory rates, uint[] memory times);

    function ratesAndInvalidForCurrencies(bytes32[] calldata currencyKeys)
        external
        view
        returns (uint[] memory rates, bool anyRateInvalid);

    function ratesForCurrencies(bytes32[] calldata currencyKeys) external view returns (uint[] memory);

    // Mutative functions
    function freezeRate(bytes32 currencyKey) external;
}


// Inheritance


// Libraries


// Internal references


// ETH Collateral v0.3 (sUSD)
// https://docs.synthetix.io/contracts/EtherCollateralsUSD
contract EtherCollateralsUSD is Owned, Pausable, ReentrancyGuard, MixinResolver, IEtherCollateralsUSD {
    using SafeMath for uint256;
    using SafeDecimalMath for uint256;

    bytes32 internal constant ETH = "ETH";

    // ========== CONSTANTS ==========
    uint256 internal constant ONE_THOUSAND = 1e18 * 1000;
    uint256 internal constant ONE_HUNDRED = 1e18 * 100;

    uint256 internal constant SECONDS_IN_A_YEAR = 31536000; // Common Year

    // Where fees are pooled in sUSD.
    address internal constant FEE_ADDRESS = 0xfeEFEEfeefEeFeefEEFEEfEeFeefEEFeeFEEFEeF;

    uint256 internal constant ACCOUNT_LOAN_LIMIT_CAP = 1000;
    bytes32 private constant sUSD = "sUSD";
    bytes32 public constant COLLATERAL = "ETH";

    // ========== SETTER STATE VARIABLES ==========

    // The ratio of Collateral to synths issued
    uint256 public collateralizationRatio = SafeDecimalMath.unit() * 150;

    // If updated, all outstanding loans will pay this interest rate in on closure of the loan. Default 5%
    uint256 public interestRate = (5 * SafeDecimalMath.unit()) / 100;
    uint256 public interestPerSecond = interestRate.div(SECONDS_IN_A_YEAR);

    // Minting fee for issuing the synths. Default 50 bips.
    uint256 public issueFeeRate = (5 * SafeDecimalMath.unit()) / 1000;

    // Maximum amount of sUSD that can be issued by the EtherCollateral contract. Default 10MM
    uint256 public issueLimit = SafeDecimalMath.unit() * 10000000;

    // Minimum amount of ETH to create loan preventing griefing and gas consumption. Min 1ETH
    uint256 public minLoanCollateralSize = SafeDecimalMath.unit() * 1;

    // Maximum number of loans an account can create
    uint256 public accountLoanLimit = 50;

    // If true then any wallet addres can close a loan not just the loan creator.
    bool public loanLiquidationOpen = false;

    // Time when remaining loans can be liquidated
    uint256 public liquidationDeadline;

    // Liquidation ratio when loans can be liquidated
    uint256 public liquidationRatio = (150 * SafeDecimalMath.unit()) / 100; // 1.5 ratio

    // Liquidation penalty when loans are liquidated. default 10%
    uint256 public liquidationPenalty = SafeDecimalMath.unit() / 10;

    // ========== STATE VARIABLES ==========

    // The total number of synths issued by the collateral in this contract
    uint256 public totalIssuedSynths;

    // Total number of loans ever created
    uint256 public totalLoansCreated;

    // Total number of open loans
    uint256 public totalOpenLoanCount;

    // Synth loan storage struct
    struct SynthLoanStruct {
        //  Acccount that created the loan
        address payable account;
        //  Amount (in collateral token ) that they deposited
        uint256 collateralAmount;
        //  Amount (in synths) that they issued to borrow
        uint256 loanAmount;
        // Minting Fee
        uint256 mintingFee;
        // When the loan was created
        uint256 timeCreated;
        // ID for the loan
        uint256 loanID;
        // When the loan was paidback (closed)
        uint256 timeClosed;
        // Applicable Interest rate
        uint256 loanInterestRate;
        // interest amounts accrued
        uint256 accruedInterest;
        // last timestamp interest amounts accrued
        uint40 lastInterestAccrued;
    }

    // Users Loans by address
    mapping(address => SynthLoanStruct[]) public accountsSynthLoans;

    // Account Open Loan Counter
    mapping(address => uint256) public accountOpenLoanCounter;

    /* ========== ADDRESS RESOLVER CONFIGURATION ========== */

    bytes32 private constant CONTRACT_SYSTEMSTATUS = "SystemStatus";
    bytes32 private constant CONTRACT_SYNTHSUSD = "SynthsUSD";
    bytes32 private constant CONTRACT_EXRATES = "ExchangeRates";
    bytes32 private constant CONTRACT_FEEPOOL = "FeePool";

    bytes32[24] private addressesToCache = [CONTRACT_SYSTEMSTATUS, CONTRACT_SYNTHSUSD, CONTRACT_EXRATES, CONTRACT_FEEPOOL];

    // ========== CONSTRUCTOR ==========
    constructor(address _owner, address _resolver)
        public
        Owned(_owner)
        Pausable()
        MixinResolver(_resolver, addressesToCache)
    {
        liquidationDeadline = block.timestamp + 92 days; // Time before loans can be open for liquidation to end the trial contract
    }

    // ========== SETTERS ==========

    function setCollateralizationRatio(uint256 ratio) external onlyOwner {
        require(ratio <= ONE_THOUSAND, "Too high");
        require(ratio >= ONE_HUNDRED, "Too low");
        collateralizationRatio = ratio;
        emit CollateralizationRatioUpdated(ratio);
    }

    function setInterestRate(uint256 _interestRate) external onlyOwner {
        require(_interestRate > SECONDS_IN_A_YEAR, "Interest rate cannot be less that the SECONDS_IN_A_YEAR");
        require(_interestRate <= SafeDecimalMath.unit(), "Interest cannot be more than 100% APR");
        interestRate = _interestRate;
        interestPerSecond = _interestRate.div(SECONDS_IN_A_YEAR);
        emit InterestRateUpdated(interestRate);
    }

    function setIssueFeeRate(uint256 _issueFeeRate) external onlyOwner {
        issueFeeRate = _issueFeeRate;
        emit IssueFeeRateUpdated(issueFeeRate);
    }

    function setIssueLimit(uint256 _issueLimit) external onlyOwner {
        issueLimit = _issueLimit;
        emit IssueLimitUpdated(issueLimit);
    }

    function setMinLoanCollateralSize(uint256 _minLoanCollateralSize) external onlyOwner {
        minLoanCollateralSize = _minLoanCollateralSize;
        emit MinLoanCollateralSizeUpdated(minLoanCollateralSize);
    }

    function setAccountLoanLimit(uint256 _loanLimit) external onlyOwner {
        require(_loanLimit < ACCOUNT_LOAN_LIMIT_CAP, "Owner cannot set higher than ACCOUNT_LOAN_LIMIT_CAP");
        accountLoanLimit = _loanLimit;
        emit AccountLoanLimitUpdated(accountLoanLimit);
    }

    function setLoanLiquidationOpen(bool _loanLiquidationOpen) external onlyOwner {
        require(block.timestamp > liquidationDeadline, "Before liquidation deadline");
        loanLiquidationOpen = _loanLiquidationOpen;
        emit LoanLiquidationOpenUpdated(loanLiquidationOpen);
    }

    function setLiquidationRatio(uint256 _liquidationRatio) external onlyOwner {
        require(_liquidationRatio > SafeDecimalMath.unit(), "Ratio less than 100%");
        liquidationRatio = _liquidationRatio;
        emit LiquidationRatioUpdated(liquidationRatio);
    }

    // ========== PUBLIC VIEWS ==========

    function getContractInfo()
        external
        view
        returns (
            uint256 _collateralizationRatio,
            uint256 _issuanceRatio,
            uint256 _interestRate,
            uint256 _interestPerSecond,
            uint256 _issueFeeRate,
            uint256 _issueLimit,
            uint256 _minLoanCollateralSize,
            uint256 _totalIssuedSynths,
            uint256 _totalLoansCreated,
            uint256 _totalOpenLoanCount,
            uint256 _ethBalance,
            uint256 _liquidationDeadline,
            bool _loanLiquidationOpen
        )
    {
        _collateralizationRatio = collateralizationRatio;
        _issuanceRatio = issuanceRatio();
        _interestRate = interestRate;
        _interestPerSecond = interestPerSecond;
        _issueFeeRate = issueFeeRate;
        _issueLimit = issueLimit;
        _minLoanCollateralSize = minLoanCollateralSize;
        _totalIssuedSynths = totalIssuedSynths;
        _totalLoansCreated = totalLoansCreated;
        _totalOpenLoanCount = totalOpenLoanCount;
        _ethBalance = address(this).balance;
        _liquidationDeadline = liquidationDeadline;
        _loanLiquidationOpen = loanLiquidationOpen;
    }

    // returns value of 100 / collateralizationRatio.
    // e.g. 100/150 = 0.6666666667
    function issuanceRatio() public view returns (uint256) {
        // this rounds so you get slightly more rather than slightly less
        return ONE_HUNDRED.divideDecimalRound(collateralizationRatio);
    }

    function loanAmountFromCollateral(uint256 collateralAmount) public view returns (uint256) {
        // a fraction more is issued due to rounding
        return collateralAmount.multiplyDecimal(issuanceRatio()).multiplyDecimal(exchangeRates().rateForCurrency(ETH));
    }

    function collateralAmountForLoan(uint256 loanAmount) external view returns (uint256) {
        return
            loanAmount
                .multiplyDecimal(collateralizationRatio.divideDecimalRound(exchangeRates().rateForCurrency(ETH)))
                .divideDecimalRound(ONE_HUNDRED);
    }

    // compound accrued interest with remaining loanAmount * (now - lastTimestampInterestPaid)
    function currentInterestOnLoan(address _account, uint256 _loanID) external view returns (uint256) {
        // Get the loan from storage
        SynthLoanStruct memory synthLoan = _getLoanFromStorage(_account, _loanID);
        uint256 currentInterest = accruedInterestOnLoan(
            synthLoan.loanAmount.add(synthLoan.accruedInterest),
            _timeSinceInterestAccrual(synthLoan)
        );
        return synthLoan.accruedInterest.add(currentInterest);
    }

    function accruedInterestOnLoan(uint256 _loanAmount, uint256 _seconds) public view returns (uint256 interestAmount) {
        // Simple interest calculated per second
        // Interest = Principal * rate * time
        interestAmount = _loanAmount.multiplyDecimalRound(interestPerSecond.mul(_seconds));
    }

    function totalFeesOnLoan(address _account, uint256 _loanID)
        external
        view
        returns (uint256 interestAmount, uint256 mintingFee)
    {
        SynthLoanStruct memory synthLoan = _getLoanFromStorage(_account, _loanID);
        uint256 loanAmountWithAccruedInterest = synthLoan.loanAmount.add(synthLoan.accruedInterest);
        interestAmount = synthLoan.accruedInterest.add(
            accruedInterestOnLoan(loanAmountWithAccruedInterest, _timeSinceInterestAccrual(synthLoan))
        );
        mintingFee = synthLoan.mintingFee;
    }

    function getMintingFee(address _account, uint256 _loanID) external view returns (uint256) {
        // Get the loan from storage
        SynthLoanStruct memory synthLoan = _getLoanFromStorage(_account, _loanID);
        return synthLoan.mintingFee;
    }

    /**
     * r = target issuance ratio
     * D = debt balance
     * V = Collateral
     * P = liquidation penalty
     * Calculates amount of synths = (D - V * r) / (1 - (1 + P) * r)
     */
    function calculateAmountToLiquidate(uint debtBalance, uint collateral) public view returns (uint) {
        uint unit = SafeDecimalMath.unit();
        uint ratio = liquidationRatio;

        uint dividend = debtBalance.sub(collateral.divideDecimal(ratio));
        uint divisor = unit.sub(unit.add(liquidationPenalty).divideDecimal(ratio));

        return dividend.divideDecimal(divisor);
    }

    function openLoanIDsByAccount(address _account) external view returns (uint256[] memory) {
        SynthLoanStruct[] memory synthLoans = accountsSynthLoans[_account];

        uint256[] memory _openLoanIDs = new uint256[](synthLoans.length);
        uint256 _counter = 0;

        for (uint256 i = 0; i < synthLoans.length; i++) {
            if (synthLoans[i].timeClosed == 0) {
                _openLoanIDs[_counter] = synthLoans[i].loanID;
                _counter++;
            }
        }
        // Create the fixed size array to return
        uint256[] memory _result = new uint256[](_counter);

        // Copy loanIDs from dynamic array to fixed array
        for (uint256 j = 0; j < _counter; j++) {
            _result[j] = _openLoanIDs[j];
        }
        // Return an array with list of open Loan IDs
        return _result;
    }

    function getLoan(address _account, uint256 _loanID)
        external
        view
        returns (
            address account,
            uint256 collateralAmount,
            uint256 loanAmount,
            uint256 timeCreated,
            uint256 loanID,
            uint256 timeClosed,
            uint256 accruedInterest,
            uint256 totalFees
        )
    {
        SynthLoanStruct memory synthLoan = _getLoanFromStorage(_account, _loanID);
        account = synthLoan.account;
        collateralAmount = synthLoan.collateralAmount;
        loanAmount = synthLoan.loanAmount;
        timeCreated = synthLoan.timeCreated;
        loanID = synthLoan.loanID;
        timeClosed = synthLoan.timeClosed;
        accruedInterest = synthLoan.accruedInterest.add(
            accruedInterestOnLoan(synthLoan.loanAmount.add(synthLoan.accruedInterest), _timeSinceInterestAccrual(synthLoan))
        );
        totalFees = accruedInterest.add(synthLoan.mintingFee);
    }

    function getLoanCollateralRatio(address _account, uint256 _loanID) external view returns (uint256 loanCollateralRatio) {
        // Get the loan from storage
        SynthLoanStruct memory synthLoan = _getLoanFromStorage(_account, _loanID);

        (loanCollateralRatio, , ) = _loanCollateralRatio(synthLoan);
    }

    function _loanCollateralRatio(SynthLoanStruct memory _loan)
        internal
        view
        returns (
            uint256 loanCollateralRatio,
            uint256 collateralValue,
            uint256 interestAmount
        )
    {
        // Any interest accrued prior is rolled up into loan amount
        uint256 loanAmountWithAccruedInterest = _loan.loanAmount.add(_loan.accruedInterest);

        interestAmount = accruedInterestOnLoan(loanAmountWithAccruedInterest, _timeSinceInterestAccrual(_loan));

        collateralValue = _loan.collateralAmount.multiplyDecimal(exchangeRates().rateForCurrency(COLLATERAL));

        loanCollateralRatio = collateralValue.divideDecimal(loanAmountWithAccruedInterest.add(interestAmount));
    }

    function timeSinceInterestAccrualOnLoan(address _account, uint256 _loanID) external view returns (uint256) {
        // Get the loan from storage
        SynthLoanStruct memory synthLoan = _getLoanFromStorage(_account, _loanID);

        return _timeSinceInterestAccrual(synthLoan);
    }

    // ========== PUBLIC FUNCTIONS ==========

    function openLoan(uint256 _loanAmount)
        external
        payable
        notPaused
        nonReentrant
        ETHRateNotInvalid
        returns (uint256 loanID)
    {
        systemStatus().requireIssuanceActive();

        // Require ETH sent to be greater than minLoanCollateralSize
        require(
            msg.value >= minLoanCollateralSize,
            "Not enough ETH to create this loan. Please see the minLoanCollateralSize"
        );

        // Require loanLiquidationOpen to be false or we are in liquidation phase
        require(loanLiquidationOpen == false, "Loans are now being liquidated");

        // Each account is limited to creating 50 (accountLoanLimit) loans
        require(accountsSynthLoans[msg.sender].length < accountLoanLimit, "Each account is limited to 50 loans");

        // Calculate issuance amount based on issuance ratio
        uint256 maxLoanAmount = loanAmountFromCollateral(msg.value);

        // Require requested _loanAmount to be less than maxLoanAmount
        // Issuance ratio caps collateral to loan value at 150%
        require(_loanAmount <= maxLoanAmount, "Loan amount exceeds max borrowing power");

        uint256 mintingFee = _calculateMintingFee(_loanAmount);
        uint256 loanAmountMinusFee = _loanAmount.sub(mintingFee);

        // Require sUSD loan to mint does not exceed cap
        require(totalIssuedSynths.add(_loanAmount) <= issueLimit, "Loan Amount exceeds the supply cap.");

        // Get a Loan ID
        loanID = _incrementTotalLoansCounter();

        // Create Loan storage object
        SynthLoanStruct memory synthLoan = SynthLoanStruct({
            account: msg.sender,
            collateralAmount: msg.value,
            loanAmount: _loanAmount,
            mintingFee: mintingFee,
            timeCreated: block.timestamp,
            loanID: loanID,
            timeClosed: 0,
            loanInterestRate: interestRate,
            accruedInterest: 0,
            lastInterestAccrued: 0
        });

        // Fee distribution. Mint the sUSD fees into the FeePool and record fees paid
        if (mintingFee > 0) {
            synthsUSD().issue(FEE_ADDRESS, mintingFee);
            feePool().recordFeePaid(mintingFee);
        }

        // Record loan in mapping to account in an array of the accounts open loans
        accountsSynthLoans[msg.sender].push(synthLoan);

        // Increment totalIssuedSynths
        totalIssuedSynths = totalIssuedSynths.add(_loanAmount);

        // Issue the synth (less fee)
        synthsUSD().issue(msg.sender, loanAmountMinusFee);

        // Tell the Dapps a loan was created
        emit LoanCreated(msg.sender, loanID, _loanAmount);
    }

    function closeLoan(uint256 loanID) external nonReentrant ETHRateNotInvalid {
        _closeLoan(msg.sender, loanID, false);
    }

    // Add ETH collateral to an open loan
    function depositCollateral(address account, uint256 loanID) external payable notPaused {
        require(msg.value > 0, "Deposit amount must be greater than 0");

        systemStatus().requireIssuanceActive();

        // Require loanLiquidationOpen to be false or we are in liquidation phase
        require(loanLiquidationOpen == false, "Loans are now being liquidated");

        // Get the loan from storage
        SynthLoanStruct memory synthLoan = _getLoanFromStorage(account, loanID);

        // Check loan exists and is open
        _checkLoanIsOpen(synthLoan);

        uint256 totalCollateral = synthLoan.collateralAmount.add(msg.value);

        _updateLoanCollateral(synthLoan, totalCollateral);

        // Tell the Dapps collateral was added to loan
        emit CollateralDeposited(account, loanID, msg.value, totalCollateral);
    }

    // Withdraw ETH collateral from an open loan
    function withdrawCollateral(uint256 loanID, uint256 withdrawAmount) external notPaused nonReentrant ETHRateNotInvalid {
        require(withdrawAmount > 0, "Amount to withdraw must be greater than 0");

        systemStatus().requireIssuanceActive();

        // Require loanLiquidationOpen to be false or we are in liquidation phase
        require(loanLiquidationOpen == false, "Loans are now being liquidated");

        // Get the loan from storage
        SynthLoanStruct memory synthLoan = _getLoanFromStorage(msg.sender, loanID);

        // Check loan exists and is open
        _checkLoanIsOpen(synthLoan);

        uint256 collateralAfter = synthLoan.collateralAmount.sub(withdrawAmount);

        SynthLoanStruct memory loanAfter = _updateLoanCollateral(synthLoan, collateralAfter);

        // require collateral ratio after to be above the liquidation ratio
        (uint256 collateralRatioAfter, , ) = _loanCollateralRatio(loanAfter);

        require(collateralRatioAfter > liquidationRatio, "Collateral ratio below liquidation after withdraw");

        // transfer ETH to msg.sender
        msg.sender.transfer(withdrawAmount);

        // Tell the Dapps collateral was added to loan
        emit CollateralWithdrawn(msg.sender, loanID, withdrawAmount, loanAfter.collateralAmount);
    }

    function repayLoan(
        address _loanCreatorsAddress,
        uint256 _loanID,
        uint256 _repayAmount
    ) external ETHRateNotInvalid {
        systemStatus().requireSystemActive();

        // check msg.sender has sufficient sUSD to pay
        require(IERC20(address(synthsUSD())).balanceOf(msg.sender) >= _repayAmount, "Not enough sUSD balance");

        SynthLoanStruct memory synthLoan = _getLoanFromStorage(_loanCreatorsAddress, _loanID);

        // Check loan exists and is open
        _checkLoanIsOpen(synthLoan);

        // Any interest accrued prior is rolled up into loan amount
        uint256 loanAmountWithAccruedInterest = synthLoan.loanAmount.add(synthLoan.accruedInterest);
        uint256 interestAmount = accruedInterestOnLoan(loanAmountWithAccruedInterest, _timeSinceInterestAccrual(synthLoan));

        // repay any accrued interests first
        // and repay principal loan amount with remaining amounts
        uint256 accruedInterest = synthLoan.accruedInterest.add(interestAmount);

        (
            uint256 interestPaid,
            uint256 loanAmountPaid,
            uint256 accruedInterestAfter,
            uint256 loanAmountAfter
        ) = _splitInterestLoanPayment(_repayAmount, accruedInterest, synthLoan.loanAmount);

        // burn sUSD from msg.sender for repaid amount
        synthsUSD().burn(msg.sender, _repayAmount);

        // Send interest paid to fee pool and record loan amount paid
        _processInterestAndLoanPayment(interestPaid, loanAmountPaid);

        // update loan with new total loan amount, record accrued interests
        _updateLoan(synthLoan, loanAmountAfter, accruedInterestAfter, block.timestamp);

        emit LoanRepaid(_loanCreatorsAddress, _loanID, _repayAmount, loanAmountAfter);
    }

    // Liquidate loans at or below issuance ratio
    function liquidateLoan(
        address _loanCreatorsAddress,
        uint256 _loanID,
        uint256 _debtToCover
    ) external nonReentrant ETHRateNotInvalid {
        systemStatus().requireSystemActive();

        // check msg.sender (liquidator's wallet) has sufficient sUSD
        require(IERC20(address(synthsUSD())).balanceOf(msg.sender) >= _debtToCover, "Not enough sUSD balance");

        SynthLoanStruct memory synthLoan = _getLoanFromStorage(_loanCreatorsAddress, _loanID);

        // Check loan exists and is open
        _checkLoanIsOpen(synthLoan);

        (uint256 collateralRatio, uint256 collateralValue, uint256 interestAmount) = _loanCollateralRatio(synthLoan);

        require(collateralRatio < liquidationRatio, "Collateral ratio above liquidation ratio");

        // calculate amount to liquidate to fix ratio including accrued interest
        uint256 liquidationAmount = calculateAmountToLiquidate(
            synthLoan.loanAmount.add(synthLoan.accruedInterest).add(interestAmount),
            collateralValue
        );

        // cap debt to liquidate
        uint256 amountToLiquidate = liquidationAmount < _debtToCover ? liquidationAmount : _debtToCover;

        // burn sUSD from msg.sender for amount to liquidate
        synthsUSD().burn(msg.sender, amountToLiquidate);

        (uint256 interestPaid, uint256 loanAmountPaid, uint256 accruedInterestAfter, ) = _splitInterestLoanPayment(
            amountToLiquidate,
            synthLoan.accruedInterest.add(interestAmount),
            synthLoan.loanAmount
        );

        // Send interests paid to fee pool and record loan amount paid
        _processInterestAndLoanPayment(interestPaid, loanAmountPaid);

        // Collateral value to redeem
        uint256 collateralRedeemed = exchangeRates().effectiveValue(sUSD, amountToLiquidate, COLLATERAL);

        // Add penalty
        uint256 totalCollateralLiquidated = collateralRedeemed.multiplyDecimal(
            SafeDecimalMath.unit().add(liquidationPenalty)
        );

        // update remaining loanAmount less amount paid and update accrued interests less interest paid
        _updateLoan(synthLoan, synthLoan.loanAmount.sub(loanAmountPaid), accruedInterestAfter, block.timestamp);

        // update remaining collateral on loan
        _updateLoanCollateral(synthLoan, synthLoan.collateralAmount.sub(totalCollateralLiquidated));

        // Send liquidated ETH collateral to msg.sender
        msg.sender.transfer(totalCollateralLiquidated);

        // emit loan liquidation event
        emit LoanPartiallyLiquidated(
            _loanCreatorsAddress,
            _loanID,
            msg.sender,
            amountToLiquidate,
            totalCollateralLiquidated
        );
    }

    function _splitInterestLoanPayment(
        uint256 _paymentAmount,
        uint256 _accruedInterest,
        uint256 _loanAmount
    )
        internal
        pure
        returns (
            uint256 interestPaid,
            uint256 loanAmountPaid,
            uint256 accruedInterestAfter,
            uint256 loanAmountAfter
        )
    {
        uint256 remainingPayment = _paymentAmount;

        // repay any accrued interests first
        accruedInterestAfter = _accruedInterest;
        if (remainingPayment > 0 && _accruedInterest > 0) {
            // Max repay is the accruedInterest amount
            interestPaid = remainingPayment > _accruedInterest ? _accruedInterest : remainingPayment;
            accruedInterestAfter = accruedInterestAfter.sub(interestPaid);
            remainingPayment = remainingPayment.sub(interestPaid);
        }

        // Remaining amounts - pay down loan amount
        loanAmountAfter = _loanAmount;
        if (remainingPayment > 0) {
            loanAmountAfter = loanAmountAfter.sub(remainingPayment);
            loanAmountPaid = remainingPayment;
        }
    }

    function _processInterestAndLoanPayment(uint256 interestPaid, uint256 loanAmountPaid) internal {
        // Fee distribution. Mint the sUSD fees into the FeePool and record fees paid
        if (interestPaid > 0) {
            synthsUSD().issue(FEE_ADDRESS, interestPaid);
            feePool().recordFeePaid(interestPaid);
        }

        // Decrement totalIssuedSynths
        if (loanAmountPaid > 0) {
            totalIssuedSynths = totalIssuedSynths.sub(loanAmountPaid);
        }
    }

    // Liquidation of an open loan available for anyone
    function liquidateUnclosedLoan(address _loanCreatorsAddress, uint256 _loanID) external nonReentrant ETHRateNotInvalid {
        require(loanLiquidationOpen, "Liquidation is not open");
        // Close the creators loan and send collateral to the closer.
        _closeLoan(_loanCreatorsAddress, _loanID, true);
        // Tell the Dapps this loan was liquidated
        emit LoanLiquidated(_loanCreatorsAddress, _loanID, msg.sender);
    }

    // ========== PRIVATE FUNCTIONS ==========

    function _closeLoan(
        address account,
        uint256 loanID,
        bool liquidation
    ) private {
        systemStatus().requireIssuanceActive();

        // Get the loan from storage
        SynthLoanStruct memory synthLoan = _getLoanFromStorage(account, loanID);

        // Check loan exists and is open
        _checkLoanIsOpen(synthLoan);

        // Calculate and deduct accrued interest (5%) for fee pool
        // Accrued interests (captured in loanAmount) + new interests
        uint256 interestAmount = accruedInterestOnLoan(
            synthLoan.loanAmount.add(synthLoan.accruedInterest),
            _timeSinceInterestAccrual(synthLoan)
        );
        uint256 repayAmount = synthLoan.loanAmount.add(interestAmount);

        uint256 totalAccruedInterest = synthLoan.accruedInterest.add(interestAmount);

        require(
            IERC20(address(synthsUSD())).balanceOf(msg.sender) >= repayAmount,
            "You do not have the required Synth balance to close this loan."
        );

        // Record loan as closed
        _recordLoanClosure(synthLoan);

        // Decrement totalIssuedSynths
        // subtract the accrued interest from the loanAmount
        totalIssuedSynths = totalIssuedSynths.sub(synthLoan.loanAmount.sub(synthLoan.accruedInterest));

        // Burn all Synths issued for the loan + the fees
        synthsUSD().burn(msg.sender, repayAmount);

        // Fee distribution. Mint the sUSD fees into the FeePool and record fees paid
        synthsUSD().issue(FEE_ADDRESS, totalAccruedInterest);
        feePool().recordFeePaid(totalAccruedInterest);

        uint256 remainingCollateral = synthLoan.collateralAmount;

        if (liquidation) {
            // Send liquidator redeemed collateral + 10% penalty
            uint256 collateralRedeemed = exchangeRates().effectiveValue(sUSD, repayAmount, COLLATERAL);

            // add penalty
            uint256 totalCollateralLiquidated = collateralRedeemed.multiplyDecimal(
                SafeDecimalMath.unit().add(liquidationPenalty)
            );

            // ensure remaining ETH collateral sufficient to cover collateral liquidated
            // will revert if the liquidated collateral + penalty is more than remaining collateral
            remainingCollateral = remainingCollateral.sub(totalCollateralLiquidated);

            // Send liquidator CollateralLiquidated
            msg.sender.transfer(totalCollateralLiquidated);
        }

        // Send remaining collateral to loan creator
        synthLoan.account.transfer(remainingCollateral);

        // Tell the Dapps
        emit LoanClosed(account, loanID, totalAccruedInterest);
    }

    function _getLoanFromStorage(address account, uint256 loanID) private view returns (SynthLoanStruct memory) {
        SynthLoanStruct[] memory synthLoans = accountsSynthLoans[account];
        for (uint256 i = 0; i < synthLoans.length; i++) {
            if (synthLoans[i].loanID == loanID) {
                return synthLoans[i];
            }
        }
    }

    function _updateLoan(
        SynthLoanStruct memory _synthLoan,
        uint256 _newLoanAmount,
        uint256 _newAccruedInterest,
        uint256 _lastInterestAccrued
    ) private {
        // Get storage pointer to the accounts array of loans
        SynthLoanStruct[] storage synthLoans = accountsSynthLoans[_synthLoan.account];
        for (uint256 i = 0; i < synthLoans.length; i++) {
            if (synthLoans[i].loanID == _synthLoan.loanID) {
                synthLoans[i].loanAmount = _newLoanAmount;
                synthLoans[i].accruedInterest = _newAccruedInterest;
                synthLoans[i].lastInterestAccrued = uint40(_lastInterestAccrued);
            }
        }
    }

    function _updateLoanCollateral(SynthLoanStruct memory _synthLoan, uint256 _newCollateralAmount)
        private
        returns (SynthLoanStruct memory)
    {
        // Get storage pointer to the accounts array of loans
        SynthLoanStruct[] storage synthLoans = accountsSynthLoans[_synthLoan.account];
        for (uint256 i = 0; i < synthLoans.length; i++) {
            if (synthLoans[i].loanID == _synthLoan.loanID) {
                synthLoans[i].collateralAmount = _newCollateralAmount;
                return synthLoans[i];
            }
        }
    }

    function _recordLoanClosure(SynthLoanStruct memory synthLoan) private {
        // Get storage pointer to the accounts array of loans
        SynthLoanStruct[] storage synthLoans = accountsSynthLoans[synthLoan.account];
        for (uint256 i = 0; i < synthLoans.length; i++) {
            if (synthLoans[i].loanID == synthLoan.loanID) {
                // Record the time the loan was closed
                synthLoans[i].timeClosed = block.timestamp;
            }
        }

        // Reduce Total Open Loans Count
        totalOpenLoanCount = totalOpenLoanCount.sub(1);
    }

    function _incrementTotalLoansCounter() private returns (uint256) {
        // Increase the total Open loan count
        totalOpenLoanCount = totalOpenLoanCount.add(1);
        // Increase the total Loans Created count
        totalLoansCreated = totalLoansCreated.add(1);
        // Return total count to be used as a unique ID.
        return totalLoansCreated;
    }

    function _calculateMintingFee(uint256 _loanAmount) private view returns (uint256 mintingFee) {
        mintingFee = _loanAmount.multiplyDecimalRound(issueFeeRate);
    }

    function _timeSinceInterestAccrual(SynthLoanStruct memory _synthLoan) private view returns (uint256 timeSinceAccrual) {
        // The last interest accrued timestamp for the loan
        // If lastInterestAccrued timestamp is not set (0), use loan timeCreated
        uint256 lastInterestAccrual = _synthLoan.lastInterestAccrued > 0
            ? uint256(_synthLoan.lastInterestAccrued)
            : _synthLoan.timeCreated;

        // diff between last interested accrued and now
        // use loan's timeClosed if loan is closed
        timeSinceAccrual = _synthLoan.timeClosed > 0
            ? _synthLoan.timeClosed.sub(lastInterestAccrual)
            : block.timestamp.sub(lastInterestAccrual);
    }

    function _checkLoanIsOpen(SynthLoanStruct memory _synthLoan) internal pure {
        require(_synthLoan.loanID > 0, "Loan does not exist");
        require(_synthLoan.timeClosed == 0, "Loan already closed");
    }

    /* ========== INTERNAL VIEWS ========== */

    function systemStatus() internal view returns (ISystemStatus) {
        return ISystemStatus(requireAndGetAddress(CONTRACT_SYSTEMSTATUS, "Missing SystemStatus address"));
    }

    function synthsUSD() internal view returns (ISynth) {
        return ISynth(requireAndGetAddress(CONTRACT_SYNTHSUSD, "Missing SynthsUSD address"));
    }

    function exchangeRates() internal view returns (IExchangeRates) {
        return IExchangeRates(requireAndGetAddress(CONTRACT_EXRATES, "Missing ExchangeRates address"));
    }

    function feePool() internal view returns (IFeePool) {
        return IFeePool(requireAndGetAddress(CONTRACT_FEEPOOL, "Missing FeePool address"));
    }

    /* ========== MODIFIERS ========== */

    modifier ETHRateNotInvalid() {
        require(!exchangeRates().rateIsInvalid(COLLATERAL), "Blocked as ETH rate is invalid");
        _;
    }

    // ========== EVENTS ==========

    event CollateralizationRatioUpdated(uint256 ratio);
    event LiquidationRatioUpdated(uint256 ratio);
    event InterestRateUpdated(uint256 interestRate);
    event IssueFeeRateUpdated(uint256 issueFeeRate);
    event IssueLimitUpdated(uint256 issueLimit);
    event MinLoanCollateralSizeUpdated(uint256 minLoanCollateralSize);
    event AccountLoanLimitUpdated(uint256 loanLimit);
    event LoanLiquidationOpenUpdated(bool loanLiquidationOpen);
    event LoanCreated(address indexed account, uint256 loanID, uint256 amount);
    event LoanClosed(address indexed account, uint256 loanID, uint256 feesPaid);
    event LoanLiquidated(address indexed account, uint256 loanID, address liquidator);
    event LoanPartiallyLiquidated(
        address indexed account,
        uint256 loanID,
        address liquidator,
        uint256 liquidatedAmount,
        uint256 liquidatedCollateral
    );
    event CollateralDeposited(address indexed account, uint256 loanID, uint256 collateralAmount, uint256 collateralAfter);
    event CollateralWithdrawn(address indexed account, uint256 loanID, uint256 amountWithdrawn, uint256 collateralAfter);
    event LoanRepaid(address indexed account, uint256 loanID, uint256 repaidAmount, uint256 newLoanAmount);
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_resolver","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"loanLimit","type":"uint256"}],"name":"AccountLoanLimitUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"loanID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collateralAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collateralAfter","type":"uint256"}],"name":"CollateralDeposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"loanID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountWithdrawn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collateralAfter","type":"uint256"}],"name":"CollateralWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"ratio","type":"uint256"}],"name":"CollateralizationRatioUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"interestRate","type":"uint256"}],"name":"InterestRateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"issueFeeRate","type":"uint256"}],"name":"IssueFeeRateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"issueLimit","type":"uint256"}],"name":"IssueLimitUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"ratio","type":"uint256"}],"name":"LiquidationRatioUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"loanID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"feesPaid","type":"uint256"}],"name":"LoanClosed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"loanID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"LoanCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"loanID","type":"uint256"},{"indexed":false,"internalType":"address","name":"liquidator","type":"address"}],"name":"LoanLiquidated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"loanLiquidationOpen","type":"bool"}],"name":"LoanLiquidationOpenUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"loanID","type":"uint256"},{"indexed":false,"internalType":"address","name":"liquidator","type":"address"},{"indexed":false,"internalType":"uint256","name":"liquidatedAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"liquidatedCollateral","type":"uint256"}],"name":"LoanPartiallyLiquidated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"loanID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"repaidAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newLoanAmount","type":"uint256"}],"name":"LoanRepaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"minLoanCollateralSize","type":"uint256"}],"name":"MinLoanCollateralSizeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerNominated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"isPaused","type":"bool"}],"name":"PauseChanged","type":"event"},{"constant":true,"inputs":[],"name":"COLLATERAL","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"MAX_ADDRESSES_FROM_RESOLVER","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"acceptOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"accountLoanLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"accountOpenLoanCounter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"accountsSynthLoans","outputs":[{"internalType":"address payable","name":"account","type":"address"},{"internalType":"uint256","name":"collateralAmount","type":"uint256"},{"internalType":"uint256","name":"loanAmount","type":"uint256"},{"internalType":"uint256","name":"mintingFee","type":"uint256"},{"internalType":"uint256","name":"timeCreated","type":"uint256"},{"internalType":"uint256","name":"loanID","type":"uint256"},{"internalType":"uint256","name":"timeClosed","type":"uint256"},{"internalType":"uint256","name":"loanInterestRate","type":"uint256"},{"internalType":"uint256","name":"accruedInterest","type":"uint256"},{"internalType":"uint40","name":"lastInterestAccrued","type":"uint40"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"_loanAmount","type":"uint256"},{"internalType":"uint256","name":"_seconds","type":"uint256"}],"name":"accruedInterestOnLoan","outputs":[{"internalType":"uint256","name":"interestAmount","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"debtBalance","type":"uint256"},{"internalType":"uint256","name":"collateral","type":"uint256"}],"name":"calculateAmountToLiquidate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"loanID","type":"uint256"}],"name":"closeLoan","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"loanAmount","type":"uint256"}],"name":"collateralAmountForLoan","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"collateralizationRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint256","name":"_loanID","type":"uint256"}],"name":"currentInterestOnLoan","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"loanID","type":"uint256"}],"name":"depositCollateral","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"getContractInfo","outputs":[{"internalType":"uint256","name":"_collateralizationRatio","type":"uint256"},{"internalType":"uint256","name":"_issuanceRatio","type":"uint256"},{"internalType":"uint256","name":"_interestRate","type":"uint256"},{"internalType":"uint256","name":"_interestPerSecond","type":"uint256"},{"internalType":"uint256","name":"_issueFeeRate","type":"uint256"},{"internalType":"uint256","name":"_issueLimit","type":"uint256"},{"internalType":"uint256","name":"_minLoanCollateralSize","type":"uint256"},{"internalType":"uint256","name":"_totalIssuedSynths","type":"uint256"},{"internalType":"uint256","name":"_totalLoansCreated","type":"uint256"},{"internalType":"uint256","name":"_totalOpenLoanCount","type":"uint256"},{"internalType":"uint256","name":"_ethBalance","type":"uint256"},{"internalType":"uint256","name":"_liquidationDeadline","type":"uint256"},{"internalType":"bool","name":"_loanLiquidationOpen","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint256","name":"_loanID","type":"uint256"}],"name":"getLoan","outputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"collateralAmount","type":"uint256"},{"internalType":"uint256","name":"loanAmount","type":"uint256"},{"internalType":"uint256","name":"timeCreated","type":"uint256"},{"internalType":"uint256","name":"loanID","type":"uint256"},{"internalType":"uint256","name":"timeClosed","type":"uint256"},{"internalType":"uint256","name":"accruedInterest","type":"uint256"},{"internalType":"uint256","name":"totalFees","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint256","name":"_loanID","type":"uint256"}],"name":"getLoanCollateralRatio","outputs":[{"internalType":"uint256","name":"loanCollateralRatio","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint256","name":"_loanID","type":"uint256"}],"name":"getMintingFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getResolverAddressesRequired","outputs":[{"internalType":"bytes32[24]","name":"addressesRequired","type":"bytes32[24]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"interestPerSecond","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"interestRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"contract AddressResolver","name":"_resolver","type":"address"}],"name":"isResolverCached","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"issuanceRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"issueFeeRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"issueLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"lastPauseTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_loanCreatorsAddress","type":"address"},{"internalType":"uint256","name":"_loanID","type":"uint256"},{"internalType":"uint256","name":"_debtToCover","type":"uint256"}],"name":"liquidateLoan","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_loanCreatorsAddress","type":"address"},{"internalType":"uint256","name":"_loanID","type":"uint256"}],"name":"liquidateUnclosedLoan","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"liquidationDeadline","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"liquidationPenalty","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"liquidationRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"collateralAmount","type":"uint256"}],"name":"loanAmountFromCollateral","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"loanLiquidationOpen","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"minLoanCollateralSize","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"nominateNewOwner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"nominatedOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_loanAmount","type":"uint256"}],"name":"openLoan","outputs":[{"internalType":"uint256","name":"loanID","type":"uint256"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"openLoanIDsByAccount","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_loanCreatorsAddress","type":"address"},{"internalType":"uint256","name":"_loanID","type":"uint256"},{"internalType":"uint256","name":"_repayAmount","type":"uint256"}],"name":"repayLoan","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"resolver","outputs":[{"internalType":"contract AddressResolver","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"resolverAddressesRequired","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_loanLimit","type":"uint256"}],"name":"setAccountLoanLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"ratio","type":"uint256"}],"name":"setCollateralizationRatio","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_interestRate","type":"uint256"}],"name":"setInterestRate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_issueFeeRate","type":"uint256"}],"name":"setIssueFeeRate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_issueLimit","type":"uint256"}],"name":"setIssueLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_liquidationRatio","type":"uint256"}],"name":"setLiquidationRatio","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bool","name":"_loanLiquidationOpen","type":"bool"}],"name":"setLoanLiquidationOpen","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_minLoanCollateralSize","type":"uint256"}],"name":"setMinLoanCollateralSize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bool","name":"_paused","type":"bool"}],"name":"setPaused","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"contract AddressResolver","name":"_resolver","type":"address"}],"name":"setResolverAndSyncCache","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint256","name":"_loanID","type":"uint256"}],"name":"timeSinceInterestAccrualOnLoan","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint256","name":"_loanID","type":"uint256"}],"name":"totalFeesOnLoan","outputs":[{"internalType":"uint256","name":"interestAmount","type":"uint256"},{"internalType":"uint256","name":"mintingFee","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalIssuedSynths","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalLoansCreated","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalOpenLoanCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"loanID","type":"uint256"},{"internalType":"uint256","name":"withdrawAmount","type":"uint256"}],"name":"withdrawCollateral","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]

60806040819052630241ebdb60e61b81527384d626b2bb4d0f064067e4bf80fce7055d8f3e7b9063907af6c09060849060209060048186803b1580156200004557600080fd5b505af41580156200005a573d6000803e3d6000fd5b505050506040513d60208110156200007157600080fd5b505160960260085560408051630241ebdb60e61b815290516064917384d626b2bb4d0f064067e4bf80fce7055d8f3e7b9163907af6c091600480820192602092909190829003018186803b158015620000c957600080fd5b505af4158015620000de573d6000803e3d6000fd5b505050506040513d6020811015620000f557600080fd5b5051600502816200010257fe5b04600955620001266301e133806009546200069360201b6200404e1790919060201c565b600a556103e87384d626b2bb4d0f064067e4bf80fce7055d8f3e7b63907af6c06040518163ffffffff1660e01b815260040160206040518083038186803b1580156200017157600080fd5b505af415801562000186573d6000803e3d6000fd5b505050506040513d60208110156200019d57600080fd5b505160050281620001aa57fe5b04600b557384d626b2bb4d0f064067e4bf80fce7055d8f3e7b63907af6c06040518163ffffffff1660e01b815260040160206040518083038186803b158015620001f357600080fd5b505af415801562000208573d6000803e3d6000fd5b505050506040513d60208110156200021f57600080fd5b50516298968002600c5560408051630241ebdb60e61b815290517384d626b2bb4d0f064067e4bf80fce7055d8f3e7b9163907af6c0916004808301926020929190829003018186803b1580156200027557600080fd5b505af41580156200028a573d6000803e3d6000fd5b505050506040513d6020811015620002a157600080fd5b5051600d556032600e55600f805460ff1916905560408051630241ebdb60e61b815290516064917384d626b2bb4d0f064067e4bf80fce7055d8f3e7b9163907af6c091600480820192602092909190829003018186803b1580156200030557600080fd5b505af41580156200031a573d6000803e3d6000fd5b505050506040513d60208110156200033157600080fd5b5051609602816200033e57fe5b04601155600a7384d626b2bb4d0f064067e4bf80fce7055d8f3e7b63907af6c06040518163ffffffff1660e01b815260040160206040518083038186803b1580156200038957600080fd5b505af41580156200039e573d6000803e3d6000fd5b505050506040513d6020811015620003b557600080fd5b505181620003bf57fe5b0460125560405180608001604052806b53797374656d53746174757360a01b81526020016814de5b9d1a1cd554d160ba1b81526020016c45786368616e6765526174657360981b815260200166119959541bdbdb60ca1b81525060189060046200042b929190620006ff565b503480156200043957600080fd5b506040516200534238038062005342833981810160405260408110156200045f57600080fd5b508051602090910151604080516103008101918290528291601890819081845b8154815260200190600101908083116200047f57508793505050506001600160a01b038116620004f6576040805162461bcd60e51b815260206004820152601960248201527f4f776e657220616464726573732063616e6e6f74206265203000000000000000604482015290519081900360640190fd5b600080546001600160a01b0319166001600160a01b038316908117825560408051928352602083019190915280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a1506000546001600160a01b0316620005a1576040805162461bcd60e51b815260206004820152601160248201527013dddb995c881b5d5cdd081899481cd95d607a1b604482015290519081900360640190fd5b60016004556000546001600160a01b0316620005f8576040805162461bcd60e51b815260206004820152601160248201527013dddb995c881b5d5cdd081899481cd95d607a1b604482015290519081900360640190fd5b60005b6018811015620006605760008282601881106200061457fe5b602002015114620006515760078282601881106200062e57fe5b602090810291909101518254600181018455600093845291909220015562000657565b62000660565b600101620005fb565b5050600580546001600160a01b0319166001600160a01b039290921691909117905550504262794a000160105562000762565b6000808211620006ea576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b6000828481620006f657fe5b04949350505050565b826018810192821562000730579160200282015b828111156200073057825182559160200191906001019062000713565b506200073e92915062000742565b5090565b6200075f91905b808211156200073e576000815560010162000749565b90565b614bd080620007726000396000f3fe6080604052600436106103815760003560e01c80637c3a00fd116101d1578063ab49848c11610102578063e3235c91116100a0578063ee5f3f5c1161006f578063ee5f3f5c14610d43578063eea8f5da14610d58578063f45f08fb14610d6d578063f53dfb8414610da657610381565b8063e3235c9114610cda578063e3c1e58c14610cef578063e40108ed14610d04578063e5829d2014610d1957610381565b8063c6c9d828116100dc578063c6c9d82814610c38578063d05951a014610c62578063dcaf9c4414610c8c578063e220a81114610ca157610381565b8063ab49848c14610ba9578063b410a03414610bf7578063bb8c6d6c14610c0c57610381565b8063946ce8cd1161016f578063a2e1734211610149578063a2e1734214610a89578063a5d5db0c14610ab9578063a76cdfa514610ae5578063aa754a2a14610b0f57610381565b8063946ce8cd146109c65780639f7d5688146109f0578063a1c5158614610a0557610381565b806389c937de116101ab57806389c937de146109395780638da5cb5b146109725780638fdc8f3b1461098757806391b4ded9146109b157610381565b80637c3a00fd146108695780637cc1f8671461087e57806380a5d3d8146108fa57610381565b80633be99e6f116102b65780635c975abb11610254578063631e144411610223578063631e1444146107dc578063675969be1461080f578063767a7b051461082457806379ba50971461085457610381565b80635c975abb1461070d5780635d1a2229146107365780635f84f3021461076057806360655ba71461078a57610381565b80634f069f66116102905780634f069f66146106785780634f11815c146106a257806353a47bb7146106db57806354e3e70d146106f057610381565b80633be99e6f146105f75780634189bb491461062a578063462b97251461063f57610381565b806323aa7f0f116103235780632f2bf15b116102fd5780632f2bf15b146104f0578063361e208614610573578063384585711461058857806339735e37146105c757610381565b806323aa7f0f146104b157806323f5589a146104c657806324bbab8b146104db57610381565b80631627540c1161035f5780631627540c1461041157806316c38b3c146104465780631775765f1461047257806317da255e1461048757610381565b806304f3bcec14610386578063089f7fb4146103b75780631474b279146103fc575b600080fd5b34801561039257600080fd5b5061039b610dd0565b604080516001600160a01b039092168252519081900360200190f35b3480156103c357600080fd5b506103ea600480360360208110156103da57600080fd5b50356001600160a01b0316610ddf565b60408051918252519081900360200190f35b34801561040857600080fd5b506103ea610df1565b34801561041d57600080fd5b506104446004803603602081101561043457600080fd5b50356001600160a01b0316610df7565b005b34801561045257600080fd5b506104446004803603602081101561046957600080fd5b50351515610e53565b34801561047e57600080fd5b506103ea610ecd565b34801561049357600080fd5b50610444600480360360208110156104aa57600080fd5b5035610ed3565b3480156104bd57600080fd5b506103ea610f16565b3480156104d257600080fd5b506103ea610f1c565b3480156104e757600080fd5b506103ea610f22565b3480156104fc57600080fd5b506105236004803603602081101561051357600080fd5b50356001600160a01b0316610f2c565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561055f578181015183820152602001610547565b505050509050019250505060405180910390f35b34801561057f57600080fd5b506103ea61111e565b34801561059457600080fd5b50610444600480360360608110156105ab57600080fd5b506001600160a01b038135169060208101359060400135611124565b3480156105d357600080fd5b506103ea600480360360408110156105ea57600080fd5b50803590602001356116ff565b34801561060357600080fd5b506104446004803603602081101561061a57600080fd5b50356001600160a01b03166117f2565b34801561063657600080fd5b506103ea61191f565b34801561064b57600080fd5b506103ea6004803603604081101561066257600080fd5b506001600160a01b038135169060200135611925565b34801561068457600080fd5b506104446004803603602081101561069b57600080fd5b5035611945565b3480156106ae57600080fd5b506103ea600480360360408110156106c557600080fd5b506001600160a01b038135169060200135611988565b3480156106e757600080fd5b5061039b6119af565b6103ea6004803603602081101561070657600080fd5b50356119be565b34801561071957600080fd5b50610722612001565b604080519115158252519081900360200190f35b34801561074257600080fd5b506104446004803603602081101561075957600080fd5b503561200a565b34801561076c57600080fd5b506104446004803603602081101561078357600080fd5b503561208d565b34801561079657600080fd5b506107c3600480360360408110156107ad57600080fd5b506001600160a01b0381351690602001356121d9565b6040805192835260208301919091528051918290030190f35b3480156107e857600080fd5b50610722600480360360208110156107ff57600080fd5b50356001600160a01b0316612249565b34801561081b57600080fd5b506103ea612364565b34801561083057600080fd5b506104446004803603604081101561084757600080fd5b508035906020013561236a565b34801561086057600080fd5b506104446126c2565b34801561087557600080fd5b506103ea61277e565b34801561088a57600080fd5b50610893612784565b604080519d8e5260208e019c909c528c8c019a909a5260608c019890985260808b019690965260a08a019490945260c089019290925260e0880152610100870152610120860152610140850152610160840152151561018083015251908190036101a00190f35b34801561090657600080fd5b506104446004803603606081101561091d57600080fd5b506001600160a01b0381351690602081013590604001356127ef565b34801561094557600080fd5b506103ea6004803603604081101561095c57600080fd5b506001600160a01b038135169060200135612b50565b34801561097e57600080fd5b5061039b612bb2565b34801561099357600080fd5b506103ea600480360360208110156109aa57600080fd5b5035612bc1565b3480156109bd57600080fd5b506103ea612c67565b3480156109d257600080fd5b50610444600480360360208110156109e957600080fd5b5035612c6d565b3480156109fc57600080fd5b506103ea612d6a565b348015610a1157600080fd5b50610a3e60048036036040811015610a2857600080fd5b506001600160a01b038135169060200135612d70565b604080516001600160a01b0390991689526020890197909752878701959095526060870193909352608086019190915260a085015260c084015260e083015251908190036101000190f35b348015610a9557600080fd5b506103ea60048036036040811015610aac57600080fd5b5080359060200135612e17565b61044460048036036040811015610acf57600080fd5b506001600160a01b038135169060200135612e45565b348015610af157600080fd5b5061044460048036036020811015610b0857600080fd5b503561300b565b348015610b1b57600080fd5b50610b4860048036036040811015610b3257600080fd5b506001600160a01b03813516906020013561304e565b604080516001600160a01b03909b168b5260208b0199909952898901979097526060890195909552608088019390935260a087019190915260c086015260e085015261010084015264ffffffffff1661012083015251908190036101400190f35b348015610bb557600080fd5b50610bbe6130cc565b604051808261030080838360005b83811015610be4578181015183820152602001610bcc565b5050505090500191505060405180910390f35b348015610c0357600080fd5b506103ea613116565b348015610c1857600080fd5b5061044460048036036020811015610c2f57600080fd5b5035151561313b565b348015610c4457600080fd5b506103ea60048036036020811015610c5b57600080fd5b50356131e5565b348015610c6e57600080fd5b5061044460048036036020811015610c8557600080fd5b5035613203565b348015610c9857600080fd5b506103ea61331b565b348015610cad57600080fd5b5061044460048036036040811015610cc457600080fd5b506001600160a01b038135169060200135613321565b348015610ce657600080fd5b506103ea6134d2565b348015610cfb57600080fd5b506107226134d7565b348015610d1057600080fd5b506103ea6134e0565b348015610d2557600080fd5b5061044460048036036020811015610d3c57600080fd5b50356134e6565b348015610d4f57600080fd5b506103ea6135ba565b348015610d6457600080fd5b506103ea6135c0565b348015610d7957600080fd5b506103ea60048036036040811015610d9057600080fd5b506001600160a01b0381351690602001356135c6565b348015610db257600080fd5b506103ea60048036036020811015610dc957600080fd5b50356135f0565b6005546001600160a01b031681565b60176020526000908152604090205481565b600e5481565b610dff61369d565b600180546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229181900360200190a150565b610e5b61369d565b60035460ff1615158115151415610e7157610eca565b6003805460ff1916821515179081905560ff1615610e8e57426002555b6003546040805160ff90921615158252517f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec59181900360200190a15b50565b60115481565b610edb61369d565b600d8190556040805182815290517f9f45df4d81199bea8f20e88707b6f7d36b8e8f20a7def01c113746f67557ffb69181900360200190a150565b60145481565b60125481565b6208aa8960eb1b81565b6001600160a01b03811660009081526016602090815260408083208054825181850281018501909352808352606094859484015b828210156110035760008481526020908190206040805161014081018252600a860290920180546001600160a01b03168352600180820154848601526002820154928401929092526003810154606084015260048101546080840152600581015460a0840152600681015460c0840152600781015460e084015260088101546101008401526009015464ffffffffff166101208301529083529092019101610f60565b50505050905060608151604051908082528060200260200182016040528015611036578160200160208202803883390190505b5090506000805b83518110156110a45783818151811061105257fe5b602002602001015160c001516000141561109c5783818151811061107257fe5b602002602001015160a0015183838151811061108a57fe5b60209081029190910101526001909101905b60010161103d565b506060816040519080825280602002602001820160405280156110d1578160200160208202803883390190505b50905060005b82811015611112578381815181106110eb57fe5b60200260200101518282815181106110ff57fe5b60209081029190910101526001016110d7565b5093505050505b919050565b600b5481565b60048054600101908190556111376136e8565b6001600160a01b0316632528f0fe6208aa8960eb1b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561118057600080fd5b505afa158015611194573d6000803e3d6000fd5b505050506040513d60208110156111aa57600080fd5b5051156111ec576040805162461bcd60e51b815260206004820152601e6024820152600080516020614995833981519152604482015290519081900360640190fd5b6111f4613739565b6001600160a01b031663086dabd16040518163ffffffff1660e01b815260040160006040518083038186803b15801561122c57600080fd5b505afa158015611240573d6000803e3d6000fd5b505050508161124d613789565b6001600160a01b03166370a08231336040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156112a257600080fd5b505afa1580156112b6573d6000803e3d6000fd5b505050506040513d60208110156112cc57600080fd5b5051101561131b576040805162461bcd60e51b81526020600482015260176024820152764e6f7420656e6f75676820735553442062616c616e636560481b604482015290519081900360640190fd5b6113236147ef565b61132d85856137d6565b905061133881613919565b6000806000611346846139b5565b925092509250601154831061138c5760405162461bcd60e51b81526004018080602001828103825260288152602001806148726028913960400191505060405180910390fd5b60006113c36113bd836113b18861010001518960400151613aa590919063ffffffff16565b9063ffffffff613aa516565b846116ff565b905060008782106113d457876113d6565b815b90506113e0613789565b6001600160a01b0316639dc29fac33836040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b15801561143f57600080fd5b505af1158015611453573d6000803e3d6000fd5b50505050600080600061148284611478888c6101000151613aa590919063ffffffff16565b8b60400151613aff565b509250925092506114938383613b78565b600061149d6136e8565b6001600160a01b031663654a60ac631cd554d160e21b876208aa8960eb1b6040518463ffffffff1660e01b815260040180848152602001838152602001828152602001935050505060206040518083038186803b1580156114fd57600080fd5b505afa158015611511573d6000803e3d6000fd5b505050506040513d602081101561152757600080fd5b505160125460408051630241ebdb60e61b815290519293506000926115cc926115bf9290917384d626b2bb4d0f064067e4bf80fce7055d8f3e7b9163907af6c0916004808301926020929190829003018186803b15801561158757600080fd5b505af415801561159b573d6000803e3d6000fd5b505050506040513d60208110156115b157600080fd5b50519063ffffffff613aa516565b839063ffffffff613c9716565b90506115f08b6115e9868e60400151613cc190919063ffffffff16565b8542613d1e565b6116108b61160b838e60200151613cc190919063ffffffff16565b613dfe565b50604051339082156108fc029083906000818181858888f1935050505015801561163e573d6000803e3d6000fd5b508e6001600160a01b03167fb6e43890aeea54fbe6c0ed628e78172a0ff30bbcb1d70d8b130b12c366bac4c58f33898560405180858152602001846001600160a01b03166001600160a01b0316815260200183815260200182815260200194505050505060405180910390a2505050505050505050505060045481146116f9576040805162461bcd60e51b815260206004820152601f60248201526000805160206148cb833981519152604482015290519081900360640190fd5b50505050565b6000807384d626b2bb4d0f064067e4bf80fce7055d8f3e7b63907af6c06040518163ffffffff1660e01b815260040160206040518083038186803b15801561174657600080fd5b505af415801561175a573d6000803e3d6000fd5b505050506040513d602081101561177057600080fd5b5051601154909150600061179a61178d868463ffffffff613f2316565b879063ffffffff613cc116565b905060006117d36117c6846117ba60125488613aa590919063ffffffff16565b9063ffffffff613f2316565b859063ffffffff613cc116565b90506117e5828263ffffffff613f2316565b9450505050505b92915050565b6117fa61369d565b600580546001600160a01b0319166001600160a01b03831617905560005b60075481101561191b5760006007828154811061183157fe5b600091825260209182902001546005546040805163dacb2d0160e01b81526004810184905260248101829052601760448201527f5265736f6c766572206d697373696e6720746172676574000000000000000000606482015290519294506001600160a01b039091169263dacb2d0192608480840193829003018186803b1580156118bb57600080fd5b505afa1580156118cf573d6000803e3d6000fd5b505050506040513d60208110156118e557600080fd5b505160009182526006602052604090912080546001600160a01b0319166001600160a01b03909216919091179055600101611818565b5050565b60155481565b600061192f6147ef565b61193984846137d6565b60600151949350505050565b61194d61369d565b600c8190556040805182815290517fbb72ce8874020b3b98429d653df927cac6618ac1932384b1446bf04bf9a1b7e59181900360200190a150565b60006119926147ef565b61199c84846137d6565b90506119a781613f4d565b949350505050565b6001546001600160a01b031681565b60035460009060ff1615611a035760405162461bcd60e51b815260040180806020018281038252603c815260200180614a7e603c913960400191505060405180910390fd5b6004805460010190819055611a166136e8565b6001600160a01b0316632528f0fe6208aa8960eb1b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015611a5f57600080fd5b505afa158015611a73573d6000803e3d6000fd5b505050506040513d6020811015611a8957600080fd5b505115611acb576040805162461bcd60e51b815260206004820152601e6024820152600080516020614995833981519152604482015290519081900360640190fd5b611ad3613739565b6001600160a01b0316637c3125416040518163ffffffff1660e01b815260040160006040518083038186803b158015611b0b57600080fd5b505afa158015611b1f573d6000803e3d6000fd5b50505050600d54341015611b645760405162461bcd60e51b8152600401808060200182810382526048815260200180614b546048913960600191505060405180910390fd5b600f5460ff1615611bbc576040805162461bcd60e51b815260206004820152601e60248201527f4c6f616e7320617265206e6f77206265696e67206c6971756964617465640000604482015290519081900360640190fd5b600e543360009081526016602052604090205410611c0b5760405162461bcd60e51b8152600401808060200182810382526023815260200180614a0b6023913960400191505060405180910390fd5b6000611c1634612bc1565b905080841115611c575760405162461bcd60e51b81526004018080602001828103825260278152602001806149456027913960400191505060405180910390fd5b6000611c6285613fb4565b90506000611c76868363ffffffff613cc116565b9050600c54611c9087601354613aa590919063ffffffff16565b1115611ccd5760405162461bcd60e51b81526004018080602001828103825260238152602001806149e86023913960400191505060405180910390fd5b611cd5613fcb565b9450611cdf6147ef565b5060408051610140810182523381523460208201529081018790526060810183905242608082015260a08101869052600060c0820181905260095460e083015261010082018190526101208201528215611e2c57611d3b613789565b6001600160a01b031663867904b473feefeefeefeefeefeefeefeefeefeefeefeefeef856040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b158015611dae57600080fd5b505af1158015611dc2573d6000803e3d6000fd5b50505050611dce614003565b6001600160a01b03166322bf55ef846040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b158015611e1357600080fd5b505af1158015611e27573d6000803e3d6000fd5b505050505b336000908152601660209081526040808320805460018082018355918552938390208551600a9095020180546001600160a01b0319166001600160a01b0390951694909417845591840151918301919091558201516002820155606082015160038201556080820151600482015560a0820151600582015560c0820151600682015560e0820151600782015561010082015160088201556101208201516009909101805464ffffffffff191664ffffffffff909216919091179055601354611ef49088613aa5565b601355611eff613789565b6001600160a01b031663867904b433846040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b158015611f5e57600080fd5b505af1158015611f72573d6000803e3d6000fd5b505060408051898152602081018b905281513394507f58d170de3a12438e22d81380f353b2fcac86f0a708a1374deaa5c6322a95992f93509081900390910190a2505050506004548114611ffb576040805162461bcd60e51b815260206004820152601f60248201526000805160206148cb833981519152604482015290519081900360640190fd5b50919050565b60035460ff1681565b61201261369d565b6103e881106120525760405162461bcd60e51b81526004018080602001828103825260338152602001806149b56033913960400191505060405180910390fd5b600e8190556040805182815290517f59822dc2d999f6f0618e8b0db5cfc8496084574c769b09609d9b5f4394a310b69181900360200190a150565b61209561369d565b6301e1338081116120d75760405162461bcd60e51b8152600401808060200182810382526037815260200180614b1d6037913960400191505060405180910390fd5b7384d626b2bb4d0f064067e4bf80fce7055d8f3e7b63907af6c06040518163ffffffff1660e01b815260040160206040518083038186803b15801561211b57600080fd5b505af415801561212f573d6000803e3d6000fd5b505050506040513d602081101561214557600080fd5b50518111156121855760405162461bcd60e51b8152600401808060200182810382526025815260200180614aba6025913960400191505060405180910390fd5b600981905561219e816301e1338063ffffffff61404e16565b600a5560095460408051918252517fa90e14be5aa57b910aa6dc16c31ff1b5cda380ae25a793b0d3f74df6131a7d749181900360200190a150565b6000806121e46147ef565b6121ee85856137d6565b9050600061220e8261010001518360400151613aa590919063ffffffff16565b90506122376122258261222085613f4d565b612e17565b6101008401519063ffffffff613aa516565b93508160600151925050509250929050565b6005546000906001600160a01b0383811691161461226957506000611119565b60005b60075481101561235b5760006007828154811061228557fe5b6000918252602080832090910154808352600682526040928390205460055484516321f8a72160e01b81526004810184905294519295506001600160a01b03918216949116926321f8a72192602480840193829003018186803b1580156122eb57600080fd5b505afa1580156122ff573d6000803e3d6000fd5b505050506040513d602081101561231557600080fd5b50516001600160a01b031614158061234257506000818152600660205260409020546001600160a01b0316155b1561235257600092505050611119565b5060010161226c565b50600192915050565b600d5481565b60035460ff16156123ac5760405162461bcd60e51b815260040180806020018281038252603c815260200180614a7e603c913960400191505060405180910390fd5b60048054600101908190556123bf6136e8565b6001600160a01b0316632528f0fe6208aa8960eb1b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561240857600080fd5b505afa15801561241c573d6000803e3d6000fd5b505050506040513d602081101561243257600080fd5b505115612474576040805162461bcd60e51b815260206004820152601e6024820152600080516020614995833981519152604482015290519081900360640190fd5b600082116124b35760405162461bcd60e51b815260040180806020018281038252602981526020018061496c6029913960400191505060405180910390fd5b6124bb613739565b6001600160a01b0316637c3125416040518163ffffffff1660e01b815260040160006040518083038186803b1580156124f357600080fd5b505afa158015612507573d6000803e3d6000fd5b5050600f5460ff161591506125659050576040805162461bcd60e51b815260206004820152601e60248201527f4c6f616e7320617265206e6f77206265696e67206c6971756964617465640000604482015290519081900360640190fd5b61256d6147ef565b61257733856137d6565b905061258281613919565b602081015160009061259a908563ffffffff613cc116565b90506125a46147ef565b6125ae8383613dfe565b905060006125bb826139b5565b5050905060115481116125ff5760405162461bcd60e51b815260040180806020018281038252603181526020018061489a6031913960400191505060405180910390fd5b604051339087156108fc029088906000818181858888f1935050505015801561262c573d6000803e3d6000fd5b50602080830151604080518a8152928301899052828101919091525133917ffae26280bca25d80f1501a9e363c73d3845e651c9aaae54f1fc09a9dcd5f3303919081900360600190a25050505060045481146126bd576040805162461bcd60e51b815260206004820152601f60248201526000805160206148cb833981519152604482015290519081900360640190fd5b505050565b6001546001600160a01b0316331461270b5760405162461bcd60e51b81526004018080602001828103825260358152602001806148eb6035913960400191505060405180910390fd5b600054600154604080516001600160a01b03938416815292909116602083015280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b60095481565b6008546000808080808080808080808061279c613116565b9b506009549a50600a549950600b549850600c549750600d5496506013549550601454945060155493504792506010549150600f60009054906101000a900460ff169050909192939495969798999a9b9c565b6127f76136e8565b6001600160a01b0316632528f0fe6208aa8960eb1b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561284057600080fd5b505afa158015612854573d6000803e3d6000fd5b505050506040513d602081101561286a57600080fd5b5051156128ac576040805162461bcd60e51b815260206004820152601e6024820152600080516020614995833981519152604482015290519081900360640190fd5b6128b4613739565b6001600160a01b031663086dabd16040518163ffffffff1660e01b815260040160006040518083038186803b1580156128ec57600080fd5b505afa158015612900573d6000803e3d6000fd5b505050508061290d613789565b6001600160a01b03166370a08231336040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561296257600080fd5b505afa158015612976573d6000803e3d6000fd5b505050506040513d602081101561298c57600080fd5b505110156129db576040805162461bcd60e51b81526020600482015260176024820152764e6f7420656e6f75676820735553442062616c616e636560481b604482015290519081900360640190fd5b6129e36147ef565b6129ed84846137d6565b90506129f881613919565b6000612a168261010001518360400151613aa590919063ffffffff16565b90506000612a278261222085613f4d565b90506000612a4382856101000151613aa590919063ffffffff16565b9050600080600080612a5a89868a60400151613aff565b9350935093509350612a6a613789565b6001600160a01b0316639dc29fac338b6040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b158015612ac957600080fd5b505af1158015612add573d6000803e3d6000fd5b50505050612aeb8484613b78565b612af788828442613d1e565b604080518b8152602081018b905280820183905290516001600160a01b038d16917f2cebe3c4a7e8e81ca2035a6cb3ee450bb6401d9b6636652e183583f047049572919081900360600190a25050505050505050505050565b6000612b5a6147ef565b612b6484846137d6565b90506000612b90612b878361010001518460400151613aa590919063ffffffff16565b61222084613f4d565b610100830151909150612ba9908263ffffffff613aa516565b95945050505050565b6000546001600160a01b031681565b60006117ec612bce6136e8565b6001600160a01b031663ac82f6086208aa8960eb1b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015612c1757600080fd5b505afa158015612c2b573d6000803e3d6000fd5b505050506040513d6020811015612c4157600080fd5b5051612c5b612c4e613116565b859063ffffffff613c9716565b9063ffffffff613c9716565b60025481565b612c7561369d565b7384d626b2bb4d0f064067e4bf80fce7055d8f3e7b63907af6c06040518163ffffffff1660e01b815260040160206040518083038186803b158015612cb957600080fd5b505af4158015612ccd573d6000803e3d6000fd5b505050506040513d6020811015612ce357600080fd5b50518111612d2f576040805162461bcd60e51b8152602060048201526014602482015273526174696f206c657373207468616e203130302560601b604482015290519081900360640190fd5b60118190556040805182815290517f5568be83e5cf7405adf8fb39305e2cdf49c43336606d23c3e0d3fe54e205150a9181900360200190a150565b60105481565b600080600080600080600080612d846147ef565b612d8e8b8b6137d6565b9050806000015198508060200151975080604001519650806080015195508060a0015194508060c001519350612dee612ddc612b878361010001518460400151613aa590919063ffffffff16565b6101008301519063ffffffff613aa516565b9250612e07816060015184613aa590919063ffffffff16565b9150509295985092959890939650565b6000612e3e612e3183600a546140b890919063ffffffff16565b849063ffffffff61411116565b9392505050565b60035460ff1615612e875760405162461bcd60e51b815260040180806020018281038252603c815260200180614a7e603c913960400191505060405180910390fd5b60003411612ec65760405162461bcd60e51b81526004018080602001828103825260258152602001806149206025913960400191505060405180910390fd5b612ece613739565b6001600160a01b0316637c3125416040518163ffffffff1660e01b815260040160006040518083038186803b158015612f0657600080fd5b505afa158015612f1a573d6000803e3d6000fd5b5050600f5460ff16159150612f789050576040805162461bcd60e51b815260206004820152601e60248201527f4c6f616e7320617265206e6f77206265696e67206c6971756964617465640000604482015290519081900360640190fd5b612f806147ef565b612f8a83836137d6565b9050612f9581613919565b6020810151600090612fad903463ffffffff613aa516565b9050612fb98282613dfe565b506040805184815234602082015280820183905290516001600160a01b038616917f0b1992dffc262be88559dcaf96464e9d661d8bfca7e82f2bb73e31932a82187c919081900360600190a250505050565b61301361369d565b600b8190556040805182815290517fe7bd72551c54d568cd97b00dc52d2787b5c5d4f0070d3582c1e8ba25141f799c9181900360200190a150565b6016602052816000526040600020818154811061306757fe5b60009182526020909120600a909102018054600182015460028301546003840154600485015460058601546006870154600788015460088901546009909901546001600160a01b039098169a50959850939692959194909392909164ffffffffff168a565b6130d4614852565b60005b60075481101561311257600781815481106130ee57fe5b906000526020600020015482826018811061310557fe5b60200201526001016130d7565b5090565b600061313660085468056bc75e2d6310000061412690919063ffffffff16565b905090565b61314361369d565b6010544211613199576040805162461bcd60e51b815260206004820152601b60248201527f4265666f7265206c69717569646174696f6e20646561646c696e650000000000604482015290519081900360640190fd5b600f805460ff191682151517908190556040805160ff90921615158252517faa52cf15c1fbb778214c66f64726e141551158858d1c06ca0392c6c5869c8567916020908290030190a150565b600781815481106131f257fe5b600091825260209091200154905081565b60048054600101908190556132166136e8565b6001600160a01b0316632528f0fe6208aa8960eb1b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561325f57600080fd5b505afa158015613273573d6000803e3d6000fd5b505050506040513d602081101561328957600080fd5b5051156132cb576040805162461bcd60e51b815260206004820152601e6024820152600080516020614995833981519152604482015290519081900360640190fd5b6132d73383600061413b565b600454811461191b576040805162461bcd60e51b815260206004820152601f60248201526000805160206148cb833981519152604482015290519081900360640190fd5b60085481565b60048054600101908190556133346136e8565b6001600160a01b0316632528f0fe6208aa8960eb1b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561337d57600080fd5b505afa158015613391573d6000803e3d6000fd5b505050506040513d60208110156133a757600080fd5b5051156133e9576040805162461bcd60e51b815260206004820152601e6024820152600080516020614995833981519152604482015290519081900360640190fd5b600f5460ff16613440576040805162461bcd60e51b815260206004820152601760248201527f4c69717569646174696f6e206973206e6f74206f70656e000000000000000000604482015290519081900360640190fd5b61344c8383600161413b565b6040805183815233602082015281516001600160a01b038616927fde21b2a43b0a2c2109c049fb1e4bb8653fd67d0ffd74fdcb662db381f1eeab38928290030190a260045481146126bd576040805162461bcd60e51b815260206004820152601f60248201526000805160206148cb833981519152604482015290519081900360640190fd5b601881565b600f5460ff1681565b600a5481565b6134ee61369d565b683635c9adc5dea00000811115613537576040805162461bcd60e51b81526020600482015260086024820152670a8dede40d0d2ced60c31b604482015290519081900360640190fd5b68056bc75e2d6310000081101561357f576040805162461bcd60e51b8152602060048201526007602482015266546f6f206c6f7760c81b604482015290519081900360640190fd5b60088190556040805182815290517ffb0ebe8c7316e6a251494c38876d13d9a3a029273fce7964c12aa2ce078695309181900360200190a150565b60135481565b600c5481565b60006135d06147ef565b6135da84846137d6565b90506135e5816139b5565b509095945050505050565b60006117ec68056bc75e2d63100000613691612c4e61360d6136e8565b6001600160a01b031663ac82f6086208aa8960eb1b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561365657600080fd5b505afa15801561366a573d6000803e3d6000fd5b505050506040513d602081101561368057600080fd5b50516008549063ffffffff61412616565b9063ffffffff61412616565b6000546001600160a01b031633146136e65760405162461bcd60e51b815260040180806020018281038252602f815260200180614a2e602f913960400191505060405180910390fd5b565b60006131366c45786368616e6765526174657360981b6040518060400160405280601d81526020017f4d697373696e672045786368616e67655261746573206164647265737300000081525061464e565b60006131366b53797374656d53746174757360a01b6040518060400160405280601c81526020017f4d697373696e672053797374656d53746174757320616464726573730000000081525061464e565b60006131366814de5b9d1a1cd554d160ba1b6040518060400160405280601981526020017f4d697373696e672053796e74687355534420616464726573730000000000000081525061464e565b6137de6147ef565b6001600160a01b0383166000908152601660209081526040808320805482518185028101850190935280835260609492939192909184015b828210156138b95760008481526020908190206040805161014081018252600a860290920180546001600160a01b03168352600180820154848601526002820154928401929092526003810154606084015260048101546080840152600581015460a0840152600681015460c0840152600781015460e084015260088101546101008401526009015464ffffffffff166101208301529083529092019101613816565b509293506000925050505b815181101561391157838282815181106138da57fe5b602002602001015160a001511415613909578181815181106138f857fe5b6020026020010151925050506117ec565b6001016138c4565b505092915050565b60008160a0015111613968576040805162461bcd60e51b8152602060048201526013602482015272131bd85b88191bd95cc81b9bdd08195e1a5cdd606a1b604482015290519081900360640190fd5b60c081015115610eca576040805162461bcd60e51b8152602060048201526013602482015272131bd85b88185b1c9958591e4818db1bdcd959606a1b604482015290519081900360640190fd5b6000806000806139d78561010001518660400151613aa590919063ffffffff16565b90506139e68161222087613f4d565b9150613a796139f36136e8565b6001600160a01b031663ac82f6086208aa8960eb1b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015613a3c57600080fd5b505afa158015613a50573d6000803e3d6000fd5b505050506040513d6020811015613a6657600080fd5b505160208701519063ffffffff613c9716565b9250613a9b613a8e828463ffffffff613aa516565b849063ffffffff613f2316565b9350509193909250565b600082820183811015612e3e576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000808381868015801590613b145750600087115b15613b4f57868111613b265780613b28565b865b9450613b3a838663ffffffff613cc116565b9250613b4c818663ffffffff613cc116565b90505b8591508015613b6e57613b68828263ffffffff613cc116565b91508093505b5093509350935093565b8115613c7757613b86613789565b6001600160a01b031663867904b473feefeefeefeefeefeefeefeefeefeefeefeefeef846040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b158015613bf957600080fd5b505af1158015613c0d573d6000803e3d6000fd5b50505050613c19614003565b6001600160a01b03166322bf55ef836040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b158015613c5e57600080fd5b505af1158015613c72573d6000803e3d6000fd5b505050505b801561191b57601354613c90908263ffffffff613cc116565b6013555050565b6000670de0b6b3a7640000613cb2848463ffffffff6140b816565b81613cb957fe5b049392505050565b600082821115613d18576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b83516001600160a01b03166000908152601660205260408120905b8154811015613df6578560a00151828281548110613d5357fe5b90600052602060002090600a0201600501541415613dee5784828281548110613d7857fe5b90600052602060002090600a02016002018190555083828281548110613d9a57fe5b90600052602060002090600a02016008018190555082828281548110613dbc57fe5b90600052602060002090600a020160090160006101000a81548164ffffffffff021916908364ffffffffff1602179055505b600101613d39565b505050505050565b613e066147ef565b82516001600160a01b03166000908152601660205260408120905b8154811015613911578460a00151828281548110613e3b57fe5b90600052602060002090600a0201600501541415613f1b5783828281548110613e6057fe5b90600052602060002090600a020160010181905550818181548110613e8157fe5b60009182526020918290206040805161014081018252600a90930290910180546001600160a01b031683526001810154938301939093526002830154908201526003820154606082015260048201546080820152600582015460a0820152600682015460c0820152600782015460e0820152600882015461010082015260099091015464ffffffffff1661012082015292506117ec915050565b600101613e21565b6000612e3e82613f4185670de0b6b3a764000063ffffffff6140b816565b9063ffffffff61404e16565b600080600083610120015164ffffffffff1611613f6e578260800151613f7c565b82610120015164ffffffffff165b905060008360c0015111613f9f57613f9a428263ffffffff613cc116565b612e3e565b60c0830151612e3e908263ffffffff613cc116565b60006117ec600b548361411190919063ffffffff16565b601554600090613fe290600163ffffffff613aa516565b601555601454613ff990600163ffffffff613aa516565b6014819055905090565b600061313666119959541bdbdb60ca1b6040518060400160405280601781526020017f4d697373696e6720466565506f6f6c206164647265737300000000000000000081525061464e565b60008082116140a4576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b60008284816140af57fe5b04949350505050565b6000826140c7575060006117ec565b828202828482816140d457fe5b0414612e3e5760405162461bcd60e51b8152600401808060200182810382526021815260200180614a5d6021913960400191505060405180910390fd5b6000612e3e8383670de0b6b3a76400006146f8565b6000612e3e8383670de0b6b3a7640000614735565b614143613739565b6001600160a01b0316637c3125416040518163ffffffff1660e01b815260040160006040518083038186803b15801561417b57600080fd5b505afa15801561418f573d6000803e3d6000fd5b5050505061419b6147ef565b6141a584846137d6565b90506141b081613919565b60006141d1612b878361010001518460400151613aa590919063ffffffff16565b905060006141ec828460400151613aa590919063ffffffff16565b9050600061420883856101000151613aa590919063ffffffff16565b905081614213613789565b6001600160a01b03166370a08231336040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561426857600080fd5b505afa15801561427c573d6000803e3d6000fd5b505050506040513d602081101561429257600080fd5b505110156142d15760405162461bcd60e51b815260040180806020018281038252603e815260200180614adf603e913960400191505060405180910390fd5b6142da8461475b565b6143086142f98561010001518660400151613cc190919063ffffffff16565b6013549063ffffffff613cc116565b601355614313613789565b6001600160a01b0316639dc29fac33846040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b15801561437257600080fd5b505af1158015614386573d6000803e3d6000fd5b50505050614392613789565b6001600160a01b031663867904b473feefeefeefeefeefeefeefeefeefeefeefeefeef836040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b15801561440557600080fd5b505af1158015614419573d6000803e3d6000fd5b50505050614425614003565b6001600160a01b03166322bf55ef826040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561446a57600080fd5b505af115801561447e573d6000803e3d6000fd5b50505050602084015185156145c75760006144976136e8565b6001600160a01b031663654a60ac631cd554d160e21b866208aa8960eb1b6040518463ffffffff1660e01b815260040180848152602001838152602001828152602001935050505060206040518083038186803b1580156144f757600080fd5b505afa15801561450b573d6000803e3d6000fd5b505050506040513d602081101561452157600080fd5b505160125460408051630241ebdb60e61b81529051929350600092614581926115bf9290917384d626b2bb4d0f064067e4bf80fce7055d8f3e7b9163907af6c0916004808301926020929190829003018186803b15801561158757600080fd5b9050614593838263ffffffff613cc116565b604051909350339082156108fc029083906000818181858888f193505050501580156145c3573d6000803e3d6000fd5b5050505b84516040516001600160a01b039091169082156108fc029083906000818181858888f19350505050158015614600573d6000803e3d6000fd5b50604080518881526020810184905281516001600160a01b038b16927f3cc9f5d298758bad94536f27fa6a3033c2793e0a387a2d78e72550a3b8dacf1e928290030190a25050505050505050565b6000828152600660205260408120546001600160a01b031682816146f05760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156146b557818101518382015260200161469d565b50505050905090810190601f1680156146e25780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b509392505050565b600080600a830461470f868663ffffffff6140b816565b8161471657fe5b0490506005600a825b061061472957600a015b600a9004949350505050565b60008061474f84613f4187600a870263ffffffff6140b816565b90506005600a8261471f565b80516001600160a01b03166000908152601660205260408120905b81548110156147d3578260a0015182828154811061479057fe5b90600052602060002090600a02016005015414156147cb57428282815481106147b557fe5b90600052602060002090600a0201600601819055505b600101614776565b506015546147e890600163ffffffff613cc116565b6015555050565b60405180610140016040528060006001600160a01b031681526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600064ffffffffff1681525090565b604051806103000160405280601890602082028038833950919291505056fe436f6c6c61746572616c20726174696f2061626f7665206c69717569646174696f6e20726174696f436f6c6c61746572616c20726174696f2062656c6f77206c69717569646174696f6e2061667465722077697468647261775265656e7472616e637947756172643a207265656e7472616e742063616c6c00596f75206d757374206265206e6f6d696e61746564206265666f726520796f752063616e20616363657074206f776e6572736869704465706f73697420616d6f756e74206d7573742062652067726561746572207468616e20304c6f616e20616d6f756e742065786365656473206d617820626f72726f77696e6720706f776572416d6f756e7420746f207769746864726177206d7573742062652067726561746572207468616e2030426c6f636b656420617320455448207261746520697320696e76616c696400004f776e65722063616e6e6f742073657420686967686572207468616e204143434f554e545f4c4f414e5f4c494d49545f4341504c6f616e20416d6f756e7420657863656564732074686520737570706c79206361702e45616368206163636f756e74206973206c696d6974656420746f203530206c6f616e734f6e6c792074686520636f6e7472616374206f776e6572206d617920706572666f726d207468697320616374696f6e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f775468697320616374696f6e2063616e6e6f7420626520706572666f726d6564207768696c652074686520636f6e747261637420697320706175736564496e7465726573742063616e6e6f74206265206d6f7265207468616e203130302520415052596f7520646f206e6f742068617665207468652072657175697265642053796e74682062616c616e636520746f20636c6f73652074686973206c6f616e2e496e74657265737420726174652063616e6e6f74206265206c657373207468617420746865205345434f4e44535f494e5f415f594541524e6f7420656e6f7567682045544820746f206372656174652074686973206c6f616e2e20506c656173652073656520746865206d696e4c6f616e436f6c6c61746572616c53697a65a265627a7a72315820e6b58a3e9729ae5feebbb211c3c89855eb0a1370b08ab5b3623dfe9c496e795b64736f6c63430005100032000000000000000000000000de910777c787903f78c89e7a0bf7f4c435cbb1fe00000000000000000000000061166014e3f04e40c953fe4eab9d9e40863c83ae

Deployed Bytecode

0x6080604052600436106103815760003560e01c80637c3a00fd116101d1578063ab49848c11610102578063e3235c91116100a0578063ee5f3f5c1161006f578063ee5f3f5c14610d43578063eea8f5da14610d58578063f45f08fb14610d6d578063f53dfb8414610da657610381565b8063e3235c9114610cda578063e3c1e58c14610cef578063e40108ed14610d04578063e5829d2014610d1957610381565b8063c6c9d828116100dc578063c6c9d82814610c38578063d05951a014610c62578063dcaf9c4414610c8c578063e220a81114610ca157610381565b8063ab49848c14610ba9578063b410a03414610bf7578063bb8c6d6c14610c0c57610381565b8063946ce8cd1161016f578063a2e1734211610149578063a2e1734214610a89578063a5d5db0c14610ab9578063a76cdfa514610ae5578063aa754a2a14610b0f57610381565b8063946ce8cd146109c65780639f7d5688146109f0578063a1c5158614610a0557610381565b806389c937de116101ab57806389c937de146109395780638da5cb5b146109725780638fdc8f3b1461098757806391b4ded9146109b157610381565b80637c3a00fd146108695780637cc1f8671461087e57806380a5d3d8146108fa57610381565b80633be99e6f116102b65780635c975abb11610254578063631e144411610223578063631e1444146107dc578063675969be1461080f578063767a7b051461082457806379ba50971461085457610381565b80635c975abb1461070d5780635d1a2229146107365780635f84f3021461076057806360655ba71461078a57610381565b80634f069f66116102905780634f069f66146106785780634f11815c146106a257806353a47bb7146106db57806354e3e70d146106f057610381565b80633be99e6f146105f75780634189bb491461062a578063462b97251461063f57610381565b806323aa7f0f116103235780632f2bf15b116102fd5780632f2bf15b146104f0578063361e208614610573578063384585711461058857806339735e37146105c757610381565b806323aa7f0f146104b157806323f5589a146104c657806324bbab8b146104db57610381565b80631627540c1161035f5780631627540c1461041157806316c38b3c146104465780631775765f1461047257806317da255e1461048757610381565b806304f3bcec14610386578063089f7fb4146103b75780631474b279146103fc575b600080fd5b34801561039257600080fd5b5061039b610dd0565b604080516001600160a01b039092168252519081900360200190f35b3480156103c357600080fd5b506103ea600480360360208110156103da57600080fd5b50356001600160a01b0316610ddf565b60408051918252519081900360200190f35b34801561040857600080fd5b506103ea610df1565b34801561041d57600080fd5b506104446004803603602081101561043457600080fd5b50356001600160a01b0316610df7565b005b34801561045257600080fd5b506104446004803603602081101561046957600080fd5b50351515610e53565b34801561047e57600080fd5b506103ea610ecd565b34801561049357600080fd5b50610444600480360360208110156104aa57600080fd5b5035610ed3565b3480156104bd57600080fd5b506103ea610f16565b3480156104d257600080fd5b506103ea610f1c565b3480156104e757600080fd5b506103ea610f22565b3480156104fc57600080fd5b506105236004803603602081101561051357600080fd5b50356001600160a01b0316610f2c565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561055f578181015183820152602001610547565b505050509050019250505060405180910390f35b34801561057f57600080fd5b506103ea61111e565b34801561059457600080fd5b50610444600480360360608110156105ab57600080fd5b506001600160a01b038135169060208101359060400135611124565b3480156105d357600080fd5b506103ea600480360360408110156105ea57600080fd5b50803590602001356116ff565b34801561060357600080fd5b506104446004803603602081101561061a57600080fd5b50356001600160a01b03166117f2565b34801561063657600080fd5b506103ea61191f565b34801561064b57600080fd5b506103ea6004803603604081101561066257600080fd5b506001600160a01b038135169060200135611925565b34801561068457600080fd5b506104446004803603602081101561069b57600080fd5b5035611945565b3480156106ae57600080fd5b506103ea600480360360408110156106c557600080fd5b506001600160a01b038135169060200135611988565b3480156106e757600080fd5b5061039b6119af565b6103ea6004803603602081101561070657600080fd5b50356119be565b34801561071957600080fd5b50610722612001565b604080519115158252519081900360200190f35b34801561074257600080fd5b506104446004803603602081101561075957600080fd5b503561200a565b34801561076c57600080fd5b506104446004803603602081101561078357600080fd5b503561208d565b34801561079657600080fd5b506107c3600480360360408110156107ad57600080fd5b506001600160a01b0381351690602001356121d9565b6040805192835260208301919091528051918290030190f35b3480156107e857600080fd5b50610722600480360360208110156107ff57600080fd5b50356001600160a01b0316612249565b34801561081b57600080fd5b506103ea612364565b34801561083057600080fd5b506104446004803603604081101561084757600080fd5b508035906020013561236a565b34801561086057600080fd5b506104446126c2565b34801561087557600080fd5b506103ea61277e565b34801561088a57600080fd5b50610893612784565b604080519d8e5260208e019c909c528c8c019a909a5260608c019890985260808b019690965260a08a019490945260c089019290925260e0880152610100870152610120860152610140850152610160840152151561018083015251908190036101a00190f35b34801561090657600080fd5b506104446004803603606081101561091d57600080fd5b506001600160a01b0381351690602081013590604001356127ef565b34801561094557600080fd5b506103ea6004803603604081101561095c57600080fd5b506001600160a01b038135169060200135612b50565b34801561097e57600080fd5b5061039b612bb2565b34801561099357600080fd5b506103ea600480360360208110156109aa57600080fd5b5035612bc1565b3480156109bd57600080fd5b506103ea612c67565b3480156109d257600080fd5b50610444600480360360208110156109e957600080fd5b5035612c6d565b3480156109fc57600080fd5b506103ea612d6a565b348015610a1157600080fd5b50610a3e60048036036040811015610a2857600080fd5b506001600160a01b038135169060200135612d70565b604080516001600160a01b0390991689526020890197909752878701959095526060870193909352608086019190915260a085015260c084015260e083015251908190036101000190f35b348015610a9557600080fd5b506103ea60048036036040811015610aac57600080fd5b5080359060200135612e17565b61044460048036036040811015610acf57600080fd5b506001600160a01b038135169060200135612e45565b348015610af157600080fd5b5061044460048036036020811015610b0857600080fd5b503561300b565b348015610b1b57600080fd5b50610b4860048036036040811015610b3257600080fd5b506001600160a01b03813516906020013561304e565b604080516001600160a01b03909b168b5260208b0199909952898901979097526060890195909552608088019390935260a087019190915260c086015260e085015261010084015264ffffffffff1661012083015251908190036101400190f35b348015610bb557600080fd5b50610bbe6130cc565b604051808261030080838360005b83811015610be4578181015183820152602001610bcc565b5050505090500191505060405180910390f35b348015610c0357600080fd5b506103ea613116565b348015610c1857600080fd5b5061044460048036036020811015610c2f57600080fd5b5035151561313b565b348015610c4457600080fd5b506103ea60048036036020811015610c5b57600080fd5b50356131e5565b348015610c6e57600080fd5b5061044460048036036020811015610c8557600080fd5b5035613203565b348015610c9857600080fd5b506103ea61331b565b348015610cad57600080fd5b5061044460048036036040811015610cc457600080fd5b506001600160a01b038135169060200135613321565b348015610ce657600080fd5b506103ea6134d2565b348015610cfb57600080fd5b506107226134d7565b348015610d1057600080fd5b506103ea6134e0565b348015610d2557600080fd5b5061044460048036036020811015610d3c57600080fd5b50356134e6565b348015610d4f57600080fd5b506103ea6135ba565b348015610d6457600080fd5b506103ea6135c0565b348015610d7957600080fd5b506103ea60048036036040811015610d9057600080fd5b506001600160a01b0381351690602001356135c6565b348015610db257600080fd5b506103ea60048036036020811015610dc957600080fd5b50356135f0565b6005546001600160a01b031681565b60176020526000908152604090205481565b600e5481565b610dff61369d565b600180546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229181900360200190a150565b610e5b61369d565b60035460ff1615158115151415610e7157610eca565b6003805460ff1916821515179081905560ff1615610e8e57426002555b6003546040805160ff90921615158252517f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec59181900360200190a15b50565b60115481565b610edb61369d565b600d8190556040805182815290517f9f45df4d81199bea8f20e88707b6f7d36b8e8f20a7def01c113746f67557ffb69181900360200190a150565b60145481565b60125481565b6208aa8960eb1b81565b6001600160a01b03811660009081526016602090815260408083208054825181850281018501909352808352606094859484015b828210156110035760008481526020908190206040805161014081018252600a860290920180546001600160a01b03168352600180820154848601526002820154928401929092526003810154606084015260048101546080840152600581015460a0840152600681015460c0840152600781015460e084015260088101546101008401526009015464ffffffffff166101208301529083529092019101610f60565b50505050905060608151604051908082528060200260200182016040528015611036578160200160208202803883390190505b5090506000805b83518110156110a45783818151811061105257fe5b602002602001015160c001516000141561109c5783818151811061107257fe5b602002602001015160a0015183838151811061108a57fe5b60209081029190910101526001909101905b60010161103d565b506060816040519080825280602002602001820160405280156110d1578160200160208202803883390190505b50905060005b82811015611112578381815181106110eb57fe5b60200260200101518282815181106110ff57fe5b60209081029190910101526001016110d7565b5093505050505b919050565b600b5481565b60048054600101908190556111376136e8565b6001600160a01b0316632528f0fe6208aa8960eb1b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561118057600080fd5b505afa158015611194573d6000803e3d6000fd5b505050506040513d60208110156111aa57600080fd5b5051156111ec576040805162461bcd60e51b815260206004820152601e6024820152600080516020614995833981519152604482015290519081900360640190fd5b6111f4613739565b6001600160a01b031663086dabd16040518163ffffffff1660e01b815260040160006040518083038186803b15801561122c57600080fd5b505afa158015611240573d6000803e3d6000fd5b505050508161124d613789565b6001600160a01b03166370a08231336040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156112a257600080fd5b505afa1580156112b6573d6000803e3d6000fd5b505050506040513d60208110156112cc57600080fd5b5051101561131b576040805162461bcd60e51b81526020600482015260176024820152764e6f7420656e6f75676820735553442062616c616e636560481b604482015290519081900360640190fd5b6113236147ef565b61132d85856137d6565b905061133881613919565b6000806000611346846139b5565b925092509250601154831061138c5760405162461bcd60e51b81526004018080602001828103825260288152602001806148726028913960400191505060405180910390fd5b60006113c36113bd836113b18861010001518960400151613aa590919063ffffffff16565b9063ffffffff613aa516565b846116ff565b905060008782106113d457876113d6565b815b90506113e0613789565b6001600160a01b0316639dc29fac33836040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b15801561143f57600080fd5b505af1158015611453573d6000803e3d6000fd5b50505050600080600061148284611478888c6101000151613aa590919063ffffffff16565b8b60400151613aff565b509250925092506114938383613b78565b600061149d6136e8565b6001600160a01b031663654a60ac631cd554d160e21b876208aa8960eb1b6040518463ffffffff1660e01b815260040180848152602001838152602001828152602001935050505060206040518083038186803b1580156114fd57600080fd5b505afa158015611511573d6000803e3d6000fd5b505050506040513d602081101561152757600080fd5b505160125460408051630241ebdb60e61b815290519293506000926115cc926115bf9290917384d626b2bb4d0f064067e4bf80fce7055d8f3e7b9163907af6c0916004808301926020929190829003018186803b15801561158757600080fd5b505af415801561159b573d6000803e3d6000fd5b505050506040513d60208110156115b157600080fd5b50519063ffffffff613aa516565b839063ffffffff613c9716565b90506115f08b6115e9868e60400151613cc190919063ffffffff16565b8542613d1e565b6116108b61160b838e60200151613cc190919063ffffffff16565b613dfe565b50604051339082156108fc029083906000818181858888f1935050505015801561163e573d6000803e3d6000fd5b508e6001600160a01b03167fb6e43890aeea54fbe6c0ed628e78172a0ff30bbcb1d70d8b130b12c366bac4c58f33898560405180858152602001846001600160a01b03166001600160a01b0316815260200183815260200182815260200194505050505060405180910390a2505050505050505050505060045481146116f9576040805162461bcd60e51b815260206004820152601f60248201526000805160206148cb833981519152604482015290519081900360640190fd5b50505050565b6000807384d626b2bb4d0f064067e4bf80fce7055d8f3e7b63907af6c06040518163ffffffff1660e01b815260040160206040518083038186803b15801561174657600080fd5b505af415801561175a573d6000803e3d6000fd5b505050506040513d602081101561177057600080fd5b5051601154909150600061179a61178d868463ffffffff613f2316565b879063ffffffff613cc116565b905060006117d36117c6846117ba60125488613aa590919063ffffffff16565b9063ffffffff613f2316565b859063ffffffff613cc116565b90506117e5828263ffffffff613f2316565b9450505050505b92915050565b6117fa61369d565b600580546001600160a01b0319166001600160a01b03831617905560005b60075481101561191b5760006007828154811061183157fe5b600091825260209182902001546005546040805163dacb2d0160e01b81526004810184905260248101829052601760448201527f5265736f6c766572206d697373696e6720746172676574000000000000000000606482015290519294506001600160a01b039091169263dacb2d0192608480840193829003018186803b1580156118bb57600080fd5b505afa1580156118cf573d6000803e3d6000fd5b505050506040513d60208110156118e557600080fd5b505160009182526006602052604090912080546001600160a01b0319166001600160a01b03909216919091179055600101611818565b5050565b60155481565b600061192f6147ef565b61193984846137d6565b60600151949350505050565b61194d61369d565b600c8190556040805182815290517fbb72ce8874020b3b98429d653df927cac6618ac1932384b1446bf04bf9a1b7e59181900360200190a150565b60006119926147ef565b61199c84846137d6565b90506119a781613f4d565b949350505050565b6001546001600160a01b031681565b60035460009060ff1615611a035760405162461bcd60e51b815260040180806020018281038252603c815260200180614a7e603c913960400191505060405180910390fd5b6004805460010190819055611a166136e8565b6001600160a01b0316632528f0fe6208aa8960eb1b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015611a5f57600080fd5b505afa158015611a73573d6000803e3d6000fd5b505050506040513d6020811015611a8957600080fd5b505115611acb576040805162461bcd60e51b815260206004820152601e6024820152600080516020614995833981519152604482015290519081900360640190fd5b611ad3613739565b6001600160a01b0316637c3125416040518163ffffffff1660e01b815260040160006040518083038186803b158015611b0b57600080fd5b505afa158015611b1f573d6000803e3d6000fd5b50505050600d54341015611b645760405162461bcd60e51b8152600401808060200182810382526048815260200180614b546048913960600191505060405180910390fd5b600f5460ff1615611bbc576040805162461bcd60e51b815260206004820152601e60248201527f4c6f616e7320617265206e6f77206265696e67206c6971756964617465640000604482015290519081900360640190fd5b600e543360009081526016602052604090205410611c0b5760405162461bcd60e51b8152600401808060200182810382526023815260200180614a0b6023913960400191505060405180910390fd5b6000611c1634612bc1565b905080841115611c575760405162461bcd60e51b81526004018080602001828103825260278152602001806149456027913960400191505060405180910390fd5b6000611c6285613fb4565b90506000611c76868363ffffffff613cc116565b9050600c54611c9087601354613aa590919063ffffffff16565b1115611ccd5760405162461bcd60e51b81526004018080602001828103825260238152602001806149e86023913960400191505060405180910390fd5b611cd5613fcb565b9450611cdf6147ef565b5060408051610140810182523381523460208201529081018790526060810183905242608082015260a08101869052600060c0820181905260095460e083015261010082018190526101208201528215611e2c57611d3b613789565b6001600160a01b031663867904b473feefeefeefeefeefeefeefeefeefeefeefeefeef856040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b158015611dae57600080fd5b505af1158015611dc2573d6000803e3d6000fd5b50505050611dce614003565b6001600160a01b03166322bf55ef846040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b158015611e1357600080fd5b505af1158015611e27573d6000803e3d6000fd5b505050505b336000908152601660209081526040808320805460018082018355918552938390208551600a9095020180546001600160a01b0319166001600160a01b0390951694909417845591840151918301919091558201516002820155606082015160038201556080820151600482015560a0820151600582015560c0820151600682015560e0820151600782015561010082015160088201556101208201516009909101805464ffffffffff191664ffffffffff909216919091179055601354611ef49088613aa5565b601355611eff613789565b6001600160a01b031663867904b433846040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b158015611f5e57600080fd5b505af1158015611f72573d6000803e3d6000fd5b505060408051898152602081018b905281513394507f58d170de3a12438e22d81380f353b2fcac86f0a708a1374deaa5c6322a95992f93509081900390910190a2505050506004548114611ffb576040805162461bcd60e51b815260206004820152601f60248201526000805160206148cb833981519152604482015290519081900360640190fd5b50919050565b60035460ff1681565b61201261369d565b6103e881106120525760405162461bcd60e51b81526004018080602001828103825260338152602001806149b56033913960400191505060405180910390fd5b600e8190556040805182815290517f59822dc2d999f6f0618e8b0db5cfc8496084574c769b09609d9b5f4394a310b69181900360200190a150565b61209561369d565b6301e1338081116120d75760405162461bcd60e51b8152600401808060200182810382526037815260200180614b1d6037913960400191505060405180910390fd5b7384d626b2bb4d0f064067e4bf80fce7055d8f3e7b63907af6c06040518163ffffffff1660e01b815260040160206040518083038186803b15801561211b57600080fd5b505af415801561212f573d6000803e3d6000fd5b505050506040513d602081101561214557600080fd5b50518111156121855760405162461bcd60e51b8152600401808060200182810382526025815260200180614aba6025913960400191505060405180910390fd5b600981905561219e816301e1338063ffffffff61404e16565b600a5560095460408051918252517fa90e14be5aa57b910aa6dc16c31ff1b5cda380ae25a793b0d3f74df6131a7d749181900360200190a150565b6000806121e46147ef565b6121ee85856137d6565b9050600061220e8261010001518360400151613aa590919063ffffffff16565b90506122376122258261222085613f4d565b612e17565b6101008401519063ffffffff613aa516565b93508160600151925050509250929050565b6005546000906001600160a01b0383811691161461226957506000611119565b60005b60075481101561235b5760006007828154811061228557fe5b6000918252602080832090910154808352600682526040928390205460055484516321f8a72160e01b81526004810184905294519295506001600160a01b03918216949116926321f8a72192602480840193829003018186803b1580156122eb57600080fd5b505afa1580156122ff573d6000803e3d6000fd5b505050506040513d602081101561231557600080fd5b50516001600160a01b031614158061234257506000818152600660205260409020546001600160a01b0316155b1561235257600092505050611119565b5060010161226c565b50600192915050565b600d5481565b60035460ff16156123ac5760405162461bcd60e51b815260040180806020018281038252603c815260200180614a7e603c913960400191505060405180910390fd5b60048054600101908190556123bf6136e8565b6001600160a01b0316632528f0fe6208aa8960eb1b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561240857600080fd5b505afa15801561241c573d6000803e3d6000fd5b505050506040513d602081101561243257600080fd5b505115612474576040805162461bcd60e51b815260206004820152601e6024820152600080516020614995833981519152604482015290519081900360640190fd5b600082116124b35760405162461bcd60e51b815260040180806020018281038252602981526020018061496c6029913960400191505060405180910390fd5b6124bb613739565b6001600160a01b0316637c3125416040518163ffffffff1660e01b815260040160006040518083038186803b1580156124f357600080fd5b505afa158015612507573d6000803e3d6000fd5b5050600f5460ff161591506125659050576040805162461bcd60e51b815260206004820152601e60248201527f4c6f616e7320617265206e6f77206265696e67206c6971756964617465640000604482015290519081900360640190fd5b61256d6147ef565b61257733856137d6565b905061258281613919565b602081015160009061259a908563ffffffff613cc116565b90506125a46147ef565b6125ae8383613dfe565b905060006125bb826139b5565b5050905060115481116125ff5760405162461bcd60e51b815260040180806020018281038252603181526020018061489a6031913960400191505060405180910390fd5b604051339087156108fc029088906000818181858888f1935050505015801561262c573d6000803e3d6000fd5b50602080830151604080518a8152928301899052828101919091525133917ffae26280bca25d80f1501a9e363c73d3845e651c9aaae54f1fc09a9dcd5f3303919081900360600190a25050505060045481146126bd576040805162461bcd60e51b815260206004820152601f60248201526000805160206148cb833981519152604482015290519081900360640190fd5b505050565b6001546001600160a01b0316331461270b5760405162461bcd60e51b81526004018080602001828103825260358152602001806148eb6035913960400191505060405180910390fd5b600054600154604080516001600160a01b03938416815292909116602083015280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b60095481565b6008546000808080808080808080808061279c613116565b9b506009549a50600a549950600b549850600c549750600d5496506013549550601454945060155493504792506010549150600f60009054906101000a900460ff169050909192939495969798999a9b9c565b6127f76136e8565b6001600160a01b0316632528f0fe6208aa8960eb1b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561284057600080fd5b505afa158015612854573d6000803e3d6000fd5b505050506040513d602081101561286a57600080fd5b5051156128ac576040805162461bcd60e51b815260206004820152601e6024820152600080516020614995833981519152604482015290519081900360640190fd5b6128b4613739565b6001600160a01b031663086dabd16040518163ffffffff1660e01b815260040160006040518083038186803b1580156128ec57600080fd5b505afa158015612900573d6000803e3d6000fd5b505050508061290d613789565b6001600160a01b03166370a08231336040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561296257600080fd5b505afa158015612976573d6000803e3d6000fd5b505050506040513d602081101561298c57600080fd5b505110156129db576040805162461bcd60e51b81526020600482015260176024820152764e6f7420656e6f75676820735553442062616c616e636560481b604482015290519081900360640190fd5b6129e36147ef565b6129ed84846137d6565b90506129f881613919565b6000612a168261010001518360400151613aa590919063ffffffff16565b90506000612a278261222085613f4d565b90506000612a4382856101000151613aa590919063ffffffff16565b9050600080600080612a5a89868a60400151613aff565b9350935093509350612a6a613789565b6001600160a01b0316639dc29fac338b6040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b158015612ac957600080fd5b505af1158015612add573d6000803e3d6000fd5b50505050612aeb8484613b78565b612af788828442613d1e565b604080518b8152602081018b905280820183905290516001600160a01b038d16917f2cebe3c4a7e8e81ca2035a6cb3ee450bb6401d9b6636652e183583f047049572919081900360600190a25050505050505050505050565b6000612b5a6147ef565b612b6484846137d6565b90506000612b90612b878361010001518460400151613aa590919063ffffffff16565b61222084613f4d565b610100830151909150612ba9908263ffffffff613aa516565b95945050505050565b6000546001600160a01b031681565b60006117ec612bce6136e8565b6001600160a01b031663ac82f6086208aa8960eb1b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015612c1757600080fd5b505afa158015612c2b573d6000803e3d6000fd5b505050506040513d6020811015612c4157600080fd5b5051612c5b612c4e613116565b859063ffffffff613c9716565b9063ffffffff613c9716565b60025481565b612c7561369d565b7384d626b2bb4d0f064067e4bf80fce7055d8f3e7b63907af6c06040518163ffffffff1660e01b815260040160206040518083038186803b158015612cb957600080fd5b505af4158015612ccd573d6000803e3d6000fd5b505050506040513d6020811015612ce357600080fd5b50518111612d2f576040805162461bcd60e51b8152602060048201526014602482015273526174696f206c657373207468616e203130302560601b604482015290519081900360640190fd5b60118190556040805182815290517f5568be83e5cf7405adf8fb39305e2cdf49c43336606d23c3e0d3fe54e205150a9181900360200190a150565b60105481565b600080600080600080600080612d846147ef565b612d8e8b8b6137d6565b9050806000015198508060200151975080604001519650806080015195508060a0015194508060c001519350612dee612ddc612b878361010001518460400151613aa590919063ffffffff16565b6101008301519063ffffffff613aa516565b9250612e07816060015184613aa590919063ffffffff16565b9150509295985092959890939650565b6000612e3e612e3183600a546140b890919063ffffffff16565b849063ffffffff61411116565b9392505050565b60035460ff1615612e875760405162461bcd60e51b815260040180806020018281038252603c815260200180614a7e603c913960400191505060405180910390fd5b60003411612ec65760405162461bcd60e51b81526004018080602001828103825260258152602001806149206025913960400191505060405180910390fd5b612ece613739565b6001600160a01b0316637c3125416040518163ffffffff1660e01b815260040160006040518083038186803b158015612f0657600080fd5b505afa158015612f1a573d6000803e3d6000fd5b5050600f5460ff16159150612f789050576040805162461bcd60e51b815260206004820152601e60248201527f4c6f616e7320617265206e6f77206265696e67206c6971756964617465640000604482015290519081900360640190fd5b612f806147ef565b612f8a83836137d6565b9050612f9581613919565b6020810151600090612fad903463ffffffff613aa516565b9050612fb98282613dfe565b506040805184815234602082015280820183905290516001600160a01b038616917f0b1992dffc262be88559dcaf96464e9d661d8bfca7e82f2bb73e31932a82187c919081900360600190a250505050565b61301361369d565b600b8190556040805182815290517fe7bd72551c54d568cd97b00dc52d2787b5c5d4f0070d3582c1e8ba25141f799c9181900360200190a150565b6016602052816000526040600020818154811061306757fe5b60009182526020909120600a909102018054600182015460028301546003840154600485015460058601546006870154600788015460088901546009909901546001600160a01b039098169a50959850939692959194909392909164ffffffffff168a565b6130d4614852565b60005b60075481101561311257600781815481106130ee57fe5b906000526020600020015482826018811061310557fe5b60200201526001016130d7565b5090565b600061313660085468056bc75e2d6310000061412690919063ffffffff16565b905090565b61314361369d565b6010544211613199576040805162461bcd60e51b815260206004820152601b60248201527f4265666f7265206c69717569646174696f6e20646561646c696e650000000000604482015290519081900360640190fd5b600f805460ff191682151517908190556040805160ff90921615158252517faa52cf15c1fbb778214c66f64726e141551158858d1c06ca0392c6c5869c8567916020908290030190a150565b600781815481106131f257fe5b600091825260209091200154905081565b60048054600101908190556132166136e8565b6001600160a01b0316632528f0fe6208aa8960eb1b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561325f57600080fd5b505afa158015613273573d6000803e3d6000fd5b505050506040513d602081101561328957600080fd5b5051156132cb576040805162461bcd60e51b815260206004820152601e6024820152600080516020614995833981519152604482015290519081900360640190fd5b6132d73383600061413b565b600454811461191b576040805162461bcd60e51b815260206004820152601f60248201526000805160206148cb833981519152604482015290519081900360640190fd5b60085481565b60048054600101908190556133346136e8565b6001600160a01b0316632528f0fe6208aa8960eb1b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561337d57600080fd5b505afa158015613391573d6000803e3d6000fd5b505050506040513d60208110156133a757600080fd5b5051156133e9576040805162461bcd60e51b815260206004820152601e6024820152600080516020614995833981519152604482015290519081900360640190fd5b600f5460ff16613440576040805162461bcd60e51b815260206004820152601760248201527f4c69717569646174696f6e206973206e6f74206f70656e000000000000000000604482015290519081900360640190fd5b61344c8383600161413b565b6040805183815233602082015281516001600160a01b038616927fde21b2a43b0a2c2109c049fb1e4bb8653fd67d0ffd74fdcb662db381f1eeab38928290030190a260045481146126bd576040805162461bcd60e51b815260206004820152601f60248201526000805160206148cb833981519152604482015290519081900360640190fd5b601881565b600f5460ff1681565b600a5481565b6134ee61369d565b683635c9adc5dea00000811115613537576040805162461bcd60e51b81526020600482015260086024820152670a8dede40d0d2ced60c31b604482015290519081900360640190fd5b68056bc75e2d6310000081101561357f576040805162461bcd60e51b8152602060048201526007602482015266546f6f206c6f7760c81b604482015290519081900360640190fd5b60088190556040805182815290517ffb0ebe8c7316e6a251494c38876d13d9a3a029273fce7964c12aa2ce078695309181900360200190a150565b60135481565b600c5481565b60006135d06147ef565b6135da84846137d6565b90506135e5816139b5565b509095945050505050565b60006117ec68056bc75e2d63100000613691612c4e61360d6136e8565b6001600160a01b031663ac82f6086208aa8960eb1b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561365657600080fd5b505afa15801561366a573d6000803e3d6000fd5b505050506040513d602081101561368057600080fd5b50516008549063ffffffff61412616565b9063ffffffff61412616565b6000546001600160a01b031633146136e65760405162461bcd60e51b815260040180806020018281038252602f815260200180614a2e602f913960400191505060405180910390fd5b565b60006131366c45786368616e6765526174657360981b6040518060400160405280601d81526020017f4d697373696e672045786368616e67655261746573206164647265737300000081525061464e565b60006131366b53797374656d53746174757360a01b6040518060400160405280601c81526020017f4d697373696e672053797374656d53746174757320616464726573730000000081525061464e565b60006131366814de5b9d1a1cd554d160ba1b6040518060400160405280601981526020017f4d697373696e672053796e74687355534420616464726573730000000000000081525061464e565b6137de6147ef565b6001600160a01b0383166000908152601660209081526040808320805482518185028101850190935280835260609492939192909184015b828210156138b95760008481526020908190206040805161014081018252600a860290920180546001600160a01b03168352600180820154848601526002820154928401929092526003810154606084015260048101546080840152600581015460a0840152600681015460c0840152600781015460e084015260088101546101008401526009015464ffffffffff166101208301529083529092019101613816565b509293506000925050505b815181101561391157838282815181106138da57fe5b602002602001015160a001511415613909578181815181106138f857fe5b6020026020010151925050506117ec565b6001016138c4565b505092915050565b60008160a0015111613968576040805162461bcd60e51b8152602060048201526013602482015272131bd85b88191bd95cc81b9bdd08195e1a5cdd606a1b604482015290519081900360640190fd5b60c081015115610eca576040805162461bcd60e51b8152602060048201526013602482015272131bd85b88185b1c9958591e4818db1bdcd959606a1b604482015290519081900360640190fd5b6000806000806139d78561010001518660400151613aa590919063ffffffff16565b90506139e68161222087613f4d565b9150613a796139f36136e8565b6001600160a01b031663ac82f6086208aa8960eb1b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015613a3c57600080fd5b505afa158015613a50573d6000803e3d6000fd5b505050506040513d6020811015613a6657600080fd5b505160208701519063ffffffff613c9716565b9250613a9b613a8e828463ffffffff613aa516565b849063ffffffff613f2316565b9350509193909250565b600082820183811015612e3e576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000808381868015801590613b145750600087115b15613b4f57868111613b265780613b28565b865b9450613b3a838663ffffffff613cc116565b9250613b4c818663ffffffff613cc116565b90505b8591508015613b6e57613b68828263ffffffff613cc116565b91508093505b5093509350935093565b8115613c7757613b86613789565b6001600160a01b031663867904b473feefeefeefeefeefeefeefeefeefeefeefeefeef846040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b158015613bf957600080fd5b505af1158015613c0d573d6000803e3d6000fd5b50505050613c19614003565b6001600160a01b03166322bf55ef836040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b158015613c5e57600080fd5b505af1158015613c72573d6000803e3d6000fd5b505050505b801561191b57601354613c90908263ffffffff613cc116565b6013555050565b6000670de0b6b3a7640000613cb2848463ffffffff6140b816565b81613cb957fe5b049392505050565b600082821115613d18576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b83516001600160a01b03166000908152601660205260408120905b8154811015613df6578560a00151828281548110613d5357fe5b90600052602060002090600a0201600501541415613dee5784828281548110613d7857fe5b90600052602060002090600a02016002018190555083828281548110613d9a57fe5b90600052602060002090600a02016008018190555082828281548110613dbc57fe5b90600052602060002090600a020160090160006101000a81548164ffffffffff021916908364ffffffffff1602179055505b600101613d39565b505050505050565b613e066147ef565b82516001600160a01b03166000908152601660205260408120905b8154811015613911578460a00151828281548110613e3b57fe5b90600052602060002090600a0201600501541415613f1b5783828281548110613e6057fe5b90600052602060002090600a020160010181905550818181548110613e8157fe5b60009182526020918290206040805161014081018252600a90930290910180546001600160a01b031683526001810154938301939093526002830154908201526003820154606082015260048201546080820152600582015460a0820152600682015460c0820152600782015460e0820152600882015461010082015260099091015464ffffffffff1661012082015292506117ec915050565b600101613e21565b6000612e3e82613f4185670de0b6b3a764000063ffffffff6140b816565b9063ffffffff61404e16565b600080600083610120015164ffffffffff1611613f6e578260800151613f7c565b82610120015164ffffffffff165b905060008360c0015111613f9f57613f9a428263ffffffff613cc116565b612e3e565b60c0830151612e3e908263ffffffff613cc116565b60006117ec600b548361411190919063ffffffff16565b601554600090613fe290600163ffffffff613aa516565b601555601454613ff990600163ffffffff613aa516565b6014819055905090565b600061313666119959541bdbdb60ca1b6040518060400160405280601781526020017f4d697373696e6720466565506f6f6c206164647265737300000000000000000081525061464e565b60008082116140a4576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b60008284816140af57fe5b04949350505050565b6000826140c7575060006117ec565b828202828482816140d457fe5b0414612e3e5760405162461bcd60e51b8152600401808060200182810382526021815260200180614a5d6021913960400191505060405180910390fd5b6000612e3e8383670de0b6b3a76400006146f8565b6000612e3e8383670de0b6b3a7640000614735565b614143613739565b6001600160a01b0316637c3125416040518163ffffffff1660e01b815260040160006040518083038186803b15801561417b57600080fd5b505afa15801561418f573d6000803e3d6000fd5b5050505061419b6147ef565b6141a584846137d6565b90506141b081613919565b60006141d1612b878361010001518460400151613aa590919063ffffffff16565b905060006141ec828460400151613aa590919063ffffffff16565b9050600061420883856101000151613aa590919063ffffffff16565b905081614213613789565b6001600160a01b03166370a08231336040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561426857600080fd5b505afa15801561427c573d6000803e3d6000fd5b505050506040513d602081101561429257600080fd5b505110156142d15760405162461bcd60e51b815260040180806020018281038252603e815260200180614adf603e913960400191505060405180910390fd5b6142da8461475b565b6143086142f98561010001518660400151613cc190919063ffffffff16565b6013549063ffffffff613cc116565b601355614313613789565b6001600160a01b0316639dc29fac33846040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b15801561437257600080fd5b505af1158015614386573d6000803e3d6000fd5b50505050614392613789565b6001600160a01b031663867904b473feefeefeefeefeefeefeefeefeefeefeefeefeef836040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b15801561440557600080fd5b505af1158015614419573d6000803e3d6000fd5b50505050614425614003565b6001600160a01b03166322bf55ef826040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561446a57600080fd5b505af115801561447e573d6000803e3d6000fd5b50505050602084015185156145c75760006144976136e8565b6001600160a01b031663654a60ac631cd554d160e21b866208aa8960eb1b6040518463ffffffff1660e01b815260040180848152602001838152602001828152602001935050505060206040518083038186803b1580156144f757600080fd5b505afa15801561450b573d6000803e3d6000fd5b505050506040513d602081101561452157600080fd5b505160125460408051630241ebdb60e61b81529051929350600092614581926115bf9290917384d626b2bb4d0f064067e4bf80fce7055d8f3e7b9163907af6c0916004808301926020929190829003018186803b15801561158757600080fd5b9050614593838263ffffffff613cc116565b604051909350339082156108fc029083906000818181858888f193505050501580156145c3573d6000803e3d6000fd5b5050505b84516040516001600160a01b039091169082156108fc029083906000818181858888f19350505050158015614600573d6000803e3d6000fd5b50604080518881526020810184905281516001600160a01b038b16927f3cc9f5d298758bad94536f27fa6a3033c2793e0a387a2d78e72550a3b8dacf1e928290030190a25050505050505050565b6000828152600660205260408120546001600160a01b031682816146f05760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156146b557818101518382015260200161469d565b50505050905090810190601f1680156146e25780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b509392505050565b600080600a830461470f868663ffffffff6140b816565b8161471657fe5b0490506005600a825b061061472957600a015b600a9004949350505050565b60008061474f84613f4187600a870263ffffffff6140b816565b90506005600a8261471f565b80516001600160a01b03166000908152601660205260408120905b81548110156147d3578260a0015182828154811061479057fe5b90600052602060002090600a02016005015414156147cb57428282815481106147b557fe5b90600052602060002090600a0201600601819055505b600101614776565b506015546147e890600163ffffffff613cc116565b6015555050565b60405180610140016040528060006001600160a01b031681526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600064ffffffffff1681525090565b604051806103000160405280601890602082028038833950919291505056fe436f6c6c61746572616c20726174696f2061626f7665206c69717569646174696f6e20726174696f436f6c6c61746572616c20726174696f2062656c6f77206c69717569646174696f6e2061667465722077697468647261775265656e7472616e637947756172643a207265656e7472616e742063616c6c00596f75206d757374206265206e6f6d696e61746564206265666f726520796f752063616e20616363657074206f776e6572736869704465706f73697420616d6f756e74206d7573742062652067726561746572207468616e20304c6f616e20616d6f756e742065786365656473206d617820626f72726f77696e6720706f776572416d6f756e7420746f207769746864726177206d7573742062652067726561746572207468616e2030426c6f636b656420617320455448207261746520697320696e76616c696400004f776e65722063616e6e6f742073657420686967686572207468616e204143434f554e545f4c4f414e5f4c494d49545f4341504c6f616e20416d6f756e7420657863656564732074686520737570706c79206361702e45616368206163636f756e74206973206c696d6974656420746f203530206c6f616e734f6e6c792074686520636f6e7472616374206f776e6572206d617920706572666f726d207468697320616374696f6e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f775468697320616374696f6e2063616e6e6f7420626520706572666f726d6564207768696c652074686520636f6e747261637420697320706175736564496e7465726573742063616e6e6f74206265206d6f7265207468616e203130302520415052596f7520646f206e6f742068617665207468652072657175697265642053796e74682062616c616e636520746f20636c6f73652074686973206c6f616e2e496e74657265737420726174652063616e6e6f74206265206c657373207468617420746865205345434f4e44535f494e5f415f594541524e6f7420656e6f7567682045544820746f206372656174652074686973206c6f616e2e20506c656173652073656520746865206d696e4c6f616e436f6c6c61746572616c53697a65a265627a7a72315820e6b58a3e9729ae5feebbb211c3c89855eb0a1370b08ab5b3623dfe9c496e795b64736f6c63430005100032

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

000000000000000000000000de910777c787903f78c89e7a0bf7f4c435cbb1fe00000000000000000000000061166014e3f04e40c953fe4eab9d9e40863c83ae

-----Decoded View---------------
Arg [0] : _owner (address): 0xDe910777C787903F78C89e7a0bf7F4C435cBB1Fe
Arg [1] : _resolver (address): 0x61166014E3f04E40C953fe4EAb9D9E40863C83AE

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000de910777c787903f78c89e7a0bf7f4c435cbb1fe
Arg [1] : 00000000000000000000000061166014e3f04e40c953fe4eab9d9e40863c83ae


Libraries Used


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

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