Contract 0x07aCC2B253218535c21a3E57BcB81eB13345a34A

Contract Overview

Balance:
0 Ether
Txn Hash
Block
From
To
Value
0xc872d857a1de6b6b482979140e8720665bfd25c4e75b21923292fd34a559484a242052422021-04-09 17:55:242 days 1 hr ago0x68bf577920d6607c52114cb5e13696a19c2c9efa IN  0x07acc2b253218535c21a3e57bcb81eb13345a34a0 Ether0.0000965582
0x03f9a5da936c7912dac0305910bcef25e8e7a107868c11d87c6347f6121b7cba242052082021-04-09 17:50:202 days 1 hr ago0xb64ff7a4a33acdf48d97dab0d764afd0f6176882 IN  0x07acc2b253218535c21a3e57bcb81eb13345a34a0 Ether0.0000440791
0x7cff1e8b716ea85c757a296bbe9684561c86d4bd8c70888dcc783f8cb1c2d862240630002021-03-26 17:58:5216 days 1 hr ago0x68bf577920d6607c52114cb5e13696a19c2c9efa IN  0x07acc2b253218535c21a3e57bcb81eb13345a34a0 Ether0.0000632911
0x21e384adab6812ea55e52bba5b8853f5753843ddf663dba57e9df310e06614eb240629612021-03-26 17:53:4016 days 1 hr ago0xb64ff7a4a33acdf48d97dab0d764afd0f6176882 IN  0x07acc2b253218535c21a3e57bcb81eb13345a34a0 Ether0.0001066021
0x2bf733dd265f2c80749c770594775c720eb63e5856fa73a82b780d5cbec95295240629092021-03-26 17:46:2816 days 1 hr ago0xb64ff7a4a33acdf48d97dab0d764afd0f6176882 IN  0x07acc2b253218535c21a3e57bcb81eb13345a34a0 Ether0.0000482791
0xa4168a80ff40a3e2caef827e3c4dff86d13832dafda97b0917d9fac37f8c5d10240628112021-03-26 17:33:2416 days 2 hrs ago0xb64ff7a4a33acdf48d97dab0d764afd0f6176882 IN  0x07acc2b253218535c21a3e57bcb81eb13345a34a0 Ether0.0000482911
0xb64cbb19f1d7e344af72529d29252f6bd11caedc740e084770416248766816b1239258752021-03-15 7:01:0027 days 12 hrs ago0x0713a0c92019d867ff978c83074d4475c2a1493b IN  0x07acc2b253218535c21a3e57bcb81eb13345a34a0 Ether0.0041414210
0x8b97a5d66dc48bf8002930c7dc208ebc0ad5917d0d018df857d702c6734c9584239258682021-03-15 7:00:2027 days 12 hrs ago0x0713a0c92019d867ff978c83074d4475c2a1493b IN  0x07acc2b253218535c21a3e57bcb81eb13345a34a0 Ether0.0066105910
0xdefcd5716e0af113b36b9889c85025f25f06f2a2414b9b4c55443aded2086689239258462021-03-15 6:58:0827 days 12 hrs ago0x0713a0c92019d867ff978c83074d4475c2a1493b IN  0x07acc2b253218535c21a3e57bcb81eb13345a34a0 Ether0.0026062710
0x87a1a7e8acbeb82f99a38b98bb749838ef2aa3461f0a26ad7933cb970b1791ca239238992021-03-15 4:02:5627 days 15 hrs ago0x0713a0c92019d867ff978c83074d4475c2a1493b IN  0x07acc2b253218535c21a3e57bcb81eb13345a34a0 Ether0.0005616410
0x76e563218defae5e7b4f2f3c105b28175d990ed8ef413d5cbd554f0f3ffebb60239238852021-03-15 4:01:4027 days 15 hrs ago0x0713a0c92019d867ff978c83074d4475c2a1493b IN  0x07acc2b253218535c21a3e57bcb81eb13345a34a0 Ether0.0003403510
0x2185809d6b00c4044108303f1b7b085bb222eb2910f7d758de2c58bd9e443101239238772021-03-15 4:01:0027 days 15 hrs ago0x0713a0c92019d867ff978c83074d4475c2a1493b IN  0x07acc2b253218535c21a3e57bcb81eb13345a34a0 Ether0.0064185310
0x20984a39782e81cbe4b31392c267a106d04e63f2d10942849ca5a0be76dc5a11239238682021-03-15 4:00:0027 days 15 hrs ago0x0713a0c92019d867ff978c83074d4475c2a1493b IN  0x07acc2b253218535c21a3e57bcb81eb13345a34a0 Ether0.0065686510
0xe627ef158d3b7bc279b8ceefd72ebe4940c018560aa0fbeefface7f713c365ad239238582021-03-15 3:59:0827 days 15 hrs ago0x0713a0c92019d867ff978c83074d4475c2a1493b IN  0x07acc2b253218535c21a3e57bcb81eb13345a34a0 Ether0.0051663610
0x1d67c457ced58e600d60be46c0b0c20c20a33b1ed0ed42da68c43ea15aad3b89239237952021-03-15 3:53:2027 days 15 hrs ago0x0713a0c92019d867ff978c83074d4475c2a1493b IN  0x07acc2b253218535c21a3e57bcb81eb13345a34a0 Ether0.0003403510
0xf25689d7962b8e06dd2061f6af97633d70237617f238c6149b268bd9a20b53e7239237882021-03-15 3:52:4427 days 15 hrs ago0x0713a0c92019d867ff978c83074d4475c2a1493b IN  0x07acc2b253218535c21a3e57bcb81eb13345a34a0 Ether0.0032170710
0x96618a8e2cecd6f2ffde04776a065eb4123a61afcac026b9040e8afee125b7f7239237442021-03-15 3:48:4827 days 15 hrs ago0x0713a0c92019d867ff978c83074d4475c2a1493b IN  0x07acc2b253218535c21a3e57bcb81eb13345a34a0 Ether0.0032168310
0x36bc6dafcec0022025356b0f6c5600f7da40e479edeaae9157a208c0f6ad0de3239237252021-03-15 3:47:0827 days 15 hrs ago0x0713a0c92019d867ff978c83074d4475c2a1493b IN  0x07acc2b253218535c21a3e57bcb81eb13345a34a0 Ether0.0043783610
0xf4deb2bb9d9962dc40e9cde413eeed8eebf2169cd9f7b3880682ddaefbc9dae0239232562021-03-15 3:05:0027 days 16 hrs ago0x0713a0c92019d867ff978c83074d4475c2a1493b IN  0x07acc2b253218535c21a3e57bcb81eb13345a34a0 Ether0.0048740110
0xbd1408884edbfd2c49f9a7d419958a49bae37f5fd2cb3da841eecf697d720496238711232021-03-11 18:55:5631 days 37 mins ago0xaa3802438a2546cee38207a14e6afc789a9102d4 IN  0x07acc2b253218535c21a3e57bcb81eb13345a34a0 Ether0.0000633991
0x985c0dfd62f566000e943c6bc8e00aa5c318288da67b04ad8c8f48e5e55fb816238710992021-03-11 18:53:4831 days 40 mins ago0xb64ff7a4a33acdf48d97dab0d764afd0f6176882 IN  0x07acc2b253218535c21a3e57bcb81eb13345a34a0 Ether0.0001518211
0x16324eac2ef18f50615d03b74b08b26c7de754f7822982aa7c9ed7cd46ba23bd238707552021-03-11 18:22:2431 days 1 hr ago0x68bf577920d6607c52114cb5e13696a19c2c9efa IN  0x07acc2b253218535c21a3e57bcb81eb13345a34a0 Ether0.0000632911
0x54554ae037868d52a49d857f44d92491f474356305215847ee53122460bdbb70238707392021-03-11 18:21:0031 days 1 hr ago0xb64ff7a4a33acdf48d97dab0d764afd0f6176882 IN  0x07acc2b253218535c21a3e57bcb81eb13345a34a0 Ether0.0001609871
0x0c8077052ca59126a093e71fd33b966023389505d02e0fe3f34505bd1458e2cf238706412021-03-11 18:12:1231 days 1 hr ago0xb64ff7a4a33acdf48d97dab0d764afd0f6176882 IN  0x07acc2b253218535c21a3e57bcb81eb13345a34a0 Ether0.0000482911
0x1fb1371c28d8fc6e2a738557220c3879cfbc50b57bd5a1dfd889aadaa1387318234809462021-02-15 7:03:4455 days 12 hrs ago0x175023d52584a5e29e6c33e88592851359941508 IN  0x07acc2b253218535c21a3e57bcb81eb13345a34a0 Ether0.0001332994.5
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0x5cbb82876bb3019ca83aee8571de42067ed7bc2c0d49870ed5a4f6f7de0fe821242151122021-04-10 17:00:201 day 2 hrs ago 0x07acc2b253218535c21a3e57bcb81eb13345a34a 0xc011a73ee8576fb46f5e1c5751ca3b9fe0af2a6f0 Ether
0x5cbb82876bb3019ca83aee8571de42067ed7bc2c0d49870ed5a4f6f7de0fe821242151122021-04-10 17:00:201 day 2 hrs ago 0xf49528689234d46724383669bd8658bfb47f8575 0x07acc2b253218535c21a3e57bcb81eb13345a34a0 Ether
0x5cbb82876bb3019ca83aee8571de42067ed7bc2c0d49870ed5a4f6f7de0fe821242151122021-04-10 17:00:201 day 2 hrs ago 0x07acc2b253218535c21a3e57bcb81eb13345a34a 0xc011a73ee8576fb46f5e1c5751ca3b9fe0af2a6f0 Ether
0x5cbb82876bb3019ca83aee8571de42067ed7bc2c0d49870ed5a4f6f7de0fe821242151122021-04-10 17:00:201 day 2 hrs ago 0xf49528689234d46724383669bd8658bfb47f8575 0x07acc2b253218535c21a3e57bcb81eb13345a34a0 Ether
0x5cbb82876bb3019ca83aee8571de42067ed7bc2c0d49870ed5a4f6f7de0fe821242151122021-04-10 17:00:201 day 2 hrs ago 0x07acc2b253218535c21a3e57bcb81eb13345a34a 0xf49528689234d46724383669bd8658bfb47f85750 Ether
0x5cbb82876bb3019ca83aee8571de42067ed7bc2c0d49870ed5a4f6f7de0fe821242151122021-04-10 17:00:201 day 2 hrs ago 0x07acc2b253218535c21a3e57bcb81eb13345a34a 0xcf8b3d452a56dab495df84905655047bc1dc41bc0 Ether
0x5cbb82876bb3019ca83aee8571de42067ed7bc2c0d49870ed5a4f6f7de0fe821242151122021-04-10 17:00:201 day 2 hrs ago 0x313d45f47b7f63a481272354c92d477e21dc9d7c 0x07acc2b253218535c21a3e57bcb81eb13345a34a0 Ether
0xdeb227b1b59a238086243159492a9379181fc0b195f43ec775cf72989bc7c5f3242083312021-04-10 0:57:481 day 18 hrs ago 0x07acc2b253218535c21a3e57bcb81eb13345a34a 0xc011a73ee8576fb46f5e1c5751ca3b9fe0af2a6f0 Ether
0xdeb227b1b59a238086243159492a9379181fc0b195f43ec775cf72989bc7c5f3242083312021-04-10 0:57:481 day 18 hrs ago 0x07acc2b253218535c21a3e57bcb81eb13345a34a 0x46824bfaafd049fb0af9a45159a88e595bbbb9f70 Ether
0xdeb227b1b59a238086243159492a9379181fc0b195f43ec775cf72989bc7c5f3242083312021-04-10 0:57:481 day 18 hrs ago 0x07acc2b253218535c21a3e57bcb81eb13345a34a 0x46824bfaafd049fb0af9a45159a88e595bbbb9f70 Ether
0xdeb227b1b59a238086243159492a9379181fc0b195f43ec775cf72989bc7c5f3242083312021-04-10 0:57:481 day 18 hrs ago 0x07acc2b253218535c21a3e57bcb81eb13345a34a 0x46824bfaafd049fb0af9a45159a88e595bbbb9f70 Ether
0xdeb227b1b59a238086243159492a9379181fc0b195f43ec775cf72989bc7c5f3242083312021-04-10 0:57:481 day 18 hrs ago 0x07acc2b253218535c21a3e57bcb81eb13345a34a 0x46824bfaafd049fb0af9a45159a88e595bbbb9f70 Ether
0xdeb227b1b59a238086243159492a9379181fc0b195f43ec775cf72989bc7c5f3242083312021-04-10 0:57:481 day 18 hrs ago 0x07acc2b253218535c21a3e57bcb81eb13345a34a 0xafcbc491b67c01b40f6c077ef53488876a0a0d6e0 Ether
0xdeb227b1b59a238086243159492a9379181fc0b195f43ec775cf72989bc7c5f3242083312021-04-10 0:57:481 day 18 hrs ago 0x07acc2b253218535c21a3e57bcb81eb13345a34a 0xcf8b3d452a56dab495df84905655047bc1dc41bc0 Ether
0xdeb227b1b59a238086243159492a9379181fc0b195f43ec775cf72989bc7c5f3242083312021-04-10 0:57:481 day 18 hrs ago 0xf92e70301e26aadeccec5016b7d0167daf416d72 0x07acc2b253218535c21a3e57bcb81eb13345a34a0 Ether
0xd1ad8c8340b8905d52d9a070a71cf326f9145ed66de525948937109649f89acd242053272021-04-09 18:06:442 days 1 hr ago 0x07acc2b253218535c21a3e57bcb81eb13345a34a 0xc011a73ee8576fb46f5e1c5751ca3b9fe0af2a6f0 Ether
0xd1ad8c8340b8905d52d9a070a71cf326f9145ed66de525948937109649f89acd242053272021-04-09 18:06:442 days 1 hr ago 0x07acc2b253218535c21a3e57bcb81eb13345a34a 0x46824bfaafd049fb0af9a45159a88e595bbbb9f70 Ether
0xd1ad8c8340b8905d52d9a070a71cf326f9145ed66de525948937109649f89acd242053272021-04-09 18:06:442 days 1 hr ago 0x07acc2b253218535c21a3e57bcb81eb13345a34a 0x46824bfaafd049fb0af9a45159a88e595bbbb9f70 Ether
0xd1ad8c8340b8905d52d9a070a71cf326f9145ed66de525948937109649f89acd242053272021-04-09 18:06:442 days 1 hr ago 0x07acc2b253218535c21a3e57bcb81eb13345a34a 0x46824bfaafd049fb0af9a45159a88e595bbbb9f70 Ether
0xd1ad8c8340b8905d52d9a070a71cf326f9145ed66de525948937109649f89acd242053272021-04-09 18:06:442 days 1 hr ago 0x07acc2b253218535c21a3e57bcb81eb13345a34a 0x46824bfaafd049fb0af9a45159a88e595bbbb9f70 Ether
0xd1ad8c8340b8905d52d9a070a71cf326f9145ed66de525948937109649f89acd242053272021-04-09 18:06:442 days 1 hr ago 0x07acc2b253218535c21a3e57bcb81eb13345a34a 0xafcbc491b67c01b40f6c077ef53488876a0a0d6e0 Ether
0xd1ad8c8340b8905d52d9a070a71cf326f9145ed66de525948937109649f89acd242053272021-04-09 18:06:442 days 1 hr ago 0x07acc2b253218535c21a3e57bcb81eb13345a34a 0xcf8b3d452a56dab495df84905655047bc1dc41bc0 Ether
0xd1ad8c8340b8905d52d9a070a71cf326f9145ed66de525948937109649f89acd242053272021-04-09 18:06:442 days 1 hr ago 0xe8bf8fe5ce9e15d30f478e1647a57cb6b0271228 0x07acc2b253218535c21a3e57bcb81eb13345a34a0 Ether
0xec68cde33b61c672e0a740a88ea7c849856403b01a1d803a09bf775e25085f99242053042021-04-09 18:03:402 days 1 hr ago 0x07acc2b253218535c21a3e57bcb81eb13345a34a 0xc011a73ee8576fb46f5e1c5751ca3b9fe0af2a6f0 Ether
0xec68cde33b61c672e0a740a88ea7c849856403b01a1d803a09bf775e25085f99242053042021-04-09 18:03:402 days 1 hr ago 0x07acc2b253218535c21a3e57bcb81eb13345a34a 0x46824bfaafd049fb0af9a45159a88e595bbbb9f70 Ether
[ Download CSV Export 
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Synthetix

Compiler Version
v0.5.16+commit.9c3226ce

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2021-02-04
*/

/*

⚠⚠⚠ 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/kovan/ProxyERC20

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

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



pragma solidity >=0.4.24;


// https://docs.synthetix.io/contracts/source/interfaces/ierc20
interface IERC20 {
    // ERC20 Optional Views
    function name() external view returns (string memory);

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

    function decimals() external view returns (uint8);

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

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

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

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

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

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

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

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


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

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

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

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

    modifier onlyOwner {
        _onlyOwner();
        _;
    }

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

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


// Inheritance


// Internal references


// https://docs.synthetix.io/contracts/source/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/source/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 {
        _onlyProxy();
        _;
    }

    function _onlyProxy() private view {
        require(Proxy(msg.sender) == proxy || Proxy(msg.sender) == integrationProxy, "Only the proxy can call");
    }

    modifier optionalProxy {
        _optionalProxy();
        _;
    }

    function _optionalProxy() private {
        if (Proxy(msg.sender) != proxy && Proxy(msg.sender) != integrationProxy && messageSender != msg.sender) {
            messageSender = msg.sender;
        }
    }

    modifier optionalProxy_onlyOwner {
        _optionalProxy_onlyOwner();
        _;
    }

    // solhint-disable-next-line func-name-mixedcase
    function _optionalProxy_onlyOwner() private {
        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);
}


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

        return c;
    }

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

        return c;
    }

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

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

        return c;
    }

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

        return c;
    }

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


// Libraries


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

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

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

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

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

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

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

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

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

        return quotientTimesTen / 10;
    }

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

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

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

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

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

        return resultTimesTen / 10;
    }

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

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

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

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

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

        return quotientTimesTen / 10;
    }
}


// Inheritance


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

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

        associatedContract = _associatedContract;
        emit AssociatedContractUpdated(_associatedContract);
    }

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

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

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

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

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

    event AssociatedContractUpdated(address associatedContract);
}


// Inheritance


// https://docs.synthetix.io/contracts/source/contracts/tokenstate
contract TokenState is Owned, State {
    /* ERC20 fields. */
    mapping(address => uint) public balanceOf;
    mapping(address => mapping(address => uint)) public allowance;

    constructor(address _owner, address _associatedContract) public Owned(_owner) State(_associatedContract) {}

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

    /**
     * @notice Set ERC20 allowance.
     * @dev Only the associated contract may call this.
     * @param tokenOwner The authorising party.
     * @param spender The authorised party.
     * @param value The total value the authorised party may spend on the
     * authorising party's behalf.
     */
    function setAllowance(
        address tokenOwner,
        address spender,
        uint value
    ) external onlyAssociatedContract {
        allowance[tokenOwner][spender] = value;
    }

    /**
     * @notice Set the balance in a given account
     * @dev Only the associated contract may call this.
     * @param account The account whose value to set.
     * @param value The new balance of the given account.
     */
    function setBalanceOf(address account, uint value) external onlyAssociatedContract {
        balanceOf[account] = value;
    }
}


// Inheritance


// Libraries


// Internal references


// https://docs.synthetix.io/contracts/source/contracts/externstatetoken
contract ExternStateToken is Owned, Proxyable {
    using SafeMath for uint;
    using SafeDecimalMath for uint;

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

    /* Stores balances and allowances. */
    TokenState public tokenState;

    /* Other ERC20 fields. */
    string public name;
    string public symbol;
    uint public totalSupply;
    uint8 public decimals;

    constructor(
        address payable _proxy,
        TokenState _tokenState,
        string memory _name,
        string memory _symbol,
        uint _totalSupply,
        uint8 _decimals,
        address _owner
    ) public Owned(_owner) Proxyable(_proxy) {
        tokenState = _tokenState;

        name = _name;
        symbol = _symbol;
        totalSupply = _totalSupply;
        decimals = _decimals;
    }

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

    /**
     * @notice Returns the ERC20 allowance of one party to spend on behalf of another.
     * @param owner The party authorising spending of their funds.
     * @param spender The party spending tokenOwner's funds.
     */
    function allowance(address owner, address spender) public view returns (uint) {
        return tokenState.allowance(owner, spender);
    }

    /**
     * @notice Returns the ERC20 token balance of a given account.
     */
    function balanceOf(address account) external view returns (uint) {
        return tokenState.balanceOf(account);
    }

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

    /**
     * @notice Set the address of the TokenState contract.
     * @dev This can be used to "pause" transfer functionality, by pointing the tokenState at 0x000..
     * as balances would be unreachable.
     */
    function setTokenState(TokenState _tokenState) external optionalProxy_onlyOwner {
        tokenState = _tokenState;
        emitTokenStateUpdated(address(_tokenState));
    }

    function _internalTransfer(
        address from,
        address to,
        uint value
    ) internal returns (bool) {
        /* Disallow transfers to irretrievable-addresses. */
        require(to != address(0) && to != address(this) && to != address(proxy), "Cannot transfer to this address");

        // Insufficient balance will be handled by the safe subtraction.
        tokenState.setBalanceOf(from, tokenState.balanceOf(from).sub(value));
        tokenState.setBalanceOf(to, tokenState.balanceOf(to).add(value));

        // Emit a standard ERC20 transfer event
        emitTransfer(from, to, value);

        return true;
    }

    /**
     * @dev Perform an ERC20 token transfer. Designed to be called by transfer functions possessing
     * the onlyProxy or optionalProxy modifiers.
     */
    function _transferByProxy(
        address from,
        address to,
        uint value
    ) internal returns (bool) {
        return _internalTransfer(from, to, value);
    }

    /*
     * @dev Perform an ERC20 token transferFrom. Designed to be called by transferFrom functions
     * possessing the optionalProxy or optionalProxy modifiers.
     */
    function _transferFromByProxy(
        address sender,
        address from,
        address to,
        uint value
    ) internal returns (bool) {
        /* Insufficient allowance will be handled by the safe subtraction. */
        tokenState.setAllowance(from, sender, tokenState.allowance(from, sender).sub(value));
        return _internalTransfer(from, to, value);
    }

    /**
     * @notice Approves spender to transfer on the message sender's behalf.
     */
    function approve(address spender, uint value) public optionalProxy returns (bool) {
        address sender = messageSender;

        tokenState.setAllowance(sender, spender, value);
        emitApproval(sender, spender, value);
        return true;
    }

    /* ========== EVENTS ========== */
    function addressToBytes32(address input) internal pure returns (bytes32) {
        return bytes32(uint256(uint160(input)));
    }

    event Transfer(address indexed from, address indexed to, uint value);
    bytes32 internal constant TRANSFER_SIG = keccak256("Transfer(address,address,uint256)");

    function emitTransfer(
        address from,
        address to,
        uint value
    ) internal {
        proxy._emit(abi.encode(value), 3, TRANSFER_SIG, addressToBytes32(from), addressToBytes32(to), 0);
    }

    event Approval(address indexed owner, address indexed spender, uint value);
    bytes32 internal constant APPROVAL_SIG = keccak256("Approval(address,address,uint256)");

    function emitApproval(
        address owner,
        address spender,
        uint value
    ) internal {
        proxy._emit(abi.encode(value), 3, APPROVAL_SIG, addressToBytes32(owner), addressToBytes32(spender), 0);
    }

    event TokenStateUpdated(address newTokenState);
    bytes32 internal constant TOKENSTATEUPDATED_SIG = keccak256("TokenStateUpdated(address)");

    function emitTokenStateUpdated(address newTokenState) internal {
        proxy._emit(abi.encode(newTokenState), 1, TOKENSTATEUPDATED_SIG, 0, 0, 0);
    }
}


// https://docs.synthetix.io/contracts/source/interfaces/iaddressresolver
interface IAddressResolver {
    function getAddress(bytes32 name) external view returns (address);

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

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


// https://docs.synthetix.io/contracts/source/interfaces/isynth
interface ISynth {
    // Views
    function currencyKey() external view returns (bytes32);

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

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

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

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

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


// https://docs.synthetix.io/contracts/source/interfaces/iissuer
interface IIssuer {
    // Views
    function anySynthOrSNXRateIsInvalid() external view returns (bool anyRateInvalid);

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

    function availableSynthCount() external view returns (uint);

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

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

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

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

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

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

    function issuanceRatio() external view returns (uint);

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

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

    function minimumStakeTime() external view returns (uint);

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

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

    function getSynths(bytes32[] calldata currencyKeys) external view returns (ISynth[] memory);

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

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

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

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

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

    function issueMaxSynths(address from) external;

    function issueMaxSynthsOnBehalf(address issueFor, address from) external;

    function burnSynths(address from, uint amount) external;

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

    function burnSynthsToTarget(address from) external;

    function burnSynthsToTargetOnBehalf(address burnForAddress, address from) external;

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


// Inheritance


// Internal references


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

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

    /* ========== RESTRICTED FUNCTIONS ========== */

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

        for (uint i = 0; i < names.length; i++) {
            bytes32 name = names[i];
            address destination = destinations[i];
            repository[name] = destination;
            emit AddressImported(name, destination);
        }
    }

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

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

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

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

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

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

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

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

    event AddressImported(bytes32 name, address destination);
}


// solhint-disable payable-fallback

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

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

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

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

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

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

    event TargetUpdated(address newTarget);
}


// Inheritance


// Internal references


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

    mapping(bytes32 => address) private addressCache;

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

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

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

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

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

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

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

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

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

    function isResolverCached() external view returns (bool) {
        bytes32[] memory requiredAddresses = resolverAddressesRequired();
        for (uint i = 0; i < requiredAddresses.length; i++) {
            bytes32 name = requiredAddresses[i];
            // false if our cache is invalid or if the resolver doesn't have the required address
            if (resolver.getAddress(name) != addressCache[name] || addressCache[name] == address(0)) {
                return false;
            }
        }

        return true;
    }

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

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

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

    event CacheUpdated(bytes32 name, address destination);
}


interface IVirtualSynth {
    // Views
    function balanceOfUnderlying(address account) external view returns (uint);

    function rate() external view returns (uint);

    function readyToSettle() external view returns (bool);

    function secsLeftInWaitingPeriod() external view returns (uint);

    function settled() external view returns (bool);

    function synth() external view returns (ISynth);

    // Mutative functions
    function settle(address account) external;
}


// https://docs.synthetix.io/contracts/source/interfaces/isynthetix
interface ISynthetix {
    // Views
    function anySynthOrSNXRateIsInvalid() external view returns (bool anyRateInvalid);

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

    function availableSynthCount() external view returns (uint);

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

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

    // 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 exchangeWithTracking(
        bytes32 sourceCurrencyKey,
        uint sourceAmount,
        bytes32 destinationCurrencyKey,
        address originator,
        bytes32 trackingCode
    ) external returns (uint amountReceived);

    function exchangeOnBehalfWithTracking(
        address exchangeForAddress,
        bytes32 sourceCurrencyKey,
        uint sourceAmount,
        bytes32 destinationCurrencyKey,
        address originator,
        bytes32 trackingCode
    ) external returns (uint amountReceived);

    function exchangeWithVirtual(
        bytes32 sourceCurrencyKey,
        uint sourceAmount,
        bytes32 destinationCurrencyKey,
        bytes32 trackingCode
    ) external returns (uint amountReceived, IVirtualSynth vSynth);

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

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

    // Restricted Functions

    function mintSecondary(address account, uint amount) external;

    function mintSecondaryRewards(uint amount) external;

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


// https://docs.synthetix.io/contracts/source/interfaces/isynthetixstate
interface ISynthetixState {
    // Views
    function debtLedger(uint index) 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;
}


// https://docs.synthetix.io/contracts/source/interfaces/isystemstatus
interface ISystemStatus {
    struct Status {
        bool canSuspend;
        bool canResume;
    }

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

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

    function requireSystemActive() external view;

    function requireIssuanceActive() external view;

    function requireExchangeActive() external view;

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

    function requireSynthActive(bytes32 currencyKey) external view;

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

    function systemSuspension() external view returns (bool suspended, uint248 reason);

    function issuanceSuspension() external view returns (bool suspended, uint248 reason);

    function exchangeSuspension() external view returns (bool suspended, uint248 reason);

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

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

    function getSynthExchangeSuspensions(bytes32[] calldata synths)
        external
        view
        returns (bool[] memory exchangeSuspensions, uint256[] memory reasons);

    function getSynthSuspensions(bytes32[] calldata synths)
        external
        view
        returns (bool[] memory suspensions, uint256[] memory reasons);

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

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


// https://docs.synthetix.io/contracts/source/interfaces/iexchanger
interface IExchanger {
    // Views
    function calculateAmountAfterSettlement(
        address from,
        bytes32 currencyKey,
        uint amount,
        uint refunded
    ) external view returns (uint amountAfterSettlement);

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

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

    function priceDeviationThresholdFactor() external view returns (uint);

    function waitingPeriodSecs() external view returns (uint);

    // 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 exchangeWithTracking(
        address from,
        bytes32 sourceCurrencyKey,
        uint sourceAmount,
        bytes32 destinationCurrencyKey,
        address destinationAddress,
        address originator,
        bytes32 trackingCode
    ) external returns (uint amountReceived);

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

    function exchangeWithVirtual(
        address from,
        bytes32 sourceCurrencyKey,
        uint sourceAmount,
        bytes32 destinationCurrencyKey,
        address destinationAddress,
        bytes32 trackingCode
    ) external returns (uint amountReceived, IVirtualSynth vSynth);

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

    function setLastExchangeRateForSynth(bytes32 currencyKey, uint rate) external;

    function suspendSynthWithInvalidRate(bytes32 currencyKey) external;
}


// https://docs.synthetix.io/contracts/source/interfaces/irewardsdistribution
interface IRewardsDistribution {
    // Structs
    struct DistributionData {
        address destination;
        uint amount;
    }

    // Views
    function authority() external view returns (address);

    function distributions(uint index) external view returns (address destination, uint amount); // DistributionData

    function distributionsLength() external view returns (uint);

    // Mutative Functions
    function distributeRewards(uint amount) external returns (bool);
}


// Inheritance


// Internal references


contract BaseSynthetix is IERC20, ExternStateToken, MixinResolver, ISynthetix {
    // ========== STATE VARIABLES ==========

    // Available Synths which can be used with the system
    string public constant TOKEN_NAME = "Synthetix Network Token";
    string public constant TOKEN_SYMBOL = "SNX";
    uint8 public constant DECIMALS = 18;
    bytes32 public constant sUSD = "sUSD";

    // ========== ADDRESS RESOLVER CONFIGURATION ==========
    bytes32 private constant CONTRACT_SYNTHETIXSTATE = "SynthetixState";
    bytes32 private constant CONTRACT_SYSTEMSTATUS = "SystemStatus";
    bytes32 private constant CONTRACT_EXCHANGER = "Exchanger";
    bytes32 private constant CONTRACT_ISSUER = "Issuer";
    bytes32 private constant CONTRACT_REWARDSDISTRIBUTION = "RewardsDistribution";

    // ========== CONSTRUCTOR ==========

    constructor(
        address payable _proxy,
        TokenState _tokenState,
        address _owner,
        uint _totalSupply,
        address _resolver
    )
        public
        ExternStateToken(_proxy, _tokenState, TOKEN_NAME, TOKEN_SYMBOL, _totalSupply, DECIMALS, _owner)
        MixinResolver(_resolver)
    {}

    // ========== VIEWS ==========

    // Note: use public visibility so that it can be invoked in a subclass
    function resolverAddressesRequired() public view returns (bytes32[] memory addresses) {
        addresses = new bytes32[](5);
        addresses[0] = CONTRACT_SYNTHETIXSTATE;
        addresses[1] = CONTRACT_SYSTEMSTATUS;
        addresses[2] = CONTRACT_EXCHANGER;
        addresses[3] = CONTRACT_ISSUER;
        addresses[4] = CONTRACT_REWARDSDISTRIBUTION;
    }

    function synthetixState() internal view returns (ISynthetixState) {
        return ISynthetixState(requireAndGetAddress(CONTRACT_SYNTHETIXSTATE));
    }

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

    function exchanger() internal view returns (IExchanger) {
        return IExchanger(requireAndGetAddress(CONTRACT_EXCHANGER));
    }

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

    function rewardsDistribution() internal view returns (IRewardsDistribution) {
        return IRewardsDistribution(requireAndGetAddress(CONTRACT_REWARDSDISTRIBUTION));
    }

    function debtBalanceOf(address account, bytes32 currencyKey) external view returns (uint) {
        return issuer().debtBalanceOf(account, currencyKey);
    }

    function totalIssuedSynths(bytes32 currencyKey) external view returns (uint) {
        return issuer().totalIssuedSynths(currencyKey, false);
    }

    function totalIssuedSynthsExcludeEtherCollateral(bytes32 currencyKey) external view returns (uint) {
        return issuer().totalIssuedSynths(currencyKey, true);
    }

    function availableCurrencyKeys() external view returns (bytes32[] memory) {
        return issuer().availableCurrencyKeys();
    }

    function availableSynthCount() external view returns (uint) {
        return issuer().availableSynthCount();
    }

    function availableSynths(uint index) external view returns (ISynth) {
        return issuer().availableSynths(index);
    }

    function synths(bytes32 currencyKey) external view returns (ISynth) {
        return issuer().synths(currencyKey);
    }

    function synthsByAddress(address synthAddress) external view returns (bytes32) {
        return issuer().synthsByAddress(synthAddress);
    }

    function isWaitingPeriod(bytes32 currencyKey) external view returns (bool) {
        return exchanger().maxSecsLeftInWaitingPeriod(messageSender, currencyKey) > 0;
    }

    function anySynthOrSNXRateIsInvalid() external view returns (bool anyRateInvalid) {
        return issuer().anySynthOrSNXRateIsInvalid();
    }

    function maxIssuableSynths(address account) external view returns (uint maxIssuable) {
        return issuer().maxIssuableSynths(account);
    }

    function remainingIssuableSynths(address account)
        external
        view
        returns (
            uint maxIssuable,
            uint alreadyIssued,
            uint totalSystemDebt
        )
    {
        return issuer().remainingIssuableSynths(account);
    }

    function collateralisationRatio(address _issuer) external view returns (uint) {
        return issuer().collateralisationRatio(_issuer);
    }

    function collateral(address account) external view returns (uint) {
        return issuer().collateral(account);
    }

    function transferableSynthetix(address account) external view returns (uint transferable) {
        (transferable, ) = issuer().transferableSynthetixAndAnyRateIsInvalid(account, tokenState.balanceOf(account));
    }

    function _canTransfer(address account, uint value) internal view returns (bool) {
        (uint initialDebtOwnership, ) = synthetixState().issuanceData(account);

        if (initialDebtOwnership > 0) {
            (uint transferable, bool anyRateIsInvalid) = issuer().transferableSynthetixAndAnyRateIsInvalid(
                account,
                tokenState.balanceOf(account)
            );
            require(value <= transferable, "Cannot transfer staked or escrowed SNX");
            require(!anyRateIsInvalid, "A synth or SNX rate is invalid");
        }
        return true;
    }

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

    function transfer(address to, uint value) external optionalProxy systemActive returns (bool) {
        // Ensure they're not trying to exceed their locked amount -- only if they have debt.
        _canTransfer(messageSender, value);

        // Perform the transfer: if there is a problem an exception will be thrown in this call.
        _transferByProxy(messageSender, to, value);

        return true;
    }

    function transferFrom(
        address from,
        address to,
        uint value
    ) external optionalProxy systemActive returns (bool) {
        // Ensure they're not trying to exceed their locked amount -- only if they have debt.
        _canTransfer(from, value);

        // Perform the transfer: if there is a problem,
        // an exception will be thrown in this call.
        return _transferFromByProxy(messageSender, from, to, value);
    }

    function issueSynths(uint amount) external issuanceActive optionalProxy {
        return issuer().issueSynths(messageSender, amount);
    }

    function issueSynthsOnBehalf(address issueForAddress, uint amount) external issuanceActive optionalProxy {
        return issuer().issueSynthsOnBehalf(issueForAddress, messageSender, amount);
    }

    function issueMaxSynths() external issuanceActive optionalProxy {
        return issuer().issueMaxSynths(messageSender);
    }

    function issueMaxSynthsOnBehalf(address issueForAddress) external issuanceActive optionalProxy {
        return issuer().issueMaxSynthsOnBehalf(issueForAddress, messageSender);
    }

    function burnSynths(uint amount) external issuanceActive optionalProxy {
        return issuer().burnSynths(messageSender, amount);
    }

    function burnSynthsOnBehalf(address burnForAddress, uint amount) external issuanceActive optionalProxy {
        return issuer().burnSynthsOnBehalf(burnForAddress, messageSender, amount);
    }

    function burnSynthsToTarget() external issuanceActive optionalProxy {
        return issuer().burnSynthsToTarget(messageSender);
    }

    function burnSynthsToTargetOnBehalf(address burnForAddress) external issuanceActive optionalProxy {
        return issuer().burnSynthsToTargetOnBehalf(burnForAddress, messageSender);
    }

    function exchange(
        bytes32,
        uint,
        bytes32
    ) external returns (uint) {
        _notImplemented();
    }

    function exchangeOnBehalf(
        address,
        bytes32,
        uint,
        bytes32
    ) external returns (uint) {
        _notImplemented();
    }

    function exchangeWithTracking(
        bytes32,
        uint,
        bytes32,
        address,
        bytes32
    ) external returns (uint) {
        _notImplemented();
    }

    function exchangeOnBehalfWithTracking(
        address,
        bytes32,
        uint,
        bytes32,
        address,
        bytes32
    ) external returns (uint) {
        _notImplemented();
    }

    function exchangeWithVirtual(
        bytes32,
        uint,
        bytes32,
        bytes32
    ) external returns (uint, IVirtualSynth) {
        _notImplemented();
    }

    function settle(bytes32)
        external
        returns (
            uint,
            uint,
            uint
        )
    {
        _notImplemented();
    }

    function mint() external returns (bool) {
        _notImplemented();
    }

    function liquidateDelinquentAccount(address, uint) external returns (bool) {
        _notImplemented();
    }

    function mintSecondary(address, uint) external {
        _notImplemented();
    }

    function mintSecondaryRewards(uint) external {
        _notImplemented();
    }

    function burnSecondary(address, uint) external {
        _notImplemented();
    }

    function _notImplemented() internal pure {
        revert("Cannot be run on this layer");
    }

    // ========== MODIFIERS ==========

    modifier systemActive() {
        _systemActive();
        _;
    }

    function _systemActive() private {
        systemStatus().requireSystemActive();
    }

    modifier issuanceActive() {
        _issuanceActive();
        _;
    }

    function _issuanceActive() private {
        systemStatus().requireIssuanceActive();
    }
}


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

    function getVestingScheduleEntry(address account, uint index) external view returns (uint[2] memory);

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

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

    function vest() external;
}


pragma experimental ABIEncoderV2;


library VestingEntries {
    struct VestingEntry {
        uint64 endTime;
        uint256 escrowAmount;
    }
    struct VestingEntryWithID {
        uint64 endTime;
        uint256 escrowAmount;
        uint256 entryID;
    }
}


interface IRewardEscrowV2 {
    // 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);

    function getVestingQuantity(address account, uint256[] calldata entryIDs) external view returns (uint);

    function getVestingSchedules(
        address account,
        uint256 index,
        uint256 pageSize
    ) external view returns (VestingEntries.VestingEntryWithID[] memory);

    function getAccountVestingEntryIDs(
        address account,
        uint256 index,
        uint256 pageSize
    ) external view returns (uint256[] memory);

    function getVestingEntryClaimable(address account, uint256 entryID) external view returns (uint);

    function getVestingEntry(address account, uint256 entryID) external view returns (uint64, uint256);

    // Mutative functions
    function vest(uint256[] calldata entryIDs) external;

    function createEscrowEntry(
        address beneficiary,
        uint256 deposit,
        uint256 duration
    ) external;

    function appendVestingEntry(
        address account,
        uint256 quantity,
        uint256 duration
    ) external;

    function migrateVestingSchedule(address _addressToMigrate) external;

    function migrateAccountEscrowBalances(
        address[] calldata accounts,
        uint256[] calldata escrowBalances,
        uint256[] calldata vestedBalances
    ) external;

    // Account Merging
    function startMergingWindow() external;

    function mergeAccount(address accountToMerge, uint256[] calldata entryIDs) external;

    function nominateAccountToMerge(address account) external;

    function accountMergingIsOpen() external view returns (bool);

    // L2 Migration
    function importVestingEntries(
        address account,
        uint256 escrowedAmount,
        VestingEntries.VestingEntry[] calldata vestingEntries
    ) external;

    // Return amount of SNX transfered to SynthetixBridgeToOptimism deposit contract
    function burnForMigration(address account, uint256[] calldata entryIDs)
        external
        returns (uint256 escrowedAccountBalance, VestingEntries.VestingEntry[] memory vestingEntries);
}


// https://docs.synthetix.io/contracts/source/interfaces/isupplyschedule
interface ISupplySchedule {
    // Views
    function mintableSupply() external view returns (uint);

    function isMintable() external view returns (bool);

    function minterReward() external view returns (uint);

    // Mutative functions
    function recordMintEvent(uint supplyMinted) external returns (bool);
}


// Inheritance


// Internal references


// https://docs.synthetix.io/contracts/source/contracts/synthetix
contract Synthetix is BaseSynthetix {
    // ========== ADDRESS RESOLVER CONFIGURATION ==========
    bytes32 private constant CONTRACT_REWARD_ESCROW = "RewardEscrow";
    bytes32 private constant CONTRACT_REWARDESCROW_V2 = "RewardEscrowV2";
    bytes32 private constant CONTRACT_SUPPLYSCHEDULE = "SupplySchedule";

    // ========== CONSTRUCTOR ==========

    constructor(
        address payable _proxy,
        TokenState _tokenState,
        address _owner,
        uint _totalSupply,
        address _resolver
    ) public BaseSynthetix(_proxy, _tokenState, _owner, _totalSupply, _resolver) {}

    function resolverAddressesRequired() public view returns (bytes32[] memory addresses) {
        bytes32[] memory existingAddresses = BaseSynthetix.resolverAddressesRequired();
        bytes32[] memory newAddresses = new bytes32[](3);
        newAddresses[0] = CONTRACT_REWARD_ESCROW;
        newAddresses[1] = CONTRACT_REWARDESCROW_V2;
        newAddresses[2] = CONTRACT_SUPPLYSCHEDULE;
        return combineArrays(existingAddresses, newAddresses);
    }

    // ========== VIEWS ==========

    function rewardEscrow() internal view returns (IRewardEscrow) {
        return IRewardEscrow(requireAndGetAddress(CONTRACT_REWARD_ESCROW));
    }

    function rewardEscrowV2() internal view returns (IRewardEscrowV2) {
        return IRewardEscrowV2(requireAndGetAddress(CONTRACT_REWARDESCROW_V2));
    }

    function supplySchedule() internal view returns (ISupplySchedule) {
        return ISupplySchedule(requireAndGetAddress(CONTRACT_SUPPLYSCHEDULE));
    }

    // ========== OVERRIDDEN FUNCTIONS ==========

    function exchange(
        bytes32 sourceCurrencyKey,
        uint sourceAmount,
        bytes32 destinationCurrencyKey
    ) external exchangeActive(sourceCurrencyKey, destinationCurrencyKey) optionalProxy returns (uint amountReceived) {
        return exchanger().exchange(messageSender, sourceCurrencyKey, sourceAmount, destinationCurrencyKey, messageSender);
    }

    function exchangeOnBehalf(
        address exchangeForAddress,
        bytes32 sourceCurrencyKey,
        uint sourceAmount,
        bytes32 destinationCurrencyKey
    ) external exchangeActive(sourceCurrencyKey, destinationCurrencyKey) optionalProxy returns (uint amountReceived) {
        return
            exchanger().exchangeOnBehalf(
                exchangeForAddress,
                messageSender,
                sourceCurrencyKey,
                sourceAmount,
                destinationCurrencyKey
            );
    }

    function exchangeWithTracking(
        bytes32 sourceCurrencyKey,
        uint sourceAmount,
        bytes32 destinationCurrencyKey,
        address originator,
        bytes32 trackingCode
    ) external exchangeActive(sourceCurrencyKey, destinationCurrencyKey) optionalProxy returns (uint amountReceived) {
        return
            exchanger().exchangeWithTracking(
                messageSender,
                sourceCurrencyKey,
                sourceAmount,
                destinationCurrencyKey,
                messageSender,
                originator,
                trackingCode
            );
    }

    function exchangeOnBehalfWithTracking(
        address exchangeForAddress,
        bytes32 sourceCurrencyKey,
        uint sourceAmount,
        bytes32 destinationCurrencyKey,
        address originator,
        bytes32 trackingCode
    ) external exchangeActive(sourceCurrencyKey, destinationCurrencyKey) optionalProxy returns (uint amountReceived) {
        return
            exchanger().exchangeOnBehalfWithTracking(
                exchangeForAddress,
                messageSender,
                sourceCurrencyKey,
                sourceAmount,
                destinationCurrencyKey,
                originator,
                trackingCode
            );
    }

    function exchangeWithVirtual(
        bytes32 sourceCurrencyKey,
        uint sourceAmount,
        bytes32 destinationCurrencyKey,
        bytes32 trackingCode
    )
        external
        exchangeActive(sourceCurrencyKey, destinationCurrencyKey)
        optionalProxy
        returns (uint amountReceived, IVirtualSynth vSynth)
    {
        return
            exchanger().exchangeWithVirtual(
                messageSender,
                sourceCurrencyKey,
                sourceAmount,
                destinationCurrencyKey,
                messageSender,
                trackingCode
            );
    }

    function settle(bytes32 currencyKey)
        external
        optionalProxy
        returns (
            uint reclaimed,
            uint refunded,
            uint numEntriesSettled
        )
    {
        return exchanger().settle(messageSender, currencyKey);
    }

    function mint() external issuanceActive returns (bool) {
        require(address(rewardsDistribution()) != address(0), "RewardsDistribution not set");

        ISupplySchedule _supplySchedule = supplySchedule();
        IRewardsDistribution _rewardsDistribution = rewardsDistribution();

        uint supplyToMint = _supplySchedule.mintableSupply();
        require(supplyToMint > 0, "No supply is mintable");

        // record minting event before mutation to token supply
        _supplySchedule.recordMintEvent(supplyToMint);

        // Set minted SNX balance to RewardEscrow's balance
        // Minus the minterReward and set balance of minter to add reward
        uint minterReward = _supplySchedule.minterReward();
        // Get the remainder
        uint amountToDistribute = supplyToMint.sub(minterReward);

        // Set the token balance to the RewardsDistribution contract
        tokenState.setBalanceOf(
            address(_rewardsDistribution),
            tokenState.balanceOf(address(_rewardsDistribution)).add(amountToDistribute)
        );
        emitTransfer(address(this), address(_rewardsDistribution), amountToDistribute);

        // Kick off the distribution of rewards
        _rewardsDistribution.distributeRewards(amountToDistribute);

        // Assign the minters reward.
        tokenState.setBalanceOf(msg.sender, tokenState.balanceOf(msg.sender).add(minterReward));
        emitTransfer(address(this), msg.sender, minterReward);

        totalSupply = totalSupply.add(supplyToMint);

        return true;
    }

    function liquidateDelinquentAccount(address account, uint susdAmount)
        external
        systemActive
        optionalProxy
        returns (bool)
    {
        (uint totalRedeemed, uint amountLiquidated) = issuer().liquidateDelinquentAccount(
            account,
            susdAmount,
            messageSender
        );

        emitAccountLiquidated(account, totalRedeemed, amountLiquidated, messageSender);

        // Transfer SNX redeemed to messageSender
        // Reverts if amount to redeem is more than balanceOf account, ie due to escrowed balance
        return _transferByProxy(account, messageSender, totalRedeemed);
    }

    /* Once off function for SIP-60 to migrate SNX balances in the RewardEscrow contract
     * To the new RewardEscrowV2 contract
     */
    function migrateEscrowBalanceToRewardEscrowV2() external onlyOwner {
        // Record balanceOf(RewardEscrow) contract
        uint rewardEscrowBalance = tokenState.balanceOf(address(rewardEscrow()));

        // transfer all of RewardEscrow's balance to RewardEscrowV2
        // _internalTransfer emits the transfer event
        _internalTransfer(address(rewardEscrow()), address(rewardEscrowV2()), rewardEscrowBalance);
    }

    // ========== EVENTS ==========
    event SynthExchange(
        address indexed account,
        bytes32 fromCurrencyKey,
        uint256 fromAmount,
        bytes32 toCurrencyKey,
        uint256 toAmount,
        address toAddress
    );
    bytes32 internal constant SYNTHEXCHANGE_SIG = keccak256(
        "SynthExchange(address,bytes32,uint256,bytes32,uint256,address)"
    );

    function emitSynthExchange(
        address account,
        bytes32 fromCurrencyKey,
        uint256 fromAmount,
        bytes32 toCurrencyKey,
        uint256 toAmount,
        address toAddress
    ) external onlyExchanger {
        proxy._emit(
            abi.encode(fromCurrencyKey, fromAmount, toCurrencyKey, toAmount, toAddress),
            2,
            SYNTHEXCHANGE_SIG,
            addressToBytes32(account),
            0,
            0
        );
    }

    event ExchangeTracking(bytes32 indexed trackingCode, bytes32 toCurrencyKey, uint256 toAmount);
    bytes32 internal constant EXCHANGE_TRACKING_SIG = keccak256("ExchangeTracking(bytes32,bytes32,uint256)");

    function emitExchangeTracking(
        bytes32 trackingCode,
        bytes32 toCurrencyKey,
        uint256 toAmount
    ) external onlyExchanger {
        proxy._emit(abi.encode(toCurrencyKey, toAmount), 2, EXCHANGE_TRACKING_SIG, trackingCode, 0, 0);
    }

    event ExchangeReclaim(address indexed account, bytes32 currencyKey, uint amount);
    bytes32 internal constant EXCHANGERECLAIM_SIG = keccak256("ExchangeReclaim(address,bytes32,uint256)");

    function emitExchangeReclaim(
        address account,
        bytes32 currencyKey,
        uint256 amount
    ) external onlyExchanger {
        proxy._emit(abi.encode(currencyKey, amount), 2, EXCHANGERECLAIM_SIG, addressToBytes32(account), 0, 0);
    }

    event ExchangeRebate(address indexed account, bytes32 currencyKey, uint amount);
    bytes32 internal constant EXCHANGEREBATE_SIG = keccak256("ExchangeRebate(address,bytes32,uint256)");

    function emitExchangeRebate(
        address account,
        bytes32 currencyKey,
        uint256 amount
    ) external onlyExchanger {
        proxy._emit(abi.encode(currencyKey, amount), 2, EXCHANGEREBATE_SIG, addressToBytes32(account), 0, 0);
    }

    event AccountLiquidated(address indexed account, uint snxRedeemed, uint amountLiquidated, address liquidator);
    bytes32 internal constant ACCOUNTLIQUIDATED_SIG = keccak256("AccountLiquidated(address,uint256,uint256,address)");

    function emitAccountLiquidated(
        address account,
        uint256 snxRedeemed,
        uint256 amountLiquidated,
        address liquidator
    ) internal {
        proxy._emit(
            abi.encode(snxRedeemed, amountLiquidated, liquidator),
            2,
            ACCOUNTLIQUIDATED_SIG,
            addressToBytes32(account),
            0,
            0
        );
    }

    // ========== MODIFIERS ==========

    modifier onlyExchanger() {
        _onlyExchanger();
        _;
    }

    function _onlyExchanger() private {
        require(msg.sender == address(exchanger()), "Only Exchanger can invoke this");
    }

    modifier exchangeActive(bytes32 src, bytes32 dest) {
        _exchangeActive(src, dest);
        _;
    }

    function _exchangeActive(bytes32 src, bytes32 dest) private {
        systemStatus().requireExchangeBetweenSynthsAllowed(src, dest);
    }
}

Contract ABI

[{"inputs":[{"internalType":"address payable","name":"_proxy","type":"address"},{"internalType":"contract TokenState","name":"_tokenState","type":"address"},{"internalType":"address","name":"_owner","type":"address"},{"internalType":"uint256","name":"_totalSupply","type":"uint256"},{"internalType":"address","name":"_resolver","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"snxRedeemed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountLiquidated","type":"uint256"},{"indexed":false,"internalType":"address","name":"liquidator","type":"address"}],"name":"AccountLiquidated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"name","type":"bytes32"},{"indexed":false,"internalType":"address","name":"destination","type":"address"}],"name":"CacheUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"bytes32","name":"currencyKey","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ExchangeRebate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"bytes32","name":"currencyKey","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ExchangeReclaim","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"trackingCode","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"toCurrencyKey","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"toAmount","type":"uint256"}],"name":"ExchangeTracking","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":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"bytes32","name":"fromCurrencyKey","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"fromAmount","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"toCurrencyKey","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"toAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"toAddress","type":"address"}],"name":"SynthExchange","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newTokenState","type":"address"}],"name":"TokenStateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"constant":true,"inputs":[],"name":"DECIMALS","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"TOKEN_NAME","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"TOKEN_SYMBOL","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"acceptOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"anySynthOrSNXRateIsInvalid","outputs":[{"internalType":"bool","name":"anyRateInvalid","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"availableCurrencyKeys","outputs":[{"internalType":"bytes32[]","name":"","type":"bytes32[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"availableSynthCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"availableSynths","outputs":[{"internalType":"contract ISynth","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"burnSecondary","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burnSynths","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"burnForAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burnSynthsOnBehalf","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"burnSynthsToTarget","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"burnForAddress","type":"address"}],"name":"burnSynthsToTargetOnBehalf","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"collateral","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_issuer","type":"address"}],"name":"collateralisationRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"currencyKey","type":"bytes32"}],"name":"debtBalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"currencyKey","type":"bytes32"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"emitExchangeRebate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"currencyKey","type":"bytes32"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"emitExchangeReclaim","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"trackingCode","type":"bytes32"},{"internalType":"bytes32","name":"toCurrencyKey","type":"bytes32"},{"internalType":"uint256","name":"toAmount","type":"uint256"}],"name":"emitExchangeTracking","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"fromCurrencyKey","type":"bytes32"},{"internalType":"uint256","name":"fromAmount","type":"uint256"},{"internalType":"bytes32","name":"toCurrencyKey","type":"bytes32"},{"internalType":"uint256","name":"toAmount","type":"uint256"},{"internalType":"address","name":"toAddress","type":"address"}],"name":"emitSynthExchange","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"sourceCurrencyKey","type":"bytes32"},{"internalType":"uint256","name":"sourceAmount","type":"uint256"},{"internalType":"bytes32","name":"destinationCurrencyKey","type":"bytes32"}],"name":"exchange","outputs":[{"internalType":"uint256","name":"amountReceived","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"exchangeForAddress","type":"address"},{"internalType":"bytes32","name":"sourceCurrencyKey","type":"bytes32"},{"internalType":"uint256","name":"sourceAmount","type":"uint256"},{"internalType":"bytes32","name":"destinationCurrencyKey","type":"bytes32"}],"name":"exchangeOnBehalf","outputs":[{"internalType":"uint256","name":"amountReceived","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"exchangeForAddress","type":"address"},{"internalType":"bytes32","name":"sourceCurrencyKey","type":"bytes32"},{"internalType":"uint256","name":"sourceAmount","type":"uint256"},{"internalType":"bytes32","name":"destinationCurrencyKey","type":"bytes32"},{"internalType":"address","name":"originator","type":"address"},{"internalType":"bytes32","name":"trackingCode","type":"bytes32"}],"name":"exchangeOnBehalfWithTracking","outputs":[{"internalType":"uint256","name":"amountReceived","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"sourceCurrencyKey","type":"bytes32"},{"internalType":"uint256","name":"sourceAmount","type":"uint256"},{"internalType":"bytes32","name":"destinationCurrencyKey","type":"bytes32"},{"internalType":"address","name":"originator","type":"address"},{"internalType":"bytes32","name":"trackingCode","type":"bytes32"}],"name":"exchangeWithTracking","outputs":[{"internalType":"uint256","name":"amountReceived","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"sourceCurrencyKey","type":"bytes32"},{"internalType":"uint256","name":"sourceAmount","type":"uint256"},{"internalType":"bytes32","name":"destinationCurrencyKey","type":"bytes32"},{"internalType":"bytes32","name":"trackingCode","type":"bytes32"}],"name":"exchangeWithVirtual","outputs":[{"internalType":"uint256","name":"amountReceived","type":"uint256"},{"internalType":"contract IVirtualSynth","name":"vSynth","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"integrationProxy","outputs":[{"internalType":"contract Proxy","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isResolverCached","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"currencyKey","type":"bytes32"}],"name":"isWaitingPeriod","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"issueMaxSynths","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"issueForAddress","type":"address"}],"name":"issueMaxSynthsOnBehalf","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"issueSynths","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"issueForAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"issueSynthsOnBehalf","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"susdAmount","type":"uint256"}],"name":"liquidateDelinquentAccount","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"maxIssuableSynths","outputs":[{"internalType":"uint256","name":"maxIssuable","type":"uint256"}],"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":[],"name":"migrateEscrowBalanceToRewardEscrowV2","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"mint","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"mintSecondary","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"mintSecondaryRewards","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"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":false,"inputs":[],"name":"rebuildCache","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"remainingIssuableSynths","outputs":[{"internalType":"uint256","name":"maxIssuable","type":"uint256"},{"internalType":"uint256","name":"alreadyIssued","type":"uint256"},{"internalType":"uint256","name":"totalSystemDebt","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"resolver","outputs":[{"internalType":"contract AddressResolver","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"resolverAddressesRequired","outputs":[{"internalType":"bytes32[]","name":"addresses","type":"bytes32[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"sUSD","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","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 TokenState","name":"_tokenState","type":"address"}],"name":"setTokenState","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"currencyKey","type":"bytes32"}],"name":"settle","outputs":[{"internalType":"uint256","name":"reclaimed","type":"uint256"},{"internalType":"uint256","name":"refunded","type":"uint256"},{"internalType":"uint256","name":"numEntriesSettled","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"currencyKey","type":"bytes32"}],"name":"synths","outputs":[{"internalType":"contract ISynth","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"synthAddress","type":"address"}],"name":"synthsByAddress","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"tokenState","outputs":[{"internalType":"contract TokenState","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"currencyKey","type":"bytes32"}],"name":"totalIssuedSynths","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"currencyKey","type":"bytes32"}],"name":"totalIssuedSynthsExcludeEtherCollateral","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"transferableSynthetix","outputs":[{"internalType":"uint256","name":"transferable","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}]

60806040523480156200001157600080fd5b5060405162004a4638038062004a46833981016040819052620000349162000315565b84848484848085856040518060400160405280601781526020017f53796e746865746978204e6574776f726b20546f6b656e000000000000000000815250604051806040016040528060038152602001620a69cb60eb1b81525086601289868160006001600160a01b0316816001600160a01b03161415620000d35760405162461bcd60e51b8152600401620000ca9062000463565b60405180910390fd5b600080546001600160a01b0319166001600160a01b0383161781556040517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c91620001209184906200042b565b60405180910390a1506000546001600160a01b0316620001545760405162461bcd60e51b8152600401620000ca9062000451565b600280546001600160a01b0319166001600160a01b0383161790556040517ffc80377ca9c49cc11ae6982f390a42db976d5530af7c43889264b13fbbd7c57e90620001a19083906200041b565b60405180910390a150600580546001600160a01b0319166001600160a01b0388161790558451620001da90600690602088019062000243565b508351620001f090600790602087019062000243565b50506008919091556009805460ff191660ff90921691909117610100600160a81b0319166101006001600160a01b0397909716969096029590951790945550620004e19c50505050505050505050505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200028657805160ff1916838001178555620002b6565b82800160010185558215620002b6579182015b82811115620002b657825182559160200191906001019062000299565b50620002c4929150620002c8565b5090565b620002e591905b80821115620002c45760008155600101620002cf565b90565b8051620002f581620004b1565b92915050565b8051620002f581620004cb565b8051620002f581620004d6565b600080600080600060a086880312156200032e57600080fd5b60006200033c8888620002e8565b95505060206200034f88828901620002fb565b94505060406200036288828901620002e8565b9350506060620003758882890162000308565b92505060806200038888828901620002e8565b9150509295509295909350565b620003a081620004a4565b82525050565b620003a0816200047e565b6000620003c060118362000475565b7013dddb995c881b5d5cdd081899481cd95d607a1b815260200192915050565b6000620003ef60198362000475565b7f4f776e657220616464726573732063616e6e6f74206265203000000000000000815260200192915050565b60208101620002f5828462000395565b604081016200043b828562000395565b6200044a6020830184620003a6565b9392505050565b60208082528101620002f581620003b1565b60208082528101620002f581620003e0565b90815260200190565b6000620002f58262000498565b6000620002f5826200047e565b6001600160a01b031690565b6000620002f5826200048b565b620004bc816200047e565b8114620004c857600080fd5b50565b620004bc816200048b565b620004bc81620002e5565b61455580620004f16000396000f3fe608060405234801561001057600080fd5b50600436106103fc5760003560e01c8063835e119c11610215578063af086c7e11610125578063dbf63340116100b8578063e8e09b8b11610087578063e8e09b8b14610829578063e90dd9e21461083c578063ec55688914610844578063edef719a146105d9578063ee52a2f31461084c576103fc565b8063dbf63340146107e8578063dd62ed3e146107f0578063ddd03a3f14610803578063e6203ed114610816576103fc565b8063d37c4d8b116100f4578063d37c4d8b146107a7578063d60888e4146107ba578063d67bdd25146107cd578063d8a1f76f146107d5576103fc565b8063af086c7e14610766578063bc67f8321461076e578063c2bf388014610781578063c836fa0a14610794576103fc565b806397107d6d116101a85780639f769807116101775780639f76980714610707578063a311c7c21461071a578063a5fdc5de1461072d578063a9059cbb14610740578063ace88afd14610753576103fc565b806397107d6d146106d15780639741fb22146106e4578063987757dd146106ec5780639cbdaeb6146106ff576103fc565b80638da5cb5b116101e45780638da5cb5b146106a657806391e56b68146106ae5780639324cac7146106c157806395d89b41146106c9576103fc565b8063835e119c1461066557806383d625d414610678578063899ffef41461068b5780638a29001414610693576103fc565b80632c955fa711610310578063666ed4f1116102a35780636f01a986116102725780636f01a9861461061a57806370a082311461062d57806372cb051f14610640578063741853601461065557806379ba50971461065d576103fc565b8063666ed4f1146105d95780636ac0bf9c146105ec5780636b76222f146105ff5780636c00f31014610607576103fc565b8063320223db116102df578063320223db1461059657806332608039146105a95780634e99bda9146105bc57806353a47bb7146105c4576103fc565b80632c955fa7146105535780632e0f26251461056657806330ead7601461057b578063313ce5671461058e576103fc565b80631627540c116103935780631fce304d116103625780631fce304d1461050a57806323b872dd1461051d578063295da87d146105305780632a905318146105435780632af64bd31461054b576103fc565b80631627540c146104d457806316b2213f146104e757806318160ddd146104fa5780631882140014610502576103fc565b80630e30963c116103cf5780630e30963c146104745780631137aedf146104955780631249c58b146104b7578063131b0ae7146104bf576103fc565b806304f3bcec1461040157806305b3c1c91461041f57806306fdde031461043f578063095ea7b314610454575b600080fd5b61040961085f565b60405161041691906142c7565b60405180910390f35b61043261042d36600461330d565b610873565b604051610416919061417f565b6104476108fe565b60405161041691906142d5565b6104676104623660046133d0565b61098c565b6040516104169190614171565b6104876104823660046136b9565b610a18565b6040516104169291906143b6565b6104a86104a336600461330d565b610ad2565b604051610416939291906143df565b610467610b67565b6104d26104cd36600461330d565b610f91565b005b6104d26104e236600461330d565b610fbb565b6104326104f536600461330d565b611019565b61043261104e565b610447611054565b6104676105183660046135e7565b61108d565b61046761052b366004613383565b611122565b6104d261053e3660046135e7565b611161565b6104476111e2565b610467611201565b6104d261056136600461330d565b61131d565b61056e611367565b60405161041691906143fa565b610432610589366004613644565b61136c565b61056e611425565b6104d26105a436600461330d565b61142e565b6104096105b73660046135e7565b611478565b6104676114fd565b6105cc61157c565b6040516104169190613f3f565b6104d26105e73660046133d0565b61158b565b6104326105fa36600461330d565b611597565b6104d261169f565b6104d261061536600461351a565b61174a565b6104d2610628366004613400565b61180c565b61043261063b36600461330d565b6118c5565b6106486118f6565b6040516104169190614160565b6104d2611974565b6104d2611ac6565b6104096106733660046135e7565b611b62565b6104326106863660046135e7565b611b97565b610648611bcf565b6104d26106a13660046135e7565b611c90565b6105cc611cda565b6104326106bc366004613493565b611ce9565b610432611da2565b610447611dad565b6104d26106df36600461330d565b611e08565b6104d2611e5b565b6104a86106fa3660046135e7565b611ed9565b610409611f4f565b6104d26107153660046136f9565b611f5e565b61043261072836600461330d565b611f8a565b61043261073b36600461330d565b611fbf565b61046761074e3660046133d0565b611ff4565b6104d2610761366004613400565b612034565b6104d2612081565b6104d261077c36600461330d565b6120ca565b6104d261078f3660046133d0565b6120f4565b6104326107a2366004613432565b612176565b6104326107b53660046133d0565b612229565b6104326107c83660046135e7565b6122b0565b6105cc6122e8565b6104d26107e33660046135e7565b6122f7565b6104326122ff565b6104326107fe366004613349565b612379565b6104d2610811366004613623565b6123ac565b6104676108243660046133d0565b612428565b6104d26108373660046133d0565b61250c565b610409612558565b610409612567565b61043261085a366004613623565b612576565b60095461010090046001600160a01b031681565b600061087d612629565b6001600160a01b03166305b3c1c9836040518263ffffffff1660e01b81526004016108a89190613f3f565b60206040518083038186803b1580156108c057600080fd5b505afa1580156108d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506108f89190810190613605565b92915050565b6006805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156109845780601f1061095957610100808354040283529160200191610984565b820191906000526020600020905b81548152906001019060200180831161096757829003601f168201915b505050505081565b600061099661263d565b60048054600554604051633691826360e21b81526001600160a01b0392831693919092169163da46098c916109d1918591899189910161402f565b600060405180830381600087803b1580156109eb57600080fd5b505af11580156109ff573d6000803e3d6000fd5b50505050610a0e818585612693565b5060019392505050565b6000808584610a278282612713565b610a2f61263d565b610a37612774565b60048054604051633ce6548960e21b81526001600160a01b039384169363f399522493610a7293909116918d918d918d9185918e91016140e9565b6040805180830381600087803b158015610a8b57600080fd5b505af1158015610a9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610ac39190810190613747565b93509350505094509492505050565b6000806000610adf612629565b6001600160a01b0316631137aedf856040518263ffffffff1660e01b8152600401610b0a9190613f3f565b60606040518083038186803b158015610b2257600080fd5b505afa158015610b36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610b5a91908101906137a7565b9250925092509193909250565b6000610b7161278b565b6000610b7b6127df565b6001600160a01b03161415610bab5760405162461bcd60e51b8152600401610ba290614376565b60405180910390fd5b6000610bb5612800565b90506000610bc16127df565b90506000826001600160a01b031663cc5c095c6040518163ffffffff1660e01b815260040160206040518083038186803b158015610bfe57600080fd5b505afa158015610c12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610c369190810190613605565b905060008111610c585760405162461bcd60e51b8152600401610ba290614396565b604051637e7961d760e01b81526001600160a01b03841690637e7961d790610c8490849060040161417f565b602060405180830381600087803b158015610c9e57600080fd5b505af1158015610cb2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610cd691908101906135c9565b506000836001600160a01b0316639bdd7ac76040518163ffffffff1660e01b815260040160206040518083038186803b158015610d1257600080fd5b505afa158015610d26573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610d4a9190810190613605565b90506000610d5e838363ffffffff61281c16565b6005546040516370a0823160e01b81529192506001600160a01b03169063b46310f6908690610dfb90859085906370a0823190610d9f908690600401613f3f565b60206040518083038186803b158015610db757600080fd5b505afa158015610dcb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610def9190810190613605565b9063ffffffff61284416565b6040518363ffffffff1660e01b8152600401610e18929190614057565b600060405180830381600087803b158015610e3257600080fd5b505af1158015610e46573d6000803e3d6000fd5b50505050610e55308583612869565b604051630b32e9c760e31b81526001600160a01b038516906359974e3890610e8190849060040161417f565b602060405180830381600087803b158015610e9b57600080fd5b505af1158015610eaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610ed391908101906135c9565b506005546040516370a0823160e01b81526001600160a01b039091169063b46310f6903390610f1490869085906370a0823190610d9f908690600401613f4d565b6040518363ffffffff1660e01b8152600401610f31929190613f5b565b600060405180830381600087803b158015610f4b57600080fd5b505af1158015610f5f573d6000803e3d6000fd5b50505050610f6e303384612869565b600854610f81908463ffffffff61284416565b6008555060019450505050505b90565b610f996128ac565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b610fc36128ac565b600180546001600160a01b0319166001600160a01b0383161790556040517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229061100e908390613f3f565b60405180910390a150565b6000611023612629565b6001600160a01b03166316b2213f836040518263ffffffff1660e01b81526004016108a89190613f3f565b60085481565b6040518060400160405280601781526020017f53796e746865746978204e6574776f726b20546f6b656e00000000000000000081525081565b600080611098612774565b600480546040516301670a7b60e21b81526001600160a01b039384169363059c29ec936110cb9390911691889101614057565b60206040518083038186803b1580156110e357600080fd5b505afa1580156110f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061111b9190810190613605565b1192915050565b600061112c61263d565b6111346128d6565b61113e8483612916565b50600454611157906001600160a01b0316858585612af4565b90505b9392505050565b61116961278b565b61117161263d565b611179612629565b6004805460405163b06e8c6560e01b81526001600160a01b039384169363b06e8c65936111ac9390911691869101614057565b600060405180830381600087803b1580156111c657600080fd5b505af11580156111da573d6000803e3d6000fd5b505050505b50565b604051806040016040528060038152602001620a69cb60eb1b81525081565b6000606061120d611bcf565b905060005b815181101561131457600082828151811061122957fe5b6020908102919091018101516000818152600a9092526040918290205460095492516321f8a72160e01b81529193506001600160a01b0390811692610100900416906321f8a7219061127f90859060040161417f565b60206040518083038186803b15801561129757600080fd5b505afa1580156112ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506112cf919081019061332b565b6001600160a01b03161415806112fa57506000818152600a60205260409020546001600160a01b0316155b1561130b5760009350505050610f8e565b50600101611212565b50600191505090565b61132561278b565b61132d61263d565b611335612629565b6004805460405163159fa0d560e11b81526001600160a01b0393841693632b3f41aa936111ac93879392169101613f76565b601281565b6000858461137a8282612713565b61138261263d565b61138a612774565b600480546040516321aea91760e21b81526001600160a01b03938416936386baa45c936113c793909116918d918d918d9185918e918e91016140a7565b602060405180830381600087803b1580156113e157600080fd5b505af11580156113f5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506114199190810190613605565b98975050505050505050565b60095460ff1681565b61143661278b565b61143e61263d565b611446612629565b6004805460405163fd864ccf60e01b81526001600160a01b039384169363fd864ccf936111ac93879392169101613f76565b6000611482612629565b6001600160a01b03166332608039836040518263ffffffff1660e01b81526004016114ad919061417f565b60206040518083038186803b1580156114c557600080fd5b505afa1580156114d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506108f891908101906136db565b6000611507612629565b6001600160a01b0316634e99bda96040518163ffffffff1660e01b815260040160206040518083038186803b15801561153f57600080fd5b505afa158015611553573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061157791908101906135c9565b905090565b6001546001600160a01b031681565b611593612bfb565b5050565b60006115a1612629565b6005546040516370a0823160e01b81526001600160a01b0392831692636bed04159286929116906370a08231906115dc908490600401613f3f565b60206040518083038186803b1580156115f457600080fd5b505afa158015611608573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061162c9190810190613605565b6040518363ffffffff1660e01b8152600401611649929190614057565b604080518083038186803b15801561166057600080fd5b505afa158015611674573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506116989190810190613717565b5092915050565b6116a76128ac565b6005546000906001600160a01b03166370a082316116c3612c13565b6040518263ffffffff1660e01b81526004016116df9190613f3f565b60206040518083038186803b1580156116f757600080fd5b505afa15801561170b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061172f9190810190613605565b905061159361173c612c13565b611744612c2d565b83612c49565b611752612dcb565b6002546040516001600160a01b039091169063907dff979061178090889088908890889088906020016141e4565b604051602081830303815290604052600260405161179d90613ee7565b60405180910390206117ae8b612e03565b6000806040518763ffffffff1660e01b81526004016117d296959493929190614246565b600060405180830381600087803b1580156117ec57600080fd5b505af1158015611800573d6000803e3d6000fd5b50505050505050505050565b611814612dcb565b6002546040516001600160a01b039091169063907dff979061183c90859085906020016141b6565b604051602081830303815290604052600260405161185990613efd565b604051809103902061186a88612e03565b6000806040518763ffffffff1660e01b815260040161188e96959493929190614246565b600060405180830381600087803b1580156118a857600080fd5b505af11580156118bc573d6000803e3d6000fd5b50505050505050565b6005546040516370a0823160e01b81526000916001600160a01b0316906370a08231906108a8908590600401613f3f565b6060611900612629565b6001600160a01b03166372cb051f6040518163ffffffff1660e01b815260040160006040518083038186803b15801561193857600080fd5b505afa15801561194c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526115779190810190613594565b606061197e611bcf565b905060005b815181101561159357600082828151811061199a57fe5b602002602001015190506000600960019054906101000a90046001600160a01b03166001600160a01b031663dacb2d0183846040516020016119dc9190613f29565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401611a089291906141c4565b60206040518083038186803b158015611a2057600080fd5b505afa158015611a34573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611a58919081019061332b565b6000838152600a60205260409081902080546001600160a01b0319166001600160a01b038416179055519091507f88a93678a3692f6789d9546fc621bf7234b101ddb7d4fe479455112831b8aa6890611ab4908490849061418d565b60405180910390a15050600101611983565b6001546001600160a01b03163314611af05760405162461bcd60e51b8152600401610ba2906142f6565b6000546001546040517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c92611b33926001600160a01b0391821692911690613f76565b60405180910390a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b6000611b6c612629565b6001600160a01b031663835e119c836040518263ffffffff1660e01b81526004016114ad919061417f565b6000611ba1612629565b6001600160a01b0316637b1001b78360006040518363ffffffff1660e01b81526004016108a892919061419b565b606080611bda612e0f565b60408051600380825260808201909252919250606091906020820183803883390190505090506b526577617264457363726f7760a01b81600081518110611c1d57fe5b6020026020010181815250506d2932bbb0b93222b9b1b937bbab1960911b81600181518110611c4857fe5b6020026020010181815250506d537570706c795363686564756c6560901b81600281518110611c7357fe5b602002602001018181525050611c898282612f02565b9250505090565b611c9861278b565b611ca061263d565b611ca8612629565b600480546040516285c0d160e31b81526001600160a01b039384169363042e0688936111ac9390911691869101614057565b6000546001600160a01b031681565b60008584611cf78282612713565b611cff61263d565b611d07612774565b60048054604051636fffe53b60e11b81526001600160a01b039384169363dfffca7693611d43938f939216918e918e918e918e918e9101613fd3565b602060405180830381600087803b158015611d5d57600080fd5b505af1158015611d71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611d959190810190613605565b9998505050505050505050565b631cd554d160e21b81565b6007805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156109845780601f1061095957610100808354040283529160200191610984565b611e106128ac565b600280546001600160a01b0319166001600160a01b0383161790556040517ffc80377ca9c49cc11ae6982f390a42db976d5530af7c43889264b13fbbd7c57e9061100e908390613f4d565b611e6361278b565b611e6b61263d565b611e73612629565b600480546040516324beb82560e11b81526001600160a01b039384169363497d704a93611ea4939091169101613f3f565b600060405180830381600087803b158015611ebe57600080fd5b505af1158015611ed2573d6000803e3d6000fd5b505050505b565b6000806000611ee661263d565b611eee612774565b600480546040516306c5a00b60e21b81526001600160a01b0393841693631b16802c93611f219390911691899101614057565b606060405180830381600087803b158015611f3b57600080fd5b505af1158015610b36573d6000803e3d6000fd5b6003546001600160a01b031681565b611f66612fb7565b600580546001600160a01b0319166001600160a01b0383161790556111df8161303c565b6000611f94612629565b6001600160a01b031663a311c7c2836040518263ffffffff1660e01b81526004016108a89190613f3f565b6000611fc9612629565b6001600160a01b031663a5fdc5de836040518263ffffffff1660e01b81526004016108a89190613f3f565b6000611ffe61263d565b6120066128d6565b60045461201c906001600160a01b031683612916565b50600454610a0e906001600160a01b031684846130ae565b61203c612dcb565b6002546040516001600160a01b039091169063907dff979061206490859085906020016141b6565b604051602081830303815290604052600260405161185990613ebc565b61208961278b565b61209161263d565b612099612629565b6004805460405163644bb89960e11b81526001600160a01b039384169363c897713293611ea4939091169101613f3f565b6120d26130bb565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b6120fc61278b565b61210461263d565b61210c612629565b60048054604051632694552d60e21b81526001600160a01b0393841693639a5154b49361214093889392169187910161402f565b600060405180830381600087803b15801561215a57600080fd5b505af115801561216e573d6000803e3d6000fd5b505050505050565b600083826121848282612713565b61218c61263d565b612194612774565b60048054604051630d4388eb60e31b81526001600160a01b0393841693636a1c4758936121cc938d939216918c918c918c9101613f91565b602060405180830381600087803b1580156121e657600080fd5b505af11580156121fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061221e9190810190613605565b979650505050505050565b6000612233612629565b6001600160a01b031663d37c4d8b84846040518363ffffffff1660e01b8152600401612260929190614057565b60206040518083038186803b15801561227857600080fd5b505afa15801561228c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061115a9190810190613605565b60006122ba612629565b6001600160a01b0316637b1001b78360016040518363ffffffff1660e01b81526004016108a892919061419b565b6004546001600160a01b031681565b6111df612bfb565b6000612309612629565b6001600160a01b031663dbf633406040518163ffffffff1660e01b815260040160206040518083038186803b15801561234157600080fd5b505afa158015612355573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506115779190810190613605565b600554604051636eb1769f60e11b81526000916001600160a01b03169063dd62ed3e906122609086908690600401613f76565b6123b4612dcb565b6002546040516001600160a01b039091169063907dff97906123dc90859085906020016141b6565b60405160208183030381529060405260026040516123f990613f08565b6040519081900381206001600160e01b031960e086901b16825261188e93929189906000908190600401614246565b60006124326128d6565b61243a61263d565b600080612445612629565b6004805460405163298f137d60e21b81526001600160a01b039384169363a63c4df49361247a938b938b939091169101614138565b6040805180830381600087803b15801561249357600080fd5b505af11580156124a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506124cb9190810190613777565b60045491935091506124eb908690849084906001600160a01b03166130fa565b6004546125039086906001600160a01b0316846130ae565b95945050505050565b61251461278b565b61251c61263d565b612524612629565b6004805460405163227635b160e11b81526001600160a01b03938416936344ec6b629361214093889392169187910161402f565b6005546001600160a01b031681565b6002546001600160a01b031681565b600083826125848282612713565b61258c61263d565b612594612774565b60048054604051630a1e187d60e01b81526001600160a01b0393841693630a1e187d936125cd93909116918b918b918b91859101614065565b602060405180830381600087803b1580156125e757600080fd5b505af11580156125fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061261f9190810190613605565b9695505050505050565b60006115776524b9b9bab2b960d11b6131ae565b6002546001600160a01b0316331480159061266357506003546001600160a01b03163314155b801561267a57506004546001600160a01b03163314155b15611ed757600480546001600160a01b03191633179055565b6002546040516001600160a01b039091169063907dff97906126b990849060200161417f565b60405160208183030381529060405260036040516126d690613ef2565b60405180910390206126e788612e03565b6126f088612e03565b60006040518763ffffffff1660e01b815260040161188e96959493929190614280565b61271b61320b565b6001600160a01b0316631ce00ba283836040518363ffffffff1660e01b81526004016127489291906141b6565b60006040518083038186803b15801561276057600080fd5b505afa15801561216e573d6000803e3d6000fd5b60006115776822bc31b430b733b2b960b91b6131ae565b61279361320b565b6001600160a01b0316637c3125416040518163ffffffff1660e01b815260040160006040518083038186803b1580156127cb57600080fd5b505afa158015611ed2573d6000803e3d6000fd5b6000611577722932bbb0b93239a234b9ba3934b13aba34b7b760691b6131ae565b60006115776d537570706c795363686564756c6560901b6131ae565b60008282111561283e5760405162461bcd60e51b8152600401610ba290614336565b50900390565b60008282018381101561115a5760405162461bcd60e51b8152600401610ba290614326565b6002546040516001600160a01b039091169063907dff979061288f90849060200161417f565b60405160208183030381529060405260036040516126d690613f34565b6000546001600160a01b03163314611ed75760405162461bcd60e51b8152600401610ba290614386565b6128de61320b565b6001600160a01b031663086dabd16040518163ffffffff1660e01b815260040160006040518083038186803b1580156127cb57600080fd5b600080612921613225565b6001600160a01b0316638b3f8088856040518263ffffffff1660e01b815260040161294c9190613f3f565b604080518083038186803b15801561296357600080fd5b505afa158015612977573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061299b9190810190613777565b5090508015610a0e576000806129af612629565b6005546040516370a0823160e01b81526001600160a01b0392831692636bed0415928a929116906370a08231906129ea908490600401613f3f565b60206040518083038186803b158015612a0257600080fd5b505afa158015612a16573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612a3a9190810190613605565b6040518363ffffffff1660e01b8152600401612a57929190614057565b604080518083038186803b158015612a6e57600080fd5b505afa158015612a82573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612aa69190810190613717565b9150915081851115612aca5760405162461bcd60e51b8152600401610ba290614356565b8015612ae85760405162461bcd60e51b8152600401610ba290614366565b50600195945050505050565b600554604051636eb1769f60e11b81526000916001600160a01b03169063da46098c9086908890612b95908790869063dd62ed3e90612b399087908790600401613f76565b60206040518083038186803b158015612b5157600080fd5b505afa158015612b65573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612b899190810190613605565b9063ffffffff61281c16565b6040518463ffffffff1660e01b8152600401612bb39392919061402f565b600060405180830381600087803b158015612bcd57600080fd5b505af1158015612be1573d6000803e3d6000fd5b50505050612bf0848484612c49565b90505b949350505050565b60405162461bcd60e51b8152600401610ba290614346565b60006115776b526577617264457363726f7760a01b6131ae565b60006115776d2932bbb0b93222b9b1b937bbab1960911b6131ae565b60006001600160a01b03831615801590612c6c57506001600160a01b0383163014155b8015612c8657506002546001600160a01b03848116911614155b612ca25760405162461bcd60e51b8152600401610ba2906142e6565b6005546040516370a0823160e01b81526001600160a01b039091169063b46310f6908690612ce290869085906370a0823190612b39908690600401613f3f565b6040518363ffffffff1660e01b8152600401612cff929190614057565b600060405180830381600087803b158015612d1957600080fd5b505af1158015612d2d573d6000803e3d6000fd5b50506005546040516370a0823160e01b81526001600160a01b03909116925063b46310f691508590612d7190869085906370a0823190610d9f908690600401613f3f565b6040518363ffffffff1660e01b8152600401612d8e929190614057565b600060405180830381600087803b158015612da857600080fd5b505af1158015612dbc573d6000803e3d6000fd5b50505050610a0e848484612869565b612dd3612774565b6001600160a01b0316336001600160a01b031614611ed75760405162461bcd60e51b8152600401610ba290614316565b6001600160a01b031690565b60408051600580825260c082019092526060916020820160a0803883390190505090506d53796e746865746978537461746560901b81600081518110612e5157fe5b6020026020010181815250506b53797374656d53746174757360a01b81600181518110612e7a57fe5b6020026020010181815250506822bc31b430b733b2b960b91b81600281518110612ea057fe5b6020026020010181815250506524b9b9bab2b960d11b81600381518110612ec357fe5b602002602001018181525050722932bbb0b93239a234b9ba3934b13aba34b7b760691b81600481518110612ef357fe5b60200260200101818152505090565b60608151835101604051908082528060200260200182016040528015612f32578160200160208202803883390190505b50905060005b8351811015612f7457838181518110612f4d57fe5b6020026020010151828281518110612f6157fe5b6020908102919091010152600101612f38565b5060005b825181101561169857828181518110612f8d57fe5b6020026020010151828286510181518110612fa457fe5b6020908102919091010152600101612f78565b6002546001600160a01b03163314801590612fdd57506003546001600160a01b03163314155b8015612ff457506004546001600160a01b03163314155b1561300c57600480546001600160a01b031916331790555b6000546004546001600160a01b03908116911614611ed75760405162461bcd60e51b8152600401610ba290614306565b6002546040516001600160a01b039091169063907dff9790613062908490602001613f3f565b604051602081830303815290604052600160405161307f90613f13565b6040519081900381206001600160e01b031960e086901b1682526111ac939291600090819081906004016141f2565b6000611157848484612c49565b6002546001600160a01b03163314806130de57506003546001600160a01b031633145b611ed75760405162461bcd60e51b8152600401610ba2906143a6565b6002546040516001600160a01b039091169063907dff9790613124908690869086906020016143d1565b604051602081830303815290604052600260405161314190613f1e565b604051809103902061315289612e03565b6000806040518763ffffffff1660e01b815260040161317696959493929190614246565b600060405180830381600087803b15801561319057600080fd5b505af11580156131a4573d6000803e3d6000fd5b5050505050505050565b6000818152600a602090815260408083205490516001600160a01b0390911691821515916131de91869101613ec7565b604051602081830303815290604052906116985760405162461bcd60e51b8152600401610ba291906142d5565b60006115776b53797374656d53746174757360a01b6131ae565b60006115776d53796e746865746978537461746560901b6131ae565b80356108f8816144e3565b80516108f8816144e3565b600082601f83011261326857600080fd5b815161327b6132768261442f565b614408565b915081818352602084019350602081019050838560208402820111156132a057600080fd5b60005b838110156132cc57816132b688826132ec565b84525060209283019291909101906001016132a3565b5050505092915050565b80516108f8816144f7565b80356108f881614500565b80516108f881614500565b80516108f881614509565b80356108f881614509565b60006020828403121561331f57600080fd5b6000612bf38484613241565b60006020828403121561333d57600080fd5b6000612bf3848461324c565b6000806040838503121561335c57600080fd5b60006133688585613241565b925050602061337985828601613241565b9150509250929050565b60008060006060848603121561339857600080fd5b60006133a48686613241565b93505060206133b586828701613241565b92505060406133c6868287016132e1565b9150509250925092565b600080604083850312156133e357600080fd5b60006133ef8585613241565b9250506020613379858286016132e1565b60008060006060848603121561341557600080fd5b60006134218686613241565b93505060206133b5868287016132e1565b6000806000806080858703121561344857600080fd5b60006134548787613241565b9450506020613465878288016132e1565b9350506040613476878288016132e1565b9250506060613487878288016132e1565b91505092959194509250565b60008060008060008060c087890312156134ac57600080fd5b60006134b88989613241565b96505060206134c989828a016132e1565b95505060406134da89828a016132e1565b94505060606134eb89828a016132e1565b93505060806134fc89828a01613241565b92505060a061350d89828a016132e1565b9150509295509295509295565b60008060008060008060c0878903121561353357600080fd5b600061353f8989613241565b965050602061355089828a016132e1565b955050604061356189828a016132e1565b945050606061357289828a016132e1565b935050608061358389828a016132e1565b92505060a061350d89828a01613241565b6000602082840312156135a657600080fd5b815167ffffffffffffffff8111156135bd57600080fd5b612bf384828501613257565b6000602082840312156135db57600080fd5b6000612bf384846132d6565b6000602082840312156135f957600080fd5b6000612bf384846132e1565b60006020828403121561361757600080fd5b6000612bf384846132ec565b60008060006060848603121561363857600080fd5b600061342186866132e1565b600080600080600060a0868803121561365c57600080fd5b600061366888886132e1565b9550506020613679888289016132e1565b945050604061368a888289016132e1565b935050606061369b88828901613241565b92505060806136ac888289016132e1565b9150509295509295909350565b600080600080608085870312156136cf57600080fd5b600061345487876132e1565b6000602082840312156136ed57600080fd5b6000612bf384846132f7565b60006020828403121561370b57600080fd5b6000612bf38484613302565b6000806040838503121561372a57600080fd5b600061373685856132ec565b9250506020613379858286016132d6565b6000806040838503121561375a57600080fd5b600061376685856132ec565b9250506020613379858286016132f7565b6000806040838503121561378a57600080fd5b600061379685856132ec565b9250506020613379858286016132ec565b6000806000606084860312156137bc57600080fd5b60006137c886866132ec565b93505060206137d9868287016132ec565b92505060406133c6868287016132ec565b60006137f68383613878565b505060200190565b61380781614489565b82525050565b61380781614468565b600061382182614456565b61382b818561445a565b935061383683614450565b8060005b8381101561386457815161384e88826137ea565b975061385983614450565b92505060010161383a565b509495945050505050565b61380781614473565b61380781610f8e565b61380761388d82610f8e565b610f8e565b600061389d82614456565b6138a7818561445a565b93506138b78185602086016144ad565b6138c0816144d9565b9093019392505050565b61380781614478565b61380781614494565b613807816144a2565b60006138f2601f8361445a565b7f43616e6e6f74207472616e7366657220746f2074686973206164647265737300815260200192915050565b600061392b60358361445a565b7f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7581527402063616e20616363657074206f776e65727368697605c1b602082015260400192915050565b600061398260138361445a565b7227bbb732b91037b7363c90333ab731ba34b7b760691b815260200192915050565b60006139b1601e8361445a565b7f4f6e6c792045786368616e6765722063616e20696e766f6b6520746869730000815260200192915050565b60006139ea601b8361445a565b7f536166654d6174683a206164646974696f6e206f766572666c6f770000000000815260200192915050565b6000613a23602883614463565b7f45786368616e67655265636c61696d28616464726573732c627974657333322c81526775696e743235362960c01b602082015260280192915050565b6000613a6d601e8361445a565b7f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815260200192915050565b6000613aa6601b8361445a565b7f43616e6e6f742062652072756e206f6e2074686973206c617965720000000000815260200192915050565b6000613adf601183614463565b70026b4b9b9b4b7339030b2323932b9b99d1607d1b815260110192915050565b6000613b0c603e83614463565b7f53796e746845786368616e676528616464726573732c627974657333322c756981527f6e743235362c627974657333322c75696e743235362c616464726573732900006020820152603e0192915050565b6000613b6b60268361445a565b7f43616e6e6f74207472616e73666572207374616b6564206f7220657363726f778152650cac840a69cb60d31b602082015260400192915050565b6000613bb3601e8361445a565b7f412073796e7468206f7220534e58207261746520697320696e76616c69640000815260200192915050565b6000613bec601b8361445a565b7f52657761726473446973747269627574696f6e206e6f74207365740000000000815260200192915050565b6000613c25602f8361445a565b7f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726681526e37b936903a3434b99030b1ba34b7b760891b602082015260400192915050565b6000613c76602183614463565b7f417070726f76616c28616464726573732c616464726573732c75696e743235368152602960f81b602082015260210192915050565b6000613cb9602783614463565b7f45786368616e676552656261746528616464726573732c627974657333322c75815266696e743235362960c81b602082015260270192915050565b6000613d02602983614463565b7f45786368616e6765547261636b696e6728627974657333322c627974657333328152682c75696e743235362960b81b602082015260290192915050565b6000613d4d601a83614463565b7f546f6b656e5374617465557064617465642861646472657373290000000000008152601a0192915050565b6000613d86603283614463565b7f4163636f756e744c69717569646174656428616464726573732c75696e743235815271362c75696e743235362c616464726573732960701b602082015260320192915050565b6000613dda601983614463565b7f5265736f6c766572206d697373696e67207461726765743a2000000000000000815260190192915050565b6000613e1360158361445a565b744e6f20737570706c79206973206d696e7461626c6560581b815260200192915050565b6000613e44602183614463565b7f5472616e7366657228616464726573732c616464726573732c75696e743235368152602960f81b602082015260210192915050565b6000613e8760178361445a565b7f4f6e6c79207468652070726f78792063616e2063616c6c000000000000000000815260200192915050565b61380781614483565b60006108f882613a16565b6000613ed282613ad2565b9150613ede8284613881565b50602001919050565b60006108f882613aff565b60006108f882613c69565b60006108f882613cac565b60006108f882613cf5565b60006108f882613d40565b60006108f882613d79565b6000613ed282613dcd565b60006108f882613e37565b602081016108f8828461380d565b602081016108f882846137fe565b60408101613f6982856137fe565b61115a6020830184613878565b60408101613f84828561380d565b61115a602083018461380d565b60a08101613f9f828861380d565b613fac602083018761380d565b613fb96040830186613878565b613fc66060830185613878565b61261f6080830184613878565b60e08101613fe1828a61380d565b613fee602083018961380d565b613ffb6040830188613878565b6140086060830187613878565b6140156080830186613878565b61402260a083018561380d565b61141960c0830184613878565b6060810161403d828661380d565b61404a602083018561380d565b612bf36040830184613878565b60408101613f69828561380d565b60a08101614073828861380d565b6140806020830187613878565b61408d6040830186613878565b61409a6060830185613878565b61261f608083018461380d565b60e081016140b5828a61380d565b6140c26020830189613878565b6140cf6040830188613878565b6140dc6060830187613878565b614015608083018661380d565b60c081016140f7828961380d565b6141046020830188613878565b6141116040830187613878565b61411e6060830186613878565b61412b608083018561380d565b61221e60a0830184613878565b60608101614146828661380d565b6141536020830185613878565b612bf3604083018461380d565b6020808252810161115a8184613816565b602081016108f8828461386f565b602081016108f88284613878565b60408101613f848285613878565b604081016141a98285613878565b61115a602083018461386f565b60408101613f698285613878565b604081016141d28285613878565b81810360208301526111578184613892565b60a081016140738288613878565b60c080825281016142038189613892565b905061421260208301886138dc565b61421f6040830187613878565b61422c60608301866138d3565b61423960808301856138d3565b61221e60a08301846138d3565b60c080825281016142578189613892565b905061426660208301886138dc565b6142736040830187613878565b61422c6060830186613878565b60c080825281016142918189613892565b90506142a060208301886138dc565b6142ad6040830187613878565b6142ba6060830186613878565b6142396080830185613878565b602081016108f882846138ca565b6020808252810161115a8184613892565b602080825281016108f8816138e5565b602080825281016108f88161391e565b602080825281016108f881613975565b602080825281016108f8816139a4565b602080825281016108f8816139dd565b602080825281016108f881613a60565b602080825281016108f881613a99565b602080825281016108f881613b5e565b602080825281016108f881613ba6565b602080825281016108f881613bdf565b602080825281016108f881613c18565b602080825281016108f881613e06565b602080825281016108f881613e7a565b604081016143c48285613878565b61115a60208301846138ca565b606081016141468286613878565b606081016143ed8286613878565b61404a6020830185613878565b602081016108f88284613eb3565b60405181810167ffffffffffffffff8111828210171561442757600080fd5b604052919050565b600067ffffffffffffffff82111561444657600080fd5b5060209081020190565b60200190565b5190565b90815260200190565b919050565b60006108f882612e03565b151590565b60006108f882614468565b60ff1690565b60006108f882614478565b60006108f861388d83610f8e565b60006108f882610f8e565b60005b838110156144c85781810151838201526020016144b0565b83811115611ed25750506000910152565b601f01601f191690565b6144ec81614468565b81146111df57600080fd5b6144ec81614473565b6144ec81610f8e565b6144ec8161447856fea365627a7a723158204cb502697553759464d0c2ad637d6ac4b23388eb5ea3062f1341f043cd0bf8516c6578706572696d656e74616cf564736f6c63430005100040000000000000000000000000c011a73ee8576fb46f5e1c5751ca3b9fe0af2a6f00000000000000000000000046824bfaafd049fb0af9a45159a88e595bbbb9f7000000000000000000000000b64ff7a4a33acdf48d97dab0d764afd0f6176882000000000000000000000000000000000000000000b20ed4c9688f57ffdae47c000000000000000000000000242a3df52c375bee81b1c668741d7c63af68fdd2

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

000000000000000000000000c011a73ee8576fb46f5e1c5751ca3b9fe0af2a6f00000000000000000000000046824bfaafd049fb0af9a45159a88e595bbbb9f7000000000000000000000000b64ff7a4a33acdf48d97dab0d764afd0f6176882000000000000000000000000000000000000000000b20ed4c9688f57ffdae47c000000000000000000000000242a3df52c375bee81b1c668741d7c63af68fdd2

-----Decoded View---------------
Arg [0] : _proxy (address): 0xc011a73ee8576fb46f5e1c5751ca3b9fe0af2a6f
Arg [1] : _tokenState (address): 0x46824bfaafd049fb0af9a45159a88e595bbbb9f7
Arg [2] : _owner (address): 0xb64ff7a4a33acdf48d97dab0d764afd0f6176882
Arg [3] : _totalSupply (uint256): 215258834244915201874519164
Arg [4] : _resolver (address): 0x242a3df52c375bee81b1c668741d7c63af68fdd2

-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 000000000000000000000000c011a73ee8576fb46f5e1c5751ca3b9fe0af2a6f
Arg [1] : 00000000000000000000000046824bfaafd049fb0af9a45159a88e595bbbb9f7
Arg [2] : 000000000000000000000000b64ff7a4a33acdf48d97dab0d764afd0f6176882
Arg [3] : 000000000000000000000000000000000000000000b20ed4c9688f57ffdae47c
Arg [4] : 000000000000000000000000242a3df52c375bee81b1c668741d7c63af68fdd2


Library Used

SafeDecimalMath : 0x1a60e2e2a8be0bc2b6381dd31fd3fd5f9a28de4c

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