Contract 0x53baE964339e8A742B5b47F6C10bbfa8Ff138F34

Contract Overview

Balance:
0 Ether
Txn Hash Method
Block
From
To
Value
0xb81070f244212a824f0d7c18bd6285874348ea0181af13611fb1cf18076bf3b9Accept Ownership243386142021-04-19 21:36:4028 days 23 hrs ago0x73570075092502472e4b61a7058df1a4a1db12f2 IN  0x53bae964339e8a742b5b47f6c10bbfa8ff138f340 Ether0.0000220881
0x20036d03113c70406fae4ddc907dad97d67cc3045e7d95a9b14e28043e8ef272Nominate New Own...243376802021-04-19 20:33:2829 days 7 mins ago0xb64ff7a4a33acdf48d97dab0d764afd0f6176882 IN  0x53bae964339e8a742b5b47f6c10bbfa8ff138f340 Ether0.0000448831
0xaf4722ea5e8974e4334a7eaad056695424ec559f06bcee268b2c8fe88e68087bSet Max Debt240317872021-03-23 19:52:1256 days 48 mins ago0xb64ff7a4a33acdf48d97dab0d764afd0f6176882 IN  0x53bae964339e8a742b5b47f6c10bbfa8ff138f340 Ether0.0000288121
0x7616a8167f17df7fc12a922f5280dcc2e580edb22f7e131b834a3ab9c88210b1Set Base Short R...229977882021-01-13 15:57:20125 days 4 hrs ago0xb64ff7a4a33acdf48d97dab0d764afd0f6176882 IN  0x53bae964339e8a742b5b47f6c10bbfa8ff138f340 Ether0.000057482
0xfcf1f15b9a808be7073e0caaad6f10b1278f5208a226e1376cb1724655ad8a4cSet Base Borrow ...229977872021-01-13 15:57:12125 days 4 hrs ago0xb64ff7a4a33acdf48d97dab0d764afd0f6176882 IN  0x53bae964339e8a742b5b47f6c10bbfa8ff138f340 Ether0.000057442
0x13f40b7d99c528c689e0e5dbfa13c2d4acaabca179d472392d9bfe60fb5dedddSet Max Debt229977852021-01-13 15:57:00125 days 4 hrs ago0xb64ff7a4a33acdf48d97dab0d764afd0f6176882 IN  0x53bae964339e8a742b5b47f6c10bbfa8ff138f340 Ether0.0000576242
0x0ee5015c8fb809c6e39d0e4dd956f87195e2b73cdb3301a9dba2b5b770210a45Add Collaterals229977812021-01-13 15:56:32125 days 4 hrs ago0xb64ff7a4a33acdf48d97dab0d764afd0f6176882 IN  0x53bae964339e8a742b5b47f6c10bbfa8ff138f340 Ether0.0003761422
0x8ef60e715c743d54647b905f74e863b45b274f0b4785bae7779d5e2474df92f6Add Collaterals229977342021-01-13 15:51:20125 days 4 hrs ago0xb64ff7a4a33acdf48d97dab0d764afd0f6176882 IN  0x53bae964339e8a742b5b47f6c10bbfa8ff138f340 Ether0.0000567542
0x36a96b69b577c2114ef5c4bdbcf610408a05a29b400628b3e682863a36372036Add Shortable Sy...227319682020-12-23 22:05:12145 days 22 hrs ago0xb64ff7a4a33acdf48d97dab0d764afd0f6176882 IN  0x53bae964339e8a742b5b47f6c10bbfa8ff138f340 Ether0.0023678355
0xe2252f981b24e1e555bc44b8dc3520a87fea0d5bae9e4913251b506ec5613473Add Synths227319672020-12-23 22:05:04145 days 22 hrs ago0xb64ff7a4a33acdf48d97dab0d764afd0f6176882 IN  0x53bae964339e8a742b5b47f6c10bbfa8ff138f340 Ether0.001170215
0x94545b4e1e8e7f25976837046ccaac46c990448ba48cc7cb9756f97ff2139618Add Collaterals227319632020-12-23 22:04:32145 days 22 hrs ago0xb64ff7a4a33acdf48d97dab0d764afd0f6176882 IN  0x53bae964339e8a742b5b47f6c10bbfa8ff138f340 Ether0.0008928755
0x2fc65fb3e84b50058cceb5a83eb29e412848d1dd52ba2c6a05fbb996f2ee214b0x670de0b6227319462020-12-23 22:02:40145 days 22 hrs ago0xb64ff7a4a33acdf48d97dab0d764afd0f6176882 IN  Contract Creation0 Ether0.017189455
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0x367a3106c89eae4d3111abb46452a59d091b1d6a1c988dbc808a27c4d7cbbbe9249191262021-05-18 19:46:4454 mins ago 0x253e60880f7393b02ef963fb98dd28eac6a0026e 0x53bae964339e8a742b5b47f6c10bbfa8ff138f340 Ether
0xa3913923f00cd03d111c700e7a10977980675f41a4fee67046733aa9c6cb03de249190452021-05-18 19:40:561 hr ago 0x253e60880f7393b02ef963fb98dd28eac6a0026e 0x53bae964339e8a742b5b47f6c10bbfa8ff138f340 Ether
0x930d8ab1dac81339898592fdf61d6fc267dd56edba1299c198d5cfa13d306498249190322021-05-18 19:40:001 hr 1 min ago 0x38635d2501f9ca46106a22be4af9b8c08c2b4823 0x53bae964339e8a742b5b47f6c10bbfa8ff138f340 Ether
0x930d8ab1dac81339898592fdf61d6fc267dd56edba1299c198d5cfa13d306498249190322021-05-18 19:40:001 hr 1 min ago 0x253e60880f7393b02ef963fb98dd28eac6a0026e 0x53bae964339e8a742b5b47f6c10bbfa8ff138f340 Ether
0x930d8ab1dac81339898592fdf61d6fc267dd56edba1299c198d5cfa13d306498249190322021-05-18 19:40:001 hr 1 min ago 0x253e60880f7393b02ef963fb98dd28eac6a0026e 0x53bae964339e8a742b5b47f6c10bbfa8ff138f340 Ether
0xa92b99e05181b09986c4cfd554504f12e96ca53347cc3d3af2a2365789982cf3249190292021-05-18 19:39:481 hr 1 min ago 0x253e60880f7393b02ef963fb98dd28eac6a0026e 0x53bae964339e8a742b5b47f6c10bbfa8ff138f340 Ether
0xa92b99e05181b09986c4cfd554504f12e96ca53347cc3d3af2a2365789982cf3249190292021-05-18 19:39:481 hr 1 min ago 0x253e60880f7393b02ef963fb98dd28eac6a0026e 0x53bae964339e8a742b5b47f6c10bbfa8ff138f340 Ether
0x7d19269c6ba694e0d7f213a0702674c17a014d093d2a1ff5d2c986e75b9dda4a249189542021-05-18 19:34:281 hr 6 mins ago 0x253e60880f7393b02ef963fb98dd28eac6a0026e 0x53bae964339e8a742b5b47f6c10bbfa8ff138f340 Ether
0xa6e1405cad6a921e7b302bb8d86a7fe2946abdf3d164c19ab69c77ba95f074b5249186242021-05-18 19:11:001 hr 30 mins ago 0x38635d2501f9ca46106a22be4af9b8c08c2b4823 0x53bae964339e8a742b5b47f6c10bbfa8ff138f340 Ether
0xa6e1405cad6a921e7b302bb8d86a7fe2946abdf3d164c19ab69c77ba95f074b5249186242021-05-18 19:11:001 hr 30 mins ago 0x253e60880f7393b02ef963fb98dd28eac6a0026e 0x53bae964339e8a742b5b47f6c10bbfa8ff138f340 Ether
0xa6e1405cad6a921e7b302bb8d86a7fe2946abdf3d164c19ab69c77ba95f074b5249186242021-05-18 19:11:001 hr 30 mins ago 0x253e60880f7393b02ef963fb98dd28eac6a0026e 0x53bae964339e8a742b5b47f6c10bbfa8ff138f340 Ether
0x60addf7c2a742bea34572cb73f6fce49f3f37c5512e62b1edb05ec8ec2473b8e249184482021-05-18 18:58:321 hr 42 mins ago 0x53bae964339e8a742b5b47f6c10bbfa8ff138f34 0x8d65ed88d6162a2b3b5f71c45d433d4aeac930650 Ether
0x60addf7c2a742bea34572cb73f6fce49f3f37c5512e62b1edb05ec8ec2473b8e249184482021-05-18 18:58:321 hr 42 mins ago 0x53bae964339e8a742b5b47f6c10bbfa8ff138f34 0xc9985cac4a69588da66f74e42845b784798fe5ab0 Ether
0x60addf7c2a742bea34572cb73f6fce49f3f37c5512e62b1edb05ec8ec2473b8e249184482021-05-18 18:58:321 hr 42 mins ago 0x53bae964339e8a742b5b47f6c10bbfa8ff138f34 0xce754192ee9265d71b6286db05329a16f20291cd0 Ether
0x60addf7c2a742bea34572cb73f6fce49f3f37c5512e62b1edb05ec8ec2473b8e249184482021-05-18 18:58:321 hr 42 mins ago 0x53bae964339e8a742b5b47f6c10bbfa8ff138f34 0x8d65ed88d6162a2b3b5f71c45d433d4aeac930650 Ether
0x60addf7c2a742bea34572cb73f6fce49f3f37c5512e62b1edb05ec8ec2473b8e249184482021-05-18 18:58:321 hr 42 mins ago 0x53bae964339e8a742b5b47f6c10bbfa8ff138f34 0xc9985cac4a69588da66f74e42845b784798fe5ab0 Ether
0x60addf7c2a742bea34572cb73f6fce49f3f37c5512e62b1edb05ec8ec2473b8e249184482021-05-18 18:58:321 hr 42 mins ago 0x53bae964339e8a742b5b47f6c10bbfa8ff138f34 0xa08868e26079c5e4c4334065a7e59192d6b3a33b0 Ether
0x60addf7c2a742bea34572cb73f6fce49f3f37c5512e62b1edb05ec8ec2473b8e249184482021-05-18 18:58:321 hr 42 mins ago 0x3ad8366b716deea3f46730debff537b713c76404 0x53bae964339e8a742b5b47f6c10bbfa8ff138f340 Ether
0x60addf7c2a742bea34572cb73f6fce49f3f37c5512e62b1edb05ec8ec2473b8e249184482021-05-18 18:58:321 hr 42 mins ago 0x53bae964339e8a742b5b47f6c10bbfa8ff138f34 0x8d65ed88d6162a2b3b5f71c45d433d4aeac930650 Ether
0x60addf7c2a742bea34572cb73f6fce49f3f37c5512e62b1edb05ec8ec2473b8e249184482021-05-18 18:58:321 hr 42 mins ago 0x53bae964339e8a742b5b47f6c10bbfa8ff138f34 0xc9985cac4a69588da66f74e42845b784798fe5ab0 Ether
0x60addf7c2a742bea34572cb73f6fce49f3f37c5512e62b1edb05ec8ec2473b8e249184482021-05-18 18:58:321 hr 42 mins ago 0x53bae964339e8a742b5b47f6c10bbfa8ff138f34 0xce754192ee9265d71b6286db05329a16f20291cd0 Ether
0x60addf7c2a742bea34572cb73f6fce49f3f37c5512e62b1edb05ec8ec2473b8e249184482021-05-18 18:58:321 hr 42 mins ago 0x53bae964339e8a742b5b47f6c10bbfa8ff138f34 0x8d65ed88d6162a2b3b5f71c45d433d4aeac930650 Ether
0x60addf7c2a742bea34572cb73f6fce49f3f37c5512e62b1edb05ec8ec2473b8e249184482021-05-18 18:58:321 hr 42 mins ago 0x53bae964339e8a742b5b47f6c10bbfa8ff138f34 0xc9985cac4a69588da66f74e42845b784798fe5ab0 Ether
0x60addf7c2a742bea34572cb73f6fce49f3f37c5512e62b1edb05ec8ec2473b8e249184482021-05-18 18:58:321 hr 42 mins ago 0x53bae964339e8a742b5b47f6c10bbfa8ff138f34 0xa08868e26079c5e4c4334065a7e59192d6b3a33b0 Ether
0x60addf7c2a742bea34572cb73f6fce49f3f37c5512e62b1edb05ec8ec2473b8e249184482021-05-18 18:58:321 hr 42 mins ago 0x53bae964339e8a742b5b47f6c10bbfa8ff138f34 0x8d65ed88d6162a2b3b5f71c45d433d4aeac930650 Ether
[ Download CSV Export 
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
CollateralManager

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-12-23
*/

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

* Synthetix: CollateralManager.sol
*
* Latest source (may be newer): https://github.com/Synthetixio/synthetix/blob/master/contracts/CollateralManager.sol
* Docs: https://docs.synthetix.io/contracts/CollateralManager
*
* Contract Dependencies: 
*	- IAddressResolver
*	- ICollateralManager
*	- MixinResolver
*	- Owned
*	- Pausable
*	- State
* Libraries: 
*	- AddressSetLib
*	- Bytes32SetLib
*	- 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/source/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/source/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");
        _;
    }
}


// https://docs.synthetix.io/contracts/source/interfaces/iaddressresolver
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);
}


// https://docs.synthetix.io/contracts/source/interfaces/isynth
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;
}


// https://docs.synthetix.io/contracts/source/interfaces/iissuer
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 getSynths(bytes32[] calldata currencyKeys) external view returns (ISynth[] memory);

    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


// Internal references


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

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

    /* ========== RESTRICTED 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++) {
            bytes32 name = names[i];
            address destination = destinations[i];
            repository[name] = destination;
            emit AddressImported(name, destination);
        }
    }

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

    function rebuildCaches(MixinResolver[] calldata destinations) external {
        for (uint i = 0; i < destinations.length; i++) {
            destinations[i].rebuildCache();
        }
    }

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

    function areAddressesImported(bytes32[] calldata names, address[] calldata destinations) external view returns (bool) {
        for (uint i = 0; i < names.length; i++) {
            if (repository[names[i]] != destinations[i]) {
                return false;
            }
        }
        return true;
    }

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

    /* ========== EVENTS ========== */

    event AddressImported(bytes32 name, address destination);
}


// solhint-disable payable-fallback

// https://docs.synthetix.io/contracts/source/contracts/readproxy
contract ReadProxy is Owned {
    address public target;

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

    function setTarget(address _target) external onlyOwner {
        target = _target;
        emit TargetUpdated(target);
    }

    function() external {
        // The basics of a proxy read call
        // Note that msg.sender in the underlying will always be the address of this contract.
        assembly {
            calldatacopy(0, 0, calldatasize)

            // Use of staticcall - this will revert if the underlying function mutates state
            let result := staticcall(gas, sload(target_slot), 0, calldatasize, 0, 0)
            returndatacopy(0, 0, returndatasize)

            if iszero(result) {
                revert(0, returndatasize)
            }
            return(0, returndatasize)
        }
    }

    event TargetUpdated(address newTarget);
}


// Inheritance


// Internal references


// https://docs.synthetix.io/contracts/source/contracts/mixinresolver
contract MixinResolver {
    AddressResolver public resolver;

    mapping(bytes32 => address) private addressCache;

    constructor(address _resolver) internal {
        resolver = AddressResolver(_resolver);
    }

    /* ========== INTERNAL FUNCTIONS ========== */

    function combineArrays(bytes32[] memory first, bytes32[] memory second)
        internal
        pure
        returns (bytes32[] memory combination)
    {
        combination = new bytes32[](first.length + second.length);

        for (uint i = 0; i < first.length; i++) {
            combination[i] = first[i];
        }

        for (uint j = 0; j < second.length; j++) {
            combination[first.length + j] = second[j];
        }
    }

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

    // Note: this function is public not external in order for it to be overridden and invoked via super in subclasses
    function resolverAddressesRequired() public view returns (bytes32[] memory addresses) {}

    function rebuildCache() public {
        bytes32[] memory requiredAddresses = resolverAddressesRequired();
        // The resolver must call this function whenver it updates its state
        for (uint i = 0; i < requiredAddresses.length; i++) {
            bytes32 name = requiredAddresses[i];
            // Note: can only be invoked once the resolver has all the targets needed added
            address destination = resolver.requireAndGetAddress(
                name,
                string(abi.encodePacked("Resolver missing target: ", name))
            );
            addressCache[name] = destination;
            emit CacheUpdated(name, destination);
        }
    }

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

    function isResolverCached() external view returns (bool) {
        bytes32[] memory requiredAddresses = resolverAddressesRequired();
        for (uint i = 0; i < requiredAddresses.length; i++) {
            bytes32 name = requiredAddresses[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;
    }

    /* ========== INTERNAL FUNCTIONS ========== */

    function requireAndGetAddress(bytes32 name) internal view returns (address) {
        address _foundAddress = addressCache[name];
        require(_foundAddress != address(0), string(abi.encodePacked("Missing address: ", name)));
        return _foundAddress;
    }

    /* ========== EVENTS ========== */

    event CacheUpdated(bytes32 name, address destination);
}


interface ICollateralManager {
    // Manager information
    function hasCollateral(address collateral) external view returns (bool);

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

    // State information
    function long(bytes32 synth) external view returns (uint amount);

    function short(bytes32 synth) external view returns (uint amount);

    function totalLong() external view returns (uint susdValue, bool anyRateIsInvalid);

    function totalShort() external view returns (uint susdValue, bool anyRateIsInvalid);

    function getBorrowRate() external view returns (uint borrowRate, bool anyRateIsInvalid);

    function getShortRate(bytes32 synth) external view returns (uint shortRate, bool rateIsInvalid);

    function getRatesAndTime(uint index)
        external
        view
        returns (
            uint entryRate,
            uint lastRate,
            uint lastUpdated,
            uint newIndex
        );

    function getShortRatesAndTime(bytes32 currency, uint index)
        external
        view
        returns (
            uint entryRate,
            uint lastRate,
            uint lastUpdated,
            uint newIndex
        );

    function exceedsDebtLimit(uint amount, bytes32 currency) external view returns (bool canIssue, bool anyRateIsInvalid);

    function areSynthsAndCurrenciesSet(bytes32[] calldata requiredSynthNamesInResolver, bytes32[] calldata synthKeys)
        external
        view
        returns (bool);

    function areShortableSynthsSet(bytes32[] calldata requiredSynthNamesInResolver, bytes32[] calldata synthKeys)
        external
        view
        returns (bool);

    // Loans
    function getNewLoanId() external returns (uint id);

    // Manager mutative
    function addCollaterals(address[] calldata collaterals) external;

    function removeCollaterals(address[] calldata collaterals) external;

    function addSynths(bytes32[] calldata synthNamesInResolver, bytes32[] calldata synthKeys) external;

    function removeSynths(bytes32[] calldata synths, bytes32[] calldata synthKeys) external;

    function addShortableSynths(bytes32[2][] calldata requiredSynthAndInverseNamesInResolver, bytes32[] calldata synthKeys)
        external;

    function removeShortableSynths(bytes32[] calldata synths) external;

    // State mutative
    function updateBorrowRates(uint rate) external;

    function updateShortRates(bytes32 currency, uint rate) external;

    function incrementLongs(bytes32 synth, uint amount) external;

    function decrementLongs(bytes32 synth, uint amount) external;

    function incrementShorts(bytes32 synth, uint amount) external;

    function decrementShorts(bytes32 synth, uint amount) external;
}


// https://docs.synthetix.io/contracts/source/libraries/addresssetlib/
library AddressSetLib {
    struct AddressSet {
        address[] elements;
        mapping(address => uint) indices;
    }

    function contains(AddressSet storage set, address candidate) internal view returns (bool) {
        if (set.elements.length == 0) {
            return false;
        }
        uint index = set.indices[candidate];
        return index != 0 || set.elements[0] == candidate;
    }

    function getPage(
        AddressSet storage set,
        uint index,
        uint pageSize
    ) internal view returns (address[] memory) {
        // NOTE: This implementation should be converted to slice operators if the compiler is updated to v0.6.0+
        uint endIndex = index + pageSize; // The check below that endIndex <= index handles overflow.

        // If the page extends past the end of the list, truncate it.
        if (endIndex > set.elements.length) {
            endIndex = set.elements.length;
        }
        if (endIndex <= index) {
            return new address[](0);
        }

        uint n = endIndex - index; // We already checked for negative overflow.
        address[] memory page = new address[](n);
        for (uint i; i < n; i++) {
            page[i] = set.elements[i + index];
        }
        return page;
    }

    function add(AddressSet storage set, address element) internal {
        // Adding to a set is an idempotent operation.
        if (!contains(set, element)) {
            set.indices[element] = set.elements.length;
            set.elements.push(element);
        }
    }

    function remove(AddressSet storage set, address element) internal {
        require(contains(set, element), "Element not in set.");
        // Replace the removed element with the last element of the list.
        uint index = set.indices[element];
        uint lastIndex = set.elements.length - 1; // We required that element is in the list, so it is not empty.
        if (index != lastIndex) {
            // No need to shift the last element if it is the one we want to delete.
            address shiftedElement = set.elements[lastIndex];
            set.elements[index] = shiftedElement;
            set.indices[shiftedElement] = index;
        }
        set.elements.pop();
        delete set.indices[element];
    }
}


// https://docs.synthetix.io/contracts/source/libraries/bytes32setlib/
library Bytes32SetLib {
    struct Bytes32Set {
        bytes32[] elements;
        mapping(bytes32 => uint) indices;
    }

    function contains(Bytes32Set storage set, bytes32 candidate) internal view returns (bool) {
        if (set.elements.length == 0) {
            return false;
        }
        uint index = set.indices[candidate];
        return index != 0 || set.elements[0] == candidate;
    }

    function getPage(
        Bytes32Set storage set,
        uint index,
        uint pageSize
    ) internal view returns (bytes32[] memory) {
        // NOTE: This implementation should be converted to slice operators if the compiler is updated to v0.6.0+
        uint endIndex = index + pageSize; // The check below that endIndex <= index handles overflow.

        // If the page extends past the end of the list, truncate it.
        if (endIndex > set.elements.length) {
            endIndex = set.elements.length;
        }
        if (endIndex <= index) {
            return new bytes32[](0);
        }

        uint n = endIndex - index; // We already checked for negative overflow.
        bytes32[] memory page = new bytes32[](n);
        for (uint i; i < n; i++) {
            page[i] = set.elements[i + index];
        }
        return page;
    }

    function add(Bytes32Set storage set, bytes32 element) internal {
        // Adding to a set is an idempotent operation.
        if (!contains(set, element)) {
            set.indices[element] = set.elements.length;
            set.elements.push(element);
        }
    }

    function remove(Bytes32Set storage set, bytes32 element) internal {
        require(contains(set, element), "Element not in set.");
        // Replace the removed element with the last element of the list.
        uint index = set.indices[element];
        uint lastIndex = set.elements.length - 1; // We required that element is in the list, so it is not empty.
        if (index != lastIndex) {
            // No need to shift the last element if it is the one we want to delete.
            bytes32 shiftedElement = set.elements[lastIndex];
            set.elements[index] = shiftedElement;
            set.indices[shiftedElement] = index;
        }
        set.elements.pop();
        delete set.indices[element];
    }
}


/**
 * @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/source/libraries/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;
    }
}


// Inheritance


// https://docs.synthetix.io/contracts/source/contracts/state
contract State is Owned {
    // the address of the contract that can modify variables
    // this can only be changed by the owner of this contract
    address public associatedContract;

    constructor(address _associatedContract) internal {
        // This contract is abstract, and thus cannot be instantiated directly
        require(owner != address(0), "Owner must be set");

        associatedContract = _associatedContract;
        emit AssociatedContractUpdated(_associatedContract);
    }

    /* ========== SETTERS ========== */

    // Change the associated contract to a new address
    function setAssociatedContract(address _associatedContract) external onlyOwner {
        associatedContract = _associatedContract;
        emit AssociatedContractUpdated(_associatedContract);
    }

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

    modifier onlyAssociatedContract {
        require(msg.sender == associatedContract, "Only the associated contract can perform this action");
        _;
    }

    /* ========== EVENTS ========== */

    event AssociatedContractUpdated(address associatedContract);
}


pragma experimental ABIEncoderV2;

// Inheritance


// Libraries


contract CollateralManagerState is Owned, State {
    using SafeMath for uint;
    using SafeDecimalMath for uint;

    struct Balance {
        uint long;
        uint short;
    }

    uint public totalLoans;

    uint[] public borrowRates;
    uint public borrowRatesLastUpdated;

    mapping(bytes32 => uint[]) public shortRates;
    mapping(bytes32 => uint) public shortRatesLastUpdated;

    // The total amount of long and short for a synth,
    mapping(bytes32 => Balance) public totalIssuedSynths;

    constructor(address _owner, address _associatedContract) public Owned(_owner) State(_associatedContract) {
        borrowRates.push(0);
        borrowRatesLastUpdated = block.timestamp;
    }

    function incrementTotalLoans() external onlyAssociatedContract returns (uint) {
        totalLoans = totalLoans.add(1);
        return totalLoans;
    }

    function long(bytes32 synth) external view onlyAssociatedContract returns (uint) {
        return totalIssuedSynths[synth].long;
    }

    function short(bytes32 synth) external view onlyAssociatedContract returns (uint) {
        return totalIssuedSynths[synth].short;
    }

    function incrementLongs(bytes32 synth, uint256 amount) external onlyAssociatedContract {
        totalIssuedSynths[synth].long = totalIssuedSynths[synth].long.add(amount);
    }

    function decrementLongs(bytes32 synth, uint256 amount) external onlyAssociatedContract {
        totalIssuedSynths[synth].long = totalIssuedSynths[synth].long.sub(amount);
    }

    function incrementShorts(bytes32 synth, uint256 amount) external onlyAssociatedContract {
        totalIssuedSynths[synth].short = totalIssuedSynths[synth].short.add(amount);
    }

    function decrementShorts(bytes32 synth, uint256 amount) external onlyAssociatedContract {
        totalIssuedSynths[synth].short = totalIssuedSynths[synth].short.sub(amount);
    }

    // Borrow rates, one array here for all currencies.

    function getRateAt(uint index) public view returns (uint) {
        return borrowRates[index];
    }

    function getRatesLength() public view returns (uint) {
        return borrowRates.length;
    }

    function updateBorrowRates(uint rate) external onlyAssociatedContract {
        borrowRates.push(rate);
        borrowRatesLastUpdated = block.timestamp;
    }

    function ratesLastUpdated() public view returns (uint) {
        return borrowRatesLastUpdated;
    }

    function getRatesAndTime(uint index)
        external
        view
        returns (
            uint entryRate,
            uint lastRate,
            uint lastUpdated,
            uint newIndex
        )
    {
        newIndex = getRatesLength();
        entryRate = getRateAt(index);
        lastRate = getRateAt(newIndex - 1);
        lastUpdated = ratesLastUpdated();
    }

    // Short rates, one array per currency.

    function addShortCurrency(bytes32 currency) external onlyAssociatedContract {
        if (shortRates[currency].length > 0) {} else {
            shortRates[currency].push(0);
            shortRatesLastUpdated[currency] = block.timestamp;
        }
    }

    function removeShortCurrency(bytes32 currency) external onlyAssociatedContract {
        delete shortRates[currency];
    }

    function getShortRateAt(bytes32 currency, uint index) internal view returns (uint) {
        return shortRates[currency][index];
    }

    function getShortRatesLength(bytes32 currency) public view returns (uint) {
        return shortRates[currency].length;
    }

    function updateShortRates(bytes32 currency, uint rate) external onlyAssociatedContract {
        shortRates[currency].push(rate);
        shortRatesLastUpdated[currency] = block.timestamp;
    }

    function shortRateLastUpdated(bytes32 currency) internal view returns (uint) {
        return shortRatesLastUpdated[currency];
    }

    function getShortRatesAndTime(bytes32 currency, uint index)
        external
        view
        returns (
            uint entryRate,
            uint lastRate,
            uint lastUpdated,
            uint newIndex
        )
    {
        newIndex = getShortRatesLength(currency);
        entryRate = getShortRateAt(currency, index);
        lastRate = getShortRateAt(currency, newIndex - 1);
        lastUpdated = shortRateLastUpdated(currency);
    }
}


// https://docs.synthetix.io/contracts/source/interfaces/isystemstatus
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;
}


// 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 rateAndInvalid(bytes32 currencyKey) external view returns (uint rate, bool isInvalid);

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


// https://docs.synthetix.io/contracts/source/interfaces/idebtcache
interface IDebtCache {
    // Views

    function cachedDebt() external view returns (uint);

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

    function cacheTimestamp() external view returns (uint);

    function cacheInvalid() external view returns (bool);

    function cacheStale() external view returns (bool);

    function currentSynthDebts(bytes32[] calldata currencyKeys)
        external
        view
        returns (uint[] memory debtValues, bool anyRateIsInvalid);

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

    function currentDebt() external view returns (uint debt, bool anyRateIsInvalid);

    function cacheInfo()
        external
        view
        returns (
            uint debt,
            uint timestamp,
            bool isInvalid,
            bool isStale
        );

    // Mutative functions

    function takeDebtSnapshot() external;

    function updateCachedSynthDebts(bytes32[] calldata currencyKeys) external;
}


// https://docs.synthetix.io/contracts/source/interfaces/ierc20
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);
}


// Inheritance


// Libraries


// Internal references


contract CollateralManager is ICollateralManager, Owned, Pausable, MixinResolver {
    /* ========== LIBRARIES ========== */
    using SafeMath for uint;
    using SafeDecimalMath for uint;
    using AddressSetLib for AddressSetLib.AddressSet;
    using Bytes32SetLib for Bytes32SetLib.Bytes32Set;

    /* ========== CONSTANTS ========== */

    bytes32 private constant sUSD = "sUSD";

    uint private constant SECONDS_IN_A_YEAR = 31556926 * 1e18;

    // Flexible storage names
    bytes32 public constant CONTRACT_NAME = "CollateralManager";
    bytes32 internal constant COLLATERAL_SYNTHS = "collateralSynth";

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

    // Stores debt balances and borrow rates.
    CollateralManagerState public state;

    // The set of all collateral contracts.
    AddressSetLib.AddressSet internal _collaterals;

    // The set of all synths issuable by the various collateral contracts
    Bytes32SetLib.Bytes32Set internal _synths;

    // Map from currency key to synth contract name.
    mapping(bytes32 => bytes32) public synthsByKey;

    // The set of all synths that are shortable.
    Bytes32SetLib.Bytes32Set internal _shortableSynths;

    mapping(bytes32 => bytes32) public synthToInverseSynth;

    // The factor that will scale the utilisation ratio.
    uint public utilisationMultiplier = 1e18;

    // The maximum amount of debt in sUSD that can be issued by non snx collateral.
    uint public maxDebt;

    // The base interest rate applied to all borrows.
    uint public baseBorrowRate;

    // The base interest rate applied to all shorts.
    uint public baseShortRate;

    /* ---------- Address Resolver Configuration ---------- */

    bytes32 private constant CONTRACT_SYSTEMSTATUS = "SystemStatus";
    bytes32 private constant CONTRACT_ISSUER = "Issuer";
    bytes32 private constant CONTRACT_EXRATES = "ExchangeRates";

    bytes32[24] private addressesToCache = [CONTRACT_SYSTEMSTATUS, CONTRACT_ISSUER, CONTRACT_EXRATES];

    /* ========== CONSTRUCTOR ========== */
    constructor(
        CollateralManagerState _state,
        address _owner,
        address _resolver,
        uint _maxDebt,
        uint _baseBorrowRate,
        uint _baseShortRate
    ) public Owned(_owner) Pausable() MixinResolver(_resolver) {
        owner = msg.sender;
        state = _state;

        setMaxDebt(_maxDebt);
        setBaseBorrowRate(_baseBorrowRate);
        setBaseShortRate(_baseShortRate);

        owner = _owner;
    }

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

    function resolverAddressesRequired() public view returns (bytes32[] memory addresses) {
        bytes32[] memory staticAddresses = new bytes32[](3);
        staticAddresses[0] = CONTRACT_ISSUER;
        staticAddresses[1] = CONTRACT_EXRATES;
        staticAddresses[2] = CONTRACT_SYSTEMSTATUS;

        // we want to cache the name of the synth and the name of its corresponding iSynth
        bytes32[] memory shortAddresses;
        uint length = _shortableSynths.elements.length;

        if (length > 0) {
            shortAddresses = new bytes32[](length * 2);

            for (uint i = 0; i < length; i++) {
                shortAddresses[i] = _shortableSynths.elements[i];
                shortAddresses[i + length] = synthToInverseSynth[_shortableSynths.elements[i]];
            }
        }

        bytes32[] memory synthAddresses = combineArrays(shortAddresses, _synths.elements);

        if (synthAddresses.length > 0) {
            addresses = combineArrays(synthAddresses, staticAddresses);
        } else {
            addresses = staticAddresses;
        }
    }

    // helper function to check whether synth "by key" is a collateral issued by multi-collateral
    function isSynthManaged(bytes32 currencyKey) external view returns (bool) {
        return synthsByKey[currencyKey] != bytes32(0);
    }

    /* ---------- Related Contracts ---------- */

    function _systemStatus() internal view returns (ISystemStatus) {
        return ISystemStatus(requireAndGetAddress(CONTRACT_SYSTEMSTATUS));
    }

    function _issuer() internal view returns (IIssuer) {
        return IIssuer(requireAndGetAddress(CONTRACT_ISSUER));
    }

    function _exchangeRates() internal view returns (IExchangeRates) {
        return IExchangeRates(requireAndGetAddress(CONTRACT_EXRATES));
    }

    function _synth(bytes32 synthName) internal view returns (ISynth) {
        return ISynth(requireAndGetAddress(synthName));
    }

    /* ---------- Manager Information ---------- */

    function hasCollateral(address collateral) public view returns (bool) {
        return _collaterals.contains(collateral);
    }

    function hasAllCollaterals(address[] memory collaterals) public view returns (bool) {
        for (uint i = 0; i < collaterals.length; i++) {
            if (!hasCollateral(collaterals[i])) {
                return false;
            }
        }
        return true;
    }

    /* ---------- State Information ---------- */

    function long(bytes32 synth) external view returns (uint amount) {
        return state.long(synth);
    }

    function short(bytes32 synth) external view returns (uint amount) {
        return state.short(synth);
    }

    function totalLong() public view returns (uint susdValue, bool anyRateIsInvalid) {
        bytes32[] memory synths = _synths.elements;

        if (synths.length > 0) {
            for (uint i = 0; i < synths.length; i++) {
                bytes32 synth = _synth(synths[i]).currencyKey();
                if (synth == sUSD) {
                    susdValue = susdValue.add(state.long(synth));
                } else {
                    (uint rate, bool invalid) = _exchangeRates().rateAndInvalid(synth);
                    uint amount = state.long(synth).multiplyDecimal(rate);
                    susdValue = susdValue.add(amount);
                    if (invalid) {
                        anyRateIsInvalid = true;
                    }
                }
            }
        }
    }

    function totalShort() public view returns (uint susdValue, bool anyRateIsInvalid) {
        bytes32[] memory synths = _shortableSynths.elements;

        if (synths.length > 0) {
            for (uint i = 0; i < synths.length; i++) {
                bytes32 synth = _synth(synths[i]).currencyKey();
                (uint rate, bool invalid) = _exchangeRates().rateAndInvalid(synth);
                uint amount = state.short(synth).multiplyDecimal(rate);
                susdValue = susdValue.add(amount);
                if (invalid) {
                    anyRateIsInvalid = true;
                }
            }
        }
    }

    function getBorrowRate() external view returns (uint borrowRate, bool anyRateIsInvalid) {
        // get the snx backed debt.
        uint snxDebt = _issuer().totalIssuedSynths(sUSD, true);

        // now get the non snx backed debt.
        (uint nonSnxDebt, bool ratesInvalid) = totalLong();

        // the total.
        uint totalDebt = snxDebt.add(nonSnxDebt);

        // now work out the utilisation ratio, and divide through to get a per second value.
        uint utilisation = nonSnxDebt.divideDecimal(totalDebt).divideDecimal(SECONDS_IN_A_YEAR);

        // scale it by the utilisation multiplier.
        uint scaledUtilisation = utilisation.multiplyDecimal(utilisationMultiplier);

        // finally, add the base borrow rate.
        borrowRate = scaledUtilisation.add(baseBorrowRate);

        anyRateIsInvalid = ratesInvalid;
    }

    function getShortRate(bytes32 synth) external view returns (uint shortRate, bool rateIsInvalid) {
        bytes32 synthKey = _synth(synth).currencyKey();

        rateIsInvalid = _exchangeRates().rateIsInvalid(synthKey);

        // get the spot supply of the synth, its iSynth
        uint longSupply = IERC20(address(_synth(synth))).totalSupply();
        uint inverseSupply = IERC20(address(_synth(synthToInverseSynth[synth]))).totalSupply();
        // add the iSynth to supply properly reflect the market skew.
        uint shortSupply = state.short(synthKey).add(inverseSupply);

        // in this case, the market is skewed long so its free to short.
        if (longSupply > shortSupply) {
            return (0, rateIsInvalid);
        }

        // otherwise workout the skew towards the short side.
        uint skew = shortSupply.sub(longSupply);

        // divide through by the size of the market
        uint proportionalSkew = skew.divideDecimal(longSupply.add(shortSupply)).divideDecimal(SECONDS_IN_A_YEAR);

        // finally, add the base short rate.
        shortRate = proportionalSkew.add(baseShortRate);
    }

    function getRatesAndTime(uint index)
        external
        view
        returns (
            uint entryRate,
            uint lastRate,
            uint lastUpdated,
            uint newIndex
        )
    {
        (entryRate, lastRate, lastUpdated, newIndex) = state.getRatesAndTime(index);
    }

    function getShortRatesAndTime(bytes32 currency, uint index)
        external
        view
        returns (
            uint entryRate,
            uint lastRate,
            uint lastUpdated,
            uint newIndex
        )
    {
        (entryRate, lastRate, lastUpdated, newIndex) = state.getShortRatesAndTime(currency, index);
    }

    function exceedsDebtLimit(uint amount, bytes32 currency) external view returns (bool canIssue, bool anyRateIsInvalid) {
        uint usdAmount = _exchangeRates().effectiveValue(currency, amount, sUSD);

        (uint longValue, bool longInvalid) = totalLong();
        (uint shortValue, bool shortInvalid) = totalShort();

        anyRateIsInvalid = longInvalid || shortInvalid;

        return (longValue.add(shortValue).add(usdAmount) <= maxDebt, anyRateIsInvalid);
    }

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

    /* ---------- SETTERS ---------- */

    function setUtilisationMultiplier(uint _utilisationMultiplier) public onlyOwner {
        require(_utilisationMultiplier > 0, "Must be greater than 0");
        utilisationMultiplier = _utilisationMultiplier;
    }

    function setMaxDebt(uint _maxDebt) public onlyOwner {
        require(_maxDebt > 0, "Must be greater than 0");
        maxDebt = _maxDebt;
        emit MaxDebtUpdated(maxDebt);
    }

    function setBaseBorrowRate(uint _baseBorrowRate) public onlyOwner {
        baseBorrowRate = _baseBorrowRate;
        emit BaseBorrowRateUpdated(baseBorrowRate);
    }

    function setBaseShortRate(uint _baseShortRate) public onlyOwner {
        baseShortRate = _baseShortRate;
        emit BaseShortRateUpdated(baseShortRate);
    }

    /* ---------- LOANS ---------- */

    function getNewLoanId() external onlyCollateral returns (uint id) {
        id = state.incrementTotalLoans();
    }

    /* ---------- MANAGER ---------- */

    function addCollaterals(address[] calldata collaterals) external onlyOwner {
        _systemStatus().requireSystemActive();

        for (uint i = 0; i < collaterals.length; i++) {
            if (!_collaterals.contains(collaterals[i])) {
                _collaterals.add(collaterals[i]);
                emit CollateralAdded(collaterals[i]);
            }
        }
    }

    function removeCollaterals(address[] calldata collaterals) external onlyOwner {
        _systemStatus().requireSystemActive();

        for (uint i = 0; i < collaterals.length; i++) {
            if (_collaterals.contains(collaterals[i])) {
                _collaterals.remove(collaterals[i]);
                emit CollateralRemoved(collaterals[i]);
            }
        }
    }

    function addSynths(bytes32[] calldata synthNamesInResolver, bytes32[] calldata synthKeys) external onlyOwner {
        _systemStatus().requireSystemActive();

        for (uint i = 0; i < synthNamesInResolver.length; i++) {
            if (!_synths.contains(synthNamesInResolver[i])) {
                bytes32 synthName = synthNamesInResolver[i];
                _synths.add(synthName);
                synthsByKey[synthKeys[i]] = synthName;
                emit SynthAdded(synthName);
            }
        }
    }

    function areSynthsAndCurrenciesSet(bytes32[] calldata requiredSynthNamesInResolver, bytes32[] calldata synthKeys)
        external
        view
        returns (bool)
    {
        if (_synths.elements.length != requiredSynthNamesInResolver.length) {
            return false;
        }

        for (uint i = 0; i < requiredSynthNamesInResolver.length; i++) {
            if (!_synths.contains(requiredSynthNamesInResolver[i])) {
                return false;
            }
            if (synthsByKey[synthKeys[i]] != requiredSynthNamesInResolver[i]) {
                return false;
            }
        }

        return true;
    }

    function removeSynths(bytes32[] calldata synths, bytes32[] calldata synthKeys) external onlyOwner {
        _systemStatus().requireSystemActive();

        for (uint i = 0; i < synths.length; i++) {
            if (_synths.contains(synths[i])) {
                // Remove it from the the address set lib.
                _synths.remove(synths[i]);
                delete synthsByKey[synthKeys[i]];

                emit SynthRemoved(synths[i]);
            }
        }
    }

    // When we add a shortable synth, we need to know the iSynth as well
    // This is so we can get the proper skew for the short rate.
    function addShortableSynths(bytes32[2][] calldata requiredSynthAndInverseNamesInResolver, bytes32[] calldata synthKeys)
        external
        onlyOwner
    {
        _systemStatus().requireSystemActive();

        require(requiredSynthAndInverseNamesInResolver.length == synthKeys.length, "Input array length mismatch");

        for (uint i = 0; i < requiredSynthAndInverseNamesInResolver.length; i++) {
            // setting these explicitly for clarity
            // Each entry in the array is [Synth, iSynth]
            bytes32 synth = requiredSynthAndInverseNamesInResolver[i][0];
            bytes32 iSynth = requiredSynthAndInverseNamesInResolver[i][1];

            if (!_shortableSynths.contains(synth)) {
                // Add it to the address set lib.
                _shortableSynths.add(synth);

                // store the mapping to the iSynth so we can get its total supply for the borrow rate.
                synthToInverseSynth[synth] = iSynth;

                emit ShortableSynthAdded(synth);

                // now the associated synth key to the CollateralManagerState
                state.addShortCurrency(synthKeys[i]);
            }
        }

        rebuildCache();
    }

    function areShortableSynthsSet(bytes32[] calldata requiredSynthNamesInResolver, bytes32[] calldata synthKeys)
        external
        view
        returns (bool)
    {
        require(requiredSynthNamesInResolver.length == synthKeys.length, "Input array length mismatch");

        if (_shortableSynths.elements.length != requiredSynthNamesInResolver.length) {
            return false;
        }

        // first check contract state
        for (uint i = 0; i < requiredSynthNamesInResolver.length; i++) {
            bytes32 synthName = requiredSynthNamesInResolver[i];
            if (!_shortableSynths.contains(synthName) || synthToInverseSynth[synthName] == bytes32(0)) {
                return false;
            }
        }

        // now check everything added to external state contract
        for (uint i = 0; i < synthKeys.length; i++) {
            if (state.getShortRatesLength(synthKeys[i]) == 0) {
                return false;
            }
        }

        return true;
    }

    function removeShortableSynths(bytes32[] calldata synths) external onlyOwner {
        _systemStatus().requireSystemActive();

        for (uint i = 0; i < synths.length; i++) {
            if (_shortableSynths.contains(synths[i])) {
                // Remove it from the the address set lib.
                _shortableSynths.remove(synths[i]);

                bytes32 synthKey = _synth(synths[i]).currencyKey();

                state.removeShortCurrency(synthKey);

                // remove the inverse mapping.
                delete synthToInverseSynth[synths[i]];

                emit ShortableSynthRemoved(synths[i]);
            }
        }
    }

    /* ---------- STATE MUTATIONS ---------- */

    function updateBorrowRates(uint rate) external onlyCollateral {
        state.updateBorrowRates(rate);
    }

    function updateShortRates(bytes32 currency, uint rate) external onlyCollateral {
        state.updateShortRates(currency, rate);
    }

    function incrementLongs(bytes32 synth, uint amount) external onlyCollateral {
        state.incrementLongs(synth, amount);
    }

    function decrementLongs(bytes32 synth, uint amount) external onlyCollateral {
        state.decrementLongs(synth, amount);
    }

    function incrementShorts(bytes32 synth, uint amount) external onlyCollateral {
        state.incrementShorts(synth, amount);
    }

    function decrementShorts(bytes32 synth, uint amount) external onlyCollateral {
        state.decrementShorts(synth, amount);
    }

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

    modifier onlyCollateral {
        bool isMultiCollateral = hasCollateral(msg.sender);

        require(isMultiCollateral, "Only collateral contracts");
        _;
    }

    // ========== EVENTS ==========
    event MaxDebtUpdated(uint maxDebt);
    event LiquidationPenaltyUpdated(uint liquidationPenalty);
    event BaseBorrowRateUpdated(uint baseBorrowRate);
    event BaseShortRateUpdated(uint baseShortRate);

    event CollateralAdded(address collateral);
    event CollateralRemoved(address collateral);

    event SynthAdded(bytes32 synth);
    event SynthRemoved(bytes32 synth);

    event ShortableSynthAdded(bytes32 synth);
    event ShortableSynthRemoved(bytes32 synth);
}

Contract ABI

[{"inputs":[{"internalType":"contract CollateralManagerState","name":"_state","type":"address"},{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_resolver","type":"address"},{"internalType":"uint256","name":"_maxDebt","type":"uint256"},{"internalType":"uint256","name":"_baseBorrowRate","type":"uint256"},{"internalType":"uint256","name":"_baseShortRate","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"baseBorrowRate","type":"uint256"}],"name":"BaseBorrowRateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"baseShortRate","type":"uint256"}],"name":"BaseShortRateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"name","type":"bytes32"},{"indexed":false,"internalType":"address","name":"destination","type":"address"}],"name":"CacheUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"collateral","type":"address"}],"name":"CollateralAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"collateral","type":"address"}],"name":"CollateralRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"liquidationPenalty","type":"uint256"}],"name":"LiquidationPenaltyUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maxDebt","type":"uint256"}],"name":"MaxDebtUpdated","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"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"synth","type":"bytes32"}],"name":"ShortableSynthAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"synth","type":"bytes32"}],"name":"ShortableSynthRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"synth","type":"bytes32"}],"name":"SynthAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"synth","type":"bytes32"}],"name":"SynthRemoved","type":"event"},{"constant":true,"inputs":[],"name":"CONTRACT_NAME","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"acceptOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address[]","name":"collaterals","type":"address[]"}],"name":"addCollaterals","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32[2][]","name":"requiredSynthAndInverseNamesInResolver","type":"bytes32[2][]"},{"internalType":"bytes32[]","name":"synthKeys","type":"bytes32[]"}],"name":"addShortableSynths","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32[]","name":"synthNamesInResolver","type":"bytes32[]"},{"internalType":"bytes32[]","name":"synthKeys","type":"bytes32[]"}],"name":"addSynths","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32[]","name":"requiredSynthNamesInResolver","type":"bytes32[]"},{"internalType":"bytes32[]","name":"synthKeys","type":"bytes32[]"}],"name":"areShortableSynthsSet","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32[]","name":"requiredSynthNamesInResolver","type":"bytes32[]"},{"internalType":"bytes32[]","name":"synthKeys","type":"bytes32[]"}],"name":"areSynthsAndCurrenciesSet","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"baseBorrowRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"baseShortRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"synth","type":"bytes32"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"decrementLongs","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"synth","type":"bytes32"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"decrementShorts","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes32","name":"currency","type":"bytes32"}],"name":"exceedsDebtLimit","outputs":[{"internalType":"bool","name":"canIssue","type":"bool"},{"internalType":"bool","name":"anyRateIsInvalid","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getBorrowRate","outputs":[{"internalType":"uint256","name":"borrowRate","type":"uint256"},{"internalType":"bool","name":"anyRateIsInvalid","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"getNewLoanId","outputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRatesAndTime","outputs":[{"internalType":"uint256","name":"entryRate","type":"uint256"},{"internalType":"uint256","name":"lastRate","type":"uint256"},{"internalType":"uint256","name":"lastUpdated","type":"uint256"},{"internalType":"uint256","name":"newIndex","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"synth","type":"bytes32"}],"name":"getShortRate","outputs":[{"internalType":"uint256","name":"shortRate","type":"uint256"},{"internalType":"bool","name":"rateIsInvalid","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"currency","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getShortRatesAndTime","outputs":[{"internalType":"uint256","name":"entryRate","type":"uint256"},{"internalType":"uint256","name":"lastRate","type":"uint256"},{"internalType":"uint256","name":"lastUpdated","type":"uint256"},{"internalType":"uint256","name":"newIndex","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address[]","name":"collaterals","type":"address[]"}],"name":"hasAllCollaterals","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"collateral","type":"address"}],"name":"hasCollateral","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"synth","type":"bytes32"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"incrementLongs","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"synth","type":"bytes32"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"incrementShorts","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"isResolverCached","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"currencyKey","type":"bytes32"}],"name":"isSynthManaged","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"lastPauseTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"synth","type":"bytes32"}],"name":"long","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"maxDebt","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":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":[],"name":"rebuildCache","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address[]","name":"collaterals","type":"address[]"}],"name":"removeCollaterals","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32[]","name":"synths","type":"bytes32[]"}],"name":"removeShortableSynths","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32[]","name":"synths","type":"bytes32[]"},{"internalType":"bytes32[]","name":"synthKeys","type":"bytes32[]"}],"name":"removeSynths","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":[],"name":"resolverAddressesRequired","outputs":[{"internalType":"bytes32[]","name":"addresses","type":"bytes32[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_baseBorrowRate","type":"uint256"}],"name":"setBaseBorrowRate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_baseShortRate","type":"uint256"}],"name":"setBaseShortRate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_maxDebt","type":"uint256"}],"name":"setMaxDebt","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":"uint256","name":"_utilisationMultiplier","type":"uint256"}],"name":"setUtilisationMultiplier","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"synth","type":"bytes32"}],"name":"short","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"state","outputs":[{"internalType":"contract CollateralManagerState","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"synthToInverseSynth","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"synthsByKey","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalLong","outputs":[{"internalType":"uint256","name":"susdValue","type":"uint256"},{"internalType":"bool","name":"anyRateIsInvalid","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalShort","outputs":[{"internalType":"uint256","name":"susdValue","type":"uint256"},{"internalType":"bool","name":"anyRateIsInvalid","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"rate","type":"uint256"}],"name":"updateBorrowRates","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"currency","type":"bytes32"},{"internalType":"uint256","name":"rate","type":"uint256"}],"name":"updateShortRates","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"utilisationMultiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}]

670de0b6b3a7640000600e5560e06040526b53797374656d53746174757360a01b60809081526524b9b9bab2b960d11b60a0526c45786368616e6765526174657360981b60c052620000569060129060036200031d565b503480156200006457600080fd5b5060405162003ee538038062003ee58339810160408190526200008791620003ad565b83856001600160a01b038116620000bb5760405162461bcd60e51b8152600401620000b290620005bc565b60405180910390fd5b600080546001600160a01b0319166001600160a01b0383161781556040517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c916200010891849062000560565b60405180910390a1506000546001600160a01b03166200013c5760405162461bcd60e51b8152600401620000b290620005aa565b60038054610100600160a81b0319166101006001600160a01b039384160217905560008054336001600160a01b031991821617909155600580549091169188169190911790556200018d83620001e2565b620001a1826001600160e01b036200025a16565b620001b5816001600160e01b03620002a416565b5050600080546001600160a01b0319166001600160a01b039490941693909317909255506200064a915050565b620001f56001600160e01b03620002ee16565b60008111620002185760405162461bcd60e51b8152600401620000b29062000586565b600f8190556040517f3620cc91bd75c6d3d752b529a1b98b38789dd2b81a13ece55801abc83531a77f906200024f908390620005ce565b60405180910390a150565b6200026d6001600160e01b03620002ee16565b60108190556040517f08f9599493340b8255c7698bded59e30079641f4a9531613ec02055739247004906200024f908390620005ce565b620002b76001600160e01b03620002ee16565b60118190556040517fe2695216766f2a627e90e17041ac2f085fd60ea503345b039f815c69bcbcccc9906200024f908390620005ce565b6000546001600160a01b031633146200031b5760405162461bcd60e51b8152600401620000b29062000598565b565b82601881019282156200034e579160200282015b828111156200034e57825182559160200191906001019062000331565b506200035c92915062000360565b5090565b6200037d91905b808211156200035c576000815560010162000367565b90565b80516200038d816200061a565b92915050565b80516200038d8162000634565b80516200038d816200063f565b60008060008060008060c08789031215620003c757600080fd5b6000620003d5898962000393565b9650506020620003e889828a0162000380565b9550506040620003fb89828a0162000380565b94505060606200040e89828a01620003a0565b93505060806200042189828a01620003a0565b92505060a06200043489828a01620003a0565b9150509295509295509295565b6200044c816200060d565b82525050565b6200044c81620005e7565b60006200046c601683620005de565b7f4d7573742062652067726561746572207468616e203000000000000000000000815260200192915050565b6000620004a7602f83620005de565b7f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726681526e37b936903a3434b99030b1ba34b7b760891b602082015260400192915050565b6000620004fa601183620005de565b7013dddb995c881b5d5cdd081899481cd95d607a1b815260200192915050565b600062000529601983620005de565b7f4f776e657220616464726573732063616e6e6f74206265203000000000000000815260200192915050565b6200044c816200037d565b6040810162000570828562000441565b6200057f602083018462000452565b9392505050565b602080825281016200038d816200045d565b602080825281016200038d8162000498565b602080825281016200038d81620004eb565b602080825281016200038d816200051a565b602081016200038d828462000555565b90815260200190565b60006200038d8262000601565b60006200038d82620005e7565b6001600160a01b031690565b60006200038d82620005f4565b6200062581620005e7565b81146200063157600080fd5b50565b6200062581620005f4565b62000625816200037d565b61388b806200065a6000396000f3fe608060405234801561001057600080fd5b50600436106102d65760003560e01c806391b4ded911610182578063c88b412e116100e9578063e32261fe116100a2578063ee81f7901161007c578063ee81f790146105ec578063f0e740c3146105ff578063f53037b614610612578063ffa749cd14610625576102d6565b8063e32261fe146105b3578063e50a31b3146105c6578063eb94bbde146105d9576102d6565b8063c88b412e14610557578063c9e180151461056a578063ca969f2314610572578063d0064c0014610585578063d2f004751461058d578063e31f27c1146105a0576102d6565b8063b3b467321161013b578063b3b4673214610503578063b4d6cb401461050b578063ba1c5e801461052c578063bbb601cd14610534578063bf38668214610547578063c19d93fb1461054f576102d6565b806391b4ded9146104a757806393a72fbe146104af5780639f7eac37146104c2578063ad79a858146104d5578063af07aa9d146104dd578063b38988f7146104f0576102d6565b806353a47bb71161024157806374185360116101fa5780638471db13116101d45780638471db1314610464578063899ffef4146104775780638b173e811461048c5780638da5cb5b1461049f576102d6565b80637418536014610441578063744d646e1461044957806379ba50971461045c576102d6565b806353a47bb7146103e35780635c975abb146103f8578063614d08f8146104005780636526941b14610408578063710388d11461041b57806372e18b6a1461042e576102d6565b806323d60e2e1161029357806323d60e2e1461036d57806324620639146103805780632af64bd31461039357806338245377146103a85780634db7764c146103c85780635246f2b9146103d0576102d6565b806303f048b0146102db57806304f3bcec146103075780630c9c81a11461031c5780631627540c1461033157806316c38b3c146103445780631e33fc6b14610357575b600080fd5b6102ee6102e936600461309c565b610638565b6040516102fe949392919061372c565b60405180910390f35b61030f6106cf565b6040516102fe919061366d565b61032f61032a36600461309c565b6106e3565b005b61032f61033f366004612f04565b61072b565b61032f610352366004613060565b61077e565b61035f6107f3565b6040516102fe9291906135fc565b61032f61037b366004613027565b610ae6565b61032f61038e3660046130d8565b610c19565b61039b610cb5565b6040516102fe91906135b7565b6103bb6103b636600461309c565b610dd2565b6040516102fe91906135e0565b6103bb610de4565b61032f6103de3660046130d8565b610dea565b6103eb610e46565b6040516102fe919061357d565b61039b610e55565b6103bb610e5e565b61032f61041636600461309c565b610e76565b61032f610429366004613027565b610ed3565b61039b61043c366004613027565b610ff4565b61032f61108e565b61039b610457366004612f82565b6111e4565b61032f61122e565b61039b61047236600461309c565b6112ca565b61047f6112de565b6040516102fe91906135a6565b61032f61049a36600461309c565b6114c0565b6103eb6114fd565b6103bb61150c565b61039b6104bd366004613027565b611512565b61032f6104d036600461309c565b61165d565b61035f61168a565b6102ee6104eb3660046130d8565b61186b565b61039b6104fe366004612f04565b611906565b6103bb61191f565b61051e6105193660046130d8565b6119d8565b6040516102fe9291906135c5565b61035f611acb565b61032f610542366004612f40565b611bee565b6103bb611d27565b61030f611d2d565b61032f610565366004612fb7565b611d3c565b6103bb611f10565b61032f610580366004612f40565b611f16565b6103bb61213f565b6103bb61059b36600461309c565b612145565b61032f6105ae3660046130d8565b6121c6565b6103bb6105c136600461309c565b612222565b61032f6105d43660046130d8565b612253565b61032f6105e73660046130d8565b6122af565b61035f6105fa36600461309c565b61230b565b6103bb61060d36600461309c565b612625565b61032f61062036600461309c565b612637565b61032f610633366004612f40565b6126c7565b600554604051623f048b60e41b81526000918291829182916001600160a01b03909116906303f048b0906106709088906004016135e0565b60806040518083038186803b15801561068857600080fd5b505afa15801561069c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506106c09190810190613142565b92989197509550909350915050565b60035461010090046001600160a01b031681565b6106eb6127d9565b60108190556040517f08f9599493340b8255c7698bded59e30079641f4a9531613ec02055739247004906107209083906135e0565b60405180910390a150565b6107336127d9565b600180546001600160a01b0319166001600160a01b0383161790556040517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229061072090839061357d565b6107866127d9565b60035460ff161515811515141561079c576107f0565b6003805460ff1916821515179081905560ff16156107b957426002555b6003546040517f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec5916107209160ff909116906135b7565b50565b6008805460408051602080840282018101909252828152600093849360609383018282801561084157602002820191906000526020600020905b81548152602001906001019080831161082d575b50505050509050600081511115610ae15760005b8151811015610adf57600061087c83838151811061086f57fe5b6020026020010151612805565b6001600160a01b031663dbd06c856040518163ffffffff1660e01b815260040160206040518083038186803b1580156108b457600080fd5b505afa1580156108c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506108ec91908101906130ba565b9050631cd554d160e21b8114156109935760055460405163d2f0047560e01b815261098c916001600160a01b03169063d2f004759061092f9085906004016135e0565b60206040518083038186803b15801561094757600080fd5b505afa15801561095b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061097f91908101906130ba565b869063ffffffff61281016565b9450610ad6565b60008061099e61283c565b6001600160a01b0316630c71cd23846040518263ffffffff1660e01b81526004016109c991906135e0565b604080518083038186803b1580156109e057600080fd5b505afa1580156109f4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610a189190810190613112565b60055460405163d2f0047560e01b8152929450909250600091610ab39185916001600160a01b039091169063d2f0047590610a579089906004016135e0565b60206040518083038186803b158015610a6f57600080fd5b505afa158015610a83573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610aa791908101906130ba565b9063ffffffff61285c16565b9050610ac5888263ffffffff61281016565b97508115610ad257600196505b5050505b50600101610855565b505b509091565b610aee6127d9565b610af6612886565b6001600160a01b031663086dabd16040518163ffffffff1660e01b815260040160006040518083038186803b158015610b2e57600080fd5b505afa158015610b42573d6000803e3d6000fd5b506000925050505b83811015610c1257610b78858583818110610b6157fe5b9050602002013560086128a090919063ffffffff16565b610c0a576000858583818110610b8a57fe5b905060200201359050610ba78160086128f090919063ffffffff16565b80600a6000868686818110610bb857fe5b905060200201358152602001908152602001600020819055507f87f8a613724bd8be7a9139e4c83bc8d58fedee7206e2d7077849f5988d78759981604051610c0091906135e0565b60405180910390a1505b600101610b4a565b5050505050565b6000610c2433611906565b905080610c4c5760405162461bcd60e51b8152600401610c439061371c565b60405180910390fd5b600554604051632462063960e01b81526001600160a01b0390911690632462063990610c7e908690869060040161362a565b600060405180830381600087803b158015610c9857600080fd5b505af1158015610cac573d6000803e3d6000fd5b50505050505050565b60006060610cc16112de565b905060005b8151811015610dc8576000828281518110610cdd57fe5b60209081029190910181015160008181526004928390526040908190205460035491516321f8a72160e01b81529294506001600160a01b039081169361010090920416916321f8a72191610d33918691016135e0565b60206040518083038186803b158015610d4b57600080fd5b505afa158015610d5f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610d839190810190612f22565b6001600160a01b0316141580610dae57506000818152600460205260409020546001600160a01b0316155b15610dbf5760009350505050610dcf565b50600101610cc6565b5060019150505b90565b600a6020526000908152604090205481565b60115481565b6000610df533611906565b905080610e145760405162461bcd60e51b8152600401610c439061371c565b600554604051635246f2b960e01b81526001600160a01b0390911690635246f2b990610c7e908690869060040161362a565b6001546001600160a01b031681565b60035460ff1681565b7021b7b63630ba32b930b626b0b730b3b2b960791b81565b610e7e6127d9565b60008111610e9e5760405162461bcd60e51b8152600401610c43906136ec565b600f8190556040517f3620cc91bd75c6d3d752b529a1b98b38789dd2b81a13ece55801abc83531a77f906107209083906135e0565b610edb6127d9565b610ee3612886565b6001600160a01b031663086dabd16040518163ffffffff1660e01b815260040160006040518083038186803b158015610f1b57600080fd5b505afa158015610f2f573d6000803e3d6000fd5b506000925050505b83811015610c1257610f4e858583818110610b6157fe5b15610fec57610f79858583818110610f6257fe5b90506020020135600861292890919063ffffffff16565b600a6000848484818110610f8957fe5b905060200201358152602001908152602001600020600090557f788aff97f65e6ddeee9246c47d08b819813066c87876a912c79baddffb138f0a858583818110610fcf57fe5b90506020020135604051610fe391906135e0565b60405180910390a15b600101610f37565b600854600090841461100857506000611086565b60005b8481101561108057611022868683818110610b6157fe5b611030576000915050611086565b85858281811061103c57fe5b90506020020135600a600086868581811061105357fe5b9050602002013581526020019081526020016000205414611078576000915050611086565b60010161100b565b50600190505b949350505050565b60606110986112de565b905060005b81518110156111e05760008282815181106110b457fe5b602002602001015190506000600360019054906101000a90046001600160a01b03166001600160a01b031663dacb2d0183846040516020016110f69190613572565b6040516020818303038152906040526040518363ffffffff1660e01b815260040161112292919061360a565b60206040518083038186803b15801561113a57600080fd5b505afa15801561114e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506111729190810190612f22565b6000838152600460205260409081902080546001600160a01b0319166001600160a01b038416179055519091507f88a93678a3692f6789d9546fc621bf7234b101ddb7d4fe479455112831b8aa68906111ce90849084906135ee565b60405180910390a1505060010161109d565b5050565b6000805b82518110156112235761120d83828151811061120057fe5b6020026020010151611906565b61121b576000915050611229565b6001016111e8565b50600190505b919050565b6001546001600160a01b031633146112585760405162461bcd60e51b8152600401610c439061369c565b6000546001546040517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9261129b926001600160a01b039182169291169061358b565b60405180910390a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b6000908152600a6020526040902054151590565b604080516003808252608082019092526060918291906020820183803883390190505090506524b9b9bab2b960d11b8160008151811061131a57fe5b6020026020010181815250506c45786368616e6765526174657360981b8160018151811061134457fe5b6020026020010181815250506b53797374656d53746174757360a01b8160028151811061136d57fe5b6020908102919091010152600b54606090801561144157806002026040519080825280602002602001820160405280156113b1578160200160208202803883390190505b50915060005b8181101561143f57600b8054829081106113cd57fe5b90600052602060002001548382815181106113e457fe5b602002602001018181525050600d6000600b600001838154811061140457fe5b9060005260206000200154815260200190815260200160002054838383018151811061142c57fe5b60209081029190910101526001016113b7565b505b600880546040805160208084028201810190925282815260609361149a93879383018282801561149057602002820191906000526020600020905b81548152602001906001019080831161147c575b50505050506129fc565b8051909150156114b5576114ae81856129fc565b94506114b9565b8394505b5050505090565b6114c86127d9565b60118190556040517fe2695216766f2a627e90e17041ac2f085fd60ea503345b039f815c69bcbcccc9906107209083906135e0565b6000546001600160a01b031681565b60025481565b60008382146115335760405162461bcd60e51b8152600401610c439061368c565b600b54841461154457506000611086565b60005b848110156115ab57600086868381811061155d57fe5b90506020020135905061157a81600b6128a090919063ffffffff16565b158061159257506000818152600d6020526040902054155b156115a257600092505050611086565b50600101611547565b5060005b82811015611080576005546001600160a01b031663a0356f6e8585848181106115d457fe5b905060200201356040518263ffffffff1660e01b81526004016115f791906135e0565b60206040518083038186803b15801561160f57600080fd5b505afa158015611623573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061164791908101906130ba565b611655576000915050611086565b6001016115af565b6116656127d9565b600081116116855760405162461bcd60e51b8152600401610c43906136ec565b600e55565b600b80546040805160208084028201810190925282815260009384936060938301828280156116d857602002820191906000526020600020905b8154815260200190600101908083116116c4575b50505050509050600081511115610ae15760005b8151811015610adf57600061170683838151811061086f57fe5b6001600160a01b031663dbd06c856040518163ffffffff1660e01b815260040160206040518083038186803b15801561173e57600080fd5b505afa158015611752573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061177691908101906130ba565b905060008061178361283c565b6001600160a01b0316630c71cd23846040518263ffffffff1660e01b81526004016117ae91906135e0565b604080518083038186803b1580156117c557600080fd5b505afa1580156117d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506117fd9190810190613112565b60055460405163719130ff60e11b815292945090925060009161183c9185916001600160a01b039091169063e32261fe90610a579089906004016135e0565b905061184e888263ffffffff61281016565b9750811561185b57600196505b5050600190920191506116ec9050565b60055460405163af07aa9d60e01b81526000918291829182916001600160a01b039091169063af07aa9d906118a6908990899060040161362a565b60806040518083038186803b1580156118be57600080fd5b505afa1580156118d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506118f69190810190613142565b9299919850965090945092505050565b600061191960068363ffffffff612ab816565b92915050565b60008061192b33611906565b90508061194a5760405162461bcd60e51b8152600401610c439061371c565b600560009054906101000a90046001600160a01b03166001600160a01b0316638c5825036040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561199a57600080fd5b505af11580156119ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506119d291908101906130ba565b91505090565b60008060006119e561283c565b6001600160a01b031663654a60ac8587631cd554d160e21b6040518463ffffffff1660e01b8152600401611a1b93929190613645565b60206040518083038186803b158015611a3357600080fd5b505afa158015611a47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611a6b91908101906130ba565b9050600080611a786107f3565b91509150600080611a8761168a565b915091508280611a945750805b600f54909650611aba86611aae878663ffffffff61281016565b9063ffffffff61281016565b1115965050505050505b9250929050565b6000806000611ad8612b25565b6001600160a01b0316637b1001b7631cd554d160e21b60016040518363ffffffff1660e01b8152600401611b0d9291906135fc565b60206040518083038186803b158015611b2557600080fd5b505afa158015611b39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611b5d91908101906130ba565b9050600080611b6a6107f3565b90925090506000611b81848463ffffffff61281016565b90506000611bb06a1a1a7062e5185d7e380000611ba4868563ffffffff612b3916565b9063ffffffff612b3916565b90506000611bc9600e548361285c90919063ffffffff16565b9050611be06010548261281090919063ffffffff16565b989397509295505050505050565b611bf66127d9565b611bfe612886565b6001600160a01b031663086dabd16040518163ffffffff1660e01b815260040160006040518083038186803b158015611c3657600080fd5b505afa158015611c4a573d6000803e3d6000fd5b506000925050505b81811015611d2257611c8c838383818110611c6957fe5b9050602002016020611c7e9190810190612f04565b60069063ffffffff612ab816565b611d1a57611cc2838383818110611c9f57fe5b9050602002016020611cb49190810190612f04565b60069063ffffffff612b6316565b7f7db05e63d635a68c62fd7fd8f3107ae8ab584a383e102d1bd8a40f4c977e465f838383818110611cef57fe5b9050602002016020611d049190810190612f04565b604051611d11919061357d565b60405180910390a15b600101611c52565b505050565b60105481565b6005546001600160a01b031681565b611d446127d9565b611d4c612886565b6001600160a01b031663086dabd16040518163ffffffff1660e01b815260040160006040518083038186803b158015611d8457600080fd5b505afa158015611d98573d6000803e3d6000fd5b5050508382149050611dbc5760405162461bcd60e51b8152600401610c439061368c565b60005b83811015611f01576000858583818110611dd557fe5b905060400201600060028110611de757fe5b602002013590506000868684818110611dfc57fe5b905060400201600160028110611e0e57fe5b60200201359050611e26600b8363ffffffff6128a016565b611ef757611e3b600b8363ffffffff6128f016565b6000828152600d602052604090819020829055517fa71e21d8a72d99830e0d382f042d37e6a20c8a33ec3185affcaf6586e9a0187a90611e7c9084906135e0565b60405180910390a16005546001600160a01b031663ed039154868686818110611ea157fe5b905060200201356040518263ffffffff1660e01b8152600401611ec491906135e0565b600060405180830381600087803b158015611ede57600080fd5b505af1158015611ef2573d6000803e3d6000fd5b505050505b5050600101611dbf565b50611f0a61108e565b50505050565b600e5481565b611f1e6127d9565b611f26612886565b6001600160a01b031663086dabd16040518163ffffffff1660e01b815260040160006040518083038186803b158015611f5e57600080fd5b505afa158015611f72573d6000803e3d6000fd5b506000925050505b81811015611d2257611fa8838383818110611f9157fe5b90506020020135600b6128a090919063ffffffff16565b1561213757611fd3838383818110611fbc57fe5b90506020020135600b61292890919063ffffffff16565b6000611ff0848484818110611fe457fe5b90506020020135612805565b6001600160a01b031663dbd06c856040518163ffffffff1660e01b815260040160206040518083038186803b15801561202857600080fd5b505afa15801561203c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061206091908101906130ba565b600554604051636431e0bd60e01b81529192506001600160a01b031690636431e0bd906120919084906004016135e0565b600060405180830381600087803b1580156120ab57600080fd5b505af11580156120bf573d6000803e3d6000fd5b50505050600d60008585858181106120d357fe5b905060200201358152602001908152602001600020600090557f23caa21d7c1015aa7051e1ae4a09f99de36dab4545dfec5f4dde3a54173a123b84848481811061211957fe5b9050602002013560405161212d91906135e0565b60405180910390a1505b600101611f7a565b600f5481565b60055460405163d2f0047560e01b81526000916001600160a01b03169063d2f00475906121769085906004016135e0565b60206040518083038186803b15801561218e57600080fd5b505afa1580156121a2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061191991908101906130ba565b60006121d133611906565b9050806121f05760405162461bcd60e51b8152600401610c439061371c565b60055460405163e31f27c160e01b81526001600160a01b039091169063e31f27c190610c7e908690869060040161362a565b60055460405163719130ff60e11b81526000916001600160a01b03169063e32261fe906121769085906004016135e0565b600061225e33611906565b90508061227d5760405162461bcd60e51b8152600401610c439061371c565b60055460405163e50a31b360e01b81526001600160a01b039091169063e50a31b390610c7e908690869060040161362a565b60006122ba33611906565b9050806122d95760405162461bcd60e51b8152600401610c439061371c565b6005546040516375ca5def60e11b81526001600160a01b039091169063eb94bbde90610c7e908690869060040161362a565b600080600061231984612805565b6001600160a01b031663dbd06c856040518163ffffffff1660e01b815260040160206040518083038186803b15801561235157600080fd5b505afa158015612365573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061238991908101906130ba565b905061239361283c565b6001600160a01b0316632528f0fe826040518263ffffffff1660e01b81526004016123be91906135e0565b60206040518083038186803b1580156123d657600080fd5b505afa1580156123ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061240e919081019061307e565b9150600061241b85612805565b6001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561245357600080fd5b505afa158015612467573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061248b91908101906130ba565b6000868152600d6020526040812054919250906124a790612805565b6001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156124df57600080fd5b505afa1580156124f3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061251791908101906130ba565b60055460405163719130ff60e11b81529192506000916125a39184916001600160a01b039091169063e32261fe906125539089906004016135e0565b60206040518083038186803b15801561256b57600080fd5b505afa15801561257f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611aae91908101906130ba565b9050808311156125bb57506000945061262092505050565b60006125cd828563ffffffff612bb516565b905060006126006a1a1a7062e5185d7e380000611ba46125f3888763ffffffff61281016565b859063ffffffff612b3916565b90506126176011548261281090919063ffffffff16565b97505050505050505b915091565b600d6020526000908152604090205481565b600061264233611906565b9050806126615760405162461bcd60e51b8152600401610c439061371c565b600554604051637a981bdb60e11b81526001600160a01b039091169063f53037b6906126919085906004016135e0565b600060405180830381600087803b1580156126ab57600080fd5b505af11580156126bf573d6000803e3d6000fd5b505050505050565b6126cf6127d9565b6126d7612886565b6001600160a01b031663086dabd16040518163ffffffff1660e01b815260040160006040518083038186803b15801561270f57600080fd5b505afa158015612723573d6000803e3d6000fd5b506000925050505b81811015611d2257612742838383818110611c6957fe5b156127d15761277983838381811061275657fe5b905060200201602061276b9190810190612f04565b60069063ffffffff612bdd16565b7fd89d2ee68ab04dca0193f48a4aff55e20fa5ec0429a8a8c1c51b8dad6178a5938383838181106127a657fe5b90506020020160206127bb9190810190612f04565b6040516127c8919061357d565b60405180910390a15b60010161272b565b6000546001600160a01b031633146128035760405162461bcd60e51b8152600401610c43906136fc565b565b600061191982612cf3565b6000828201838110156128355760405162461bcd60e51b8152600401610c43906136ac565b9392505050565b60006128576c45786368616e6765526174657360981b612cf3565b905090565b6000670de0b6b3a7640000612877848463ffffffff612d5016565b8161287e57fe5b049392505050565b60006128576b53797374656d53746174757360a01b612cf3565b81546000906128b157506000611919565b600082815260018401602052604090205480151580611086575082846000016000815481106128dc57fe5b906000526020600020015414949350505050565b6128fa82826128a0565b6111e05781546000828152600180850160209081526040832084905590830185558482529020018190555050565b61293282826128a0565b61294e5760405162461bcd60e51b8152600401610c43906136bc565b60008181526001830160205260409020548254600019018082146129bc57600084600001828154811061297d57fe5b906000526020600020015490508085600001848154811061299a57fe5b6000918252602080832090910192909255918252600186019052604090208290555b83548490806129c757fe5b600190038181906000526020600020016000905590558360010160008481526020019081526020016000206000905550505050565b60608151835101604051908082528060200260200182016040528015612a2c578160200160208202803883390190505b50905060005b8351811015612a6e57838181518110612a4757fe5b6020026020010151828281518110612a5b57fe5b6020908102919091010152600101612a32565b5060005b8251811015612ab157828181518110612a8757fe5b6020026020010151828286510181518110612a9e57fe5b6020908102919091010152600101612a72565b5092915050565b8154600090612ac957506000611919565b6001600160a01b0382166000908152600184016020526040902054801515806110865750826001600160a01b031684600001600081548110612b0757fe5b6000918252602090912001546001600160a01b031614949350505050565b60006128576524b9b9bab2b960d11b612cf3565b600061283582612b5785670de0b6b3a764000063ffffffff612d5016565b9063ffffffff612d8a16565b612b6d8282612ab8565b6111e05781546001600160a01b038216600081815260018086016020908152604083208590559084018655858252902090910180546001600160a01b03191690911790555050565b600082821115612bd75760405162461bcd60e51b8152600401610c43906136cc565b50900390565b612be78282612ab8565b612c035760405162461bcd60e51b8152600401610c43906136bc565b6001600160a01b0381166000908152600183016020526040902054825460001901808214612ca2576000846000018281548110612c3c57fe5b60009182526020909120015485546001600160a01b0390911691508190869085908110612c6557fe5b600091825260208083209190910180546001600160a01b0319166001600160a01b0394851617905592909116815260018601909152604090208290555b8354849080612cad57fe5b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b0394909416815260019490940190925250506040812055565b60008181526004602090815260408083205490516001600160a01b039091169182151591612d2391869101613552565b60405160208183030381529060405290612ab15760405162461bcd60e51b8152600401610c43919061367b565b600082612d5f57506000611919565b82820282848281612d6c57fe5b04146128355760405162461bcd60e51b8152600401610c439061370c565b6000808211612dab5760405162461bcd60e51b8152600401610c43906136dc565b6000828481612db657fe5b04949350505050565b803561191981613822565b805161191981613822565b60008083601f840112612de757600080fd5b50813567ffffffffffffffff811115612dff57600080fd5b602083019150836020820283011115611ac457600080fd5b600082601f830112612e2857600080fd5b8135612e3b612e3682613791565b61376a565b91508181835260208401935060208101905083856020840282011115612e6057600080fd5b60005b83811015612e8c5781612e768882612dbf565b8452506020928301929190910190600101612e63565b5050505092915050565b60008083601f840112612ea857600080fd5b50813567ffffffffffffffff811115612ec057600080fd5b602083019150836040820283011115611ac457600080fd5b803561191981613836565b805161191981613836565b80356119198161383f565b80516119198161383f565b600060208284031215612f1657600080fd5b60006110868484612dbf565b600060208284031215612f3457600080fd5b60006110868484612dca565b60008060208385031215612f5357600080fd5b823567ffffffffffffffff811115612f6a57600080fd5b612f7685828601612dd5565b92509250509250929050565b600060208284031215612f9457600080fd5b813567ffffffffffffffff811115612fab57600080fd5b61108684828501612e17565b60008060008060408587031215612fcd57600080fd5b843567ffffffffffffffff811115612fe457600080fd5b612ff087828801612e96565b9450945050602085013567ffffffffffffffff81111561300f57600080fd5b61301b87828801612dd5565b95989497509550505050565b6000806000806040858703121561303d57600080fd5b843567ffffffffffffffff81111561305457600080fd5b612ff087828801612dd5565b60006020828403121561307257600080fd5b60006110868484612ed8565b60006020828403121561309057600080fd5b60006110868484612ee3565b6000602082840312156130ae57600080fd5b60006110868484612eee565b6000602082840312156130cc57600080fd5b60006110868484612ef9565b600080604083850312156130eb57600080fd5b60006130f78585612eee565b925050602061310885828601612eee565b9150509250929050565b6000806040838503121561312557600080fd5b60006131318585612ef9565b925050602061310885828601612ee3565b6000806000806080858703121561315857600080fd5b60006131648787612ef9565b945050602061317587828801612ef9565b935050604061318687828801612ef9565b925050606061319787828801612ef9565b91505092959194509250565b60006131af8383613228565b505060200190565b6131c0816137c5565b82525050565b60006131d1826137b8565b6131db81856137bc565b93506131e6836137b2565b8060005b838110156132145781516131fe88826131a3565b9750613209836137b2565b9250506001016131ea565b509495945050505050565b6131c0816137d0565b6131c081610dcf565b6131c061323d82610dcf565b610dcf565b6131c0816137e1565b6000613256826137b8565b61326081856137bc565b93506132708185602086016137ec565b61327981613818565b9093019392505050565b6000613290601b836137bc565b7f496e707574206172726179206c656e677468206d69736d617463680000000000815260200192915050565b60006132c96035836137bc565b7f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7581527402063616e20616363657074206f776e65727368697605c1b602082015260400192915050565b6000613320601b836137bc565b7f536166654d6174683a206164646974696f6e206f766572666c6f770000000000815260200192915050565b60006133596013836137bc565b7222b632b6b2b73a103737ba1034b71039b2ba1760691b815260200192915050565b6000613388601e836137bc565b7f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815260200192915050565b60006133c1601a836137bc565b7f536166654d6174683a206469766973696f6e206279207a65726f000000000000815260200192915050565b60006133fa601183611229565b70026b4b9b9b4b7339030b2323932b9b99d1607d1b815260110192915050565b60006134276016836137bc565b7504d7573742062652067726561746572207468616e20360541b815260200192915050565b6000613459602f836137bc565b7f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726681526e37b936903a3434b99030b1ba34b7b760891b602082015260400192915050565b60006134aa6021836137bc565b7f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f8152607760f81b602082015260400192915050565b60006134ed6019836137bc565b7f4f6e6c7920636f6c6c61746572616c20636f6e74726163747300000000000000815260200192915050565b6000613526601983611229565b7f5265736f6c766572206d697373696e67207461726765743a2000000000000000815260190192915050565b600061355d826133ed565b91506135698284613231565b50602001919050565b600061355d82613519565b6020810161191982846131b7565b6040810161359982856131b7565b61283560208301846131b7565b6020808252810161283581846131c6565b60208101611919828461321f565b604081016135d3828561321f565b612835602083018461321f565b602081016119198284613228565b604081016135998285613228565b604081016135d38285613228565b604081016136188285613228565b8181036020830152611086818461324b565b604081016136388285613228565b6128356020830184613228565b606081016136538286613228565b6136606020830185613228565b6110866040830184613228565b602081016119198284613242565b60208082528101612835818461324b565b6020808252810161191981613283565b60208082528101611919816132bc565b6020808252810161191981613313565b602080825281016119198161334c565b602080825281016119198161337b565b60208082528101611919816133b4565b602080825281016119198161341a565b602080825281016119198161344c565b602080825281016119198161349d565b60208082528101611919816134e0565b6080810161373a8287613228565b6137476020830186613228565b6137546040830185613228565b6137616060830184613228565b95945050505050565b60405181810167ffffffffffffffff8111828210171561378957600080fd5b604052919050565b600067ffffffffffffffff8211156137a857600080fd5b5060209081020190565b60200190565b5190565b90815260200190565b6000611919826137d5565b151590565b6001600160a01b031690565b6000611919826137c5565b60005b838110156138075781810151838201526020016137ef565b83811115611f0a5750506000910152565b601f01601f191690565b61382b816137c5565b81146107f057600080fd5b61382b816137d0565b61382b81610dcf56fea365627a7a72315820a4c382fd8fe764e7ef6c76ca50c059853603f22c08f675f621c9c5e0e8df724d6c6578706572696d656e74616cf564736f6c634300051000400000000000000000000000008d65ed88d6162a2b3b5f71c45d433d4aeac93065000000000000000000000000b64ff7a4a33acdf48d97dab0d764afd0f6176882000000000000000000000000242a3df52c375bee81b1c668741d7c63af68fdd200000000000000000000000000000000000000000052b7d2dcc80cd2e40000000000000000000000000000000000000000000000000000000001c6bf526340000000000000000000000000000000000000000000000000000001c6bf52634000

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

0000000000000000000000008d65ed88d6162a2b3b5f71c45d433d4aeac93065000000000000000000000000b64ff7a4a33acdf48d97dab0d764afd0f6176882000000000000000000000000242a3df52c375bee81b1c668741d7c63af68fdd200000000000000000000000000000000000000000052b7d2dcc80cd2e40000000000000000000000000000000000000000000000000000000001c6bf526340000000000000000000000000000000000000000000000000000001c6bf52634000

-----Decoded View---------------
Arg [0] : _state (address): 0x8d65ed88d6162a2b3b5f71c45d433d4aeac93065
Arg [1] : _owner (address): 0xb64ff7a4a33acdf48d97dab0d764afd0f6176882
Arg [2] : _resolver (address): 0x242a3df52c375bee81b1c668741d7c63af68fdd2
Arg [3] : _maxDebt (uint256): 100000000000000000000000000
Arg [4] : _baseBorrowRate (uint256): 500000000000000
Arg [5] : _baseShortRate (uint256): 500000000000000

-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 0000000000000000000000008d65ed88d6162a2b3b5f71c45d433d4aeac93065
Arg [1] : 000000000000000000000000b64ff7a4a33acdf48d97dab0d764afd0f6176882
Arg [2] : 000000000000000000000000242a3df52c375bee81b1c668741d7c63af68fdd2
Arg [3] : 00000000000000000000000000000000000000000052b7d2dcc80cd2e4000000
Arg [4] : 0000000000000000000000000000000000000000000000000001c6bf52634000
Arg [5] : 0000000000000000000000000000000000000000000000000001c6bf52634000


Library Used

SafeDecimalMath : 0x1a60e2e2a8be0bc2b6381dd31fd3fd5f9a28de4c

Block Transaction Difficulty Gas Used Reward
Block Uncle Number Difficulty Gas Used Reward
Loading