ETH Price: $1,971.63 (+3.38%)
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Close Current Fe...103277852020-06-24 9:57:192076 days ago1592992639IN
Synthetix: Old Fee Pool 13
0 ETH0.0018484132
Claim On Behalf103259422020-06-24 3:02:312076 days ago1592967751IN
Synthetix: Old Fee Pool 13
0 ETH0.0286689726.69185744
Claim On Behalf103257292020-06-24 2:15:212076 days ago1592964921IN
Synthetix: Old Fee Pool 13
0 ETH0.0296633826.76638346
Claim On Behalf103256952020-06-24 2:08:262076 days ago1592964506IN
Synthetix: Old Fee Pool 13
0 ETH0.0295143727.86385816
Claim On Behalf103254332020-06-24 1:08:342076 days ago1592960914IN
Synthetix: Old Fee Pool 13
0 ETH0.035787732.55863422
Claim On Behalf103254132020-06-24 1:04:122076 days ago1592960652IN
Synthetix: Old Fee Pool 13
0 ETH0.0356640933.86016505
Claim On Behalf103253472020-06-24 0:50:332076 days ago1592959833IN
Synthetix: Old Fee Pool 13
0 ETH0.0330955131.24962918
Claim On Behalf103252982020-06-24 0:37:032076 days ago1592959023IN
Synthetix: Old Fee Pool 13
0 ETH0.0333063831.44785237
Claim On Behalf103250922020-06-23 23:49:362076 days ago1592956176IN
Synthetix: Old Fee Pool 13
0 ETH0.0301140428.59165351
Claim On Behalf103250722020-06-23 23:45:292076 days ago1592955929IN
Synthetix: Old Fee Pool 13
0 ETH0.0316085629.84460414
Claim On Behalf103249162020-06-23 23:09:452076 days ago1592953785IN
Synthetix: Old Fee Pool 13
0 ETH0.0259141424.1240921
Claim On Behalf103247632020-06-23 22:35:162076 days ago1592951716IN
Synthetix: Old Fee Pool 13
0 ETH0.0234913621.87051802
Claim On Behalf103245192020-06-23 21:39:462076 days ago1592948386IN
Synthetix: Old Fee Pool 13
0 ETH0.0237411722.41651492
Claim On Behalf103244442020-06-23 21:23:052076 days ago1592947385IN
Synthetix: Old Fee Pool 13
0 ETH0.0271589525.28533455
Claim On Behalf103243992020-06-23 21:12:422076 days ago1592946762IN
Synthetix: Old Fee Pool 13
0 ETH0.027266425.88856001
Claim On Behalf103243732020-06-23 21:08:122076 days ago1592946492IN
Synthetix: Old Fee Pool 13
0 ETH0.0268117625.45660323
Claim On Behalf103243132020-06-23 20:56:252076 days ago1592945785IN
Synthetix: Old Fee Pool 13
0 ETH0.0250086623.61314674
Claim On Behalf103242172020-06-23 20:33:132076 days ago1592944393IN
Synthetix: Old Fee Pool 13
0 ETH0.0248834723.49507864
Claim On Behalf103241902020-06-23 20:28:112076 days ago1592944091IN
Synthetix: Old Fee Pool 13
0 ETH0.025144423.87229694
Claim On Behalf103241412020-06-23 20:16:012076 days ago1592943361IN
Synthetix: Old Fee Pool 13
0 ETH0.024922823.3300606
Claim On Behalf103241302020-06-23 20:14:402076 days ago1592943280IN
Synthetix: Old Fee Pool 13
0 ETH0.0251857923.91173048
Claim On Behalf103241052020-06-23 20:08:562076 days ago1592942936IN
Synthetix: Old Fee Pool 13
0 ETH0.0261238424.80204513
Claim On Behalf103240842020-06-23 20:05:412076 days ago1592942741IN
Synthetix: Old Fee Pool 13
0 ETH0.0263705724.89849697
Claim On Behalf103240602020-06-23 20:00:332076 days ago1592942433IN
Synthetix: Old Fee Pool 13
0 ETH0.0265090525.02667825
Claim On Behalf103240312020-06-23 19:55:172076 days ago1592942117IN
Synthetix: Old Fee Pool 13
0 ETH0.0281800126.75463464
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
FeePool

Compiler Version
v0.5.16+commit.9c3226ce

Optimization Enabled:
Yes with 1500 runs

Other Settings:
default evmVersion
/**
 *Submitted for verification at Etherscan.io on 2020-06-05
*/

/*

⚠⚠⚠ WARNING WARNING WARNING ⚠⚠⚠

This is a TARGET contract - DO NOT CONNECT TO IT DIRECTLY IN YOUR CONTRACTS or DAPPS!

This contract has an associated PROXY that MUST be used for all integrations - this TARGET will be REPLACED in an upcoming Synthetix release!
The proxy for this contract can be found here:

https://contracts.synthetix.io/ProxyFeePool

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

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

/* ===============================================
* Flattened with Solidifier by Coinage
* 
* https://solidifier.coina.ge
* ===============================================
*/


pragma solidity ^0.5.16;


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

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

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

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

    modifier onlyOwner {
        require(msg.sender == owner, "Only the contract owner may perform this action");
        _;
    }

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


// Inheritance


// Internal references


// https://docs.synthetix.io/contracts/Proxy
contract Proxy is Owned {
    Proxyable public target;

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

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

    function _emit(
        bytes calldata callData,
        uint numTopics,
        bytes32 topic1,
        bytes32 topic2,
        bytes32 topic3,
        bytes32 topic4
    ) external onlyTarget {
        uint size = callData.length;
        bytes memory _callData = callData;

        assembly {
            /* The first 32 bytes of callData contain its length (as specified by the abi).
             * Length is assumed to be a uint256 and therefore maximum of 32 bytes
             * in length. It is also leftpadded to be a multiple of 32 bytes.
             * This means moving call_data across 32 bytes guarantees we correctly access
             * the data itself. */
            switch numTopics
                case 0 {
                    log0(add(_callData, 32), size)
                }
                case 1 {
                    log1(add(_callData, 32), size, topic1)
                }
                case 2 {
                    log2(add(_callData, 32), size, topic1, topic2)
                }
                case 3 {
                    log3(add(_callData, 32), size, topic1, topic2, topic3)
                }
                case 4 {
                    log4(add(_callData, 32), size, topic1, topic2, topic3, topic4)
                }
        }
    }

    // solhint-disable no-complex-fallback
    function() external payable {
        // Mutable call setting Proxyable.messageSender as this is using call not delegatecall
        target.setMessageSender(msg.sender);

        assembly {
            let free_ptr := mload(0x40)
            calldatacopy(free_ptr, 0, calldatasize)

            /* We must explicitly forward ether to the underlying contract as well. */
            let result := call(gas, sload(target_slot), callvalue, free_ptr, calldatasize, 0, 0)
            returndatacopy(free_ptr, 0, returndatasize)

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

    modifier onlyTarget {
        require(Proxyable(msg.sender) == target, "Must be proxy target");
        _;
    }

    event TargetUpdated(Proxyable newTarget);
}


// Inheritance


// Internal references


// https://docs.synthetix.io/contracts/Proxyable
contract Proxyable is Owned {
    // This contract should be treated like an abstract contract

    /* The proxy this contract exists behind. */
    Proxy public proxy;
    Proxy public integrationProxy;

    /* The caller of the proxy, passed through to this contract.
     * Note that every function using this member must apply the onlyProxy or
     * optionalProxy modifiers, otherwise their invocations can use stale values. */
    address public messageSender;

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

        proxy = Proxy(_proxy);
        emit ProxyUpdated(_proxy);
    }

    function setProxy(address payable _proxy) external onlyOwner {
        proxy = Proxy(_proxy);
        emit ProxyUpdated(_proxy);
    }

    function setIntegrationProxy(address payable _integrationProxy) external onlyOwner {
        integrationProxy = Proxy(_integrationProxy);
    }

    function setMessageSender(address sender) external onlyProxy {
        messageSender = sender;
    }

    modifier onlyProxy {
        require(Proxy(msg.sender) == proxy || Proxy(msg.sender) == integrationProxy, "Only the proxy can call");
        _;
    }

    modifier optionalProxy {
        if (Proxy(msg.sender) != proxy && Proxy(msg.sender) != integrationProxy && messageSender != msg.sender) {
            messageSender = msg.sender;
        }
        _;
    }

    modifier optionalProxy_onlyOwner {
        if (Proxy(msg.sender) != proxy && Proxy(msg.sender) != integrationProxy && messageSender != msg.sender) {
            messageSender = msg.sender;
        }
        require(messageSender == owner, "Owner only function");
        _;
    }

    event ProxyUpdated(address proxyAddress);
}


// Inheritance


// https://docs.synthetix.io/contracts/SelfDestructible
contract SelfDestructible is Owned {
    uint public constant SELFDESTRUCT_DELAY = 4 weeks;

    uint public initiationTime;
    bool public selfDestructInitiated;

    address public selfDestructBeneficiary;

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

    /**
     * @notice Set the beneficiary address of this contract.
     * @dev Only the contract owner may call this. The provided beneficiary must be non-null.
     * @param _beneficiary The address to pay any eth contained in this contract to upon self-destruction.
     */
    function setSelfDestructBeneficiary(address payable _beneficiary) external onlyOwner {
        require(_beneficiary != address(0), "Beneficiary must not be zero");
        selfDestructBeneficiary = _beneficiary;
        emit SelfDestructBeneficiaryUpdated(_beneficiary);
    }

    /**
     * @notice Begin the self-destruction counter of this contract.
     * Once the delay has elapsed, the contract may be self-destructed.
     * @dev Only the contract owner may call this.
     */
    function initiateSelfDestruct() external onlyOwner {
        initiationTime = now;
        selfDestructInitiated = true;
        emit SelfDestructInitiated(SELFDESTRUCT_DELAY);
    }

    /**
     * @notice Terminate and reset the self-destruction timer.
     * @dev Only the contract owner may call this.
     */
    function terminateSelfDestruct() external onlyOwner {
        initiationTime = 0;
        selfDestructInitiated = false;
        emit SelfDestructTerminated();
    }

    /**
     * @notice If the self-destruction delay has elapsed, destroy this contract and
     * remit any ether it owns to the beneficiary address.
     * @dev Only the contract owner may call this.
     */
    function selfDestruct() external onlyOwner {
        require(selfDestructInitiated, "Self Destruct not yet initiated");
        require(initiationTime + SELFDESTRUCT_DELAY < now, "Self destruct delay not met");
        emit SelfDestructed(selfDestructBeneficiary);
        selfdestruct(address(uint160(selfDestructBeneficiary)));
    }

    event SelfDestructTerminated();
    event SelfDestructed(address beneficiary);
    event SelfDestructInitiated(uint selfDestructDelay);
    event SelfDestructBeneficiaryUpdated(address newBeneficiary);
}


// https://docs.synthetix.io/contracts/LimitedSetup
contract LimitedSetup {
    uint public setupExpiryTime;

    /**
     * @dev LimitedSetup Constructor.
     * @param setupDuration The time the setup period will last for.
     */
    constructor(uint setupDuration) internal {
        setupExpiryTime = now + setupDuration;
    }

    modifier onlyDuringSetup {
        require(now < setupExpiryTime, "Can only perform this action during setup");
        _;
    }
}


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

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

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


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

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

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

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

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

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


interface ISynthetix {
    // Views
    function availableCurrencyKeys() external view returns (bytes32[] memory);

    function availableSynthCount() external view returns (uint);

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

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

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

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

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

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

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

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

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

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

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

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

    // Mutative Functions
    function burnSynths(uint amount) external;

    function burnSynthsOnBehalf(address burnForAddress, uint amount) external;

    function burnSynthsToTarget() external;

    function burnSynthsToTargetOnBehalf(address burnForAddress) external;

    function exchange(
        bytes32 sourceCurrencyKey,
        uint sourceAmount,
        bytes32 destinationCurrencyKey
    ) external returns (uint amountReceived);

    function exchangeOnBehalf(
        address exchangeForAddress,
        bytes32 sourceCurrencyKey,
        uint sourceAmount,
        bytes32 destinationCurrencyKey
    ) external returns (uint amountReceived);

    function issueMaxSynths() external;

    function issueMaxSynthsOnBehalf(address issueForAddress) external;

    function issueSynths(uint amount) external;

    function issueSynthsOnBehalf(address issueForAddress, uint amount) external;

    function mint() external returns (bool);

    function settle(bytes32 currencyKey)
        external
        returns (
            uint reclaimed,
            uint refunded,
            uint numEntries
        );

    function liquidateDelinquentAccount(address account, uint susdAmount) external returns (bool);
}


// Inheritance


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

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

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

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

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

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

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

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

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


// Inheritance


// Internal references


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

    mapping(bytes32 => address) private addressCache;

    bytes32[] public resolverAddressesRequired;

    uint public constant MAX_ADDRESSES_FROM_RESOLVER = 24;

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

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

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

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

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

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

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

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

        return true;
    }

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

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


interface IFeePool {
    // Views
    function getExchangeFeeRateForSynth(bytes32 synthKey) external view returns (uint);

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

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

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

    function totalFeesAvailable() external view returns (uint);

    function totalRewardsAvailable() external view returns (uint);

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

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

    function closeCurrentFeePeriod() external;

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

    function recordFeePaid(uint sUSDAmount) external;

    function setRewardsToDistribute(uint amount) external;
}


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

        return c;
    }

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

        return c;
    }

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

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

        return c;
    }

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

        return c;
    }

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


// Libraries


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

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

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

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

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

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

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

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

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

        return quotientTimesTen / 10;
    }

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

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

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

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

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

        return resultTimesTen / 10;
    }

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

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

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

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

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

        return quotientTimesTen / 10;
    }
}


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


interface ISystemStatus {
    // Views
    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;
}


interface IRewardEscrow {
    // Views
    function balanceOf(address account) external view returns (uint);

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

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

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

    // Mutative functions
    function appendVestingEntry(address account, uint quantity) external;

    function vest() external;
}


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

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

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

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

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

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

    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 rateForCurrency(bytes32 currencyKey) external view returns (uint);

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

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

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

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

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


interface ISynthetixState {
    // Views
    function debtLedger(uint index) external view returns (uint);

    function issuanceRatio() external view returns (uint);

    function issuanceData(address account) external view returns (uint initialDebtOwnership, uint debtEntryIndex);

    function debtLedgerLength() external view returns (uint);

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

    function lastDebtLedgerEntry() external view returns (uint);

    // Mutative functions
    function incrementTotalIssuerCount() external;

    function decrementTotalIssuerCount() external;

    function setCurrentIssuanceData(address account, uint initialDebtOwnership) external;

    function appendDebtLedgerValue(uint value) external;

    function clearIssuanceData(address account) external;
}


interface IExchanger {
    // Views
    function calculateAmountAfterSettlement(
        address from,
        bytes32 currencyKey,
        uint amount,
        uint refunded
    ) external view returns (uint amountAfterSettlement);

    function maxSecsLeftInWaitingPeriod(address account, bytes32 currencyKey) external view returns (uint);

    function settlementOwing(address account, bytes32 currencyKey)
        external
        view
        returns (
            uint reclaimAmount,
            uint rebateAmount,
            uint numEntries
        );

    function hasWaitingPeriodOrSettlementOwing(address account, bytes32 currencyKey) external view returns (bool);

    function feeRateForExchange(bytes32 sourceCurrencyKey, bytes32 destinationCurrencyKey)
        external
        view
        returns (uint exchangeFeeRate);

    function getAmountsForExchange(
        uint sourceAmount,
        bytes32 sourceCurrencyKey,
        bytes32 destinationCurrencyKey
    )
        external
        view
        returns (
            uint amountReceived,
            uint fee,
            uint exchangeFeeRate
        );

    // Mutative functions
    function exchange(
        address from,
        bytes32 sourceCurrencyKey,
        uint sourceAmount,
        bytes32 destinationCurrencyKey,
        address destinationAddress
    ) external returns (uint amountReceived);

    function exchangeOnBehalf(
        address exchangeForAddress,
        address from,
        bytes32 sourceCurrencyKey,
        uint sourceAmount,
        bytes32 destinationCurrencyKey
    ) external returns (uint amountReceived);

    function settle(address from, bytes32 currencyKey)
        external
        returns (
            uint reclaimed,
            uint refunded,
            uint numEntries
        );
}


interface IIssuer {
    // Views
    function canBurnSynths(address account) external view returns (bool);

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

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


interface IRewardsDistribution {
    // Mutative functions
    function distributeRewards(uint amount) external returns (bool);
}


interface IDelegateApprovals {
    // Views
    function canBurnFor(address authoriser, address delegate) external view returns (bool);

    function canIssueFor(address authoriser, address delegate) external view returns (bool);

    function canClaimFor(address authoriser, address delegate) external view returns (bool);

    function canExchangeFor(address authoriser, address delegate) external view returns (bool);

    // Mutative
    function approveAllDelegatePowers(address delegate) external;

    function removeAllDelegatePowers(address delegate) external;

    function approveBurnOnBehalf(address delegate) external;

    function removeBurnOnBehalf(address delegate) external;

    function approveIssueOnBehalf(address delegate) external;

    function removeIssueOnBehalf(address delegate) external;

    function approveClaimOnBehalf(address delegate) external;

    function removeClaimOnBehalf(address delegate) external;

    function approveExchangeOnBehalf(address delegate) external;

    function removeExchangeOnBehalf(address delegate) external;
}


// Inheritance


// Libraries


// Internal references


// https://docs.synthetix.io/contracts/FeePoolState
contract FeePoolState is Owned, SelfDestructible, LimitedSetup {
    using SafeMath for uint;
    using SafeDecimalMath for uint;

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

    uint8 public constant FEE_PERIOD_LENGTH = 6;

    address public feePool;

    // The IssuanceData activity that's happened in a fee period.
    struct IssuanceData {
        uint debtPercentage;
        uint debtEntryIndex;
    }

    // The IssuanceData activity that's happened in a fee period.
    mapping(address => IssuanceData[FEE_PERIOD_LENGTH]) public accountIssuanceLedger;

    constructor(address _owner, IFeePool _feePool) public Owned(_owner) SelfDestructible() LimitedSetup(6 weeks) {
        feePool = address(_feePool);
    }

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

    /**
     * @notice set the FeePool contract as it is the only authority to be able to call
     * appendAccountIssuanceRecord with the onlyFeePool modifer
     * @dev Must be set by owner when FeePool logic is upgraded
     */
    function setFeePool(IFeePool _feePool) external onlyOwner {
        feePool = address(_feePool);
    }

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

    /**
     * @notice Get an accounts issuanceData for
     * @param account users account
     * @param index Index in the array to retrieve. Upto FEE_PERIOD_LENGTH
     */
    function getAccountsDebtEntry(address account, uint index)
        public
        view
        returns (uint debtPercentage, uint debtEntryIndex)
    {
        require(index < FEE_PERIOD_LENGTH, "index exceeds the FEE_PERIOD_LENGTH");

        debtPercentage = accountIssuanceLedger[account][index].debtPercentage;
        debtEntryIndex = accountIssuanceLedger[account][index].debtEntryIndex;
    }

    /**
     * @notice Find the oldest debtEntryIndex for the corresponding closingDebtIndex
     * @param account users account
     * @param closingDebtIndex the last periods debt index on close
     */
    function applicableIssuanceData(address account, uint closingDebtIndex) external view returns (uint, uint) {
        IssuanceData[FEE_PERIOD_LENGTH] memory issuanceData = accountIssuanceLedger[account];

        // We want to use the user's debtEntryIndex at when the period closed
        // Find the oldest debtEntryIndex for the corresponding closingDebtIndex
        for (uint i = 0; i < FEE_PERIOD_LENGTH; i++) {
            if (closingDebtIndex >= issuanceData[i].debtEntryIndex) {
                return (issuanceData[i].debtPercentage, issuanceData[i].debtEntryIndex);
            }
        }
    }

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

    /**
     * @notice Logs an accounts issuance data in the current fee period which is then stored historically
     * @param account Message.Senders account address
     * @param debtRatio Debt of this account as a percentage of the global debt.
     * @param debtEntryIndex The index in the global debt ledger. synthetix.synthetixState().issuanceData(account)
     * @param currentPeriodStartDebtIndex The startingDebtIndex of the current fee period
     * @dev onlyFeePool to call me on synthetix.issue() & synthetix.burn() calls to store the locked SNX
     * per fee period so we know to allocate the correct proportions of fees and rewards per period
      accountIssuanceLedger[account][0] has the latest locked amount for the current period. This can be update as many time
      accountIssuanceLedger[account][1-2] has the last locked amount for a previous period they minted or burned
     */
    function appendAccountIssuanceRecord(
        address account,
        uint debtRatio,
        uint debtEntryIndex,
        uint currentPeriodStartDebtIndex
    ) external onlyFeePool {
        // Is the current debtEntryIndex within this fee period
        if (accountIssuanceLedger[account][0].debtEntryIndex < currentPeriodStartDebtIndex) {
            // If its older then shift the previous IssuanceData entries periods down to make room for the new one.
            issuanceDataIndexOrder(account);
        }

        // Always store the latest IssuanceData entry at [0]
        accountIssuanceLedger[account][0].debtPercentage = debtRatio;
        accountIssuanceLedger[account][0].debtEntryIndex = debtEntryIndex;
    }

    /**
     * @notice Pushes down the entire array of debt ratios per fee period
     */
    function issuanceDataIndexOrder(address account) private {
        for (uint i = FEE_PERIOD_LENGTH - 2; i < FEE_PERIOD_LENGTH; i--) {
            uint next = i + 1;
            accountIssuanceLedger[account][next].debtPercentage = accountIssuanceLedger[account][i].debtPercentage;
            accountIssuanceLedger[account][next].debtEntryIndex = accountIssuanceLedger[account][i].debtEntryIndex;
        }
    }

    /**
     * @notice Import issuer data from synthetixState.issuerData on FeePeriodClose() block #
     * @dev Only callable by the contract owner, and only for 6 weeks after deployment.
     * @param accounts Array of issuing addresses
     * @param ratios Array of debt ratios
     * @param periodToInsert The Fee Period to insert the historical records into
     * @param feePeriodCloseIndex An accounts debtEntryIndex is valid when within the fee peroid,
     * since the input ratio will be an average of the pervious periods it just needs to be
     * > recentFeePeriods[periodToInsert].startingDebtIndex
     * < recentFeePeriods[periodToInsert - 1].startingDebtIndex
     */
    function importIssuerData(
        address[] calldata accounts,
        uint[] calldata ratios,
        uint periodToInsert,
        uint feePeriodCloseIndex
    ) external onlyOwner onlyDuringSetup {
        require(accounts.length == ratios.length, "Length mismatch");

        for (uint i = 0; i < accounts.length; i++) {
            accountIssuanceLedger[accounts[i]][periodToInsert].debtPercentage = ratios[i];
            accountIssuanceLedger[accounts[i]][periodToInsert].debtEntryIndex = feePeriodCloseIndex;
            emit IssuanceDebtRatioEntry(accounts[i], ratios[i], feePeriodCloseIndex);
        }
    }

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

    modifier onlyFeePool {
        require(msg.sender == address(feePool), "Only the FeePool contract can perform this action");
        _;
    }

    /* ========== Events ========== */
    event IssuanceDebtRatioEntry(address indexed account, uint debtRatio, uint feePeriodCloseIndex);
}


// Inheritance


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


// Inheritance


/**
 * @notice  This contract is based on the code available from this blog
 * https://blog.colony.io/writing-upgradeable-contracts-in-solidity-6743f0eecc88/
 * Implements support for storing a keccak256 key and value pairs. It is the more flexible
 * and extensible option. This ensures data schema changes can be implemented without
 * requiring upgrades to the storage contract.
 */
// https://docs.synthetix.io/contracts/EternalStorage
contract EternalStorage is Owned, State {
    constructor(address _owner, address _associatedContract) public Owned(_owner) State(_associatedContract) {}

    /* ========== DATA TYPES ========== */
    mapping(bytes32 => uint) internal UIntStorage;
    mapping(bytes32 => string) internal StringStorage;
    mapping(bytes32 => address) internal AddressStorage;
    mapping(bytes32 => bytes) internal BytesStorage;
    mapping(bytes32 => bytes32) internal Bytes32Storage;
    mapping(bytes32 => bool) internal BooleanStorage;
    mapping(bytes32 => int) internal IntStorage;

    // UIntStorage;
    function getUIntValue(bytes32 record) external view returns (uint) {
        return UIntStorage[record];
    }

    function setUIntValue(bytes32 record, uint value) external onlyAssociatedContract {
        UIntStorage[record] = value;
    }

    function deleteUIntValue(bytes32 record) external onlyAssociatedContract {
        delete UIntStorage[record];
    }

    // StringStorage
    function getStringValue(bytes32 record) external view returns (string memory) {
        return StringStorage[record];
    }

    function setStringValue(bytes32 record, string calldata value) external onlyAssociatedContract {
        StringStorage[record] = value;
    }

    function deleteStringValue(bytes32 record) external onlyAssociatedContract {
        delete StringStorage[record];
    }

    // AddressStorage
    function getAddressValue(bytes32 record) external view returns (address) {
        return AddressStorage[record];
    }

    function setAddressValue(bytes32 record, address value) external onlyAssociatedContract {
        AddressStorage[record] = value;
    }

    function deleteAddressValue(bytes32 record) external onlyAssociatedContract {
        delete AddressStorage[record];
    }

    // BytesStorage
    function getBytesValue(bytes32 record) external view returns (bytes memory) {
        return BytesStorage[record];
    }

    function setBytesValue(bytes32 record, bytes calldata value) external onlyAssociatedContract {
        BytesStorage[record] = value;
    }

    function deleteBytesValue(bytes32 record) external onlyAssociatedContract {
        delete BytesStorage[record];
    }

    // Bytes32Storage
    function getBytes32Value(bytes32 record) external view returns (bytes32) {
        return Bytes32Storage[record];
    }

    function setBytes32Value(bytes32 record, bytes32 value) external onlyAssociatedContract {
        Bytes32Storage[record] = value;
    }

    function deleteBytes32Value(bytes32 record) external onlyAssociatedContract {
        delete Bytes32Storage[record];
    }

    // BooleanStorage
    function getBooleanValue(bytes32 record) external view returns (bool) {
        return BooleanStorage[record];
    }

    function setBooleanValue(bytes32 record, bool value) external onlyAssociatedContract {
        BooleanStorage[record] = value;
    }

    function deleteBooleanValue(bytes32 record) external onlyAssociatedContract {
        delete BooleanStorage[record];
    }

    // IntStorage
    function getIntValue(bytes32 record) external view returns (int) {
        return IntStorage[record];
    }

    function setIntValue(bytes32 record, int value) external onlyAssociatedContract {
        IntStorage[record] = value;
    }

    function deleteIntValue(bytes32 record) external onlyAssociatedContract {
        delete IntStorage[record];
    }
}


// Inheritance


// https://docs.synthetix.io/contracts/FeePoolEternalStorage
contract FeePoolEternalStorage is EternalStorage, LimitedSetup {
    bytes32 internal constant LAST_FEE_WITHDRAWAL = "last_fee_withdrawal";

    constructor(address _owner, address _feePool) public EternalStorage(_owner, _feePool) LimitedSetup(6 weeks) {}

    function importFeeWithdrawalData(address[] calldata accounts, uint[] calldata feePeriodIDs)
        external
        onlyOwner
        onlyDuringSetup
    {
        require(accounts.length == feePeriodIDs.length, "Length mismatch");

        for (uint8 i = 0; i < accounts.length; i++) {
            this.setUIntValue(keccak256(abi.encodePacked(LAST_FEE_WITHDRAWAL, accounts[i])), feePeriodIDs[i]);
        }
    }
}


// Inheritance


// Libraries


// Internal references


// https://docs.synthetix.io/contracts/FeePool
contract FeePool is Owned, Proxyable, SelfDestructible, LimitedSetup, MixinResolver, IFeePool {
    using SafeMath for uint;
    using SafeDecimalMath for uint;

    // Exchange fee may not exceed 10%.
    uint public constant MAX_EXCHANGE_FEE_RATE = 1e18 / 10;

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

    // sUSD currencyKey. Fees stored and paid in sUSD
    bytes32 private sUSD = "sUSD";

    // This struct represents the issuance activity that's happened in a fee period.
    struct FeePeriod {
        uint64 feePeriodId;
        uint64 startingDebtIndex;
        uint64 startTime;
        uint feesToDistribute;
        uint feesClaimed;
        uint rewardsToDistribute;
        uint rewardsClaimed;
    }

    // A staker(mintr) can claim from the previous fee period (7 days) only.
    // Fee Periods stored and managed from [0], such that [0] is always
    // the current active fee period which is not claimable until the
    // public function closeCurrentFeePeriod() is called closing the
    // current weeks collected fees. [1] is last weeks feeperiod
    uint8 public constant FEE_PERIOD_LENGTH = 2;

    FeePeriod[FEE_PERIOD_LENGTH] private _recentFeePeriods;
    uint256 private _currentFeePeriod;

    // How long a fee period lasts at a minimum. It is required for
    // anyone to roll over the periods, so they are not guaranteed
    // to roll over at exactly this duration, but the contract enforces
    // that they cannot roll over any quicker than this duration.
    uint public feePeriodDuration = 1 weeks;
    // The fee period must be between 1 day and 60 days.
    uint public constant MIN_FEE_PERIOD_DURATION = 1 days;
    uint public constant MAX_FEE_PERIOD_DURATION = 60 days;

    // Users are unable to claim fees if their collateralisation ratio drifts out of target treshold
    uint public targetThreshold = (1 * SafeDecimalMath.unit()) / 100;

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

    bytes32 private constant CONTRACT_SYSTEMSTATUS = "SystemStatus";
    bytes32 private constant CONTRACT_SYNTHETIX = "Synthetix";
    bytes32 private constant CONTRACT_FEEPOOLSTATE = "FeePoolState";
    bytes32 private constant CONTRACT_FEEPOOLETERNALSTORAGE = "FeePoolEternalStorage";
    bytes32 private constant CONTRACT_EXCHANGER = "Exchanger";
    bytes32 private constant CONTRACT_ISSUER = "Issuer";
    bytes32 private constant CONTRACT_SYNTHETIXSTATE = "SynthetixState";
    bytes32 private constant CONTRACT_REWARDESCROW = "RewardEscrow";
    bytes32 private constant CONTRACT_DELEGATEAPPROVALS = "DelegateApprovals";
    bytes32 private constant CONTRACT_REWARDSDISTRIBUTION = "RewardsDistribution";

    bytes32[24] private addressesToCache = [
        CONTRACT_SYSTEMSTATUS,
        CONTRACT_SYNTHETIX,
        CONTRACT_FEEPOOLSTATE,
        CONTRACT_FEEPOOLETERNALSTORAGE,
        CONTRACT_EXCHANGER,
        CONTRACT_ISSUER,
        CONTRACT_SYNTHETIXSTATE,
        CONTRACT_REWARDESCROW,
        CONTRACT_DELEGATEAPPROVALS,
        CONTRACT_REWARDSDISTRIBUTION
    ];

    /* ========== ETERNAL STORAGE CONSTANTS ========== */

    bytes32 private constant LAST_FEE_WITHDRAWAL = "last_fee_withdrawal";
    bytes32 private constant SYNTH_EXCHANGE_FEE_RATE = "synth_exchange_fee_rate";

    constructor(
        address payable _proxy,
        address _owner,
        address _resolver
    )
        public
        Owned(_owner)
        SelfDestructible()
        Proxyable(_proxy)
        LimitedSetup(3 weeks)
        MixinResolver(_resolver, addressesToCache)
    {
        // Set our initial fee period
        _recentFeePeriodsStorage(0).feePeriodId = 1;
        _recentFeePeriodsStorage(0).startTime = uint64(now);
    }

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

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

    function synthetix() internal view returns (ISynthetix) {
        return ISynthetix(requireAndGetAddress(CONTRACT_SYNTHETIX, "Missing Synthetix address"));
    }

    function feePoolState() internal view returns (FeePoolState) {
        return FeePoolState(requireAndGetAddress(CONTRACT_FEEPOOLSTATE, "Missing FeePoolState address"));
    }

    function feePoolEternalStorage() internal view returns (FeePoolEternalStorage) {
        return
            FeePoolEternalStorage(
                requireAndGetAddress(CONTRACT_FEEPOOLETERNALSTORAGE, "Missing FeePoolEternalStorage address")
            );
    }

    function exchanger() internal view returns (IExchanger) {
        return IExchanger(requireAndGetAddress(CONTRACT_EXCHANGER, "Missing Exchanger address"));
    }

    function issuer() internal view returns (IIssuer) {
        return IIssuer(requireAndGetAddress(CONTRACT_ISSUER, "Missing Issuer address"));
    }

    function synthetixState() internal view returns (ISynthetixState) {
        return ISynthetixState(requireAndGetAddress(CONTRACT_SYNTHETIXSTATE, "Missing SynthetixState address"));
    }

    function rewardEscrow() internal view returns (IRewardEscrow) {
        return IRewardEscrow(requireAndGetAddress(CONTRACT_REWARDESCROW, "Missing RewardEscrow address"));
    }

    function delegateApprovals() internal view returns (IDelegateApprovals) {
        return IDelegateApprovals(requireAndGetAddress(CONTRACT_DELEGATEAPPROVALS, "Missing DelegateApprovals address"));
    }

    function rewardsDistribution() internal view returns (IRewardsDistribution) {
        return
            IRewardsDistribution(requireAndGetAddress(CONTRACT_REWARDSDISTRIBUTION, "Missing RewardsDistribution address"));
    }

    function recentFeePeriods(uint index)
        external
        view
        returns (
            uint64 feePeriodId,
            uint64 startingDebtIndex,
            uint64 startTime,
            uint feesToDistribute,
            uint feesClaimed,
            uint rewardsToDistribute,
            uint rewardsClaimed
        )
    {
        FeePeriod memory feePeriod = _recentFeePeriodsStorage(index);
        return (
            feePeriod.feePeriodId,
            feePeriod.startingDebtIndex,
            feePeriod.startTime,
            feePeriod.feesToDistribute,
            feePeriod.feesClaimed,
            feePeriod.rewardsToDistribute,
            feePeriod.rewardsClaimed
        );
    }

    function _recentFeePeriodsStorage(uint index) internal view returns (FeePeriod storage) {
        return _recentFeePeriods[(_currentFeePeriod + index) % FEE_PERIOD_LENGTH];
    }

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

    /**
     * @notice Logs an accounts issuance data per fee period
     * @param account Message.Senders account address
     * @param debtRatio Debt percentage this account has locked after minting or burning their synth
     * @param debtEntryIndex The index in the global debt ledger. synthetixState.issuanceData(account)
     * @dev onlyIssuer to call me on synthetix.issue() & synthetix.burn() calls to store the locked SNX
     * per fee period so we know to allocate the correct proportions of fees and rewards per period
     */
    function appendAccountIssuanceRecord(
        address account,
        uint debtRatio,
        uint debtEntryIndex
    ) external onlyIssuer {
        feePoolState().appendAccountIssuanceRecord(
            account,
            debtRatio,
            debtEntryIndex,
            _recentFeePeriodsStorage(0).startingDebtIndex
        );

        emitIssuanceDebtRatioEntry(account, debtRatio, debtEntryIndex, _recentFeePeriodsStorage(0).startingDebtIndex);
    }

    /**
     * @notice Set the fee period duration
     */
    function setFeePeriodDuration(uint _feePeriodDuration) external optionalProxy_onlyOwner {
        require(_feePeriodDuration >= MIN_FEE_PERIOD_DURATION, "value < MIN_FEE_PERIOD_DURATION");
        require(_feePeriodDuration <= MAX_FEE_PERIOD_DURATION, "value > MAX_FEE_PERIOD_DURATION");

        feePeriodDuration = _feePeriodDuration;

        emitFeePeriodDurationUpdated(_feePeriodDuration);
    }

    function setTargetThreshold(uint _percent) external optionalProxy_onlyOwner {
        require(_percent <= 50, "Threshold too high");
        targetThreshold = _percent.mul(SafeDecimalMath.unit()).div(100);
    }

    /**
     * @notice The Exchanger contract informs us when fees are paid.
     * @param amount susd amount in fees being paid.
     */
    function recordFeePaid(uint amount) external onlyExchangerOrSynth {
        // Keep track off fees in sUSD in the open fee pool period.
        _recentFeePeriodsStorage(0).feesToDistribute = _recentFeePeriodsStorage(0).feesToDistribute.add(amount);
    }

    /**
     * @notice The RewardsDistribution contract informs us how many SNX rewards are sent to RewardEscrow to be claimed.
     */
    function setRewardsToDistribute(uint amount) external {
        address rewardsAuthority = address(rewardsDistribution());
        require(messageSender == rewardsAuthority || msg.sender == rewardsAuthority, "Caller is not rewardsAuthority");
        // Add the amount of SNX rewards to distribute on top of any rolling unclaimed amount
        _recentFeePeriodsStorage(0).rewardsToDistribute = _recentFeePeriodsStorage(0).rewardsToDistribute.add(amount);
    }

    /**
     * @notice Close the current fee period and start a new one.
     */
    function closeCurrentFeePeriod() external {
        require(_recentFeePeriodsStorage(0).startTime <= (now - feePeriodDuration), "Too early to close fee period");

        systemStatus().requireIssuanceActive();

        // Note:  when FEE_PERIOD_LENGTH = 2, periodClosing is the current period & periodToRollover is the last open claimable period
        FeePeriod storage periodClosing = _recentFeePeriodsStorage(FEE_PERIOD_LENGTH - 2);
        FeePeriod storage periodToRollover = _recentFeePeriodsStorage(FEE_PERIOD_LENGTH - 1);

        // Any unclaimed fees from the last period in the array roll back one period.
        // Because of the subtraction here, they're effectively proportionally redistributed to those who
        // have already claimed from the old period, available in the new period.
        // The subtraction is important so we don't create a ticking time bomb of an ever growing
        // number of fees that can never decrease and will eventually overflow at the end of the fee pool.
        _recentFeePeriodsStorage(FEE_PERIOD_LENGTH - 2).feesToDistribute = periodToRollover
            .feesToDistribute
            .sub(periodToRollover.feesClaimed)
            .add(periodClosing.feesToDistribute);
        _recentFeePeriodsStorage(FEE_PERIOD_LENGTH - 2).rewardsToDistribute = periodToRollover
            .rewardsToDistribute
            .sub(periodToRollover.rewardsClaimed)
            .add(periodClosing.rewardsToDistribute);

        // Shift the previous fee periods across to make room for the new one.
        _currentFeePeriod = _currentFeePeriod.add(FEE_PERIOD_LENGTH).sub(1).mod(FEE_PERIOD_LENGTH);

        // Clear the first element of the array to make sure we don't have any stale values.
        delete _recentFeePeriods[_currentFeePeriod];

        // Open up the new fee period.
        // Increment periodId from the recent closed period feePeriodId
        _recentFeePeriodsStorage(0).feePeriodId = uint64(uint256(_recentFeePeriodsStorage(1).feePeriodId).add(1));
        _recentFeePeriodsStorage(0).startingDebtIndex = uint64(synthetixState().debtLedgerLength());
        _recentFeePeriodsStorage(0).startTime = uint64(now);

        emitFeePeriodClosed(_recentFeePeriodsStorage(1).feePeriodId);
    }

    /**
     * @notice Claim fees for last period when available or not already withdrawn.
     */
    function claimFees() external optionalProxy returns (bool) {
        return _claimFees(messageSender);
    }

    /**
     * @notice Delegated claimFees(). Call from the deletegated address
     * and the fees will be sent to the claimingForAddress.
     * approveClaimOnBehalf() must be called first to approve the deletage address
     * @param claimingForAddress The account you are claiming fees for
     */
    function claimOnBehalf(address claimingForAddress) external optionalProxy returns (bool) {
        require(delegateApprovals().canClaimFor(claimingForAddress, messageSender), "Not approved to claim on behalf");

        return _claimFees(claimingForAddress);
    }

    function _claimFees(address claimingAddress) internal returns (bool) {
        systemStatus().requireIssuanceActive();

        uint rewardsPaid = 0;
        uint feesPaid = 0;
        uint availableFees;
        uint availableRewards;

        // Address won't be able to claim fees if it is too far below the target c-ratio.
        // It will need to burn synths then try claiming again.
        require(isFeesClaimable(claimingAddress), "C-Ratio below penalty threshold");

        // Get the claimingAddress available fees and rewards
        (availableFees, availableRewards) = feesAvailable(claimingAddress);

        require(
            availableFees > 0 || availableRewards > 0,
            "No fees or rewards available for period, or fees already claimed"
        );

        // Record the address has claimed for this period
        _setLastFeeWithdrawal(claimingAddress, _recentFeePeriodsStorage(1).feePeriodId);

        if (availableFees > 0) {
            // Record the fee payment in our recentFeePeriods
            feesPaid = _recordFeePayment(availableFees);

            // Send them their fees
            _payFees(claimingAddress, feesPaid);
        }

        if (availableRewards > 0) {
            // Record the reward payment in our recentFeePeriods
            rewardsPaid = _recordRewardPayment(availableRewards);

            // Send them their rewards
            _payRewards(claimingAddress, rewardsPaid);
        }

        emitFeesClaimed(claimingAddress, feesPaid, rewardsPaid);

        return true;
    }

    /**
     * @notice Admin function to import the FeePeriod data from the previous contract
     */
    function importFeePeriod(
        uint feePeriodIndex,
        uint feePeriodId,
        uint startingDebtIndex,
        uint startTime,
        uint feesToDistribute,
        uint feesClaimed,
        uint rewardsToDistribute,
        uint rewardsClaimed
    ) public optionalProxy_onlyOwner onlyDuringSetup {
        require(startingDebtIndex <= synthetixState().debtLedgerLength(), "Cannot import bad data");

        _recentFeePeriods[_currentFeePeriod.add(feePeriodIndex).mod(FEE_PERIOD_LENGTH)] = FeePeriod({
            feePeriodId: uint64(feePeriodId),
            startingDebtIndex: uint64(startingDebtIndex),
            startTime: uint64(startTime),
            feesToDistribute: feesToDistribute,
            feesClaimed: feesClaimed,
            rewardsToDistribute: rewardsToDistribute,
            rewardsClaimed: rewardsClaimed
        });
    }

    function setExchangeFeeRateForSynths(bytes32[] calldata synthKeys, uint256[] calldata exchangeFeeRates) external optionalProxy_onlyOwner
    {
        require(synthKeys.length == exchangeFeeRates.length, "Array lengths dont match");
        for (uint i = 0; i < synthKeys.length; i++) {
            require(exchangeFeeRates[i] <= MAX_EXCHANGE_FEE_RATE, "MAX_EXCHANGE_FEE_RATE exceeded");
            feePoolEternalStorage().setUIntValue(
                keccak256(abi.encodePacked(SYNTH_EXCHANGE_FEE_RATE, synthKeys[i])),
                exchangeFeeRates[i]
            );
            emitExchangeFeeUpdated(synthKeys[i], exchangeFeeRates[i]);
        }
    }

    function getExchangeFeeRateForSynth(bytes32 synthKey) external view returns (uint exchangeFeeRate) {
        exchangeFeeRate = feePoolEternalStorage().getUIntValue(
            keccak256(abi.encodePacked(SYNTH_EXCHANGE_FEE_RATE, synthKey))
        );
    }

    /**
     * @notice Owner can escrow SNX. Owner to send the tokens to the RewardEscrow
     * @param account Address to escrow tokens for
     * @param quantity Amount of tokens to escrow
     */
    function appendVestingEntry(address account, uint quantity) public optionalProxy_onlyOwner {
        // Transfer SNX from messageSender to the Reward Escrow
        IERC20(address(synthetix())).transferFrom(messageSender, address(rewardEscrow()), quantity);

        // Create Vesting Entry
        rewardEscrow().appendVestingEntry(account, quantity);
    }

    /**
     * @notice Record the fee payment in our recentFeePeriods.
     * @param sUSDAmount The amount of fees priced in sUSD.
     */
    function _recordFeePayment(uint sUSDAmount) internal returns (uint) {
        // Don't assign to the parameter
        uint remainingToAllocate = sUSDAmount;

        uint feesPaid;
        // Start at the oldest period and record the amount, moving to newer periods
        // until we've exhausted the amount.
        // The condition checks for overflow because we're going to 0 with an unsigned int.
        for (uint i = FEE_PERIOD_LENGTH - 1; i < FEE_PERIOD_LENGTH; i--) {
            uint feesAlreadyClaimed = _recentFeePeriodsStorage(i).feesClaimed;
            uint delta = _recentFeePeriodsStorage(i).feesToDistribute.sub(feesAlreadyClaimed);

            if (delta > 0) {
                // Take the smaller of the amount left to claim in the period and the amount we need to allocate
                uint amountInPeriod = delta < remainingToAllocate ? delta : remainingToAllocate;

                _recentFeePeriodsStorage(i).feesClaimed = feesAlreadyClaimed.add(amountInPeriod);
                remainingToAllocate = remainingToAllocate.sub(amountInPeriod);
                feesPaid = feesPaid.add(amountInPeriod);

                // No need to continue iterating if we've recorded the whole amount;
                if (remainingToAllocate == 0) return feesPaid;

                // We've exhausted feePeriods to distribute and no fees remain in last period
                // User last to claim would in this scenario have their remainder slashed
                if (i == 0 && remainingToAllocate > 0) {
                    remainingToAllocate = 0;
                }
            }
        }

        return feesPaid;
    }

    /**
     * @notice Record the reward payment in our recentFeePeriods.
     * @param snxAmount The amount of SNX tokens.
     */
    function _recordRewardPayment(uint snxAmount) internal returns (uint) {
        // Don't assign to the parameter
        uint remainingToAllocate = snxAmount;

        uint rewardPaid;

        // Start at the oldest period and record the amount, moving to newer periods
        // until we've exhausted the amount.
        // The condition checks for overflow because we're going to 0 with an unsigned int.
        for (uint i = FEE_PERIOD_LENGTH - 1; i < FEE_PERIOD_LENGTH; i--) {
            uint toDistribute = _recentFeePeriodsStorage(i).rewardsToDistribute.sub(
                _recentFeePeriodsStorage(i).rewardsClaimed
            );

            if (toDistribute > 0) {
                // Take the smaller of the amount left to claim in the period and the amount we need to allocate
                uint amountInPeriod = toDistribute < remainingToAllocate ? toDistribute : remainingToAllocate;

                _recentFeePeriodsStorage(i).rewardsClaimed = _recentFeePeriodsStorage(i).rewardsClaimed.add(amountInPeriod);
                remainingToAllocate = remainingToAllocate.sub(amountInPeriod);
                rewardPaid = rewardPaid.add(amountInPeriod);

                // No need to continue iterating if we've recorded the whole amount;
                if (remainingToAllocate == 0) return rewardPaid;

                // We've exhausted feePeriods to distribute and no rewards remain in last period
                // User last to claim would in this scenario have their remainder slashed
                // due to rounding up of PreciseDecimal
                if (i == 0 && remainingToAllocate > 0) {
                    remainingToAllocate = 0;
                }
            }
        }
        return rewardPaid;
    }

    /**
     * @notice Send the fees to claiming address.
     * @param account The address to send the fees to.
     * @param sUSDAmount The amount of fees priced in sUSD.
     */
    function _payFees(address account, uint sUSDAmount) internal notFeeAddress(account) {
        // Grab the sUSD Synth
        ISynth sUSDSynth = synthetix().synths(sUSD);

        // NOTE: we do not control the FEE_ADDRESS so it is not possible to do an
        // ERC20.approve() transaction to allow this feePool to call ERC20.transferFrom
        // to the accounts address

        // Burn the source amount
        sUSDSynth.burn(FEE_ADDRESS, sUSDAmount);

        // Mint their new synths
        sUSDSynth.issue(account, sUSDAmount);
    }

    /**
     * @notice Send the rewards to claiming address - will be locked in rewardEscrow.
     * @param account The address to send the fees to.
     * @param snxAmount The amount of SNX.
     */
    function _payRewards(address account, uint snxAmount) internal notFeeAddress(account) {
        // Record vesting entry for claiming address and amount
        // SNX already minted to rewardEscrow balance
        rewardEscrow().appendVestingEntry(account, snxAmount);
    }

    /**
     * @notice The total fees available in the system to be withdrawnn in sUSD
     */
    function totalFeesAvailable() external view returns (uint) {
        uint totalFees = 0;

        // Fees in fee period [0] are not yet available for withdrawal
        for (uint i = 1; i < FEE_PERIOD_LENGTH; i++) {
            totalFees = totalFees.add(_recentFeePeriodsStorage(i).feesToDistribute);
            totalFees = totalFees.sub(_recentFeePeriodsStorage(i).feesClaimed);
        }

        return totalFees;
    }

    /**
     * @notice The total SNX rewards available in the system to be withdrawn
     */
    function totalRewardsAvailable() external view returns (uint) {
        uint totalRewards = 0;

        // Rewards in fee period [0] are not yet available for withdrawal
        for (uint i = 1; i < FEE_PERIOD_LENGTH; i++) {
            totalRewards = totalRewards.add(_recentFeePeriodsStorage(i).rewardsToDistribute);
            totalRewards = totalRewards.sub(_recentFeePeriodsStorage(i).rewardsClaimed);
        }

        return totalRewards;
    }

    /**
     * @notice The fees available to be withdrawn by a specific account, priced in sUSD
     * @dev Returns two amounts, one for fees and one for SNX rewards
     */
    function feesAvailable(address account) public view returns (uint, uint) {
        // Add up the fees
        uint[2][FEE_PERIOD_LENGTH] memory userFees = feesByPeriod(account);

        uint totalFees = 0;
        uint totalRewards = 0;

        // Fees & Rewards in fee period [0] are not yet available for withdrawal
        for (uint i = 1; i < FEE_PERIOD_LENGTH; i++) {
            totalFees = totalFees.add(userFees[i][0]);
            totalRewards = totalRewards.add(userFees[i][1]);
        }

        // And convert totalFees to sUSD
        // Return totalRewards as is in SNX amount
        return (totalFees, totalRewards);
    }

    /**
     * @notice Check if a particular address is able to claim fees right now
     * @param account The address you want to query for
     */
    function isFeesClaimable(address account) public view returns (bool) {
        // Threshold is calculated from ratio % above the target ratio (issuanceRatio).
        //  0  <  10%:   Claimable
        // 10% > above:  Unable to claim
        uint ratio = synthetix().collateralisationRatio(account);
        uint targetRatio = synthetixState().issuanceRatio();

        // Claimable if collateral ratio below target ratio
        if (ratio < targetRatio) {
            return true;
        }

        // Calculate the threshold for collateral ratio before fees can't be claimed.
        uint ratio_threshold = targetRatio.multiplyDecimal(SafeDecimalMath.unit().add(targetThreshold));

        // Not claimable if collateral ratio above threshold
        if (ratio > ratio_threshold) {
            return false;
        }

        return true;
    }

    /**
     * @notice Calculates fees by period for an account, priced in sUSD
     * @param account The address you want to query the fees for
     */
    function feesByPeriod(address account) public view returns (uint[2][FEE_PERIOD_LENGTH] memory results) {
        // What's the user's debt entry index and the debt they owe to the system at current feePeriod
        uint userOwnershipPercentage;
        uint debtEntryIndex;
        FeePoolState _feePoolState = feePoolState();

        (userOwnershipPercentage, debtEntryIndex) = _feePoolState.getAccountsDebtEntry(account, 0);

        // If they don't have any debt ownership and they never minted, they don't have any fees.
        // User ownership can reduce to 0 if user burns all synths,
        // however they could have fees applicable for periods they had minted in before so we check debtEntryIndex.
        if (debtEntryIndex == 0 && userOwnershipPercentage == 0) {
            uint[2][FEE_PERIOD_LENGTH] memory nullResults;
            return nullResults;
        }

        // The [0] fee period is not yet ready to claim, but it is a fee period that they can have
        // fees owing for, so we need to report on it anyway.
        uint feesFromPeriod;
        uint rewardsFromPeriod;
        (feesFromPeriod, rewardsFromPeriod) = _feesAndRewardsFromPeriod(0, userOwnershipPercentage, debtEntryIndex);

        results[0][0] = feesFromPeriod;
        results[0][1] = rewardsFromPeriod;

        // Retrieve user's last fee claim by periodId
        uint lastFeeWithdrawal = getLastFeeWithdrawal(account);

        // Go through our fee periods from the oldest feePeriod[FEE_PERIOD_LENGTH - 1] and figure out what we owe them.
        // Condition checks for periods > 0
        for (uint i = FEE_PERIOD_LENGTH - 1; i > 0; i--) {
            uint next = i - 1;
            uint nextPeriodStartingDebtIndex = _recentFeePeriodsStorage(next).startingDebtIndex;

            // We can skip the period, as no debt minted during period (next period's startingDebtIndex is still 0)
            if (nextPeriodStartingDebtIndex > 0 && lastFeeWithdrawal < _recentFeePeriodsStorage(i).feePeriodId) {
                // We calculate a feePeriod's closingDebtIndex by looking at the next feePeriod's startingDebtIndex
                // we can use the most recent issuanceData[0] for the current feePeriod
                // else find the applicableIssuanceData for the feePeriod based on the StartingDebtIndex of the period
                uint closingDebtIndex = uint256(nextPeriodStartingDebtIndex).sub(1);

                // Gas optimisation - to reuse debtEntryIndex if found new applicable one
                // if applicable is 0,0 (none found) we keep most recent one from issuanceData[0]
                // return if userOwnershipPercentage = 0)
                (userOwnershipPercentage, debtEntryIndex) = _feePoolState.applicableIssuanceData(account, closingDebtIndex);

                (feesFromPeriod, rewardsFromPeriod) = _feesAndRewardsFromPeriod(i, userOwnershipPercentage, debtEntryIndex);

                results[i][0] = feesFromPeriod;
                results[i][1] = rewardsFromPeriod;
            }
        }
    }

    /**
     * @notice ownershipPercentage is a high precision decimals uint based on
     * wallet's debtPercentage. Gives a precise amount of the feesToDistribute
     * for fees in the period. Precision factor is removed before results are
     * returned.
     * @dev The reported fees owing for the current period [0] are just a
     * running balance until the fee period closes
     */
    function _feesAndRewardsFromPeriod(
        uint period,
        uint ownershipPercentage,
        uint debtEntryIndex
    ) internal view returns (uint, uint) {
        // If it's zero, they haven't issued, and they have no fees OR rewards.
        if (ownershipPercentage == 0) return (0, 0);

        uint debtOwnershipForPeriod = ownershipPercentage;

        // If period has closed we want to calculate debtPercentage for the period
        if (period > 0) {
            uint closingDebtIndex = uint256(_recentFeePeriodsStorage(period - 1).startingDebtIndex).sub(1);
            debtOwnershipForPeriod = _effectiveDebtRatioForPeriod(closingDebtIndex, ownershipPercentage, debtEntryIndex);
        }

        // Calculate their percentage of the fees / rewards in this period
        // This is a high precision integer.
        uint feesFromPeriod = _recentFeePeriodsStorage(period).feesToDistribute.multiplyDecimal(debtOwnershipForPeriod);

        uint rewardsFromPeriod = _recentFeePeriodsStorage(period).rewardsToDistribute.multiplyDecimal(
            debtOwnershipForPeriod
        );

        return (feesFromPeriod.preciseDecimalToDecimal(), rewardsFromPeriod.preciseDecimalToDecimal());
    }

    function _effectiveDebtRatioForPeriod(
        uint closingDebtIndex,
        uint ownershipPercentage,
        uint debtEntryIndex
    ) internal view returns (uint) {
        // Figure out their global debt percentage delta at end of fee Period.
        // This is a high precision integer.
        ISynthetixState _synthetixState = synthetixState();
        uint feePeriodDebtOwnership = _synthetixState
            .debtLedger(closingDebtIndex)
            .divideDecimalRoundPrecise(_synthetixState.debtLedger(debtEntryIndex))
            .multiplyDecimalRoundPrecise(ownershipPercentage);

        return feePeriodDebtOwnership;
    }

    function effectiveDebtRatioForPeriod(address account, uint period) external view returns (uint) {
        require(period != 0, "Current period is not closed yet");
        require(period < FEE_PERIOD_LENGTH, "Exceeds the FEE_PERIOD_LENGTH");

        // If the period being checked is uninitialised then return 0. This is only at the start of the system.
        if (_recentFeePeriodsStorage(period - 1).startingDebtIndex == 0) return 0;

        uint closingDebtIndex = uint256(_recentFeePeriodsStorage(period - 1).startingDebtIndex).sub(1);

        uint ownershipPercentage;
        uint debtEntryIndex;
        (ownershipPercentage, debtEntryIndex) = feePoolState().applicableIssuanceData(account, closingDebtIndex);

        // internal function will check closingDebtIndex has corresponding debtLedger entry
        return _effectiveDebtRatioForPeriod(closingDebtIndex, ownershipPercentage, debtEntryIndex);
    }

    /**
     * @notice Get the feePeriodID of the last claim this account made
     * @param _claimingAddress account to check the last fee period ID claim for
     * @return uint of the feePeriodID this account last claimed
     */
    function getLastFeeWithdrawal(address _claimingAddress) public view returns (uint) {
        return feePoolEternalStorage().getUIntValue(keccak256(abi.encodePacked(LAST_FEE_WITHDRAWAL, _claimingAddress)));
    }

    /**
     * @notice Calculate the collateral ratio before user is blocked from claiming.
     */
    function getPenaltyThresholdRatio() public view returns (uint) {
        uint targetRatio = synthetixState().issuanceRatio();

        return targetRatio.multiplyDecimal(SafeDecimalMath.unit().add(targetThreshold));
    }

    /**
     * @notice Set the feePeriodID of the last claim this account made
     * @param _claimingAddress account to set the last feePeriodID claim for
     * @param _feePeriodID the feePeriodID this account claimed fees for
     */
    function _setLastFeeWithdrawal(address _claimingAddress, uint _feePeriodID) internal {
        feePoolEternalStorage().setUIntValue(
            keccak256(abi.encodePacked(LAST_FEE_WITHDRAWAL, _claimingAddress)),
            _feePeriodID
        );
    }

    /* ========== Modifiers ========== */
    modifier onlyExchangerOrSynth {
        bool isExchanger = msg.sender == address(exchanger());
        bool isSynth = synthetix().synthsByAddress(msg.sender) != bytes32(0);

        require(isExchanger || isSynth, "Only Exchanger, Synths Authorised");
        _;
    }

    modifier onlyIssuer {
        require(msg.sender == address(issuer()), "FeePool: Only Issuer Authorised");
        _;
    }

    modifier notFeeAddress(address account) {
        require(account != FEE_ADDRESS, "Fee address not allowed");
        _;
    }

    /* ========== Proxy Events ========== */

    event IssuanceDebtRatioEntry(
        address indexed account,
        uint debtRatio,
        uint debtEntryIndex,
        uint feePeriodStartingDebtIndex
    );
    bytes32 private constant ISSUANCEDEBTRATIOENTRY_SIG = keccak256(
        "IssuanceDebtRatioEntry(address,uint256,uint256,uint256)"
    );

    function emitIssuanceDebtRatioEntry(
        address account,
        uint debtRatio,
        uint debtEntryIndex,
        uint feePeriodStartingDebtIndex
    ) internal {
        proxy._emit(
            abi.encode(debtRatio, debtEntryIndex, feePeriodStartingDebtIndex),
            2,
            ISSUANCEDEBTRATIOENTRY_SIG,
            bytes32(uint256(uint160(account))),
            0,
            0
        );
    }

    event SynthExchangeFeeUpdated(bytes32 synthKey, uint newExchangeFeeRate);
    bytes32 private constant SYNTHEXCHANGEFEEUPDATED_SIG = keccak256("SynthExchangeFeeUpdated(bytes32,uint256)");

    function emitExchangeFeeUpdated(bytes32 synthKey, uint newExchangeFeeRate) internal {
        proxy._emit(abi.encode(synthKey, newExchangeFeeRate), 1, SYNTHEXCHANGEFEEUPDATED_SIG, 0, 0, 0);
    }

    event FeePeriodDurationUpdated(uint newFeePeriodDuration);
    bytes32 private constant FEEPERIODDURATIONUPDATED_SIG = keccak256("FeePeriodDurationUpdated(uint256)");

    function emitFeePeriodDurationUpdated(uint newFeePeriodDuration) internal {
        proxy._emit(abi.encode(newFeePeriodDuration), 1, FEEPERIODDURATIONUPDATED_SIG, 0, 0, 0);
    }

    event FeePeriodClosed(uint feePeriodId);
    bytes32 private constant FEEPERIODCLOSED_SIG = keccak256("FeePeriodClosed(uint256)");

    function emitFeePeriodClosed(uint feePeriodId) internal {
        proxy._emit(abi.encode(feePeriodId), 1, FEEPERIODCLOSED_SIG, 0, 0, 0);
    }

    event FeesClaimed(address account, uint sUSDAmount, uint snxRewards);
    bytes32 private constant FEESCLAIMED_SIG = keccak256("FeesClaimed(address,uint256,uint256)");

    function emitFeesClaimed(
        address account,
        uint sUSDAmount,
        uint snxRewards
    ) internal {
        proxy._emit(abi.encode(account, sUSDAmount, snxRewards), 1, FEESCLAIMED_SIG, 0, 0, 0);
    }
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address payable","name":"_proxy","type":"address"},{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_resolver","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"feePeriodId","type":"uint256"}],"name":"FeePeriodClosed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newFeePeriodDuration","type":"uint256"}],"name":"FeePeriodDurationUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"sUSDAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"snxRewards","type":"uint256"}],"name":"FeesClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"debtRatio","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"debtEntryIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"feePeriodStartingDebtIndex","type":"uint256"}],"name":"IssuanceDebtRatioEntry","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":"address","name":"proxyAddress","type":"address"}],"name":"ProxyUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newBeneficiary","type":"address"}],"name":"SelfDestructBeneficiaryUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"selfDestructDelay","type":"uint256"}],"name":"SelfDestructInitiated","type":"event"},{"anonymous":false,"inputs":[],"name":"SelfDestructTerminated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"beneficiary","type":"address"}],"name":"SelfDestructed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"synthKey","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"newExchangeFeeRate","type":"uint256"}],"name":"SynthExchangeFeeUpdated","type":"event"},{"constant":true,"inputs":[],"name":"FEE_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"FEE_PERIOD_LENGTH","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"MAX_ADDRESSES_FROM_RESOLVER","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"MAX_EXCHANGE_FEE_RATE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"MAX_FEE_PERIOD_DURATION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"MIN_FEE_PERIOD_DURATION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"SELFDESTRUCT_DELAY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"acceptOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"debtRatio","type":"uint256"},{"internalType":"uint256","name":"debtEntryIndex","type":"uint256"}],"name":"appendAccountIssuanceRecord","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"appendVestingEntry","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"claimFees","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"claimingForAddress","type":"address"}],"name":"claimOnBehalf","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"closeCurrentFeePeriod","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"period","type":"uint256"}],"name":"effectiveDebtRatioForPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"feePeriodDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"feesAvailable","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"feesByPeriod","outputs":[{"internalType":"uint256[2][2]","name":"results","type":"uint256[2][2]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"synthKey","type":"bytes32"}],"name":"getExchangeFeeRateForSynth","outputs":[{"internalType":"uint256","name":"exchangeFeeRate","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_claimingAddress","type":"address"}],"name":"getLastFeeWithdrawal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getPenaltyThresholdRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getResolverAddressesRequired","outputs":[{"internalType":"bytes32[24]","name":"addressesRequired","type":"bytes32[24]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"feePeriodIndex","type":"uint256"},{"internalType":"uint256","name":"feePeriodId","type":"uint256"},{"internalType":"uint256","name":"startingDebtIndex","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"feesToDistribute","type":"uint256"},{"internalType":"uint256","name":"feesClaimed","type":"uint256"},{"internalType":"uint256","name":"rewardsToDistribute","type":"uint256"},{"internalType":"uint256","name":"rewardsClaimed","type":"uint256"}],"name":"importFeePeriod","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"initiateSelfDestruct","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"initiationTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"integrationProxy","outputs":[{"internalType":"contract Proxy","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isFeesClaimable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"contract AddressResolver","name":"_resolver","type":"address"}],"name":"isResolverCached","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"messageSender","outputs":[{"internalType":"address","name":"","type":"address"}],"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":"proxy","outputs":[{"internalType":"contract Proxy","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"recentFeePeriods","outputs":[{"internalType":"uint64","name":"feePeriodId","type":"uint64"},{"internalType":"uint64","name":"startingDebtIndex","type":"uint64"},{"internalType":"uint64","name":"startTime","type":"uint64"},{"internalType":"uint256","name":"feesToDistribute","type":"uint256"},{"internalType":"uint256","name":"feesClaimed","type":"uint256"},{"internalType":"uint256","name":"rewardsToDistribute","type":"uint256"},{"internalType":"uint256","name":"rewardsClaimed","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"recordFeePaid","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"resolver","outputs":[{"internalType":"contract AddressResolver","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"resolverAddressesRequired","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"selfDestruct","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"selfDestructBeneficiary","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"selfDestructInitiated","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32[]","name":"synthKeys","type":"bytes32[]"},{"internalType":"uint256[]","name":"exchangeFeeRates","type":"uint256[]"}],"name":"setExchangeFeeRateForSynths","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_feePeriodDuration","type":"uint256"}],"name":"setFeePeriodDuration","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address payable","name":"_integrationProxy","type":"address"}],"name":"setIntegrationProxy","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"setMessageSender","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address payable","name":"_proxy","type":"address"}],"name":"setProxy","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"contract AddressResolver","name":"_resolver","type":"address"}],"name":"setResolverAndSyncCache","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"setRewardsToDistribute","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address payable","name":"_beneficiary","type":"address"}],"name":"setSelfDestructBeneficiary","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_percent","type":"uint256"}],"name":"setTargetThreshold","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"setupExpiryTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"targetThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"terminateSelfDestruct","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalFeesAvailable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalRewardsAvailable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}]

60806040819052631cd554d160e21b600b5562093a80601755630241ebdb60e61b81526064907384d626b2bb4d0f064067e4bf80fce7055d8f3e7b9063907af6c09060849060209060048186803b1580156200005a57600080fd5b505af41580156200006f573d6000803e3d6000fd5b505050506040513d60208110156200008657600080fd5b5051816200009057fe5b046018556040518061014001604052806b53797374656d53746174757360a01b8152602001680a6f2dce8d0cae8d2f60bb1b81526020016b466565506f6f6c537461746560a01b81526020017f466565506f6f6c457465726e616c53746f72616765000000000000000000000081526020016822bc31b430b733b2b960b91b81526020016524b9b9bab2b960d11b81526020016d53796e746865746978537461746560901b81526020016b526577617264457363726f7760a01b81526020017044656c6567617465417070726f76616c7360781b81526020017f52657761726473446973747269627574696f6e00000000000000000000000000815250601990600a6200019f929190620005a7565b50348015620001ad57600080fd5b5060405162004f6338038062004f6383398181016040526060811015620001d357600080fd5b5080516020820151604092830151835161030081019485905292939192909182919060199060189082845b815481526020019060010190808311620001fe575050505050621baf80858560006001600160a01b0316816001600160a01b0316141562000286576040805162461bcd60e51b815260206004820152601960248201527f4f776e657220616464726573732063616e6e6f74206265203000000000000000604482015290519081900360640190fd5b600080546001600160a01b0319166001600160a01b038316908117825560408051928352602083019190915280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a1506000546001600160a01b031662000331576040805162461bcd60e51b815260206004820152601160248201527013dddb995c881b5d5cdd081899481cd95d607a1b604482015290519081900360640190fd5b600280546001600160a01b0383166001600160a01b0319909116811790915560408051918252517ffc80377ca9c49cc11ae6982f390a42db976d5530af7c43889264b13fbbd7c57e9181900360200190a1506000546001600160a01b0316620003d5576040805162461bcd60e51b815260206004820152601160248201527013dddb995c881b5d5cdd081899481cd95d607a1b604482015290519081900360640190fd5b60005460068054610100600160a81b0319166101006001600160a01b0390931692830217905560408051918252517fd5da63a0b864b315bc04128dedbc93888c8529ee6cf47ce664dc204339228c53916020908290030190a142016007556000546001600160a01b031662000485576040805162461bcd60e51b815260206004820152601160248201527013dddb995c881b5d5cdd081899481cd95d607a1b604482015290519081900360640190fd5b60005b6018811015620004ed576000828260188110620004a157fe5b602002015114620004de57600a828260188110620004bb57fe5b6020908102919091015182546001810184556000938452919092200155620004e4565b620004ed565b60010162000488565b5050600880546001600160a01b0319166001600160a01b039290921691909117905560016200051d60006200057b565b80546001600160401b0319166001600160401b0392909216919091179055426200054860006200057b565b80546001600160401b0392909216600160801b02600160801b600160c01b0319909216919091179055506200060a915050565b6000600c600260ff168360165401816200059157fe5b06600281106200059d57fe5b6005020192915050565b8260188101928215620005d8579160200282015b82811115620005d8578251825591602001919060010190620005bb565b50620005e6929150620005ea565b5090565b6200060791905b80821115620005e65760008155600101620005f1565b90565b614949806200061a6000396000f3fe608060405234801561001057600080fd5b50600436106103575760003560e01c806380803fff116101c8578063bd32aa4411610104578063e0e6393d116100a2578063ec5568891161007c578063ec55688914610984578063f344da671461098c578063fb1b4c7e14610994578063fd1f498d1461099c57610357565b8063e0e6393d1461096c578063e3235c9114610974578063eb1edd611461097c57610357565b8063cff2ddad116100de578063cff2ddad14610936578063d294f09314610954578063d62ae3991461095c578063d67bdd251461096457610357565b8063bd32aa4414610909578063c58aaae614610911578063c6c9d8281461091957610357565b8063a461fc8211610171578063b10090b81161014b578063b10090b814610867578063b5ddb9c7146108af578063b8225dec146108db578063bc67f832146108e357610357565b8063a461fc8214610816578063ab49848c1461081e578063ac8341931461085f57610357565b806397107d6d116101a257806397107d6d146107e05780639cb8a26a146108065780639cbdaeb61461080e57610357565b806380803fff1461078957806386645274146107a65780638da5cb5b146107d857610357565b80633278c9601161029757806353a47bb711610240578063631e14441161021a578063631e14441461072d5780636466f45e146107535780636de813f11461077957806379ba50971461078157610357565b806353a47bb7146106e3578063569249d0146106eb57806359a2f19f146106f357610357565b80633ebc457a116102715780633ebc457a1461066e5780633fcd22401461067657806346ba2d90146106db57610357565b80633278c960146105c057806333140016146105c85780633be99e6f1461064857610357565b80631627540c1161030457806322425fa4116102de57806322425fa4146104bc57806322bf55ef146104c457806328a1170d146104e15780632cce0e54146105a357610357565b80631627540c1461046857806317c70de41461048e57806320714f881461049657610357565b80630813071c116103355780630813071c146103d75780630de5861514610403578063131b0ae71461044257610357565b806304c49f2c1461035c57806304f3bcec1461037b57806307ea50cd1461039f575b600080fd5b6103796004803603602081101561037257600080fd5b50356109b9565b005b610383610b2a565b604080516001600160a01b039092168252519081900360200190f35b6103c5600480360360208110156103b557600080fd5b50356001600160a01b0316610b39565b60408051918252519081900360200190f35b6103c5600480360360408110156103ed57600080fd5b506001600160a01b038135169060200135610c1d565b6104296004803603602081101561041957600080fd5b50356001600160a01b0316610dce565b6040805192835260208301919091528051918290030190f35b6103796004803603602081101561045857600080fd5b50356001600160a01b0316610e4f565b6103796004803603602081101561047e57600080fd5b50356001600160a01b0316610eba565b6103c5610f57565b610379600480360360208110156104ac57600080fd5b50356001600160a01b0316610f5d565b6103c5611074565b610379600480360360208110156104da57600080fd5b503561107a565b610379600480360360408110156104f757600080fd5b81019060208101813564010000000081111561051257600080fd5b82018360208201111561052457600080fd5b8035906020019184602083028401116401000000008311171561054657600080fd5b91939092909160208101903564010000000081111561056457600080fd5b82018360208201111561057657600080fd5b8035906020019184602083028401116401000000008311171561059857600080fd5b509092509050611196565b610379600480360360208110156105b957600080fd5b5035611430565b6103796115cd565b6105ee600480360360208110156105de57600080fd5b50356001600160a01b0316611650565b6040516000826002835b818410156106385760208402830151604080838360005b8381101561062757818101518382015260200161060f565b5050505090500192600101926105f8565b9250505091505060405180910390f35b6103796004803603602081101561065e57600080fd5b50356001600160a01b03166118a0565b610379611a27565b6106936004803603602081101561068c57600080fd5b5035611d72565b6040805167ffffffffffffffff9889168152968816602088015294909616858501526060850192909252608084015260a083015260c082019290925290519081900360e00190f35b6103c5611e1b565b610383611e21565b6103c5611e30565b6107196004803603602081101561070957600080fd5b50356001600160a01b0316611e8b565b604080519115158252519081900360200190f35b6107196004803603602081101561074357600080fd5b50356001600160a01b0316612051565b6107196004803603602081101561076957600080fd5b50356001600160a01b0316612185565b6103c56122dc565b610379612331565b6103c56004803603602081101561079f57600080fd5b50356123ed565b610379600480360360608110156107bc57600080fd5b506001600160a01b038135169060208101359060400135612488565b6103836125ec565b610379600480360360208110156107f657600080fd5b50356001600160a01b03166125fb565b610379612698565b6103836127ea565b6103c56127f9565b610826612800565b604051808261030080838360005b8381101561084c578181015183820152602001610834565b5050505090500191505060405180910390f35b6103c561284a565b610379600480360361010081101561087e57600080fd5b5080359060208101359060408101359060608101359060808101359060a08101359060c08101359060e00135612940565b610379600480360360408110156108c557600080fd5b506001600160a01b038135169060200135612c2a565b610719612e19565b610379600480360360208110156108f957600080fd5b50356001600160a01b0316612e22565b610379612eb8565b610383612f4a565b6103c56004803603602081101561092f57600080fd5b5035612f5e565b61093e612f7c565b6040805160ff9092168252519081900360200190f35b610719612f81565b6103c5612ff3565b610383612ffa565b6103c5613009565b6103c561300f565b610383613014565b61038361302c565b6103c561303b565b6103c5613042565b610379600480360360208110156109b257600080fd5b503561304e565b6002546001600160a01b031633148015906109df57506003546001600160a01b03163314155b80156109f657506004546001600160a01b03163314155b15610a0e57600480546001600160a01b031916331790555b6000546004546001600160a01b03908116911614610a69576040805162461bcd60e51b815260206004820152601360248201527227bbb732b91037b7363c90333ab731ba34b7b760691b604482015290519081900360640190fd5b62015180811015610ac1576040805162461bcd60e51b815260206004820152601f60248201527f76616c7565203c204d494e5f4645455f504552494f445f4455524154494f4e00604482015290519081900360640190fd5b624f1a00811115610b19576040805162461bcd60e51b815260206004820152601f60248201527f76616c7565203e204d41585f4645455f504552494f445f4455524154494f4e00604482015290519081900360640190fd5b6017819055610b2781613100565b50565b6008546001600160a01b031681565b6000610b43613227565b6001600160a01b031663bdc963d87f6c6173745f6665655f7769746864726177616c000000000000000000000000008460405160200180838152602001826001600160a01b03166001600160a01b031660601b815260140192505050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610be957600080fd5b505afa158015610bfd573d6000803e3d6000fd5b505050506040513d6020811015610c1357600080fd5b505190505b919050565b600081610c71576040805162461bcd60e51b815260206004820181905260248201527f43757272656e7420706572696f64206973206e6f7420636c6f73656420796574604482015290519081900360640190fd5b60028210610cc6576040805162461bcd60e51b815260206004820152601d60248201527f4578636565647320746865204645455f504552494f445f4c454e475448000000604482015290519081900360640190fd5b610cd26001830361326b565b5468010000000000000000900467ffffffffffffffff16610cf557506000610dc8565b6000610d256001610d086001860361326b565b5468010000000000000000900467ffffffffffffffff1690613295565b9050600080610d326132f2565b6040805163694e000560e11b81526001600160a01b03898116600483015260248201879052825193169263d29c000a92604480840193919291829003018186803b158015610d7f57600080fd5b505afa158015610d93573d6000803e3d6000fd5b505050506040513d6040811015610da957600080fd5b5080516020909101519092509050610dc2838383613353565b93505050505b92915050565b600080610dd9614633565b610de284611650565b905060008060015b6002811015610e4357610e0f848260028110610e0257fe5b6020020151518490613487565b9250610e39848260028110610e2057fe5b602002015160016020020151839063ffffffff61348716565b9150600101610dea565b50909350915050915091565b6000546001600160a01b03163314610e985760405162461bcd60e51b815260040180806020018281038252602f81526020018061480b602f913960400191505060405180910390fd5b600380546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b03163314610f035760405162461bcd60e51b815260040180806020018281038252602f81526020018061480b602f913960400191505060405180910390fd5b600180546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229181900360200190a150565b60055481565b6000546001600160a01b03163314610fa65760405162461bcd60e51b815260040180806020018281038252602f81526020018061480b602f913960400191505060405180910390fd5b6001600160a01b038116611001576040805162461bcd60e51b815260206004820152601c60248201527f42656e6566696369617279206d757374206e6f74206265207a65726f00000000604482015290519081900360640190fd5b600680546001600160a01b03831661010081027fffffffffffffffffffffff0000000000000000000000000000000000000000ff9092169190911790915560408051918252517fd5da63a0b864b315bc04128dedbc93888c8529ee6cf47ce664dc204339228c539181900360200190a150565b60175481565b60006110846134e8565b6001600160a01b03163314905060008061109c613549565b6001600160a01b03166316b2213f336040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156110f157600080fd5b505afa158015611105573d6000803e3d6000fd5b505050506040513d602081101561111b57600080fd5b505114159050818061112a5750805b6111655760405162461bcd60e51b81526004018080602001828103825260218152602001806148cf6021913960400191505060405180910390fd5b61118383611173600061326b565b600101549063ffffffff61348716565b61118d600061326b565b60010155505050565b6002546001600160a01b031633148015906111bc57506003546001600160a01b03163314155b80156111d357506004546001600160a01b03163314155b156111eb57600480546001600160a01b031916331790555b6000546004546001600160a01b03908116911614611246576040805162461bcd60e51b815260206004820152601360248201527227bbb732b91037b7363c90333ab731ba34b7b760691b604482015290519081900360640190fd5b82811461129a576040805162461bcd60e51b815260206004820152601860248201527f4172726179206c656e6774687320646f6e74206d617463680000000000000000604482015290519081900360640190fd5b60005b838110156114295767016345785d8a00008383838181106112ba57fe5b905060200201351115611314576040805162461bcd60e51b815260206004820152601e60248201527f4d41585f45584348414e47455f4645455f524154452065786365656465640000604482015290519081900360640190fd5b61131c613227565b6001600160a01b0316633562fd207f73796e74685f65786368616e67655f6665655f7261746500000000000000000087878581811061135757fe5b9050602002013560405160200180838152602001828152602001925050506040516020818303038152906040528051906020012085858581811061139757fe5b905060200201356040518363ffffffff1660e01b81526004018083815260200182815260200192505050600060405180830381600087803b1580156113db57600080fd5b505af11580156113ef573d6000803e3d6000fd5b5050505061142185858381811061140257fe5b9050602002013584848481811061141557fe5b905060200201356135aa565b60010161129d565b5050505050565b6002546001600160a01b0316331480159061145657506003546001600160a01b03163314155b801561146d57506004546001600160a01b03163314155b1561148557600480546001600160a01b031916331790555b6000546004546001600160a01b039081169116146114e0576040805162461bcd60e51b815260206004820152601360248201527227bbb732b91037b7363c90333ab731ba34b7b760691b604482015290519081900360640190fd5b6032811115611536576040805162461bcd60e51b815260206004820152601260248201527f5468726573686f6c6420746f6f20686967680000000000000000000000000000604482015290519081900360640190fd5b6115c760646115bb7384d626b2bb4d0f064067e4bf80fce7055d8f3e7b63907af6c06040518163ffffffff1660e01b815260040160206040518083038186803b15801561158257600080fd5b505af4158015611596573d6000803e3d6000fd5b505050506040513d60208110156115ac57600080fd5b5051849063ffffffff6136c316565b9063ffffffff61371c16565b60185550565b6000546001600160a01b031633146116165760405162461bcd60e51b815260040180806020018281038252602f81526020018061480b602f913960400191505060405180910390fd5b600060058190556006805460ff191690556040517f6adcc7125002935e0aa31697538ebbd65cfddf20431eb6ecdcfc3e238bfd082c9190a1565b611658614633565b60008060006116656132f2565b604080517fb326f84e0000000000000000000000000000000000000000000000000000000081526001600160a01b03888116600483015260006024830152825193945084169263b326f84e92604480840193919291829003018186803b1580156116ce57600080fd5b505afa1580156116e2573d6000803e3d6000fd5b505050506040513d60408110156116f857600080fd5b508051602090910151909350915081158015611712575082155b1561172a5761171f614633565b9350610c1892505050565b60008061173960008686613786565b875182905287516020018190529092509050600061175688610b39565b905060015b801561189457600019810160006117718261326b565b5468010000000000000000900467ffffffffffffffff16905080158015906117ab575061179d8361326b565b5467ffffffffffffffff1684105b156118895760006117c382600163ffffffff61329516565b6040805163694e000560e11b81526001600160a01b038f811660048301526024820184905282519394508b169263d29c000a92604480840193919291829003018186803b15801561181357600080fd5b505afa158015611827573d6000803e3d6000fd5b505050506040513d604081101561183d57600080fd5b508051602090910151909a509850611856848b8b613786565b9097509550868b856002811061186857fe5b602002015152858b856002811061187b57fe5b602002015160016020020152505b50506000190161175b565b50505050505050919050565b6000546001600160a01b031633146118e95760405162461bcd60e51b815260040180806020018281038252602f81526020018061480b602f913960400191505060405180910390fd5b600880546001600160a01b0319166001600160a01b03831617905560005b600a54811015611a23576000600a828154811061192057fe5b60009182526020918290200154600854604080517fdacb2d010000000000000000000000000000000000000000000000000000000081526004810184905260248101829052601760448201527f5265736f6c766572206d697373696e6720746172676574000000000000000000606482015290519294506001600160a01b039091169263dacb2d0192608480840193829003018186803b1580156119c357600080fd5b505afa1580156119d7573d6000803e3d6000fd5b505050506040513d60208110156119ed57600080fd5b505160009182526009602052604090912080546001600160a01b0319166001600160a01b03909216919091179055600101611907565b5050565b6017544203611a36600061326b565b54600160801b900467ffffffffffffffff161115611a9b576040805162461bcd60e51b815260206004820152601d60248201527f546f6f206561726c7920746f20636c6f73652066656520706572696f64000000604482015290519081900360640190fd5b611aa3613828565b6001600160a01b0316637c3125416040518163ffffffff1660e01b815260040160006040518083038186803b158015611adb57600080fd5b505afa158015611aef573d6000803e3d6000fd5b5060009250611b01915082905061326b565b90506000611b0f600161326b565b9050611b408260010154611b348360020154846001015461329590919063ffffffff16565b9063ffffffff61348716565b611b4a600061326b565b60010155600380830154600483015491830154611b7192611b34919063ffffffff61329516565b611b7b600061326b565b60030155601654611bb890600290611bac90600190611ba0908463ffffffff61348716565b9063ffffffff61329516565b9063ffffffff61388916565b6016819055600c9060028110611bca57fe5b6005020180547fffffffffffffffff000000000000000000000000000000000000000000000000168155600060018083018290556002830182905560038301829055600490920155611c3690611c1f8161326b565b5467ffffffffffffffff169063ffffffff61348716565b611c40600061326b565b805467ffffffffffffffff191667ffffffffffffffff92909216919091179055611c686138ee565b6001600160a01b031663cd92eba96040518163ffffffff1660e01b815260040160206040518083038186803b158015611ca057600080fd5b505afa158015611cb4573d6000803e3d6000fd5b505050506040513d6020811015611cca57600080fd5b5051611cd6600061326b565b805467ffffffffffffffff9290921668010000000000000000026fffffffffffffffff00000000000000001990921691909117905542611d16600061326b565b805467ffffffffffffffff92909216600160801b027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff909216919091179055611a23611d62600161326b565b5467ffffffffffffffff1661394f565b6000806000806000806000611d85614660565b611d8e8961326b565b6040805160e081018252825467ffffffffffffffff808216808452680100000000000000008304821660208501819052600160801b909304909116938301849052600185015460608401819052600286015460808501819052600387015460a0860181905260049097015460c0909501859052919f929e50939c50929a5091985091965090945092505050565b60075481565b6001546001600160a01b031681565b60008060015b6002811015611e8557611e5c611e4b8261326b565b60010154839063ffffffff61348716565b9150611e7b611e6a8261326b565b60020154839063ffffffff61329516565b9150600101611e36565b50905090565b600080611e96613549565b6001600160a01b031663a311c7c2846040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015611eeb57600080fd5b505afa158015611eff573d6000803e3d6000fd5b505050506040513d6020811015611f1557600080fd5b505190506000611f236138ee565b6001600160a01b031663b410a0346040518163ffffffff1660e01b815260040160206040518083038186803b158015611f5b57600080fd5b505afa158015611f6f573d6000803e3d6000fd5b505050506040513d6020811015611f8557600080fd5b5051905080821015611f9c57600192505050610c18565b60006120306120236018547384d626b2bb4d0f064067e4bf80fce7055d8f3e7b63907af6c06040518163ffffffff1660e01b815260040160206040518083038186803b158015611feb57600080fd5b505af4158015611fff573d6000803e3d6000fd5b505050506040513d602081101561201557600080fd5b50519063ffffffff61348716565b839063ffffffff613a3816565b9050808311156120465760009350505050610c18565b506001949350505050565b6008546000906001600160a01b0383811691161461207157506000610c18565b60005b600a5481101561217c576000600a828154811061208d57fe5b6000918252602080832090910154808352600982526040928390205460085484517f21f8a7210000000000000000000000000000000000000000000000000000000081526004810184905294519295506001600160a01b03918216949116926321f8a72192602480840193829003018186803b15801561210c57600080fd5b505afa158015612120573d6000803e3d6000fd5b505050506040513d602081101561213657600080fd5b50516001600160a01b031614158061216357506000818152600960205260409020546001600160a01b0316155b1561217357600092505050610c18565b50600101612074565b50600192915050565b6002546000906001600160a01b031633148015906121ae57506003546001600160a01b03163314155b80156121c557506004546001600160a01b03163314155b156121dd57600480546001600160a01b031916331790555b6121e5613a62565b60048054604080517f21f4ae570000000000000000000000000000000000000000000000000000000081526001600160a01b038781169482019490945291831660248301525192909116916321f4ae5791604480820192602092909190829003018186803b15801561225657600080fd5b505afa15801561226a573d6000803e3d6000fd5b505050506040513d602081101561228057600080fd5b50516122d3576040805162461bcd60e51b815260206004820152601f60248201527f4e6f7420617070726f76656420746f20636c61696d206f6e20626568616c6600604482015290519081900360640190fd5b610dc882613aa6565b60008060015b6002811015611e85576123086122f78261326b565b60030154839063ffffffff61348716565b91506123276123168261326b565b60040154839063ffffffff61329516565b91506001016122e2565b6001546001600160a01b0316331461237a5760405162461bcd60e51b81526004018080602001828103825260358152602001806146f96035913960400191505060405180910390fd5b600054600154604080516001600160a01b03938416815292909116602083015280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b60006123f7613227565b6001600160a01b031663bdc963d87f73796e74685f65786368616e67655f6665655f72617465000000000000000000846040516020018083815260200182815260200192505050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610be957600080fd5b612490613c24565b6001600160a01b0316336001600160a01b0316146124f5576040805162461bcd60e51b815260206004820152601f60248201527f466565506f6f6c3a204f6e6c792049737375657220417574686f726973656400604482015290519081900360640190fd5b6124fd6132f2565b6001600160a01b03166394e1a448848484612518600061326b565b54604080517fffffffff0000000000000000000000000000000000000000000000000000000060e088901b1681526001600160a01b0390951660048601526024850193909352604484019190915267ffffffffffffffff6801000000000000000090910416606483015251608480830192600092919082900301818387803b1580156125a357600080fd5b505af11580156125b7573d6000803e3d6000fd5b505050506125e78383836125cb600061326b565b5468010000000000000000900467ffffffffffffffff16613c85565b505050565b6000546001600160a01b031681565b6000546001600160a01b031633146126445760405162461bcd60e51b815260040180806020018281038252602f81526020018061480b602f913960400191505060405180910390fd5b600280546001600160a01b0383166001600160a01b0319909116811790915560408051918252517ffc80377ca9c49cc11ae6982f390a42db976d5530af7c43889264b13fbbd7c57e9181900360200190a150565b6000546001600160a01b031633146126e15760405162461bcd60e51b815260040180806020018281038252602f81526020018061480b602f913960400191505060405180910390fd5b60065460ff16612738576040805162461bcd60e51b815260206004820152601f60248201527f53656c66204465737472756374206e6f742079657420696e6974696174656400604482015290519081900360640190fd5b426224ea006005540110612793576040805162461bcd60e51b815260206004820152601b60248201527f53656c662064657374727563742064656c6179206e6f74206d65740000000000604482015290519081900360640190fd5b600654604080516101009092046001600160a01b03168252517f8a09e1677ced846cb537dc2b172043bd05a1a81ad7e0033a7ef8ba762df990b7916020908290030190a160065461010090046001600160a01b0316ff5b6003546001600160a01b031681565b6224ea0081565b6128086146bb565b60005b600a5481101561284657600a818154811061282257fe5b906000526020600020015482826018811061283957fe5b602002015260010161280b565b5090565b6000806128556138ee565b6001600160a01b031663b410a0346040518163ffffffff1660e01b815260040160206040518083038186803b15801561288d57600080fd5b505afa1580156128a1573d6000803e3d6000fd5b505050506040513d60208110156128b757600080fd5b5051601854604080517f907af6c0000000000000000000000000000000000000000000000000000000008152905192935061293a9261292d92917384d626b2bb4d0f064067e4bf80fce7055d8f3e7b9163907af6c091600480820192602092909190829003018186803b158015611feb57600080fd5b829063ffffffff613a3816565b91505090565b6002546001600160a01b0316331480159061296657506003546001600160a01b03163314155b801561297d57506004546001600160a01b03163314155b1561299557600480546001600160a01b031916331790555b6000546004546001600160a01b039081169116146129f0576040805162461bcd60e51b815260206004820152601360248201527227bbb732b91037b7363c90333ab731ba34b7b760691b604482015290519081900360640190fd5b6007544210612a305760405162461bcd60e51b815260040180806020018281038252602981526020018061487e6029913960400191505060405180910390fd5b612a386138ee565b6001600160a01b031663cd92eba96040518163ffffffff1660e01b815260040160206040518083038186803b158015612a7057600080fd5b505afa158015612a84573d6000803e3d6000fd5b505050506040513d6020811015612a9a57600080fd5b5051861115612af0576040805162461bcd60e51b815260206004820152601660248201527f43616e6e6f7420696d706f727420626164206461746100000000000000000000604482015290519081900360640190fd5b6040518060e001604052808867ffffffffffffffff1681526020018767ffffffffffffffff1681526020018667ffffffffffffffff16815260200185815260200184815260200183815260200182815250600c612b60600260ff16611bac8c60165461348790919063ffffffff16565b60028110612b6a57fe5b82516005919091029190910180546020840151604085015167ffffffffffffffff1990921667ffffffffffffffff948516176fffffffffffffffff000000000000000019166801000000000000000091851691909102177fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff16600160801b9390911692909202919091178155606082015160018201556080820151600282015560a0820151600382015560c0909101516004909101555050505050505050565b6002546001600160a01b03163314801590612c5057506003546001600160a01b03163314155b8015612c6757506004546001600160a01b03163314155b15612c7f57600480546001600160a01b031916331790555b6000546004546001600160a01b03908116911614612cda576040805162461bcd60e51b815260206004820152601360248201527227bbb732b91037b7363c90333ab731ba34b7b760691b604482015290519081900360640190fd5b612ce2613549565b6004546001600160a01b03918216916323b872dd9116612d00613dcc565b846040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050602060405180830381600087803b158015612d6957600080fd5b505af1158015612d7d573d6000803e3d6000fd5b505050506040513d6020811015612d9357600080fd5b50612d9e9050613dcc565b6001600160a01b031663b5ddb9c783836040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b158015612dfd57600080fd5b505af1158015612e11573d6000803e3d6000fd5b505050505050565b60065460ff1681565b6002546001600160a01b0316331480612e4557506003546001600160a01b031633145b612e96576040805162461bcd60e51b815260206004820152601760248201527f4f6e6c79207468652070726f78792063616e2063616c6c000000000000000000604482015290519081900360640190fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b03163314612f015760405162461bcd60e51b815260040180806020018281038252602f81526020018061480b602f913960400191505060405180910390fd5b426005556006805460ff19166001179055604080516224ea00815290517fcbd94ca75b8dc45c9d80c77e851670e78843c0d75180cb81db3e2158228fa9a69181900360200190a1565b60065461010090046001600160a01b031681565b600a8181548110612f6b57fe5b600091825260209091200154905081565b600281565b6002546000906001600160a01b03163314801590612faa57506003546001600160a01b03163314155b8015612fc157506004546001600160a01b03163314155b15612fd957600480546001600160a01b031916331790555b600454612fee906001600160a01b0316613aa6565b905090565b6201518081565b6004546001600160a01b031681565b60185481565b601881565b73feefeefeefeefeefeefeefeefeefeefeefeefeef81565b6002546001600160a01b031681565b624f1a0081565b67016345785d8a000081565b6000613058613e2d565b6004549091506001600160a01b038083169116148061307f5750336001600160a01b038216145b6130d0576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206973206e6f742072657761726473417574686f726974790000604482015290519081900360640190fd5b6130ee826130de600061326b565b600301549063ffffffff61348716565b6130f8600061326b565b600301555050565b60025460408051602080820185905282518083039091018152908201918290526001600160a01b039092169163907dff97916001908060216147ea82396021019050604051809103902060008060006040518763ffffffff1660e01b815260040180806020018781526020018681526020018560001b81526020018460001b81526020018360001b8152602001828103825288818151815260200191508051906020019080838360005b838110156131c25781810151838201526020016131aa565b50505050905090810190601f1680156131ef5780820380516001836020036101000a031916815260200191505b50975050505050505050600060405180830381600087803b15801561321357600080fd5b505af1158015611429573d6000803e3d6000fd5b6000612fee7f466565506f6f6c457465726e616c53746f7261676500000000000000000000006040518060600160405280602581526020016148f060259139613e6d565b6000600c600260ff1683601654018161328057fe5b066002811061328b57fe5b6005020192915050565b6000828211156132ec576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6000612fee7f466565506f6f6c537461746500000000000000000000000000000000000000006040518060400160405280601c81526020017f4d697373696e6720466565506f6f6c5374617465206164647265737300000000815250613e6d565b60008061335e6138ee565b9050600061347d85613471846001600160a01b03166308d95cd5886040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b1580156133ad57600080fd5b505afa1580156133c1573d6000803e3d6000fd5b505050506040513d60208110156133d757600080fd5b5051604080517f08d95cd5000000000000000000000000000000000000000000000000000000008152600481018c905290516001600160a01b038816916308d95cd5916024808301926020929190829003018186803b15801561343957600080fd5b505afa15801561344d573d6000803e3d6000fd5b505050506040513d602081101561346357600080fd5b50519063ffffffff613f1716565b9063ffffffff613f3016565b9695505050505050565b6000828201838110156134e1576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6000612fee7f45786368616e67657200000000000000000000000000000000000000000000006040518060400160405280601981526020017f4d697373696e672045786368616e676572206164647265737300000000000000815250613e6d565b6000612fee7f53796e74686574697800000000000000000000000000000000000000000000006040518060400160405280601981526020017f4d697373696e672053796e746865746978206164647265737300000000000000815250613e6d565b60025460408051602081018590528082018490528151808203830181526060909101918290526001600160a01b039092169163907dff97916001908060286148a782396028019050604051809103902060008060006040518763ffffffff1660e01b815260040180806020018781526020018681526020018560001b81526020018460001b81526020018360001b8152602001828103825288818151815260200191508051906020019080838360005b8381101561367257818101518382015260200161365a565b50505050905090810190601f16801561369f5780820380516001836020036101000a031916815260200191505b50975050505050505050600060405180830381600087803b158015612dfd57600080fd5b6000826136d257506000610dc8565b828202828482816136df57fe5b04146134e15760405162461bcd60e51b815260040180806020018281038252602181526020018061485d6021913960400191505060405180910390fd5b6000808211613772576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b600082848161377d57fe5b04949350505050565b6000808361379957506000905080613820565b8385156137c45760006137b36001610d0860018a0361326b565b90506137c0818787613353565b9150505b60006137e3826137d38961326b565b600101549063ffffffff613a3816565b90506000613804836137f48a61326b565b600301549063ffffffff613a3816565b905061380f82613f49565b61381882613f49565b945094505050505b935093915050565b6000612fee7f53797374656d53746174757300000000000000000000000000000000000000006040518060400160405280601c81526020017f4d697373696e672053797374656d537461747573206164647265737300000000815250613e6d565b6000816138dd576040805162461bcd60e51b815260206004820152601860248201527f536166654d6174683a206d6f64756c6f206279207a65726f0000000000000000604482015290519081900360640190fd5b8183816138e657fe5b069392505050565b6000612fee7f53796e74686574697853746174650000000000000000000000000000000000006040518060400160405280601e81526020017f4d697373696e672053796e746865746978537461746520616464726573730000815250613e6d565b6002546040805160208082018590528251808303820181528284018085527f466565506572696f64436c6f7365642875696e74323536290000000000000000905292519182900360580182207f907dff97000000000000000000000000000000000000000000000000000000008352600160248401819052604484018290526000606485018190526084850181905260a4850181905260c060048601908152865160c487015286516001600160a01b039098169763907dff979796939592938493849392839260e401918a019080838388838110156131c25781810151838201526020016131aa565b6000670de0b6b3a7640000613a53848463ffffffff6136c316565b81613a5a57fe5b049392505050565b6000612fee7f44656c6567617465417070726f76616c7300000000000000000000000000000060405180606001604052806021815260200161475260219139613e6d565b6000613ab0613828565b6001600160a01b0316637c3125416040518163ffffffff1660e01b815260040160006040518083038186803b158015613ae857600080fd5b505afa158015613afc573d6000803e3d6000fd5b506000925082915081905080613b1186611e8b565b613b62576040805162461bcd60e51b815260206004820152601f60248201527f432d526174696f2062656c6f772070656e616c7479207468726573686f6c6400604482015290519081900360640190fd5b613b6b86610dce565b909250905081151580613b7e5750600081115b613bb95760405162461bcd60e51b81526004018080602001828103825260408152602001806147aa6040913960400191505060405180910390fd5b613bd786613bc7600161326b565b5467ffffffffffffffff16613f6b565b8115613bf257613be682614023565b9250613bf286846140f7565b8015613c0d57613c01816142dc565b9350613c0d86856143b6565b613c188684866144ad565b50600195945050505050565b6000612fee7f49737375657200000000000000000000000000000000000000000000000000006040518060400160405280601681526020017f4d697373696e6720497373756572206164647265737300000000000000000000815250613e6d565b6002805460408051602081018790528082018690526060808201869052825180830390910181526080909101918290526001600160a01b039092169263907dff979291806037614773823960370190506040518091039020886001600160a01b031660001b6000806040518763ffffffff1660e01b815260040180806020018781526020018681526020018581526020018460001b81526020018360001b8152602001828103825288818151815260200191508051906020019080838360005b83811015613d5d578181015183820152602001613d45565b50505050905090810190601f168015613d8a5780820380516001836020036101000a031916815260200191505b50975050505050505050600060405180830381600087803b158015613dae57600080fd5b505af1158015613dc2573d6000803e3d6000fd5b5050505050505050565b6000612fee7f526577617264457363726f7700000000000000000000000000000000000000006040518060400160405280601c81526020017f4d697373696e6720526577617264457363726f77206164647265737300000000815250613e6d565b6000612fee7f52657761726473446973747269627574696f6e0000000000000000000000000060405180606001604052806023815260200161483a602391395b6000828152600960205260408120546001600160a01b03168281613f0f5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613ed4578181015183820152602001613ebc565b50505050905090810190601f168015613f015780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b509392505050565b60006134e183836b033b2e3c9fd0803ce80000006145d0565b60006134e183836b033b2e3c9fd0803ce8000000614608565b60006305f5e10082046005600a820610613f6157600a015b600a900492915050565b613f73613227565b6001600160a01b0316633562fd207f6c6173745f6665655f7769746864726177616c000000000000000000000000008460405160200180838152602001826001600160a01b03166001600160a01b031660601b81526014019250505060405160208183030381529060405280519060200120836040518363ffffffff1660e01b81526004018083815260200182815260200192505050600060405180830381600087803b158015612dfd57600080fd5b6000818160015b6002811015613f0f57600061403e8261326b565b6002015490506000614063826140538561326b565b600101549063ffffffff61329516565b905080156140ec57600085821061407a578561407c565b815b905061408e838263ffffffff61348716565b6140978561326b565b600201556140ab868263ffffffff61329516565b95506140bd858263ffffffff61348716565b9450856140d257849650505050505050610c18565b831580156140e05750600086115b156140ea57600095505b505b50506000190161402a565b816001600160a01b03811673feefeefeefeefeefeefeefeefeefeefeefeefeef141561416a576040805162461bcd60e51b815260206004820152601760248201527f4665652061646472657373206e6f7420616c6c6f776564000000000000000000604482015290519081900360640190fd5b6000614174613549565b6001600160a01b03166332608039600b546040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b1580156141b957600080fd5b505afa1580156141cd573d6000803e3d6000fd5b505050506040513d60208110156141e357600080fd5b5051604080517f9dc29fac00000000000000000000000000000000000000000000000000000000815273feefeefeefeefeefeefeefeefeefeefeefeefeef60048201526024810186905290519192506001600160a01b03831691639dc29fac9160448082019260009290919082900301818387803b15801561426457600080fd5b505af1158015614278573d6000803e3d6000fd5b50505050806001600160a01b031663867904b485856040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b158015613dae57600080fd5b6000818160015b6002811015613f0f5760006143176142fa8361326b565b600401546143078461326b565b600301549063ffffffff61329516565b905080156143ac57600084821061432e5784614330565b815b905061434f8161433f8561326b565b600401549063ffffffff61348716565b6143588461326b565b6004015561436c858263ffffffff61329516565b945061437e848263ffffffff61348716565b935084614392578395505050505050610c18565b821580156143a05750600085115b156143aa57600094505b505b50600019016142e3565b816001600160a01b03811673feefeefeefeefeefeefeefeefeefeefeefeefeef1415614429576040805162461bcd60e51b815260206004820152601760248201527f4665652061646472657373206e6f7420616c6c6f776564000000000000000000604482015290519081900360640190fd5b614431613dcc565b6001600160a01b031663b5ddb9c784846040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b15801561449057600080fd5b505af11580156144a4573d6000803e3d6000fd5b50505050505050565b600254604080516001600160a01b0386811660208301528183018690526060808301869052835180840390910181526080909201928390529092169163907dff979160019080602461472e82396024019050604051809103902060008060006040518763ffffffff1660e01b815260040180806020018781526020018681526020018560001b81526020018460001b81526020018360001b8152602001828103825288818151815260200191508051906020019080838360005b8381101561457f578181015183820152602001614567565b50505050905090810190601f1680156145ac5780820380516001836020036101000a031916815260200191505b50975050505050505050600060405180830381600087803b15801561449057600080fd5b6000806145ea846115bb87600a870263ffffffff6136c316565b90506005600a825b06106145fc57600a015b600a9004949350505050565b600080600a830461461f868663ffffffff6136c316565b8161462657fe5b0490506005600a826145f2565b60405180604001604052806002905b61464a6146da565b8152602001906001900390816146425790505090565b6040518060e00160405280600067ffffffffffffffff168152602001600067ffffffffffffffff168152602001600067ffffffffffffffff168152602001600081526020016000815260200160008152602001600081525090565b6040518061030001604052806018906020820280388339509192915050565b6040518060400160405280600290602082028038833950919291505056fe596f75206d757374206265206e6f6d696e61746564206265666f726520796f752063616e20616363657074206f776e65727368697046656573436c61696d656428616464726573732c75696e743235362c75696e74323536294d697373696e672044656c6567617465417070726f76616c73206164647265737349737375616e636544656274526174696f456e74727928616464726573732c75696e743235362c75696e743235362c75696e74323536294e6f2066656573206f72207265776172647320617661696c61626c6520666f7220706572696f642c206f72206665657320616c726561647920636c61696d6564466565506572696f644475726174696f6e557064617465642875696e74323536294f6e6c792074686520636f6e7472616374206f776e6572206d617920706572666f726d207468697320616374696f6e4d697373696e672052657761726473446973747269627574696f6e2061646472657373536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7743616e206f6e6c7920706572666f726d207468697320616374696f6e20647572696e6720736574757053796e746845786368616e67654665655570646174656428627974657333322c75696e74323536294f6e6c792045786368616e6765722c2053796e74687320417574686f72697365644d697373696e6720466565506f6f6c457465726e616c53746f726167652061646472657373a265627a7a72315820df3d94c204228d52bdeab83f2e8f4a1142a185790336acf62f2437c0d7be5c7264736f6c63430005100032000000000000000000000000b440dd674e1243644791a4adfe3a2abb0a92d309000000000000000000000000de910777c787903f78c89e7a0bf7f4c435cbb1fe000000000000000000000000fbb6526ed92da8915d4843a86166020d0b7baad0

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106103575760003560e01c806380803fff116101c8578063bd32aa4411610104578063e0e6393d116100a2578063ec5568891161007c578063ec55688914610984578063f344da671461098c578063fb1b4c7e14610994578063fd1f498d1461099c57610357565b8063e0e6393d1461096c578063e3235c9114610974578063eb1edd611461097c57610357565b8063cff2ddad116100de578063cff2ddad14610936578063d294f09314610954578063d62ae3991461095c578063d67bdd251461096457610357565b8063bd32aa4414610909578063c58aaae614610911578063c6c9d8281461091957610357565b8063a461fc8211610171578063b10090b81161014b578063b10090b814610867578063b5ddb9c7146108af578063b8225dec146108db578063bc67f832146108e357610357565b8063a461fc8214610816578063ab49848c1461081e578063ac8341931461085f57610357565b806397107d6d116101a257806397107d6d146107e05780639cb8a26a146108065780639cbdaeb61461080e57610357565b806380803fff1461078957806386645274146107a65780638da5cb5b146107d857610357565b80633278c9601161029757806353a47bb711610240578063631e14441161021a578063631e14441461072d5780636466f45e146107535780636de813f11461077957806379ba50971461078157610357565b806353a47bb7146106e3578063569249d0146106eb57806359a2f19f146106f357610357565b80633ebc457a116102715780633ebc457a1461066e5780633fcd22401461067657806346ba2d90146106db57610357565b80633278c960146105c057806333140016146105c85780633be99e6f1461064857610357565b80631627540c1161030457806322425fa4116102de57806322425fa4146104bc57806322bf55ef146104c457806328a1170d146104e15780632cce0e54146105a357610357565b80631627540c1461046857806317c70de41461048e57806320714f881461049657610357565b80630813071c116103355780630813071c146103d75780630de5861514610403578063131b0ae71461044257610357565b806304c49f2c1461035c57806304f3bcec1461037b57806307ea50cd1461039f575b600080fd5b6103796004803603602081101561037257600080fd5b50356109b9565b005b610383610b2a565b604080516001600160a01b039092168252519081900360200190f35b6103c5600480360360208110156103b557600080fd5b50356001600160a01b0316610b39565b60408051918252519081900360200190f35b6103c5600480360360408110156103ed57600080fd5b506001600160a01b038135169060200135610c1d565b6104296004803603602081101561041957600080fd5b50356001600160a01b0316610dce565b6040805192835260208301919091528051918290030190f35b6103796004803603602081101561045857600080fd5b50356001600160a01b0316610e4f565b6103796004803603602081101561047e57600080fd5b50356001600160a01b0316610eba565b6103c5610f57565b610379600480360360208110156104ac57600080fd5b50356001600160a01b0316610f5d565b6103c5611074565b610379600480360360208110156104da57600080fd5b503561107a565b610379600480360360408110156104f757600080fd5b81019060208101813564010000000081111561051257600080fd5b82018360208201111561052457600080fd5b8035906020019184602083028401116401000000008311171561054657600080fd5b91939092909160208101903564010000000081111561056457600080fd5b82018360208201111561057657600080fd5b8035906020019184602083028401116401000000008311171561059857600080fd5b509092509050611196565b610379600480360360208110156105b957600080fd5b5035611430565b6103796115cd565b6105ee600480360360208110156105de57600080fd5b50356001600160a01b0316611650565b6040516000826002835b818410156106385760208402830151604080838360005b8381101561062757818101518382015260200161060f565b5050505090500192600101926105f8565b9250505091505060405180910390f35b6103796004803603602081101561065e57600080fd5b50356001600160a01b03166118a0565b610379611a27565b6106936004803603602081101561068c57600080fd5b5035611d72565b6040805167ffffffffffffffff9889168152968816602088015294909616858501526060850192909252608084015260a083015260c082019290925290519081900360e00190f35b6103c5611e1b565b610383611e21565b6103c5611e30565b6107196004803603602081101561070957600080fd5b50356001600160a01b0316611e8b565b604080519115158252519081900360200190f35b6107196004803603602081101561074357600080fd5b50356001600160a01b0316612051565b6107196004803603602081101561076957600080fd5b50356001600160a01b0316612185565b6103c56122dc565b610379612331565b6103c56004803603602081101561079f57600080fd5b50356123ed565b610379600480360360608110156107bc57600080fd5b506001600160a01b038135169060208101359060400135612488565b6103836125ec565b610379600480360360208110156107f657600080fd5b50356001600160a01b03166125fb565b610379612698565b6103836127ea565b6103c56127f9565b610826612800565b604051808261030080838360005b8381101561084c578181015183820152602001610834565b5050505090500191505060405180910390f35b6103c561284a565b610379600480360361010081101561087e57600080fd5b5080359060208101359060408101359060608101359060808101359060a08101359060c08101359060e00135612940565b610379600480360360408110156108c557600080fd5b506001600160a01b038135169060200135612c2a565b610719612e19565b610379600480360360208110156108f957600080fd5b50356001600160a01b0316612e22565b610379612eb8565b610383612f4a565b6103c56004803603602081101561092f57600080fd5b5035612f5e565b61093e612f7c565b6040805160ff9092168252519081900360200190f35b610719612f81565b6103c5612ff3565b610383612ffa565b6103c5613009565b6103c561300f565b610383613014565b61038361302c565b6103c561303b565b6103c5613042565b610379600480360360208110156109b257600080fd5b503561304e565b6002546001600160a01b031633148015906109df57506003546001600160a01b03163314155b80156109f657506004546001600160a01b03163314155b15610a0e57600480546001600160a01b031916331790555b6000546004546001600160a01b03908116911614610a69576040805162461bcd60e51b815260206004820152601360248201527227bbb732b91037b7363c90333ab731ba34b7b760691b604482015290519081900360640190fd5b62015180811015610ac1576040805162461bcd60e51b815260206004820152601f60248201527f76616c7565203c204d494e5f4645455f504552494f445f4455524154494f4e00604482015290519081900360640190fd5b624f1a00811115610b19576040805162461bcd60e51b815260206004820152601f60248201527f76616c7565203e204d41585f4645455f504552494f445f4455524154494f4e00604482015290519081900360640190fd5b6017819055610b2781613100565b50565b6008546001600160a01b031681565b6000610b43613227565b6001600160a01b031663bdc963d87f6c6173745f6665655f7769746864726177616c000000000000000000000000008460405160200180838152602001826001600160a01b03166001600160a01b031660601b815260140192505050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610be957600080fd5b505afa158015610bfd573d6000803e3d6000fd5b505050506040513d6020811015610c1357600080fd5b505190505b919050565b600081610c71576040805162461bcd60e51b815260206004820181905260248201527f43757272656e7420706572696f64206973206e6f7420636c6f73656420796574604482015290519081900360640190fd5b60028210610cc6576040805162461bcd60e51b815260206004820152601d60248201527f4578636565647320746865204645455f504552494f445f4c454e475448000000604482015290519081900360640190fd5b610cd26001830361326b565b5468010000000000000000900467ffffffffffffffff16610cf557506000610dc8565b6000610d256001610d086001860361326b565b5468010000000000000000900467ffffffffffffffff1690613295565b9050600080610d326132f2565b6040805163694e000560e11b81526001600160a01b03898116600483015260248201879052825193169263d29c000a92604480840193919291829003018186803b158015610d7f57600080fd5b505afa158015610d93573d6000803e3d6000fd5b505050506040513d6040811015610da957600080fd5b5080516020909101519092509050610dc2838383613353565b93505050505b92915050565b600080610dd9614633565b610de284611650565b905060008060015b6002811015610e4357610e0f848260028110610e0257fe5b6020020151518490613487565b9250610e39848260028110610e2057fe5b602002015160016020020151839063ffffffff61348716565b9150600101610dea565b50909350915050915091565b6000546001600160a01b03163314610e985760405162461bcd60e51b815260040180806020018281038252602f81526020018061480b602f913960400191505060405180910390fd5b600380546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b03163314610f035760405162461bcd60e51b815260040180806020018281038252602f81526020018061480b602f913960400191505060405180910390fd5b600180546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229181900360200190a150565b60055481565b6000546001600160a01b03163314610fa65760405162461bcd60e51b815260040180806020018281038252602f81526020018061480b602f913960400191505060405180910390fd5b6001600160a01b038116611001576040805162461bcd60e51b815260206004820152601c60248201527f42656e6566696369617279206d757374206e6f74206265207a65726f00000000604482015290519081900360640190fd5b600680546001600160a01b03831661010081027fffffffffffffffffffffff0000000000000000000000000000000000000000ff9092169190911790915560408051918252517fd5da63a0b864b315bc04128dedbc93888c8529ee6cf47ce664dc204339228c539181900360200190a150565b60175481565b60006110846134e8565b6001600160a01b03163314905060008061109c613549565b6001600160a01b03166316b2213f336040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156110f157600080fd5b505afa158015611105573d6000803e3d6000fd5b505050506040513d602081101561111b57600080fd5b505114159050818061112a5750805b6111655760405162461bcd60e51b81526004018080602001828103825260218152602001806148cf6021913960400191505060405180910390fd5b61118383611173600061326b565b600101549063ffffffff61348716565b61118d600061326b565b60010155505050565b6002546001600160a01b031633148015906111bc57506003546001600160a01b03163314155b80156111d357506004546001600160a01b03163314155b156111eb57600480546001600160a01b031916331790555b6000546004546001600160a01b03908116911614611246576040805162461bcd60e51b815260206004820152601360248201527227bbb732b91037b7363c90333ab731ba34b7b760691b604482015290519081900360640190fd5b82811461129a576040805162461bcd60e51b815260206004820152601860248201527f4172726179206c656e6774687320646f6e74206d617463680000000000000000604482015290519081900360640190fd5b60005b838110156114295767016345785d8a00008383838181106112ba57fe5b905060200201351115611314576040805162461bcd60e51b815260206004820152601e60248201527f4d41585f45584348414e47455f4645455f524154452065786365656465640000604482015290519081900360640190fd5b61131c613227565b6001600160a01b0316633562fd207f73796e74685f65786368616e67655f6665655f7261746500000000000000000087878581811061135757fe5b9050602002013560405160200180838152602001828152602001925050506040516020818303038152906040528051906020012085858581811061139757fe5b905060200201356040518363ffffffff1660e01b81526004018083815260200182815260200192505050600060405180830381600087803b1580156113db57600080fd5b505af11580156113ef573d6000803e3d6000fd5b5050505061142185858381811061140257fe5b9050602002013584848481811061141557fe5b905060200201356135aa565b60010161129d565b5050505050565b6002546001600160a01b0316331480159061145657506003546001600160a01b03163314155b801561146d57506004546001600160a01b03163314155b1561148557600480546001600160a01b031916331790555b6000546004546001600160a01b039081169116146114e0576040805162461bcd60e51b815260206004820152601360248201527227bbb732b91037b7363c90333ab731ba34b7b760691b604482015290519081900360640190fd5b6032811115611536576040805162461bcd60e51b815260206004820152601260248201527f5468726573686f6c6420746f6f20686967680000000000000000000000000000604482015290519081900360640190fd5b6115c760646115bb7384d626b2bb4d0f064067e4bf80fce7055d8f3e7b63907af6c06040518163ffffffff1660e01b815260040160206040518083038186803b15801561158257600080fd5b505af4158015611596573d6000803e3d6000fd5b505050506040513d60208110156115ac57600080fd5b5051849063ffffffff6136c316565b9063ffffffff61371c16565b60185550565b6000546001600160a01b031633146116165760405162461bcd60e51b815260040180806020018281038252602f81526020018061480b602f913960400191505060405180910390fd5b600060058190556006805460ff191690556040517f6adcc7125002935e0aa31697538ebbd65cfddf20431eb6ecdcfc3e238bfd082c9190a1565b611658614633565b60008060006116656132f2565b604080517fb326f84e0000000000000000000000000000000000000000000000000000000081526001600160a01b03888116600483015260006024830152825193945084169263b326f84e92604480840193919291829003018186803b1580156116ce57600080fd5b505afa1580156116e2573d6000803e3d6000fd5b505050506040513d60408110156116f857600080fd5b508051602090910151909350915081158015611712575082155b1561172a5761171f614633565b9350610c1892505050565b60008061173960008686613786565b875182905287516020018190529092509050600061175688610b39565b905060015b801561189457600019810160006117718261326b565b5468010000000000000000900467ffffffffffffffff16905080158015906117ab575061179d8361326b565b5467ffffffffffffffff1684105b156118895760006117c382600163ffffffff61329516565b6040805163694e000560e11b81526001600160a01b038f811660048301526024820184905282519394508b169263d29c000a92604480840193919291829003018186803b15801561181357600080fd5b505afa158015611827573d6000803e3d6000fd5b505050506040513d604081101561183d57600080fd5b508051602090910151909a509850611856848b8b613786565b9097509550868b856002811061186857fe5b602002015152858b856002811061187b57fe5b602002015160016020020152505b50506000190161175b565b50505050505050919050565b6000546001600160a01b031633146118e95760405162461bcd60e51b815260040180806020018281038252602f81526020018061480b602f913960400191505060405180910390fd5b600880546001600160a01b0319166001600160a01b03831617905560005b600a54811015611a23576000600a828154811061192057fe5b60009182526020918290200154600854604080517fdacb2d010000000000000000000000000000000000000000000000000000000081526004810184905260248101829052601760448201527f5265736f6c766572206d697373696e6720746172676574000000000000000000606482015290519294506001600160a01b039091169263dacb2d0192608480840193829003018186803b1580156119c357600080fd5b505afa1580156119d7573d6000803e3d6000fd5b505050506040513d60208110156119ed57600080fd5b505160009182526009602052604090912080546001600160a01b0319166001600160a01b03909216919091179055600101611907565b5050565b6017544203611a36600061326b565b54600160801b900467ffffffffffffffff161115611a9b576040805162461bcd60e51b815260206004820152601d60248201527f546f6f206561726c7920746f20636c6f73652066656520706572696f64000000604482015290519081900360640190fd5b611aa3613828565b6001600160a01b0316637c3125416040518163ffffffff1660e01b815260040160006040518083038186803b158015611adb57600080fd5b505afa158015611aef573d6000803e3d6000fd5b5060009250611b01915082905061326b565b90506000611b0f600161326b565b9050611b408260010154611b348360020154846001015461329590919063ffffffff16565b9063ffffffff61348716565b611b4a600061326b565b60010155600380830154600483015491830154611b7192611b34919063ffffffff61329516565b611b7b600061326b565b60030155601654611bb890600290611bac90600190611ba0908463ffffffff61348716565b9063ffffffff61329516565b9063ffffffff61388916565b6016819055600c9060028110611bca57fe5b6005020180547fffffffffffffffff000000000000000000000000000000000000000000000000168155600060018083018290556002830182905560038301829055600490920155611c3690611c1f8161326b565b5467ffffffffffffffff169063ffffffff61348716565b611c40600061326b565b805467ffffffffffffffff191667ffffffffffffffff92909216919091179055611c686138ee565b6001600160a01b031663cd92eba96040518163ffffffff1660e01b815260040160206040518083038186803b158015611ca057600080fd5b505afa158015611cb4573d6000803e3d6000fd5b505050506040513d6020811015611cca57600080fd5b5051611cd6600061326b565b805467ffffffffffffffff9290921668010000000000000000026fffffffffffffffff00000000000000001990921691909117905542611d16600061326b565b805467ffffffffffffffff92909216600160801b027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff909216919091179055611a23611d62600161326b565b5467ffffffffffffffff1661394f565b6000806000806000806000611d85614660565b611d8e8961326b565b6040805160e081018252825467ffffffffffffffff808216808452680100000000000000008304821660208501819052600160801b909304909116938301849052600185015460608401819052600286015460808501819052600387015460a0860181905260049097015460c0909501859052919f929e50939c50929a5091985091965090945092505050565b60075481565b6001546001600160a01b031681565b60008060015b6002811015611e8557611e5c611e4b8261326b565b60010154839063ffffffff61348716565b9150611e7b611e6a8261326b565b60020154839063ffffffff61329516565b9150600101611e36565b50905090565b600080611e96613549565b6001600160a01b031663a311c7c2846040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015611eeb57600080fd5b505afa158015611eff573d6000803e3d6000fd5b505050506040513d6020811015611f1557600080fd5b505190506000611f236138ee565b6001600160a01b031663b410a0346040518163ffffffff1660e01b815260040160206040518083038186803b158015611f5b57600080fd5b505afa158015611f6f573d6000803e3d6000fd5b505050506040513d6020811015611f8557600080fd5b5051905080821015611f9c57600192505050610c18565b60006120306120236018547384d626b2bb4d0f064067e4bf80fce7055d8f3e7b63907af6c06040518163ffffffff1660e01b815260040160206040518083038186803b158015611feb57600080fd5b505af4158015611fff573d6000803e3d6000fd5b505050506040513d602081101561201557600080fd5b50519063ffffffff61348716565b839063ffffffff613a3816565b9050808311156120465760009350505050610c18565b506001949350505050565b6008546000906001600160a01b0383811691161461207157506000610c18565b60005b600a5481101561217c576000600a828154811061208d57fe5b6000918252602080832090910154808352600982526040928390205460085484517f21f8a7210000000000000000000000000000000000000000000000000000000081526004810184905294519295506001600160a01b03918216949116926321f8a72192602480840193829003018186803b15801561210c57600080fd5b505afa158015612120573d6000803e3d6000fd5b505050506040513d602081101561213657600080fd5b50516001600160a01b031614158061216357506000818152600960205260409020546001600160a01b0316155b1561217357600092505050610c18565b50600101612074565b50600192915050565b6002546000906001600160a01b031633148015906121ae57506003546001600160a01b03163314155b80156121c557506004546001600160a01b03163314155b156121dd57600480546001600160a01b031916331790555b6121e5613a62565b60048054604080517f21f4ae570000000000000000000000000000000000000000000000000000000081526001600160a01b038781169482019490945291831660248301525192909116916321f4ae5791604480820192602092909190829003018186803b15801561225657600080fd5b505afa15801561226a573d6000803e3d6000fd5b505050506040513d602081101561228057600080fd5b50516122d3576040805162461bcd60e51b815260206004820152601f60248201527f4e6f7420617070726f76656420746f20636c61696d206f6e20626568616c6600604482015290519081900360640190fd5b610dc882613aa6565b60008060015b6002811015611e85576123086122f78261326b565b60030154839063ffffffff61348716565b91506123276123168261326b565b60040154839063ffffffff61329516565b91506001016122e2565b6001546001600160a01b0316331461237a5760405162461bcd60e51b81526004018080602001828103825260358152602001806146f96035913960400191505060405180910390fd5b600054600154604080516001600160a01b03938416815292909116602083015280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b60006123f7613227565b6001600160a01b031663bdc963d87f73796e74685f65786368616e67655f6665655f72617465000000000000000000846040516020018083815260200182815260200192505050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610be957600080fd5b612490613c24565b6001600160a01b0316336001600160a01b0316146124f5576040805162461bcd60e51b815260206004820152601f60248201527f466565506f6f6c3a204f6e6c792049737375657220417574686f726973656400604482015290519081900360640190fd5b6124fd6132f2565b6001600160a01b03166394e1a448848484612518600061326b565b54604080517fffffffff0000000000000000000000000000000000000000000000000000000060e088901b1681526001600160a01b0390951660048601526024850193909352604484019190915267ffffffffffffffff6801000000000000000090910416606483015251608480830192600092919082900301818387803b1580156125a357600080fd5b505af11580156125b7573d6000803e3d6000fd5b505050506125e78383836125cb600061326b565b5468010000000000000000900467ffffffffffffffff16613c85565b505050565b6000546001600160a01b031681565b6000546001600160a01b031633146126445760405162461bcd60e51b815260040180806020018281038252602f81526020018061480b602f913960400191505060405180910390fd5b600280546001600160a01b0383166001600160a01b0319909116811790915560408051918252517ffc80377ca9c49cc11ae6982f390a42db976d5530af7c43889264b13fbbd7c57e9181900360200190a150565b6000546001600160a01b031633146126e15760405162461bcd60e51b815260040180806020018281038252602f81526020018061480b602f913960400191505060405180910390fd5b60065460ff16612738576040805162461bcd60e51b815260206004820152601f60248201527f53656c66204465737472756374206e6f742079657420696e6974696174656400604482015290519081900360640190fd5b426224ea006005540110612793576040805162461bcd60e51b815260206004820152601b60248201527f53656c662064657374727563742064656c6179206e6f74206d65740000000000604482015290519081900360640190fd5b600654604080516101009092046001600160a01b03168252517f8a09e1677ced846cb537dc2b172043bd05a1a81ad7e0033a7ef8ba762df990b7916020908290030190a160065461010090046001600160a01b0316ff5b6003546001600160a01b031681565b6224ea0081565b6128086146bb565b60005b600a5481101561284657600a818154811061282257fe5b906000526020600020015482826018811061283957fe5b602002015260010161280b565b5090565b6000806128556138ee565b6001600160a01b031663b410a0346040518163ffffffff1660e01b815260040160206040518083038186803b15801561288d57600080fd5b505afa1580156128a1573d6000803e3d6000fd5b505050506040513d60208110156128b757600080fd5b5051601854604080517f907af6c0000000000000000000000000000000000000000000000000000000008152905192935061293a9261292d92917384d626b2bb4d0f064067e4bf80fce7055d8f3e7b9163907af6c091600480820192602092909190829003018186803b158015611feb57600080fd5b829063ffffffff613a3816565b91505090565b6002546001600160a01b0316331480159061296657506003546001600160a01b03163314155b801561297d57506004546001600160a01b03163314155b1561299557600480546001600160a01b031916331790555b6000546004546001600160a01b039081169116146129f0576040805162461bcd60e51b815260206004820152601360248201527227bbb732b91037b7363c90333ab731ba34b7b760691b604482015290519081900360640190fd5b6007544210612a305760405162461bcd60e51b815260040180806020018281038252602981526020018061487e6029913960400191505060405180910390fd5b612a386138ee565b6001600160a01b031663cd92eba96040518163ffffffff1660e01b815260040160206040518083038186803b158015612a7057600080fd5b505afa158015612a84573d6000803e3d6000fd5b505050506040513d6020811015612a9a57600080fd5b5051861115612af0576040805162461bcd60e51b815260206004820152601660248201527f43616e6e6f7420696d706f727420626164206461746100000000000000000000604482015290519081900360640190fd5b6040518060e001604052808867ffffffffffffffff1681526020018767ffffffffffffffff1681526020018667ffffffffffffffff16815260200185815260200184815260200183815260200182815250600c612b60600260ff16611bac8c60165461348790919063ffffffff16565b60028110612b6a57fe5b82516005919091029190910180546020840151604085015167ffffffffffffffff1990921667ffffffffffffffff948516176fffffffffffffffff000000000000000019166801000000000000000091851691909102177fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff16600160801b9390911692909202919091178155606082015160018201556080820151600282015560a0820151600382015560c0909101516004909101555050505050505050565b6002546001600160a01b03163314801590612c5057506003546001600160a01b03163314155b8015612c6757506004546001600160a01b03163314155b15612c7f57600480546001600160a01b031916331790555b6000546004546001600160a01b03908116911614612cda576040805162461bcd60e51b815260206004820152601360248201527227bbb732b91037b7363c90333ab731ba34b7b760691b604482015290519081900360640190fd5b612ce2613549565b6004546001600160a01b03918216916323b872dd9116612d00613dcc565b846040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050602060405180830381600087803b158015612d6957600080fd5b505af1158015612d7d573d6000803e3d6000fd5b505050506040513d6020811015612d9357600080fd5b50612d9e9050613dcc565b6001600160a01b031663b5ddb9c783836040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b158015612dfd57600080fd5b505af1158015612e11573d6000803e3d6000fd5b505050505050565b60065460ff1681565b6002546001600160a01b0316331480612e4557506003546001600160a01b031633145b612e96576040805162461bcd60e51b815260206004820152601760248201527f4f6e6c79207468652070726f78792063616e2063616c6c000000000000000000604482015290519081900360640190fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b03163314612f015760405162461bcd60e51b815260040180806020018281038252602f81526020018061480b602f913960400191505060405180910390fd5b426005556006805460ff19166001179055604080516224ea00815290517fcbd94ca75b8dc45c9d80c77e851670e78843c0d75180cb81db3e2158228fa9a69181900360200190a1565b60065461010090046001600160a01b031681565b600a8181548110612f6b57fe5b600091825260209091200154905081565b600281565b6002546000906001600160a01b03163314801590612faa57506003546001600160a01b03163314155b8015612fc157506004546001600160a01b03163314155b15612fd957600480546001600160a01b031916331790555b600454612fee906001600160a01b0316613aa6565b905090565b6201518081565b6004546001600160a01b031681565b60185481565b601881565b73feefeefeefeefeefeefeefeefeefeefeefeefeef81565b6002546001600160a01b031681565b624f1a0081565b67016345785d8a000081565b6000613058613e2d565b6004549091506001600160a01b038083169116148061307f5750336001600160a01b038216145b6130d0576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206973206e6f742072657761726473417574686f726974790000604482015290519081900360640190fd5b6130ee826130de600061326b565b600301549063ffffffff61348716565b6130f8600061326b565b600301555050565b60025460408051602080820185905282518083039091018152908201918290526001600160a01b039092169163907dff97916001908060216147ea82396021019050604051809103902060008060006040518763ffffffff1660e01b815260040180806020018781526020018681526020018560001b81526020018460001b81526020018360001b8152602001828103825288818151815260200191508051906020019080838360005b838110156131c25781810151838201526020016131aa565b50505050905090810190601f1680156131ef5780820380516001836020036101000a031916815260200191505b50975050505050505050600060405180830381600087803b15801561321357600080fd5b505af1158015611429573d6000803e3d6000fd5b6000612fee7f466565506f6f6c457465726e616c53746f7261676500000000000000000000006040518060600160405280602581526020016148f060259139613e6d565b6000600c600260ff1683601654018161328057fe5b066002811061328b57fe5b6005020192915050565b6000828211156132ec576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6000612fee7f466565506f6f6c537461746500000000000000000000000000000000000000006040518060400160405280601c81526020017f4d697373696e6720466565506f6f6c5374617465206164647265737300000000815250613e6d565b60008061335e6138ee565b9050600061347d85613471846001600160a01b03166308d95cd5886040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b1580156133ad57600080fd5b505afa1580156133c1573d6000803e3d6000fd5b505050506040513d60208110156133d757600080fd5b5051604080517f08d95cd5000000000000000000000000000000000000000000000000000000008152600481018c905290516001600160a01b038816916308d95cd5916024808301926020929190829003018186803b15801561343957600080fd5b505afa15801561344d573d6000803e3d6000fd5b505050506040513d602081101561346357600080fd5b50519063ffffffff613f1716565b9063ffffffff613f3016565b9695505050505050565b6000828201838110156134e1576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6000612fee7f45786368616e67657200000000000000000000000000000000000000000000006040518060400160405280601981526020017f4d697373696e672045786368616e676572206164647265737300000000000000815250613e6d565b6000612fee7f53796e74686574697800000000000000000000000000000000000000000000006040518060400160405280601981526020017f4d697373696e672053796e746865746978206164647265737300000000000000815250613e6d565b60025460408051602081018590528082018490528151808203830181526060909101918290526001600160a01b039092169163907dff97916001908060286148a782396028019050604051809103902060008060006040518763ffffffff1660e01b815260040180806020018781526020018681526020018560001b81526020018460001b81526020018360001b8152602001828103825288818151815260200191508051906020019080838360005b8381101561367257818101518382015260200161365a565b50505050905090810190601f16801561369f5780820380516001836020036101000a031916815260200191505b50975050505050505050600060405180830381600087803b158015612dfd57600080fd5b6000826136d257506000610dc8565b828202828482816136df57fe5b04146134e15760405162461bcd60e51b815260040180806020018281038252602181526020018061485d6021913960400191505060405180910390fd5b6000808211613772576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b600082848161377d57fe5b04949350505050565b6000808361379957506000905080613820565b8385156137c45760006137b36001610d0860018a0361326b565b90506137c0818787613353565b9150505b60006137e3826137d38961326b565b600101549063ffffffff613a3816565b90506000613804836137f48a61326b565b600301549063ffffffff613a3816565b905061380f82613f49565b61381882613f49565b945094505050505b935093915050565b6000612fee7f53797374656d53746174757300000000000000000000000000000000000000006040518060400160405280601c81526020017f4d697373696e672053797374656d537461747573206164647265737300000000815250613e6d565b6000816138dd576040805162461bcd60e51b815260206004820152601860248201527f536166654d6174683a206d6f64756c6f206279207a65726f0000000000000000604482015290519081900360640190fd5b8183816138e657fe5b069392505050565b6000612fee7f53796e74686574697853746174650000000000000000000000000000000000006040518060400160405280601e81526020017f4d697373696e672053796e746865746978537461746520616464726573730000815250613e6d565b6002546040805160208082018590528251808303820181528284018085527f466565506572696f64436c6f7365642875696e74323536290000000000000000905292519182900360580182207f907dff97000000000000000000000000000000000000000000000000000000008352600160248401819052604484018290526000606485018190526084850181905260a4850181905260c060048601908152865160c487015286516001600160a01b039098169763907dff979796939592938493849392839260e401918a019080838388838110156131c25781810151838201526020016131aa565b6000670de0b6b3a7640000613a53848463ffffffff6136c316565b81613a5a57fe5b049392505050565b6000612fee7f44656c6567617465417070726f76616c7300000000000000000000000000000060405180606001604052806021815260200161475260219139613e6d565b6000613ab0613828565b6001600160a01b0316637c3125416040518163ffffffff1660e01b815260040160006040518083038186803b158015613ae857600080fd5b505afa158015613afc573d6000803e3d6000fd5b506000925082915081905080613b1186611e8b565b613b62576040805162461bcd60e51b815260206004820152601f60248201527f432d526174696f2062656c6f772070656e616c7479207468726573686f6c6400604482015290519081900360640190fd5b613b6b86610dce565b909250905081151580613b7e5750600081115b613bb95760405162461bcd60e51b81526004018080602001828103825260408152602001806147aa6040913960400191505060405180910390fd5b613bd786613bc7600161326b565b5467ffffffffffffffff16613f6b565b8115613bf257613be682614023565b9250613bf286846140f7565b8015613c0d57613c01816142dc565b9350613c0d86856143b6565b613c188684866144ad565b50600195945050505050565b6000612fee7f49737375657200000000000000000000000000000000000000000000000000006040518060400160405280601681526020017f4d697373696e6720497373756572206164647265737300000000000000000000815250613e6d565b6002805460408051602081018790528082018690526060808201869052825180830390910181526080909101918290526001600160a01b039092169263907dff979291806037614773823960370190506040518091039020886001600160a01b031660001b6000806040518763ffffffff1660e01b815260040180806020018781526020018681526020018581526020018460001b81526020018360001b8152602001828103825288818151815260200191508051906020019080838360005b83811015613d5d578181015183820152602001613d45565b50505050905090810190601f168015613d8a5780820380516001836020036101000a031916815260200191505b50975050505050505050600060405180830381600087803b158015613dae57600080fd5b505af1158015613dc2573d6000803e3d6000fd5b5050505050505050565b6000612fee7f526577617264457363726f7700000000000000000000000000000000000000006040518060400160405280601c81526020017f4d697373696e6720526577617264457363726f77206164647265737300000000815250613e6d565b6000612fee7f52657761726473446973747269627574696f6e0000000000000000000000000060405180606001604052806023815260200161483a602391395b6000828152600960205260408120546001600160a01b03168281613f0f5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613ed4578181015183820152602001613ebc565b50505050905090810190601f168015613f015780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b509392505050565b60006134e183836b033b2e3c9fd0803ce80000006145d0565b60006134e183836b033b2e3c9fd0803ce8000000614608565b60006305f5e10082046005600a820610613f6157600a015b600a900492915050565b613f73613227565b6001600160a01b0316633562fd207f6c6173745f6665655f7769746864726177616c000000000000000000000000008460405160200180838152602001826001600160a01b03166001600160a01b031660601b81526014019250505060405160208183030381529060405280519060200120836040518363ffffffff1660e01b81526004018083815260200182815260200192505050600060405180830381600087803b158015612dfd57600080fd5b6000818160015b6002811015613f0f57600061403e8261326b565b6002015490506000614063826140538561326b565b600101549063ffffffff61329516565b905080156140ec57600085821061407a578561407c565b815b905061408e838263ffffffff61348716565b6140978561326b565b600201556140ab868263ffffffff61329516565b95506140bd858263ffffffff61348716565b9450856140d257849650505050505050610c18565b831580156140e05750600086115b156140ea57600095505b505b50506000190161402a565b816001600160a01b03811673feefeefeefeefeefeefeefeefeefeefeefeefeef141561416a576040805162461bcd60e51b815260206004820152601760248201527f4665652061646472657373206e6f7420616c6c6f776564000000000000000000604482015290519081900360640190fd5b6000614174613549565b6001600160a01b03166332608039600b546040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b1580156141b957600080fd5b505afa1580156141cd573d6000803e3d6000fd5b505050506040513d60208110156141e357600080fd5b5051604080517f9dc29fac00000000000000000000000000000000000000000000000000000000815273feefeefeefeefeefeefeefeefeefeefeefeefeef60048201526024810186905290519192506001600160a01b03831691639dc29fac9160448082019260009290919082900301818387803b15801561426457600080fd5b505af1158015614278573d6000803e3d6000fd5b50505050806001600160a01b031663867904b485856040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b158015613dae57600080fd5b6000818160015b6002811015613f0f5760006143176142fa8361326b565b600401546143078461326b565b600301549063ffffffff61329516565b905080156143ac57600084821061432e5784614330565b815b905061434f8161433f8561326b565b600401549063ffffffff61348716565b6143588461326b565b6004015561436c858263ffffffff61329516565b945061437e848263ffffffff61348716565b935084614392578395505050505050610c18565b821580156143a05750600085115b156143aa57600094505b505b50600019016142e3565b816001600160a01b03811673feefeefeefeefeefeefeefeefeefeefeefeefeef1415614429576040805162461bcd60e51b815260206004820152601760248201527f4665652061646472657373206e6f7420616c6c6f776564000000000000000000604482015290519081900360640190fd5b614431613dcc565b6001600160a01b031663b5ddb9c784846040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b15801561449057600080fd5b505af11580156144a4573d6000803e3d6000fd5b50505050505050565b600254604080516001600160a01b0386811660208301528183018690526060808301869052835180840390910181526080909201928390529092169163907dff979160019080602461472e82396024019050604051809103902060008060006040518763ffffffff1660e01b815260040180806020018781526020018681526020018560001b81526020018460001b81526020018360001b8152602001828103825288818151815260200191508051906020019080838360005b8381101561457f578181015183820152602001614567565b50505050905090810190601f1680156145ac5780820380516001836020036101000a031916815260200191505b50975050505050505050600060405180830381600087803b15801561449057600080fd5b6000806145ea846115bb87600a870263ffffffff6136c316565b90506005600a825b06106145fc57600a015b600a9004949350505050565b600080600a830461461f868663ffffffff6136c316565b8161462657fe5b0490506005600a826145f2565b60405180604001604052806002905b61464a6146da565b8152602001906001900390816146425790505090565b6040518060e00160405280600067ffffffffffffffff168152602001600067ffffffffffffffff168152602001600067ffffffffffffffff168152602001600081526020016000815260200160008152602001600081525090565b6040518061030001604052806018906020820280388339509192915050565b6040518060400160405280600290602082028038833950919291505056fe596f75206d757374206265206e6f6d696e61746564206265666f726520796f752063616e20616363657074206f776e65727368697046656573436c61696d656428616464726573732c75696e743235362c75696e74323536294d697373696e672044656c6567617465417070726f76616c73206164647265737349737375616e636544656274526174696f456e74727928616464726573732c75696e743235362c75696e743235362c75696e74323536294e6f2066656573206f72207265776172647320617661696c61626c6520666f7220706572696f642c206f72206665657320616c726561647920636c61696d6564466565506572696f644475726174696f6e557064617465642875696e74323536294f6e6c792074686520636f6e7472616374206f776e6572206d617920706572666f726d207468697320616374696f6e4d697373696e672052657761726473446973747269627574696f6e2061646472657373536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7743616e206f6e6c7920706572666f726d207468697320616374696f6e20647572696e6720736574757053796e746845786368616e67654665655570646174656428627974657333322c75696e74323536294f6e6c792045786368616e6765722c2053796e74687320417574686f72697365644d697373696e6720466565506f6f6c457465726e616c53746f726167652061646472657373a265627a7a72315820df3d94c204228d52bdeab83f2e8f4a1142a185790336acf62f2437c0d7be5c7264736f6c63430005100032

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

000000000000000000000000b440dd674e1243644791a4adfe3a2abb0a92d309000000000000000000000000de910777c787903f78c89e7a0bf7f4c435cbb1fe000000000000000000000000fbb6526ed92da8915d4843a86166020d0b7baad0

-----Decoded View---------------
Arg [0] : _proxy (address): 0xb440DD674e1243644791a4AdfE3A2AbB0A92d309
Arg [1] : _owner (address): 0xDe910777C787903F78C89e7a0bf7F4C435cBB1Fe
Arg [2] : _resolver (address): 0xFbB6526ed92DA8915d4843a86166020d0B7bAAd0

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000b440dd674e1243644791a4adfe3a2abb0a92d309
Arg [1] : 000000000000000000000000de910777c787903f78c89e7a0bf7f4c435cbb1fe
Arg [2] : 000000000000000000000000fbb6526ed92da8915d4843a86166020d0b7baad0


Libraries Used


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

OVERVIEW

Synthetix: Fee Pool contract has migrated to 0x6AAeBDfbf23134eF8d81deB2E253f32394B2857B.

Loading...
Loading
[ Download: CSV Export  ]

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