ETH Price: $2,509.16 (-5.53%)
Gas: 5.35 Gwei

Token

Amp (AMP)
 

Overview

Max Total Supply

99,669,226,784.089273487347798526 AMP

Holders

98,231 ( 0.001%)

Market

Price

$0.00 @ 0.000001 ETH (-3.50%)

Onchain Market Cap

$364,033,877.29

Circulating Supply Market Cap

$294,695,558.00

Other Info

Token Contract (WITH 18 Decimals)

Filtered by Token Holder
FTX: Banruptcy Dust Collector
Balance
0 AMP

Value
$0.00
0x77f33da6046a03ebb0e6d33a26cb49bd738774ff
Loading...
Loading
Loading...
Loading
Loading...
Loading

OVERVIEW

Amp is a digital collateral token designed to facilitate fast and efficient value transfer, especially for use cases that prioritize security and irreversibility. Using Amp as collateral, individuals and entities benefit from instant, verifiable assurances for any kind of asset exchange.

Market

Volume (24H):$21,370,273.00
Market Capitalization:$294,695,558.00
Circulating Supply:80,722,574,661.00 AMP
Market Data Source: Coinmarketcap

# Exchange Pair Price  24H Volume % Volume
1
Binance
AMP-USDT$0.0037
0.0000015 Eth
$4,172,493.00
1,111,178,256.000 AMP
19.1839%
2
BtcTurk | Kripto
AMP-TRY$0.0037
0.0000015 Eth
$3,927,704.00
1,072,935,483.387 AMP
18.5236%
3
Binance
AMP-TRY$0.0037
0.0000015 Eth
$1,761,836.00
466,884,087.000 AMP
8.0605%
4
LBank
AMP-USDT$0.0036
0.0000015 Eth
$1,492,348.00
409,194,476.515 AMP
7.0645%
5
Coinbase Exchange
AMP-USD$0.0037
0.0000015 Eth
$1,066,624.00
292,225,675.000 AMP
5.0451%
6
Nami.Exchange
AMP-USDT$0.0037
0.0000015 Eth
$1,048,157.00
286,826,907.000 AMP
4.9519%
7
Bitget
AMP-USDT$0.0037
0.0000015 Eth
$1,031,876.00
277,472,068.201 AMP
4.7904%
8
Nami.Exchange
AMP-VNST$0.0036
0.0000015 Eth
$1,019,315.00
280,679,203.000 AMP
4.8458%
9
WhiteBIT
AMP-USDT$0.0036
0.0000015 Eth
$955,353.00
262,236,191.887 AMP
4.5274%
10
Trubit
AMP-USDT$0.0037
0.0000015 Eth
$917,356.00
247,568,909.000 AMP
4.2741%
11
Hotcoin
AMP-USDT$0.0037
0.0000015 Eth
$470,796.00
128,861,405.000 AMP
2.2247%
12
BitMart
AMP-USDT$0.0037
0.0000015 Eth
$340,277.00
93,204,872.000 AMP
1.6091%
13
HTX
AMP-USDT$0.0036
0.0000015 Eth
$319,812.00
86,211,223.137 AMP
1.4884%
14
Bitrue
AMP-USDT$0.0036
0.0000015 Eth
$314,901.00
86,401,422.000 AMP
1.4917%
15
Bitunix
AMP-USDT$0.0036
0.0000015 Eth
$285,646.00
78,230,761.000 AMP
1.3506%
16
BtcTurk | Kripto
AMP-USDT$0.0037
0.0000015 Eth
$244,781.00
66,809,017.023 AMP
1.1534%
17
Toobit
AMP-USDT$0.0037
0.0000015 Eth
$230,526.00
61,451,938.000 AMP
1.0609%
18
XT.COM
AMP-USDT$0.0037
0.0000015 Eth
$208,746.00
55,587,778.000 AMP
0.9597%
19
CoinTR
AMP-TRY$0.0037
0.0000015 Eth
$194,686.00
52,405,016.000 AMP
0.9047%
20
Ourbit
AMP-USDT$0.0036
0.0000015 Eth
$194,323.00
51,777,920.140 AMP
0.8939%
21
FameEX
AMP-USDT$0.0036
0.0000015 Eth
$170,668.00
45,437,897.670 AMP
0.7845%
22
MEXC
AMP-USDT$0.0036
0.0000015 Eth
$168,777.00
46,309,925.250 AMP
0.7995%
23
BingX
AMP-USDT$0.0037
0.0000015 Eth
$163,344.00
43,199,850.293 AMP
0.7458%
24
CoinTR
AMP-USDT$0.0036
0.0000015 Eth
$152,092.00
40,923,097.000 AMP
0.7065%
25
Slex
AMP-USDT$0.0036
0.0000015 Eth
$118,033.00
31,441,444.000 AMP
0.5428%
26
Bitvavo
AMP-EUR$0.0037
0.0000015 Eth
$105,093.00
28,725,604.382 AMP
0.4959%
27
KuCoin
AMP-USDT$0.0036
0.0000015 Eth
$76,808.00
21,119,414.165 AMP
0.3646%
28
BloFin
AMP-USDT$0.0037
0.0000015 Eth
$38,881.00
10,462,962.000 AMP
0.1806%
29
CoinCatch
AMP-USDT$0.0036
0.0000015 Eth
$37,396.00
10,071,742.268 AMP
0.1739%
30
Bilaxy
AMP-ETH$0.0041
0.0000016 Eth
$31,799.00
7,777,240.000 AMP
0.1343%
31
Tapbit
AMP-USDT$0.0036
0.0000015 Eth
$30,330.00
8,119,000.000 AMP
0.1402%
32
Gemini
AMP-USD$0.0037
0.0000015 Eth
$29,809.00
8,056,419.102 AMP
0.1391%
33
Nominex
AMP-USDT$0.0037
0.0000015 Eth
$28,316.00
7,750,326.802 AMP
0.1338%
34
Gate.io
AMP-USDT$0.0037
0.0000015 Eth
$25,122.00
6,713,737.200 AMP
0.1159%
35
Uniswap V2 (Ethereum)
0XFF20817765CB7F73D4BDE2E66E067E58D11095C2-0XC02AAA39B223FE8D0A0E5C4F27EAD9083C756CC2$0.0037
0.0000015 Eth
$16,071.41
4,429,917.991 0XFF20817765CB7F73D4BDE2E66E067E58D11095C2
0.0765%
36
Crypto.com Exchange
AMP-USD$0.0037
0.0000015 Eth
$14,626.90
4,003,420.000 AMP
0.0691%
37
Sushiswap
0XFF20817765CB7F73D4BDE2E66E067E58D11095C2-0XC02AAA39B223FE8D0A0E5C4F27EAD9083C756CC2$0.0037
0.0000015 Eth
$13,712.98
3,720,249.075 0XFF20817765CB7F73D4BDE2E66E067E58D11095C2
0.0642%
38
Nominex
AMP-TRY$0.0037
0.0000015 Eth
$11,621.65
3,176,377.754 AMP
0.0548%
39
Uniswap V3 (Ethereum)
0XFF20817765CB7F73D4BDE2E66E067E58D11095C2-0XC02AAA39B223FE8D0A0E5C4F27EAD9083C756CC2$0.0037
0.0000015 Eth
$10,357.86
2,855,887.251 0XFF20817765CB7F73D4BDE2E66E067E58D11095C2
0.0493%
40
Bitlo
AMP-TRY$0.0037
0.0000015 Eth
$9,858.36
2,628,153.359 AMP
0.0454%
41
WEEX
AMP-USDT$0.0037
0.0000015 Eth
$8,137.65
2,189,593.000 AMP
0.0378%
42
Cryptology
AMP-USDT$0.0036
0.0000015 Eth
$4,905.94
1,346,477.172 AMP
0.0232%
43
Bitstamp
AMP-EUR$0.0038
0.0000015 Eth
$4,327.26
1,133,321.385 AMP
0.0196%
44
CoinEx
AMP-USDT$0.0037
0.0000015 Eth
$4,056.48
1,093,944.048 AMP
0.0189%
45
Indodax
AMP-IDR$0.0038
0.0000015 Eth
$2,547.22
667,101.985 AMP
0.0115%
46
Crypto.com Exchange
AMP-USDT$0.0036
0.0000015 Eth
$1,257.36
345,230.000 AMP
0.0060%
47
TokoCrypto
AMP-USDT$0.0037
0.0000015 Eth
$1,099.77
301,170.167 AMP
0.0052%
48
Foxbit
AMP-BRL$0.0037
0.0000015 Eth
$1,002.60
299,073.007 AMP
0.0052%
49
Mudrex
AMP-USDT$0.0037
0.0000015 Eth
$976.04
267,062.039 AMP
0.0046%
50
Coinone
AMP-KRW$0.0036
0.0000014 Eth
$661.72
183,295.786 AMP
0.0032%
51
CoinDCX
AMP-INR$0.0037
0.0000015 Eth
$404.20
0.000 AMP
0.0000%
52
CoinJar Exchange
AMP-USDC$0.0038
0.0000014 Eth
$380.61
100,000.000 AMP
0.0017%
53
Mercado Bitcoin
AMP-BRL$0.0036
0.0000015 Eth
$376.43
103,804.825 AMP
0.0018%
54
Bitstamp
AMP-USD$0.0038
0.0000015 Eth
$354.40
94,005.150 AMP
0.0016%
55
Gate.io
AMP-TRY$0.0037
0.0000015 Eth
$331.18
88,979.284 AMP
0.0015%
56
CoinJar Exchange
AMP-AUD$0.0037
0.0000015 Eth
$224.61
60,000.000 AMP
0.0010%
57
Loopring AMM
AMP-ETH$0.004
0.0000015 Eth
$203.34
50,862.200 AMP
0.0009%
58
Gate.io
AMP-ETH$0.0036
0.0000014 Eth
$156.46
43,120.357 AMP
0.0007%
59
Bittime
AMP-IDR$0.0037
0.0000015 Eth
$92.39
25,078.759 AMP
0.0004%
60
NovaDAX
AMP-BRL$0.0039
0.0000016 Eth
$57.05
14,684.000 AMP
0.0003%
61
Korbit
AMP-KRW$0.0045
0.0000018 Eth
$50.83
11,343.205 AMP
0.0002%
62
Energiswap
0XAD7ABE6F12F1059BDF48AE67BFF92B00438CED95-0XA55F26319462355474A9F2C8790860776A329AA4$0.0037
0.0000015 Eth
$47.90
12,687.974 0XAD7ABE6F12F1059BDF48AE67BFF92B00438CED95
0.0002%
63
Poloniex
AMP-BTC$0.0033
0.0000013 Eth
$40.75
12,193.000 AMP
0.0002%
64
Sushiswap
0XFF20817765CB7F73D4BDE2E66E067E58D11095C2-0X6B175474E89094C44DA98B954EEDEAC495271D0F$0.0038
0.0000015 Eth
$18.98
5,050.679 0XFF20817765CB7F73D4BDE2E66E067E58D11095C2
0.0001%
65
Poloniex
AMP-USDT$0.0035
0.0000014 Eth
$11.44
3,157.890 AMP
0.0001%
66
Shibaswap (Ethereum)
0XFF20817765CB7F73D4BDE2E66E067E58D11095C2-0XC02AAA39B223FE8D0A0E5C4F27EAD9083C756CC2$0.0035
0.0000014 Eth
$4.72
1,349.803 0XFF20817765CB7F73D4BDE2E66E067E58D11095C2
0.0000%
67
Uniswap V3 (Ethereum)
0XFF20817765CB7F73D4BDE2E66E067E58D11095C2-0XA0B86991C6218B36C1D19D4A2E9EB0CE3606EB48$0.0038
0.0000015 Eth
$2.91
775.342 0XFF20817765CB7F73D4BDE2E66E067E58D11095C2
0.0000%

Contract Source Code Verified (Exact Match)

Contract Name:
Amp

Compiler Version
v0.6.10+commit.00c0fcaf

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2020-08-28
*/

// SPDX-License-Identifier: MIT

pragma solidity 0.6.10;

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

        return c;
    }

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

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

        return c;
    }

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

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

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

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

        return c;
    }

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

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

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

/**
 * @title Ownable is a contract the provides contract ownership functionality, including a two-
 * phase transfer.
 */
contract Ownable {
    address private _owner;
    address private _authorizedNewOwner;

    /**
     * @notice Emitted when the owner authorizes ownership transfer to a new address
     * @param authorizedAddress New owner address
     */
    event OwnershipTransferAuthorization(address indexed authorizedAddress);

    /**
     * @notice Emitted when the authorized address assumed ownership
     * @param oldValue Old owner
     * @param newValue New owner
     */
    event OwnerUpdate(address indexed oldValue, address indexed newValue);

    /**
     * @notice Sets the owner to the sender / contract creator
     */
    constructor() internal {
        _owner = msg.sender;
    }

    /**
     * @notice Retrieves the owner of the contract
     * @return The contract owner
     */
    function owner() public view returns (address) {
        return _owner;
    }

    /**
     * @notice Retrieves the authorized new owner of the contract
     * @return The authorized new contract owner
     */
    function authorizedNewOwner() public view returns (address) {
        return _authorizedNewOwner;
    }

    /**
     * @notice Authorizes the transfer of ownership from owner to the provided address.
     * NOTE: No transfer will occur unless authorizedAddress calls assumeOwnership().
     * This authorization may be removed by another call to this function authorizing the zero
     * address.
     * @param _authorizedAddress The address authorized to become the new owner
     */
    function authorizeOwnershipTransfer(address _authorizedAddress) external {
        require(msg.sender == _owner, "Invalid sender");

        _authorizedNewOwner = _authorizedAddress;

        emit OwnershipTransferAuthorization(_authorizedNewOwner);
    }

    /**
     * @notice Transfers ownership of this contract to the _authorizedNewOwner
     * @dev Error invalid sender.
     */
    function assumeOwnership() external {
        require(msg.sender == _authorizedNewOwner, "Invalid sender");

        address oldValue = _owner;
        _owner = _authorizedNewOwner;
        _authorizedNewOwner = address(0);

        emit OwnerUpdate(oldValue, _owner);
    }
}

abstract contract ERC1820Registry {
    function setInterfaceImplementer(
        address _addr,
        bytes32 _interfaceHash,
        address _implementer
    ) external virtual;

    function getInterfaceImplementer(address _addr, bytes32 _interfaceHash)
        external
        virtual
        view
        returns (address);

    function setManager(address _addr, address _newManager) external virtual;

    function getManager(address _addr) public virtual view returns (address);
}

/// Base client to interact with the registry.
contract ERC1820Client {
    ERC1820Registry constant ERC1820REGISTRY = ERC1820Registry(
        0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24
    );

    function setInterfaceImplementation(
        string memory _interfaceLabel,
        address _implementation
    ) internal {
        bytes32 interfaceHash = keccak256(abi.encodePacked(_interfaceLabel));
        ERC1820REGISTRY.setInterfaceImplementer(
            address(this),
            interfaceHash,
            _implementation
        );
    }

    function interfaceAddr(address addr, string memory _interfaceLabel)
        internal
        view
        returns (address)
    {
        bytes32 interfaceHash = keccak256(abi.encodePacked(_interfaceLabel));
        return ERC1820REGISTRY.getInterfaceImplementer(addr, interfaceHash);
    }

    function delegateManagement(address _newManager) internal {
        ERC1820REGISTRY.setManager(address(this), _newManager);
    }
}

contract ERC1820Implementer {
    /**
     * @dev ERC1820 well defined magic value indicating the contract has
     * registered with the ERC1820Registry that it can implement an interface.
     */
    bytes32 constant ERC1820_ACCEPT_MAGIC = keccak256(
        abi.encodePacked("ERC1820_ACCEPT_MAGIC")
    );

    /**
     * @dev Mapping of interface name keccak256 hashes for which this contract
     * implements the interface.
     * @dev Only settable internally.
     */
    mapping(bytes32 => bool) internal _interfaceHashes;

    /**
     * @notice Indicates whether the contract implements the interface `_interfaceHash`
     * for the address `_addr`.
     * @param _interfaceHash keccak256 hash of the name of the interface.
     * @return ERC1820_ACCEPT_MAGIC only if the contract implements `ìnterfaceHash`
     * for the address `_addr`.
     * @dev In this implementation, the `_addr` (the address for which the
     * contract will implement the interface) is always `address(this)`.
     */
    function canImplementInterfaceForAddress(
        bytes32 _interfaceHash,
        address // Comments to avoid compilation warnings for unused variables. /*addr*/
    ) external view returns (bytes32) {
        if (_interfaceHashes[_interfaceHash]) {
            return ERC1820_ACCEPT_MAGIC;
        } else {
            return "";
        }
    }

    /**
     * @notice Internally set the fact this contract implements the interface
     * identified by `_interfaceLabel`
     * @param _interfaceLabel String representation of the interface.
     */
    function _setInterface(string memory _interfaceLabel) internal {
        _interfaceHashes[keccak256(abi.encodePacked(_interfaceLabel))] = true;
    }
}

/**
 * @title IAmpTokensSender
 * @dev IAmpTokensSender token transfer hook interface
 */
interface IAmpTokensSender {
    /**
     * @dev Report if the transfer will succeed from the pespective of the
     * token sender
     */
    function canTransfer(
        bytes4 functionSig,
        bytes32 partition,
        address operator,
        address from,
        address to,
        uint256 value,
        bytes calldata data,
        bytes calldata operatorData
    ) external view returns (bool);

    /**
     * @dev Hook executed upon a transfer on behalf of the sender
     */
    function tokensToTransfer(
        bytes4 functionSig,
        bytes32 partition,
        address operator,
        address from,
        address to,
        uint256 value,
        bytes calldata data,
        bytes calldata operatorData
    ) external;
}

/**
 * @title IAmpTokensRecipient
 * @dev IAmpTokensRecipient token transfer hook interface
 */
interface IAmpTokensRecipient {
    /**
     * @dev Report if the recipient will successfully receive the tokens
     */
    function canReceive(
        bytes4 functionSig,
        bytes32 partition,
        address operator,
        address from,
        address to,
        uint256 value,
        bytes calldata data,
        bytes calldata operatorData
    ) external view returns (bool);

    /**
     * @dev Hook executed upon a transfer to the recipient
     */
    function tokensReceived(
        bytes4 functionSig,
        bytes32 partition,
        address operator,
        address from,
        address to,
        uint256 value,
        bytes calldata data,
        bytes calldata operatorData
    ) external;
}

/**
 * @notice Partition strategy validator hooks for Amp
 */
interface IAmpPartitionStrategyValidator {
    function tokensFromPartitionToValidate(
        bytes4 _functionSig,
        bytes32 _partition,
        address _operator,
        address _from,
        address _to,
        uint256 _value,
        bytes calldata _data,
        bytes calldata _operatorData
    ) external;

    function tokensToPartitionToValidate(
        bytes4 _functionSig,
        bytes32 _partition,
        address _operator,
        address _from,
        address _to,
        uint256 _value,
        bytes calldata _data,
        bytes calldata _operatorData
    ) external;

    function isOperatorForPartitionScope(
        bytes32 _partition,
        address _operator,
        address _tokenHolder
    ) external view returns (bool);
}

/**
 * @title PartitionUtils
 * @notice Partition related helper functions.
 */

library PartitionUtils {
    bytes32 public constant CHANGE_PARTITION_FLAG = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;

    /**
     * @notice Retrieve the destination partition from the 'data' field.
     * A partition change is requested ONLY when 'data' starts with the flag:
     *
     *   0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
     *
     * When the flag is detected, the destination partition is extracted from the
     * 32 bytes following the flag.
     * @param _data Information attached to the transfer. Will contain the
     * destination partition if a change is requested.
     * @param _fallbackPartition Partition value to return if a partition change
     * is not requested in the `_data`.
     * @return toPartition Destination partition. If the `_data` does not contain
     * the prefix and bytes32 partition in the first 64 bytes, the method will
     * return the provided `_fromPartition`.
     */
    function _getDestinationPartition(bytes memory _data, bytes32 _fallbackPartition)
        internal
        pure
        returns (bytes32)
    {
        if (_data.length < 64) {
            return _fallbackPartition;
        }

        (bytes32 flag, bytes32 toPartition) = abi.decode(_data, (bytes32, bytes32));
        if (flag == CHANGE_PARTITION_FLAG) {
            return toPartition;
        }

        return _fallbackPartition;
    }

    /**
     * @notice Helper to get the strategy identifying prefix from the `_partition`.
     * @param _partition Partition to get the prefix for.
     * @return 4 byte partition strategy prefix.
     */
    function _getPartitionPrefix(bytes32 _partition) internal pure returns (bytes4) {
        return bytes4(_partition);
    }

    /**
     * @notice Helper method to split the partition into the prefix, sub partition
     * and partition owner components.
     * @param _partition The partition to split into parts.
     * @return The 4 byte partition prefix, 8 byte sub partition, and final 20
     * bytes representing an address.
     */
    function _splitPartition(bytes32 _partition)
        internal
        pure
        returns (
            bytes4,
            bytes8,
            address
        )
    {
        bytes4 prefix = bytes4(_partition);
        bytes8 subPartition = bytes8(_partition << 32);
        address addressPart = address(uint160(uint256(_partition)));
        return (prefix, subPartition, addressPart);
    }

    /**
     * @notice Helper method to get a partition strategy ERC1820 interface name
     * based on partition prefix.
     * @param _prefix 4 byte partition prefix.
     * @dev Each 4 byte prefix has a unique interface name so that an individual
     * hook implementation can be set for each prefix.
     */
    function _getPartitionStrategyValidatorIName(bytes4 _prefix)
        internal
        pure
        returns (string memory)
    {
        return string(abi.encodePacked("AmpPartitionStrategyValidator", _prefix));
    }
}

/**
 * @title ErrorCodes
 * @notice Amp error codes.
 */
contract ErrorCodes {
    string internal EC_50_TRANSFER_FAILURE = "50";
    string internal EC_51_TRANSFER_SUCCESS = "51";
    string internal EC_52_INSUFFICIENT_BALANCE = "52";
    string internal EC_53_INSUFFICIENT_ALLOWANCE = "53";

    string internal EC_56_INVALID_SENDER = "56";
    string internal EC_57_INVALID_RECEIVER = "57";
    string internal EC_58_INVALID_OPERATOR = "58";

    string internal EC_59_INSUFFICIENT_RIGHTS = "59";

    string internal EC_5A_INVALID_SWAP_TOKEN_ADDRESS = "5A";
    string internal EC_5B_INVALID_VALUE_0 = "5B";
    string internal EC_5C_ADDRESS_CONFLICT = "5C";
    string internal EC_5D_PARTITION_RESERVED = "5D";
    string internal EC_5E_PARTITION_PREFIX_CONFLICT = "5E";
    string internal EC_5F_INVALID_PARTITION_PREFIX_0 = "5F";
    string internal EC_60_SWAP_TRANSFER_FAILURE = "60";
}

interface ISwapToken {
    function allowance(address owner, address spender)
        external
        view
        returns (uint256 remaining);

    function transferFrom(
        address from,
        address to,
        uint256 value
    ) external returns (bool success);
}

/**
 * @title Amp
 * @notice Amp is an ERC20 compatible collateral token designed to support
 * multiple classes of collateralization systems.
 * @dev The Amp token contract includes the following features:
 *
 * Partitions
 *   Tokens can be segmented within a given address by "partition", which in
 *   pracice is a 32 byte identifier. These partitions can have unique
 *   permissions globally, through the using of partition strategies, and
 *   locally, on a per address basis. The ability to create the sub-segments
 *   of tokens and assign special behavior gives collateral managers
 *   flexibility in how they are implemented.
 *
 * Operators
 *   Inspired by ERC777, Amp allows token holders to assign "operators" on
 *   all (or any number of partitions) of their tokens. Operators are allowed
 *   to execute transfers on behalf of token owners without the need to use the
 *   ERC20 "allowance" semantics.
 *
 * Transfers with Data
 *   Inspired by ERC777, Amp transfers can include arbitrary data, as well as
 *   operator data. This data can be used to change the partition of tokens,
 *   be used by collateral manager hooks to validate a transfer, be propagated
 *   via event to an off chain system, etc.
 *
 * Token Transfer Hooks on Send and Receive
 *   Inspired by ERC777, Amp uses the ERC1820 Registry to allow collateral
 *   manager implementations to register hooks to be called upon sending to
 *   or transferring from the collateral manager's address or, using partition
 *   strategies, owned partition space. The hook implementations can be used
 *   to validate transfer properties, gate transfers, emit custom events,
 *   update local state, etc.
 *
 * Collateral Management Partition Strategies
 *   Amp is able to define certain sets of partitions, identified by a 4 byte
 *   prefix, that will allow special, custom logic to be executed when transfers
 *   are made to or from those partitions. This opens up the possibility of
 *   entire classes of collateral management systems that would not be possible
 *   without it.
 *
 * These features give collateral manager implementers flexibility while
 * providing a consistent, "collateral-in-place", interface for interacting
 * with collateral systems directly through the Amp contract.
 */
contract Amp is IERC20, ERC1820Client, ERC1820Implementer, ErrorCodes, Ownable {
    using SafeMath for uint256;

    /**************************************************************************/
    /********************** ERC1820 Interface Constants ***********************/

    /**
     * @dev AmpToken interface label.
     */
    string internal constant AMP_INTERFACE_NAME = "AmpToken";

    /**
     * @dev ERC20Token interface label.
     */
    string internal constant ERC20_INTERFACE_NAME = "ERC20Token";

    /**
     * @dev AmpTokensSender interface label.
     */
    string internal constant AMP_TOKENS_SENDER = "AmpTokensSender";

    /**
     * @dev AmpTokensRecipient interface label.
     */
    string internal constant AMP_TOKENS_RECIPIENT = "AmpTokensRecipient";

    /**
     * @dev AmpTokensChecker interface label.
     */
    string internal constant AMP_TOKENS_CHECKER = "AmpTokensChecker";

    /**************************************************************************/
    /*************************** Token properties *****************************/

    /**
     * @dev Token name (Amp).
     */
    string internal _name;

    /**
     * @dev Token symbol (AMP).
     */
    string internal _symbol;

    /**
     * @dev Total minted supply of token. This will increase comensurately with
     * successful swaps of the swap token.
     */
    uint256 internal _totalSupply;

    /**
     * @dev The granularity of the token. Hard coded to 1.
     */
    uint256 internal constant _granularity = 1;

    /**************************************************************************/
    /***************************** Token mappings *****************************/

    /**
     * @dev Mapping from tokenHolder to balance. This reflects the balance
     * across all partitions of an address.
     */
    mapping(address => uint256) internal _balances;

    /**************************************************************************/
    /************************** Partition mappings ****************************/

    /**
     * @dev List of active partitions. This list reflects all partitions that
     * have tokens assigned to them.
     */
    bytes32[] internal _totalPartitions;

    /**
     * @dev Mapping from partition to their index.
     */
    mapping(bytes32 => uint256) internal _indexOfTotalPartitions;

    /**
     * @dev Mapping from partition to global balance of corresponding partition.
     */
    mapping(bytes32 => uint256) public totalSupplyByPartition;

    /**
     * @dev Mapping from tokenHolder to their partitions.
     */
    mapping(address => bytes32[]) internal _partitionsOf;

    /**
     * @dev Mapping from (tokenHolder, partition) to their index.
     */
    mapping(address => mapping(bytes32 => uint256)) internal _indexOfPartitionsOf;

    /**
     * @dev Mapping from (tokenHolder, partition) to balance of corresponding
     * partition.
     */
    mapping(address => mapping(bytes32 => uint256)) internal _balanceOfByPartition;

    /**
     * @notice Default partition of the token.
     * @dev All ERC20 operations operate solely on this partition.
     */
    bytes32
        public constant defaultPartition = 0x0000000000000000000000000000000000000000000000000000000000000000;

    /**
     * @dev Zero partition prefix. Parititions with this prefix can not have
     * a strategy assigned, and partitions with a different prefix must have one.
     */
    bytes4 internal constant ZERO_PREFIX = 0x00000000;

    /**************************************************************************/
    /***************************** Operator mappings **************************/

    /**
     * @dev Mapping from (tokenHolder, operator) to authorized status. This is
     * specific to the token holder.
     */
    mapping(address => mapping(address => bool)) internal _authorizedOperator;

    /**************************************************************************/
    /********************** Partition operator mappings ***********************/

    /**
     * @dev Mapping from (partition, tokenHolder, spender) to allowed value.
     * This is specific to the token holder.
     */
    mapping(bytes32 => mapping(address => mapping(address => uint256)))
        internal _allowedByPartition;

    /**
     * @dev Mapping from (tokenHolder, partition, operator) to 'approved for
     * partition' status. This is specific to the token holder.
     */
    mapping(address => mapping(bytes32 => mapping(address => bool)))
        internal _authorizedOperatorByPartition;

    /**************************************************************************/
    /********************** Collateral Manager mappings ***********************/
    /**
     * @notice Collection of registered collateral managers.
     */
    address[] public collateralManagers;
    /**
     * @dev Mapping of collateral manager addresses to registration status.
     */
    mapping(address => bool) internal _isCollateralManager;

    /**************************************************************************/
    /********************* Partition Strategy mappings ************************/

    /**
     * @notice Collection of reserved partition strategies.
     */
    bytes4[] public partitionStrategies;

    /**
     * @dev Mapping of partition strategy flag to registration status.
     */
    mapping(bytes4 => bool) internal _isPartitionStrategy;

    /**************************************************************************/
    /***************************** Swap storage *******************************/

    /**
     * @notice Swap token address. Immutable.
     */
    ISwapToken public swapToken;

    /**
     * @notice Swap token graveyard address.
     * @dev This is the address that the incoming swapped tokens will be
     * forwarded to upon successfully minting Amp.
     */
    address
        public constant swapTokenGraveyard = 0x000000000000000000000000000000000000dEaD;

    /**************************************************************************/
    /** EVENTS ****************************************************************/
    /**************************************************************************/

    /**************************************************************************/
    /**************************** Transfer Events *****************************/

    /**
     * @notice Emitted when a transfer has been successfully completed.
     * @param fromPartition The partition the tokens were transfered from.
     * @param operator The address that initiated the transfer.
     * @param from The address the tokens were transferred from.
     * @param to The address the tokens were transferred to.
     * @param value The amount of tokens transferred.
     * @param data Additional metadata included with the transfer. Can include
     * the partition the tokens were transferred to (if different than
     * `fromPartition`).
     * @param operatorData Additional metadata included with the transfer on
     * behalf of the operator.
     */
    event TransferByPartition(
        bytes32 indexed fromPartition,
        address operator,
        address indexed from,
        address indexed to,
        uint256 value,
        bytes data,
        bytes operatorData
    );

    /**
     * @notice Emitted when a transfer has been successfully completed and the
     * tokens that were transferred have changed partitions.
     * @param fromPartition The partition the tokens were transfered from.
     * @param toPartition The partition the tokens were transfered to.
     * @param value The amount of tokens transferred.
     */
    event ChangedPartition(
        bytes32 indexed fromPartition,
        bytes32 indexed toPartition,
        uint256 value
    );

    /**************************************************************************/
    /**************************** Operator Events *****************************/

    /**
     * @notice Emitted when a token holder specifies an amount of tokens in a
     * a partition that an operator can transfer.
     * @param partition The partition of the tokens the holder has authorized the
     * operator to transfer from.
     * @param owner The token holder.
     * @param spender The operator the `owner` has authorized the allowance for.
     */
    event ApprovalByPartition(
        bytes32 indexed partition,
        address indexed owner,
        address indexed spender,
        uint256 value
    );

    /**
     * @notice Emitted when a token holder has authorized an operator for their
     * tokens.
     * @dev This event applies to the token holder address across all partitions.
     * @param operator The address that was authorized to transfer tokens on
     * behalf of the `tokenHolder`.
     * @param tokenHolder The address that authorized the `operator` to transfer
     * their tokens.
     */
    event AuthorizedOperator(address indexed operator, address indexed tokenHolder);

    /**
     * @notice Emitted when a token holder has de-authorized an operator from
     * transferring their tokens.
     * @dev This event applies to the token holder address across all partitions.
     * @param operator The address that was de-authorized from transferring tokens
     * on behalf of the `tokenHolder`.
     * @param tokenHolder The address that revoked the `operator`'s permission
     * to transfer their tokens.
     */
    event RevokedOperator(address indexed operator, address indexed tokenHolder);

    /**
     * @notice Emitted when a token holder has authorized an operator to transfer
     * their tokens of one partition.
     * @param partition The partition the `operator` is allowed to transfer
     * tokens from.
     * @param operator The address that was authorized to transfer tokens on
     * behalf of the `tokenHolder`.
     * @param tokenHolder The address that authorized the `operator` to transfer
     * their tokens in `partition`.
     */
    event AuthorizedOperatorByPartition(
        bytes32 indexed partition,
        address indexed operator,
        address indexed tokenHolder
    );

    /**
     * @notice Emitted when a token holder has de-authorized an operator from
     * transferring their tokens from a specific partition.
     * @param partition The partition the `operator` is no longer allowed to
     * transfer tokens from on behalf of the `tokenHolder`.
     * @param operator The address that was de-authorized from transferring
     * tokens on behalf of the `tokenHolder`.
     * @param tokenHolder The address that revoked the `operator`'s permission
     * to transfer their tokens from `partition`.
     */
    event RevokedOperatorByPartition(
        bytes32 indexed partition,
        address indexed operator,
        address indexed tokenHolder
    );

    /**************************************************************************/
    /********************** Collateral Manager Events *************************/

    /**
     * @notice Emitted when a collateral manager has been registered.
     * @param collateralManager The address of the collateral manager.
     */
    event CollateralManagerRegistered(address collateralManager);

    /**************************************************************************/
    /*********************** Partition Strategy Events ************************/

    /**
     * @notice Emitted when a new partition strategy validator is set.
     * @param flag The 4 byte prefix of the partitions that the stratgy affects.
     * @param name The name of the partition strategy.
     * @param implementation The address of the partition strategy hook
     * implementation.
     */
    event PartitionStrategySet(bytes4 flag, string name, address indexed implementation);

    // ************** Mint & Swap **************

    /**
     * @notice Emitted when tokens are minted as a result of a token swap
     * @param operator Address that executed the swap that resulted in tokens being minted
     * @param to Address that received the newly minted tokens.
     * @param value Amount of tokens minted
     * @param data Empty bytes, required for interface compatibility
     */
    event Minted(address indexed operator, address indexed to, uint256 value, bytes data);

    /**
     * @notice Indicates tokens swapped for Amp.
     * @dev The tokens that are swapped for Amp will be transferred to a
     * graveyard address that is for all practical purposes inaccessible.
     * @param operator Address that executed the swap.
     * @param from Address that the tokens were swapped from, and Amp minted for.
     * @param value Amount of tokens swapped into Amp.
     */
    event Swap(address indexed operator, address indexed from, uint256 value);

    /**************************************************************************/
    /** CONSTRUCTOR ***********************************************************/
    /**************************************************************************/

    /**
     * @notice Initialize Amp, initialize the default partition, and register the
     * contract implementation in the global ERC1820Registry.
     * @param _swapTokenAddress_ The address of the ERC20 token that is set to be
     * swappable for Amp.
     * @param _name_ Name of the token.
     * @param _symbol_ Symbol of the token.
     */
    constructor(
        address _swapTokenAddress_,
        string memory _name_,
        string memory _symbol_
    ) public {
        // "Swap token cannot be 0 address"
        require(_swapTokenAddress_ != address(0), EC_5A_INVALID_SWAP_TOKEN_ADDRESS);
        swapToken = ISwapToken(_swapTokenAddress_);

        _name = _name_;
        _symbol = _symbol_;
        _totalSupply = 0;

        // Add the default partition to the total partitions on deploy
        _addPartitionToTotalPartitions(defaultPartition);

        // Register contract in ERC1820 registry
        ERC1820Client.setInterfaceImplementation(AMP_INTERFACE_NAME, address(this));
        ERC1820Client.setInterfaceImplementation(ERC20_INTERFACE_NAME, address(this));

        // Indicate token verifies Amp and ERC20 interfaces
        ERC1820Implementer._setInterface(AMP_INTERFACE_NAME);
        ERC1820Implementer._setInterface(ERC20_INTERFACE_NAME);
    }

    /**************************************************************************/
    /** EXTERNAL FUNCTIONS (ERC20) ********************************************/
    /**************************************************************************/

    /**
     * @notice Get the total number of issued tokens.
     * @return Total supply of tokens currently in circulation.
     */
    function totalSupply() external override view returns (uint256) {
        return _totalSupply;
    }

    /**
     * @notice Get the balance of the account with address `_tokenHolder`.
     * @dev This returns the balance of the holder across all partitions. Note
     * that due to other functionality in Amp, this figure should not be used
     * as the arbiter of the amount a token holder will successfully be able to
     * send via the ERC20 compatible `transfer` method. In order to get that
     * figure, use `balanceOfByParition` and to get the balance of the default
     * partition.
     * @param _tokenHolder Address for which the balance is returned.
     * @return Amount of token held by `_tokenHolder` in the default partition.
     */
    function balanceOf(address _tokenHolder) external override view returns (uint256) {
        return _balances[_tokenHolder];
    }

    /**
     * @notice Transfer token for a specified address.
     * @dev This method is for ERC20 compatibility, and only affects the
     * balance of the `msg.sender` address's default partition.
     * @param _to The address to transfer to.
     * @param _value The value to be transferred.
     * @return A boolean that indicates if the operation was successful.
     */
    function transfer(address _to, uint256 _value) external override returns (bool) {
        _transferByDefaultPartition(msg.sender, msg.sender, _to, _value, "");
        return true;
    }

    /**
     * @notice Transfer tokens from one address to another.
     * @dev This method is for ERC20 compatibility, and only affects the
     * balance and allowance of the `_from` address's default partition.
     * @param _from The address which you want to transfer tokens from.
     * @param _to The address which you want to transfer to.
     * @param _value The amount of tokens to be transferred.
     * @return A boolean that indicates if the operation was successful.
     */
    function transferFrom(
        address _from,
        address _to,
        uint256 _value
    ) external override returns (bool) {
        _transferByDefaultPartition(msg.sender, _from, _to, _value, "");
        return true;
    }

    /**
     * @notice Check the value of tokens that an owner allowed to a spender.
     * @dev This method is for ERC20 compatibility, and only affects the
     * allowance of the `msg.sender`'s default partition.
     * @param _owner address The address which owns the funds.
     * @param _spender address The address which will spend the funds.
     * @return A uint256 specifying the value of tokens still available for the
     * spender.
     */
    function allowance(address _owner, address _spender)
        external
        override
        view
        returns (uint256)
    {
        return _allowedByPartition[defaultPartition][_owner][_spender];
    }

    /**
     * @notice Approve the passed address to spend the specified amount of
     * tokens from the default partition on behalf of 'msg.sender'.
     * @dev This method is for ERC20 compatibility, and only affects the
     * allowance of the `msg.sender`'s default partition.
     * @param _spender The address which will spend the funds.
     * @param _value The amount of tokens to be spent.
     * @return A boolean that indicates if the operation was successful.
     */
    function approve(address _spender, uint256 _value) external override returns (bool) {
        _approveByPartition(defaultPartition, msg.sender, _spender, _value);
        return true;
    }

    /**
     * @notice Atomically increases the allowance granted to `_spender` by the
     * for caller.
     * @dev This is an alternative to {approve} that can be used as a mitigation
     * problems described in {IERC20-approve}.
     * Emits an {Approval} event indicating the updated allowance.
     * Requirements:
     * - `_spender` cannot be the zero address.
     * @dev This method is for ERC20 compatibility, and only affects the
     * allowance of the `msg.sender`'s default partition.
     * @param _spender Operator allowed to transfer the tokens
     * @param _addedValue Additional amount of the `msg.sender`s tokens `_spender`
     * is allowed to transfer
     * @return 'true' is successful, 'false' otherwise
     */
    function increaseAllowance(address _spender, uint256 _addedValue)
        external
        returns (bool)
    {
        _approveByPartition(
            defaultPartition,
            msg.sender,
            _spender,
            _allowedByPartition[defaultPartition][msg.sender][_spender].add(_addedValue)
        );
        return true;
    }

    /**
     * @notice Atomically decreases the allowance granted to `_spender` by the
     * caller.
     * @dev This is an alternative to {approve} that can be used as a mitigation
     * for bugs caused by reentrancy.
     * Emits an {Approval} event indicating the updated allowance.
     * Requirements:
     * - `_spender` cannot be the zero address.
     * - `_spender` must have allowance for the caller of at least
     * `_subtractedValue`.
     * @dev This method is for ERC20 compatibility, and only affects the
     * allowance of the `msg.sender`'s default partition.
     * @param _spender Operator allowed to transfer the tokens
     * @param _subtractedValue Amount of the `msg.sender`s tokens `_spender`
     * is no longer allowed to transfer
     * @return 'true' is successful, 'false' otherwise
     */
    function decreaseAllowance(address _spender, uint256 _subtractedValue)
        external
        returns (bool)
    {
        _approveByPartition(
            defaultPartition,
            msg.sender,
            _spender,
            _allowedByPartition[defaultPartition][msg.sender][_spender].sub(
                _subtractedValue
            )
        );
        return true;
    }

    /**************************************************************************/
    /** EXTERNAL FUNCTIONS (AMP) **********************************************/
    /**************************************************************************/

    /******************************** Swap  ***********************************/

    /**
     * @notice Swap tokens to mint AMP.
     * @dev Requires `_from` to have given allowance of swap token to contract.
     * Otherwise will throw error code 53 (Insuffient Allowance).
     * @param _from Token holder to execute the swap for.
     */
    function swap(address _from) public {
        uint256 amount = swapToken.allowance(_from, address(this));
        require(amount > 0, EC_53_INSUFFICIENT_ALLOWANCE);

        require(
            swapToken.transferFrom(_from, swapTokenGraveyard, amount),
            EC_60_SWAP_TRANSFER_FAILURE
        );

        _mint(msg.sender, _from, amount);

        emit Swap(msg.sender, _from, amount);
    }

    /**************************************************************************/
    /************************** Holder information ****************************/

    /**
     * @notice Get balance of a tokenholder for a specific partition.
     * @param _partition Name of the partition.
     * @param _tokenHolder Address for which the balance is returned.
     * @return Amount of token of partition `_partition` held by `_tokenHolder` in the token contract.
     */
    function balanceOfByPartition(bytes32 _partition, address _tokenHolder)
        external
        view
        returns (uint256)
    {
        return _balanceOfByPartition[_tokenHolder][_partition];
    }

    /**
     * @notice Get partitions index of a token holder.
     * @param _tokenHolder Address for which the partitions index are returned.
     * @return Array of partitions index of '_tokenHolder'.
     */
    function partitionsOf(address _tokenHolder) external view returns (bytes32[] memory) {
        return _partitionsOf[_tokenHolder];
    }

    /**************************************************************************/
    /************************** Advanced Transfers ****************************/

    /**
     * @notice Transfer tokens from a specific partition on behalf of a token
     * holder, optionally changing the parittion and optionally including
     * arbitrary data with the transfer.
     * @dev This can be used to transfer an address's own tokens, or transfer
     * a different addresses tokens by specifying the `_from` param. If
     * attempting to transfer from a different address than `msg.sender`, the
     * `msg.sender` will need to be an operator or have enough allowance for the
     * `_partition` of the `_from` address.
     * @param _partition Name of the partition to transfer from.
     * @param _from Token holder.
     * @param _to Token recipient.
     * @param _value Number of tokens to transfer.
     * @param _data Information attached to the transfer. Will contain the
     * destination partition (if changing partitions).
     * @param _operatorData Information attached to the transfer, by the operator.
     * @return Destination partition.
     */
    function transferByPartition(
        bytes32 _partition,
        address _from,
        address _to,
        uint256 _value,
        bytes calldata _data,
        bytes calldata _operatorData
    ) external returns (bytes32) {
        return
            _transferByPartition(
                _partition,
                msg.sender,
                _from,
                _to,
                _value,
                _data,
                _operatorData
            );
    }

    /**************************************************************************/
    /************************** Operator Management ***************************/

    /**
     * @notice Set a third party operator address as an operator of 'msg.sender'
     * to transfer and redeem tokens on its behalf.
     * @dev The msg.sender is always an operator for itself, and does not need to
     * be explicitly added.
     * @param _operator Address to set as an operator for 'msg.sender'.
     */
    function authorizeOperator(address _operator) external {
        require(_operator != msg.sender, EC_58_INVALID_OPERATOR);

        _authorizedOperator[msg.sender][_operator] = true;
        emit AuthorizedOperator(_operator, msg.sender);
    }

    /**
     * @notice Remove the right of the operator address to be an operator for
     * 'msg.sender' and to transfer and redeem tokens on its behalf.
     * @dev The msg.sender is always an operator for itself, and cannot be
     * removed.
     * @param _operator Address to rescind as an operator for 'msg.sender'.
     */
    function revokeOperator(address _operator) external {
        require(_operator != msg.sender, EC_58_INVALID_OPERATOR);

        _authorizedOperator[msg.sender][_operator] = false;
        emit RevokedOperator(_operator, msg.sender);
    }

    /**
     * @notice Set `_operator` as an operator for 'msg.sender' for a given partition.
     * @dev The msg.sender is always an operator for itself, and does not need to
     * be explicitly added to a partition.
     * @param _partition Name of the partition.
     * @param _operator Address to set as an operator for 'msg.sender'.
     */
    function authorizeOperatorByPartition(bytes32 _partition, address _operator)
        external
    {
        require(_operator != msg.sender, EC_58_INVALID_OPERATOR);

        _authorizedOperatorByPartition[msg.sender][_partition][_operator] = true;
        emit AuthorizedOperatorByPartition(_partition, _operator, msg.sender);
    }

    /**
     * @notice Remove the right of the operator address to be an operator on a
     * given partition for 'msg.sender' and to transfer and redeem tokens on its
     * behalf.
     * @dev The msg.sender is always an operator for itself, and cannot be
     * removed from a partition.
     * @param _partition Name of the partition.
     * @param _operator Address to rescind as an operator on given partition for
     * 'msg.sender'.
     */
    function revokeOperatorByPartition(bytes32 _partition, address _operator) external {
        require(_operator != msg.sender, EC_58_INVALID_OPERATOR);

        _authorizedOperatorByPartition[msg.sender][_partition][_operator] = false;
        emit RevokedOperatorByPartition(_partition, _operator, msg.sender);
    }

    /**************************************************************************/
    /************************** Operator Information **************************/
    /**
     * @notice Indicate whether the `_operator` address is an operator of the
     * `_tokenHolder` address.
     * @dev An operator in this case is an operator across all of the partitions
     * of the `msg.sender` address.
     * @param _operator Address which may be an operator of `_tokenHolder`.
     * @param _tokenHolder Address of a token holder which may have the
     * `_operator` address as an operator.
     * @return 'true' if operator is an operator of 'tokenHolder' and 'false'
     * otherwise.
     */
    function isOperator(address _operator, address _tokenHolder)
        external
        view
        returns (bool)
    {
        return _isOperator(_operator, _tokenHolder);
    }

    /**
     * @notice Indicate whether the operator address is an operator of the
     * `_tokenHolder` address for the given partition.
     * @param _partition Name of the partition.
     * @param _operator Address which may be an operator of tokenHolder for the
     * given partition.
     * @param _tokenHolder Address of a token holder which may have the
     * `_operator` address as an operator for the given partition.
     * @return 'true' if 'operator' is an operator of `_tokenHolder` for
     * partition '_partition' and 'false' otherwise.
     */
    function isOperatorForPartition(
        bytes32 _partition,
        address _operator,
        address _tokenHolder
    ) external view returns (bool) {
        return _isOperatorForPartition(_partition, _operator, _tokenHolder);
    }

    /**
     * @notice Indicate when the `_operator` address is an operator of the
     * `_collateralManager` address for the given partition.
     * @dev This method is the same as `isOperatorForPartition`, except that it
     * also requires the address that `_operator` is being checked for MUST be
     * a registered collateral manager, and this method will not execute
     * partition strategy operator check hooks.
     * @param _partition Name of the partition.
     * @param _operator Address which may be an operator of `_collateralManager`
     * for the given partition.
     * @param _collateralManager Address of a collateral manager which may have
     * the `_operator` address as an operator for the given partition.
     */
    function isOperatorForCollateralManager(
        bytes32 _partition,
        address _operator,
        address _collateralManager
    ) external view returns (bool) {
        return
            _isCollateralManager[_collateralManager] &&
            (_isOperator(_operator, _collateralManager) ||
                _authorizedOperatorByPartition[_collateralManager][_partition][_operator]);
    }

    /**************************************************************************/
    /***************************** Token metadata *****************************/
    /**
     * @notice Get the name of the token (Amp).
     * @return Name of the token.
     */
    function name() external view returns (string memory) {
        return _name;
    }

    /**
     * @notice Get the symbol of the token (AMP).
     * @return Symbol of the token.
     */
    function symbol() external view returns (string memory) {
        return _symbol;
    }

    /**
     * @notice Get the number of decimals of the token.
     * @dev Hard coded to 18.
     * @return The number of decimals of the token (18).
     */
    function decimals() external pure returns (uint8) {
        return uint8(18);
    }

    /**
     * @notice Get the smallest part of the token that’s not divisible.
     * @dev Hard coded to 1.
     * @return The smallest non-divisible part of the token.
     */
    function granularity() external pure returns (uint256) {
        return _granularity;
    }

    /**
     * @notice Get list of existing partitions.
     * @return Array of all exisiting partitions.
     */
    function totalPartitions() external view returns (bytes32[] memory) {
        return _totalPartitions;
    }

    /************************************************************************************************/
    /******************************** Partition Token Allowances ************************************/
    /**
     * @notice Check the value of tokens that an owner allowed to a spender.
     * @param _partition Name of the partition.
     * @param _owner The address which owns the tokens.
     * @param _spender The address which will spend the tokens.
     * @return The value of tokens still for the spender to transfer.
     */
    function allowanceByPartition(
        bytes32 _partition,
        address _owner,
        address _spender
    ) external view returns (uint256) {
        return _allowedByPartition[_partition][_owner][_spender];
    }

    /**
     * @notice Approve the `_spender` address to spend the specified amount of
     * tokens in `_partition` on behalf of 'msg.sender'.
     * @param _partition Name of the partition.
     * @param _spender The address which will spend the tokens.
     * @param _value The amount of tokens to be tokens.
     * @return A boolean that indicates if the operation was successful.
     */
    function approveByPartition(
        bytes32 _partition,
        address _spender,
        uint256 _value
    ) external returns (bool) {
        _approveByPartition(_partition, msg.sender, _spender, _value);
        return true;
    }

    /**
     * @notice Atomically increases the allowance granted to `_spender` by the
     * caller.
     * @dev This is an alternative to {approveByPartition} that can be used as
     * a mitigation for bugs caused by reentrancy.
     * Emits an {ApprovalByPartition} event indicating the updated allowance.
     * Requirements:
     * - `_spender` cannot be the zero address.
     * @param _partition Name of the partition.
     * @param _spender Operator allowed to transfer the tokens
     * @param _addedValue Additional amount of the `msg.sender`s tokens `_spender`
     * is allowed to transfer
     * @return 'true' is successful, 'false' otherwise
     */
    function increaseAllowanceByPartition(
        bytes32 _partition,
        address _spender,
        uint256 _addedValue
    ) external returns (bool) {
        _approveByPartition(
            _partition,
            msg.sender,
            _spender,
            _allowedByPartition[_partition][msg.sender][_spender].add(_addedValue)
        );
        return true;
    }

    /**
     * @notice Atomically decreases the allowance granted to `_spender` by the
     * caller.
     * @dev This is an alternative to {approveByPartition} that can be used as
     * a mitigation for bugs caused by reentrancy.
     * Emits an {ApprovalByPartition} event indicating the updated allowance.
     * Requirements:
     * - `_spender` cannot be the zero address.
     * - `_spender` must have allowance for the caller of at least
     * `_subtractedValue`.
     * @param _spender Operator allowed to transfer the tokens
     * @param _subtractedValue Amount of the `msg.sender`s tokens `_spender` is
     * no longer allowed to transfer
     * @return 'true' is successful, 'false' otherwise
     */
    function decreaseAllowanceByPartition(
        bytes32 _partition,
        address _spender,
        uint256 _subtractedValue
    ) external returns (bool) {
        // TOOD: Figure out if safe math will panic below 0
        _approveByPartition(
            _partition,
            msg.sender,
            _spender,
            _allowedByPartition[_partition][msg.sender][_spender].sub(_subtractedValue)
        );
        return true;
    }

    /**************************************************************************/
    /************************ Collateral Manager Admin ************************/

    /**
     * @notice Allow a collateral manager to self-register.
     * @dev Error 0x5c.
     */
    function registerCollateralManager() external {
        // Short circuit a double registry
        require(!_isCollateralManager[msg.sender], EC_5C_ADDRESS_CONFLICT);

        collateralManagers.push(msg.sender);
        _isCollateralManager[msg.sender] = true;

        emit CollateralManagerRegistered(msg.sender);
    }

    /**
     * @notice Get the status of a collateral manager.
     * @param _collateralManager The address of the collateral mananger in question.
     * @return 'true' if `_collateralManager` has self registered, 'false'
     * otherwise.
     */
    function isCollateralManager(address _collateralManager)
        external
        view
        returns (bool)
    {
        return _isCollateralManager[_collateralManager];
    }

    /**************************************************************************/
    /************************ Partition Strategy Admin ************************/
    /**
     * @notice Sets an implementation for a partition strategy identified by prefix.
     * @dev This is an administration method, callable only by the owner of the
     * Amp contract.
     * @param _prefix The 4 byte partition prefix the strategy applies to.
     * @param _implementation The address of the implementation of the strategy hooks.
     */
    function setPartitionStrategy(bytes4 _prefix, address _implementation) external {
        require(msg.sender == owner(), EC_56_INVALID_SENDER);
        require(!_isPartitionStrategy[_prefix], EC_5E_PARTITION_PREFIX_CONFLICT);
        require(_prefix != ZERO_PREFIX, EC_5F_INVALID_PARTITION_PREFIX_0);

        string memory iname = PartitionUtils._getPartitionStrategyValidatorIName(_prefix);

        ERC1820Client.setInterfaceImplementation(iname, _implementation);
        partitionStrategies.push(_prefix);
        _isPartitionStrategy[_prefix] = true;

        emit PartitionStrategySet(_prefix, iname, _implementation);
    }

    /**
     * @notice Return if a partition strategy has been reserved and has an
     * implementation registered.
     * @param _prefix The partition strategy identifier.
     * @return 'true' if the strategy has been registered, 'false' if not.
     */
    function isPartitionStrategy(bytes4 _prefix) external view returns (bool) {
        return _isPartitionStrategy[_prefix];
    }

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

    /**************************************************************************/
    /**************************** Token Transfers *****************************/

    /**
     * @dev Transfer tokens from a specific partition.
     * @param _fromPartition Partition of the tokens to transfer.
     * @param _operator The address performing the transfer.
     * @param _from Token holder.
     * @param _to Token recipient.
     * @param _value Number of tokens to transfer.
     * @param _data Information attached to the transfer. Contains the destination
     * partition if a partition change is requested.
     * @param _operatorData Information attached to the transfer, by the operator
     * (if any).
     * @return Destination partition.
     */
    function _transferByPartition(
        bytes32 _fromPartition,
        address _operator,
        address _from,
        address _to,
        uint256 _value,
        bytes memory _data,
        bytes memory _operatorData
    ) internal returns (bytes32) {
        require(_to != address(0), EC_57_INVALID_RECEIVER);

        // If the `_operator` is attempting to transfer from a different `_from`
        // address, first check that they have the requisite operator or
        // allowance permissions.
        if (_from != _operator) {
            require(
                _isOperatorForPartition(_fromPartition, _operator, _from) ||
                    (_value <= _allowedByPartition[_fromPartition][_from][_operator]),
                EC_53_INSUFFICIENT_ALLOWANCE
            );

            // If the sender has an allowance for the partition, that should
            // be decremented
            if (_allowedByPartition[_fromPartition][_from][_operator] >= _value) {
                _allowedByPartition[_fromPartition][_from][msg
                    .sender] = _allowedByPartition[_fromPartition][_from][_operator].sub(
                    _value
                );
            } else {
                _allowedByPartition[_fromPartition][_from][_operator] = 0;
            }
        }

        _callPreTransferHooks(
            _fromPartition,
            _operator,
            _from,
            _to,
            _value,
            _data,
            _operatorData
        );

        require(
            _balanceOfByPartition[_from][_fromPartition] >= _value,
            EC_52_INSUFFICIENT_BALANCE
        );

        bytes32 toPartition = PartitionUtils._getDestinationPartition(
            _data,
            _fromPartition
        );

        _removeTokenFromPartition(_from, _fromPartition, _value);
        _addTokenToPartition(_to, toPartition, _value);
        _callPostTransferHooks(
            toPartition,
            _operator,
            _from,
            _to,
            _value,
            _data,
            _operatorData
        );

        emit Transfer(_from, _to, _value);
        emit TransferByPartition(
            _fromPartition,
            _operator,
            _from,
            _to,
            _value,
            _data,
            _operatorData
        );

        if (toPartition != _fromPartition) {
            emit ChangedPartition(_fromPartition, toPartition, _value);
        }

        return toPartition;
    }

    /**
     * @notice Transfer tokens from default partitions.
     * @dev Used as a helper method for ERC20 compatibility.
     * @param _operator The address performing the transfer.
     * @param _from Token holder.
     * @param _to Token recipient.
     * @param _value Number of tokens to transfer.
     * @param _data Information attached to the transfer, and intended for the
     * token holder (`_from`). Should contain the destination partition if
     * changing partitions.
     */
    function _transferByDefaultPartition(
        address _operator,
        address _from,
        address _to,
        uint256 _value,
        bytes memory _data
    ) internal {
        _transferByPartition(defaultPartition, _operator, _from, _to, _value, _data, "");
    }

    /**
     * @dev Remove a token from a specific partition.
     * @param _from Token holder.
     * @param _partition Name of the partition.
     * @param _value Number of tokens to transfer.
     */
    function _removeTokenFromPartition(
        address _from,
        bytes32 _partition,
        uint256 _value
    ) internal {
        if (_value == 0) {
            return;
        }

        _balances[_from] = _balances[_from].sub(_value);

        _balanceOfByPartition[_from][_partition] = _balanceOfByPartition[_from][_partition]
            .sub(_value);
        totalSupplyByPartition[_partition] = totalSupplyByPartition[_partition].sub(
            _value
        );

        // If the total supply is zero, finds and deletes the partition.
        // Do not delete the _defaultPartition from totalPartitions.
        if (totalSupplyByPartition[_partition] == 0 && _partition != defaultPartition) {
            _removePartitionFromTotalPartitions(_partition);
        }

        // If the balance of the TokenHolder's partition is zero, finds and
        // deletes the partition.
        if (_balanceOfByPartition[_from][_partition] == 0) {
            uint256 index = _indexOfPartitionsOf[_from][_partition];

            if (index == 0) {
                return;
            }

            // move the last item into the index being vacated
            bytes32 lastValue = _partitionsOf[_from][_partitionsOf[_from].length - 1];
            _partitionsOf[_from][index - 1] = lastValue; // adjust for 1-based indexing
            _indexOfPartitionsOf[_from][lastValue] = index;

            _partitionsOf[_from].pop();
            _indexOfPartitionsOf[_from][_partition] = 0;
        }
    }

    /**
     * @dev Add a token to a specific partition.
     * @param _to Token recipient.
     * @param _partition Name of the partition.
     * @param _value Number of tokens to transfer.
     */
    function _addTokenToPartition(
        address _to,
        bytes32 _partition,
        uint256 _value
    ) internal {
        if (_value == 0) {
            return;
        }

        _balances[_to] = _balances[_to].add(_value);

        if (_indexOfPartitionsOf[_to][_partition] == 0) {
            _partitionsOf[_to].push(_partition);
            _indexOfPartitionsOf[_to][_partition] = _partitionsOf[_to].length;
        }
        _balanceOfByPartition[_to][_partition] = _balanceOfByPartition[_to][_partition]
            .add(_value);

        if (_indexOfTotalPartitions[_partition] == 0) {
            _addPartitionToTotalPartitions(_partition);
        }
        totalSupplyByPartition[_partition] = totalSupplyByPartition[_partition].add(
            _value
        );
    }

    /**
     * @dev Add a partition to the total partitions collection.
     * @param _partition Name of the partition.
     */
    function _addPartitionToTotalPartitions(bytes32 _partition) internal {
        _totalPartitions.push(_partition);
        _indexOfTotalPartitions[_partition] = _totalPartitions.length;
    }

    /**
     * @dev Remove a partition to the total partitions collection.
     * @param _partition Name of the partition.
     */
    function _removePartitionFromTotalPartitions(bytes32 _partition) internal {
        uint256 index = _indexOfTotalPartitions[_partition];

        if (index == 0) {
            return;
        }

        // move the last item into the index being vacated
        bytes32 lastValue = _totalPartitions[_totalPartitions.length - 1];
        _totalPartitions[index - 1] = lastValue; // adjust for 1-based indexing
        _indexOfTotalPartitions[lastValue] = index;

        _totalPartitions.pop();
        _indexOfTotalPartitions[_partition] = 0;
    }

    /**************************************************************************/
    /********************************* Hooks **********************************/
    /**
     * @notice Check for and call the 'AmpTokensSender' hook on the sender address
     * (`_from`), and, if `_fromPartition` is within the scope of a strategy,
     * check for and call the 'AmpPartitionStrategy.tokensFromPartitionToTransfer'
     * hook for the strategy.
     * @param _fromPartition Name of the partition to transfer tokens from.
     * @param _operator Address which triggered the balance decrease (through
     * transfer).
     * @param _from Token holder.
     * @param _to Token recipient for a transfer.
     * @param _value Number of tokens the token holder balance is decreased by.
     * @param _data Extra information, pertaining to the `_from` address.
     * @param _operatorData Extra information, attached by the operator (if any).
     */
    function _callPreTransferHooks(
        bytes32 _fromPartition,
        address _operator,
        address _from,
        address _to,
        uint256 _value,
        bytes memory _data,
        bytes memory _operatorData
    ) internal {
        address senderImplementation;
        senderImplementation = interfaceAddr(_from, AMP_TOKENS_SENDER);
        if (senderImplementation != address(0)) {
            IAmpTokensSender(senderImplementation).tokensToTransfer(
                msg.sig,
                _fromPartition,
                _operator,
                _from,
                _to,
                _value,
                _data,
                _operatorData
            );
        }

        // Used to ensure that hooks implemented by a collateral manager to validate
        // transfers from it's owned partitions are called
        bytes4 fromPartitionPrefix = PartitionUtils._getPartitionPrefix(_fromPartition);
        if (_isPartitionStrategy[fromPartitionPrefix]) {
            address fromPartitionValidatorImplementation;
            fromPartitionValidatorImplementation = interfaceAddr(
                address(this),
                PartitionUtils._getPartitionStrategyValidatorIName(fromPartitionPrefix)
            );
            if (fromPartitionValidatorImplementation != address(0)) {
                IAmpPartitionStrategyValidator(fromPartitionValidatorImplementation)
                    .tokensFromPartitionToValidate(
                    msg.sig,
                    _fromPartition,
                    _operator,
                    _from,
                    _to,
                    _value,
                    _data,
                    _operatorData
                );
            }
        }
    }

    /**
     * @dev Check for 'AmpTokensRecipient' hook on the recipient and call it.
     * @param _toPartition Name of the partition the tokens were transferred to.
     * @param _operator Address which triggered the balance increase (through
     * transfer or mint).
     * @param _from Token holder for a transfer (0x when mint).
     * @param _to Token recipient.
     * @param _value Number of tokens the recipient balance is increased by.
     * @param _data Extra information related to the token holder (`_from`).
     * @param _operatorData Extra information attached by the operator (if any).
     */
    function _callPostTransferHooks(
        bytes32 _toPartition,
        address _operator,
        address _from,
        address _to,
        uint256 _value,
        bytes memory _data,
        bytes memory _operatorData
    ) internal {
        bytes4 toPartitionPrefix = PartitionUtils._getPartitionPrefix(_toPartition);
        if (_isPartitionStrategy[toPartitionPrefix]) {
            address partitionManagerImplementation;
            partitionManagerImplementation = interfaceAddr(
                address(this),
                PartitionUtils._getPartitionStrategyValidatorIName(toPartitionPrefix)
            );
            if (partitionManagerImplementation != address(0)) {
                IAmpPartitionStrategyValidator(partitionManagerImplementation)
                    .tokensToPartitionToValidate(
                    msg.sig,
                    _toPartition,
                    _operator,
                    _from,
                    _to,
                    _value,
                    _data,
                    _operatorData
                );
            }
        } else {
            require(toPartitionPrefix == ZERO_PREFIX, EC_5D_PARTITION_RESERVED);
        }

        address recipientImplementation;
        recipientImplementation = interfaceAddr(_to, AMP_TOKENS_RECIPIENT);

        if (recipientImplementation != address(0)) {
            IAmpTokensRecipient(recipientImplementation).tokensReceived(
                msg.sig,
                _toPartition,
                _operator,
                _from,
                _to,
                _value,
                _data,
                _operatorData
            );
        }
    }

    /**************************************************************************/
    /******************************* Allowance ********************************/
    /**
     * @notice Approve the `_spender` address to spend the specified amount of
     * tokens in `_partition` on behalf of 'msg.sender'.
     * @param _partition Name of the partition.
     * @param _tokenHolder Owner of the tokens.
     * @param _spender The address which will spend the tokens.
     * @param _amount The amount of tokens to be tokens.
     */
    function _approveByPartition(
        bytes32 _partition,
        address _tokenHolder,
        address _spender,
        uint256 _amount
    ) internal {
        require(_tokenHolder != address(0), EC_56_INVALID_SENDER);
        require(_spender != address(0), EC_58_INVALID_OPERATOR);

        _allowedByPartition[_partition][_tokenHolder][_spender] = _amount;
        emit ApprovalByPartition(_partition, _tokenHolder, _spender, _amount);

        if (_partition == defaultPartition) {
            emit Approval(_tokenHolder, _spender, _amount);
        }
    }

    /**************************************************************************/
    /************************** Operator Information **************************/
    /**
     * @dev Indicate whether the operator address is an operator of the
     * tokenHolder address. An operator in this case is an operator across all
     * partitions of the `msg.sender` address.
     * @param _operator Address which may be an operator of '_tokenHolder'.
     * @param _tokenHolder Address of a token holder which may have the '_operator'
     * address as an operator.
     * @return 'true' if `_operator` is an operator of `_tokenHolder` and 'false'
     * otherwise.
     */
    function _isOperator(address _operator, address _tokenHolder)
        internal
        view
        returns (bool)
    {
        return (_operator == _tokenHolder ||
            _authorizedOperator[_tokenHolder][_operator]);
    }

    /**
     * @dev Indicate whether the operator address is an operator of the
     * tokenHolder address for the given partition.
     * @param _partition Name of the partition.
     * @param _operator Address which may be an operator of tokenHolder for the
     * given partition.
     * @param _tokenHolder Address of a token holder which may have the operator
     * address as an operator for the given partition.
     * @return 'true' if 'operator' is an operator of 'tokenHolder' for partition
     * `_partition` and 'false' otherwise.
     */
    function _isOperatorForPartition(
        bytes32 _partition,
        address _operator,
        address _tokenHolder
    ) internal view returns (bool) {
        return (_isOperator(_operator, _tokenHolder) ||
            _authorizedOperatorByPartition[_tokenHolder][_partition][_operator] ||
            _callPartitionStrategyOperatorHook(_partition, _operator, _tokenHolder));
    }

    /**
     * @notice Check if the `_partition` is within the scope of a strategy, and
     * call it's isOperatorForPartitionScope hook if so.
     * @dev This allows implicit granting of operatorByPartition permissions
     * based on the partition being used being of a strategy.
     * @param _partition The partition to check.
     * @param _operator The address to check if is an operator for `_tokenHolder`.
     * @param _tokenHolder The address to validate that `_operator` is an
     * operator for.
     */
    function _callPartitionStrategyOperatorHook(
        bytes32 _partition,
        address _operator,
        address _tokenHolder
    ) internal view returns (bool) {
        bytes4 prefix = PartitionUtils._getPartitionPrefix(_partition);

        if (!_isPartitionStrategy[prefix]) {
            return false;
        }

        address strategyValidatorImplementation;
        strategyValidatorImplementation = interfaceAddr(
            address(this),
            PartitionUtils._getPartitionStrategyValidatorIName(prefix)
        );
        if (strategyValidatorImplementation != address(0)) {
            return
                IAmpPartitionStrategyValidator(strategyValidatorImplementation)
                    .isOperatorForPartitionScope(_partition, _operator, _tokenHolder);
        }

        // Not a partition format that imbues special operator rules
        return false;
    }

    /**************************************************************************/
    /******************************** Minting *********************************/
    /**
     * @notice Perform the minting of tokens.
     * @dev The tokens will be minted on behalf of the `_to` address, and will be
     * minted to the address's default partition.
     * @param _operator Address which triggered the issuance.
     * @param _to Token recipient.
     * @param _value Number of tokens issued.
     */
    function _mint(
        address _operator,
        address _to,
        uint256 _value
    ) internal {
        require(_to != address(0), EC_57_INVALID_RECEIVER);

        _totalSupply = _totalSupply.add(_value);
        _addTokenToPartition(_to, defaultPartition, _value);
        _callPostTransferHooks(
            defaultPartition,
            _operator,
            address(0),
            _to,
            _value,
            "",
            ""
        );

        emit Minted(_operator, _to, _value, "");
        emit Transfer(address(0), _to, _value);
        emit TransferByPartition(bytes32(0), _operator, address(0), _to, _value, "", "");
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_swapTokenAddress_","type":"address"},{"internalType":"string","name":"_name_","type":"string"},{"internalType":"string","name":"_symbol_","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"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":true,"internalType":"bytes32","name":"partition","type":"bytes32"},{"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":"ApprovalByPartition","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"tokenHolder","type":"address"}],"name":"AuthorizedOperator","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"partition","type":"bytes32"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"tokenHolder","type":"address"}],"name":"AuthorizedOperatorByPartition","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"fromPartition","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"toPartition","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"ChangedPartition","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"collateralManager","type":"address"}],"name":"CollateralManagerRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"Minted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldValue","type":"address"},{"indexed":true,"internalType":"address","name":"newValue","type":"address"}],"name":"OwnerUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"authorizedAddress","type":"address"}],"name":"OwnershipTransferAuthorization","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes4","name":"flag","type":"bytes4"},{"indexed":false,"internalType":"string","name":"name","type":"string"},{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"PartitionStrategySet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"tokenHolder","type":"address"}],"name":"RevokedOperator","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"partition","type":"bytes32"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"tokenHolder","type":"address"}],"name":"RevokedOperatorByPartition","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Swap","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"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"fromPartition","type":"bytes32"},{"indexed":false,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"operatorData","type":"bytes"}],"name":"TransferByPartition","type":"event"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_partition","type":"bytes32"},{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_spender","type":"address"}],"name":"allowanceByPartition","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_partition","type":"bytes32"},{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"approveByPartition","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"assumeOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_operator","type":"address"}],"name":"authorizeOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_partition","type":"bytes32"},{"internalType":"address","name":"_operator","type":"address"}],"name":"authorizeOperatorByPartition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_authorizedAddress","type":"address"}],"name":"authorizeOwnershipTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"authorizedNewOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenHolder","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_partition","type":"bytes32"},{"internalType":"address","name":"_tokenHolder","type":"address"}],"name":"balanceOfByPartition","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_interfaceHash","type":"bytes32"},{"internalType":"address","name":"","type":"address"}],"name":"canImplementInterfaceForAddress","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"collateralManagers","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_partition","type":"bytes32"},{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_subtractedValue","type":"uint256"}],"name":"decreaseAllowanceByPartition","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"defaultPartition","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"granularity","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_partition","type":"bytes32"},{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_addedValue","type":"uint256"}],"name":"increaseAllowanceByPartition","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_collateralManager","type":"address"}],"name":"isCollateralManager","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_operator","type":"address"},{"internalType":"address","name":"_tokenHolder","type":"address"}],"name":"isOperator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_partition","type":"bytes32"},{"internalType":"address","name":"_operator","type":"address"},{"internalType":"address","name":"_collateralManager","type":"address"}],"name":"isOperatorForCollateralManager","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_partition","type":"bytes32"},{"internalType":"address","name":"_operator","type":"address"},{"internalType":"address","name":"_tokenHolder","type":"address"}],"name":"isOperatorForPartition","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"_prefix","type":"bytes4"}],"name":"isPartitionStrategy","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"partitionStrategies","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenHolder","type":"address"}],"name":"partitionsOf","outputs":[{"internalType":"bytes32[]","name":"","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"registerCollateralManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_operator","type":"address"}],"name":"revokeOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_partition","type":"bytes32"},{"internalType":"address","name":"_operator","type":"address"}],"name":"revokeOperatorByPartition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"_prefix","type":"bytes4"},{"internalType":"address","name":"_implementation","type":"address"}],"name":"setPartitionStrategy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"}],"name":"swap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"swapToken","outputs":[{"internalType":"contract ISwapToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"swapTokenGraveyard","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalPartitions","outputs":[{"internalType":"bytes32[]","name":"","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"totalSupplyByPartition","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_partition","type":"bytes32"},{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"},{"internalType":"bytes","name":"_operatorData","type":"bytes"}],"name":"transferByPartition","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"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"}],"stateMutability":"nonpayable","type":"function"}]

60c06040526002608081905261035360f41b60a09081526200002591600191906200080e565b5060408051808201909152600280825261353160f01b60209092019182526200004f91816200080e565b50604080518082019091526002808252611a9960f11b60209092019182526200007b916003916200080e565b5060408051808201909152600280825261353360f01b6020909201918252620000a7916004916200080e565b50604080518082019091526002808252611a9b60f11b6020909201918252620000d3916005916200080e565b5060408051808201909152600280825261353760f01b6020909201918252620000ff916006916200080e565b506040805180820190915260028082526106a760f31b60209092019182526200012b916007916200080e565b5060408051808201909152600280825261353960f01b602090920191825262000157916008916200080e565b5060408051808201909152600280825261354160f01b602090920191825262000183916009916200080e565b50604080518082019091526002808252611aa160f11b6020909201918252620001af91600a916200080e565b5060408051808201909152600280825261354360f01b6020909201918252620001db91600b916200080e565b50604080518082019091526002808252610d5160f21b60209092019182526200020791600c916200080e565b5060408051808201909152600280825261354560f01b60209092019182526200023391600d916200080e565b50604080518082019091526002808252611aa360f11b60209092019182526200025f91600e916200080e565b5060408051808201909152600280825261036360f41b60209092019182526200028b91600f916200080e565b503480156200029957600080fd5b5060405162003f2338038062003f2383398181016040526060811015620002bf57600080fd5b815160208301805160405192949293830192919084640100000000821115620002e757600080fd5b908301906020820185811115620002fd57600080fd5b82516401000000008111828201881017156200031857600080fd5b82525081516020918201929091019080838360005b83811015620003475781810151838201526020016200032d565b50505050905090810190601f168015620003755780820380516001836020036101000a031916815260200191505b50604052602001805160405193929190846401000000008211156200039957600080fd5b908301906020820185811115620003af57600080fd5b8251640100000000811182820188101715620003ca57600080fd5b82525081516020918201929091019080838360005b83811015620003f9578181015183820152602001620003df565b50505050905090810190601f168015620004275780820380516001836020036101000a031916815260200191505b506040525050601080546001600160a01b031916331790555060096001600160a01b038416620004ee5760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015620004df5780601f10620004b357610100808354040283529160200191620004df565b820191906000526020600020905b815481529060010190602001808311620004c157829003601f168201915b50509250505060405180910390fd5b50602380546001600160a01b0319166001600160a01b03851617905581516200051f9060129060208501906200080e565b508051620005359060139060208401906200080e565b506000601481905562000551906001600160e01b036200063816565b620005886040518060400160405280600881526020016720b6b82a37b5b2b760c11b815250306200067a60201b62001b2c1760201c565b620005c16040518060400160405280600a81526020016922a92199182a37b5b2b760b11b815250306200067a60201b62001b2c1760201c565b620005f76040518060400160405280600881526020016720b6b82a37b5b2b760c11b8152506200077160201b62001c1f1760201c565b6200062f6040518060400160405280600a81526020016922a92199182a37b5b2b760b11b8152506200077160201b62001c1f1760201c565b505050620008b3565b601680546001810182557fd833147d7dc355ba459fc788f669e58cfaf9dc25ddcd0702e87d69c7b5124289018290555460009182526017602052604090912055565b6000826040516020018082805190602001908083835b60208310620006b15780518252601f19909201916020918201910162000690565b51815160209384036101000a60001901801990921691161790526040805192909401828103601f19018352808552825192909101919091206329965a1d60e01b8252306004830152602482018190526001600160a01b03881660448301529251929550731820a4b7618bde71dce8cdc73aab6c95905fad2494506329965a1d9350606480820193600093509182900301818387803b1580156200075357600080fd5b505af115801562000768573d6000803e3d6000fd5b50505050505050565b6001600080836040516020018082805190602001908083835b60208310620007ab5780518252601f1990920191602091820191016200078a565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200085157805160ff191683800117855562000881565b8280016001018555821562000881579182015b828111156200088157825182559160200191906001019062000864565b506200088f92915062000893565b5090565b620008b091905b808211156200088f57600081556001016200089a565b90565b61366080620008c36000396000f3fe608060405234801561001057600080fd5b50600436106102695760003560e01c8063740ab8f411610151578063a2c1cae2116100c3578063b9d7b47111610087578063b9d7b4711461090f578063c2f89a5114610917578063dc73e49c14610949578063dd62ed3e14610951578063e30834e01461097f578063fad8b32a146109b557610269565b8063a2c1cae21461084d578063a457c2d714610855578063a9059cbb14610881578063aeb72e70146108ad578063b6363cf2146108e157610269565b80638da5cb5b116101155780638da5cb5b146107cb578063900ff16d146107d3578063959b8c3f146107fa57806395d89b4114610820578063a0cf6b8414610828578063a26734dc1461083057610269565b8063740ab8f41461072057806375deca02146107465780637e3a262d14610780578063814435af1461078857806387f4427e146107a557610269565b80632036a94d116101ea57806339509351116101ae57806339509351146106165780635481eed314610642578063556f0dc71461066657806369598efe1461066e5780636d77cad6146106c657806370a08231146106fa57610269565b80632036a94d1461048357806323b872dd1461056a578063249cb3fa146105a057806330e82803146105cc578063313ce567146105f857610269565b806314d1e62f1161023157806314d1e62f146103a5578063168ecec5146103d757806317ec83ca1461040357806318160ddd146104495780631ff6442e1461045157610269565b806303438dd01461026e57806306fdde0314610296578063095ea7b3146103135780630e0e923b14610353578063103ef9e114610379575b600080fd5b6102946004803603602081101561028457600080fd5b50356001600160a01b03166109db565b005b61029e610c41565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102d85781810151838201526020016102c0565b50505050905090810190601f1680156103055780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61033f6004803603604081101561032957600080fd5b506001600160a01b038135169060200135610cd7565b604080519115158252519081900360200190f35b61033f6004803603602081101561036957600080fd5b50356001600160a01b0316610cef565b6102946004803603604081101561038f57600080fd5b50803590602001356001600160a01b0316610d0c565b61033f600480360360608110156103bb57600080fd5b508035906001600160a01b036020820135169060400135610de3565b610294600480360360408110156103ed57600080fd5b50803590602001356001600160a01b0316610dfc565b6104376004803603606081101561041957600080fd5b508035906001600160a01b0360208201358116916040013516610ed0565b60408051918252519081900360200190f35b610437610f00565b61033f6004803603606081101561046757600080fd5b508035906001600160a01b036020820135169060400135610f06565b610437600480360360c081101561049957600080fd5b8135916001600160a01b03602082013581169260408301359091169160608101359181019060a0810160808201356401000000008111156104d957600080fd5b8201836020820111156104eb57600080fd5b8035906020019184600183028401116401000000008311171561050d57600080fd5b91939092909160208101903564010000000081111561052b57600080fd5b82018360208201111561053d57600080fd5b8035906020019184600183028401116401000000008311171561055f57600080fd5b509092509050610f50565b61033f6004803603606081101561058057600080fd5b506001600160a01b03813581169160208101359091169060400135610fd7565b610437600480360360408110156105b657600080fd5b50803590602001356001600160a01b0316610ff5565b610437600480360360408110156105e257600080fd5b50803590602001356001600160a01b0316611059565b61060061107e565b6040805160ff9092168252519081900360200190f35b61033f6004803603604081101561062c57600080fd5b506001600160a01b038135169060200135611083565b61064a6110e1565b604080516001600160a01b039092168252519081900360200190f35b6104376110f0565b6106766110f5565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156106b257818101518382015260200161069a565b505050509050019250505060405180910390f35b61033f600480360360608110156106dc57600080fd5b508035906001600160a01b036020820135811691604001351661114c565b6104376004803603602081101561071057600080fd5b50356001600160a01b0316611161565b6106766004803603602081101561073657600080fd5b50356001600160a01b031661117c565b6107636004803603602081101561075c57600080fd5b50356111e8565b604080516001600160e01b03199092168252519081900360200190f35b61043761121c565b61064a6004803603602081101561079e57600080fd5b5035611221565b610294600480360360208110156107bb57600080fd5b50356001600160a01b0316611248565b61064a6112e8565b61033f600480360360208110156107e957600080fd5b50356001600160e01b0319166112f7565b6102946004803603602081101561081057600080fd5b50356001600160a01b0316611316565b61029e6113e1565b61064a611442565b6104376004803603602081101561084657600080fd5b5035611448565b61029461145a565b61033f6004803603604081101561086b57600080fd5b506001600160a01b03813516906020013561150a565b61033f6004803603604081101561089757600080fd5b506001600160a01b038135169060200135611568565b61033f600480360360608110156108c357600080fd5b508035906001600160a01b0360208201358116916040013516611586565b61033f600480360360408110156108f757600080fd5b506001600160a01b03813581169160200135166115ef565b6102946115fb565b61033f6004803603606081101561092d57600080fd5b508035906001600160a01b036020820135169060400135611705565b61064a61174a565b6104376004803603604081101561096757600080fd5b506001600160a01b0381358116916020013516611759565b6102946004803603604081101561099557600080fd5b5080356001600160e01b03191690602001356001600160a01b03166117a3565b610294600480360360208110156109cb57600080fd5b50356001600160a01b0316611a64565b60235460408051636eb1769f60e11b81526001600160a01b0384811660048301523060248301529151600093929092169163dd62ed3e91604480820192602092909190829003018186803b158015610a3257600080fd5b505afa158015610a46573d6000803e3d6000fd5b505050506040513d6020811015610a5c57600080fd5b50519050600481610b005760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b820191906000526020600020905b815481529060010190602001808311610ad457829003601f168201915b50509250505060405180910390fd5b50602354604080516323b872dd60e01b81526001600160a01b03858116600483015261dead602483015260448201859052915191909216916323b872dd9160648083019260209291908290030181600087803b158015610b5f57600080fd5b505af1158015610b73573d6000803e3d6000fd5b505050506040513d6020811015610b8957600080fd5b5051600f90610bf15760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b50610bfd338383611cba565b6040805182815290516001600160a01b0384169133917fea368a40e9570069bb8e6511d668293ad2e1f03b0d982431fd223de9f3b70ca69181900360200190a35050565b60128054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610ccd5780601f10610ca257610100808354040283529160200191610ccd565b820191906000526020600020905b815481529060010190602001808311610cb057829003601f168201915b5050505050905090565b6000610ce581338585611e7d565b5060015b92915050565b6001600160a01b0316600090815260208052604090205460ff1690565b60076001600160a01b038216331415610d7e5760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b50336000818152601e6020908152604080832086845282528083206001600160a01b0386168085529252808320805460ff1916600117905551909185917f3646a897c70797ecc134b0adc32f471b07bf1d6f451133b0384badab531e3fd69190a45050565b6000610df184338585611e7d565b5060015b9392505050565b60076001600160a01b038216331415610e6e5760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b50336000818152601e6020908152604080832086845282528083206001600160a01b0386168085529252808320805460ff1916905551909185917f3b287c4f1bab4df949b33bceacef984f544dc5d5479930d00e4ee8c9d8dd96f29190a45050565b6000928352601d602090815260408085206001600160a01b03948516865282528085209290931684525290205490565b60145490565b6000838152601d60209081526040808320338085529083528184206001600160a01b0387168552909252822054610df19186918690610f4b908763ffffffff61201f16565b611e7d565b6000610fca89338a8a8a8a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8e018190048102820181019092528c815292508c91508b908190840183828082843760009201919091525061206192505050565b9998505050505050505050565b6000610df13385858560405180602001604052806000815250612508565b60008281526020819052604081205460ff161561105157604051602001808073455243313832305f4143434550545f4d4147494360601b8152506014019050604051602081830303815290604052805190602001209050610ce9565b506000610ce9565b6001600160a01b03166000908152601b60209081526040808320938352929052205490565b601290565b3360008181527f0a51588b1664495f089dd83d2d26f247920f94a57a4a09f20cf068efc8f82bd4602090815260408083206001600160a01b03871684529091528120549091610ce5918391908690610f4b908763ffffffff61253116565b6011546001600160a01b031690565b600190565b60606016805480602002602001604051908101604052809291908181526020018280548015610ccd57602002820191906000526020600020905b81548152602001906001019080831161112f575050505050905090565b600061115984848461258b565b949350505050565b6001600160a01b031660009081526015602052604090205490565b6001600160a01b0381166000908152601960209081526040918290208054835181840281018401909452808452606093928301828280156111dc57602002820191906000526020600020905b8154815260200190600101908083116111c8575b50505050509050919050565b602181815481106111f557fe5b9060005260206000209060089182820401919006600402915054906101000a900460e01b81565b600081565b601f818154811061122e57fe5b6000918252602090912001546001600160a01b0316905081565b6010546001600160a01b03163314611298576040805162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b21039b2b73232b960911b604482015290519081900360640190fd5b601180546001600160a01b0319166001600160a01b0383811691909117918290556040519116907fb58bcc286020502f4931905baafed22acc969c092ed724234c73361efc68839090600090a250565b6010546001600160a01b031690565b6001600160e01b03191660009081526022602052604090205460ff1690565b60076001600160a01b0382163314156113885760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b50336000818152601c602090815260408083206001600160a01b0386168085529252808320805460ff191660011790555190917ff4caeb2d6ca8932a215a353d0703c326ec2d81fc68170f320eb2ab49e9df61f991a350565b60138054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610ccd5780601f10610ca257610100808354040283529160200191610ccd565b61dead81565b60186020526000908152604090205481565b6011546001600160a01b031633146114aa576040805162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b21039b2b73232b960911b604482015290519081900360640190fd5b60108054601180546001600160a01b03198084166001600160a01b038381169190911795869055911690915560405191811692169082907f343765429aea5a34b3ff6a3785a98a5abb2597aca87bfbb58632c173d585373a90600090a350565b3360008181527f0a51588b1664495f089dd83d2d26f247920f94a57a4a09f20cf068efc8f82bd4602090815260408083206001600160a01b03871684529091528120549091610ce5918391908690610f4b908763ffffffff61201f16565b6000610ce53333858560405180602001604052806000815250612508565b6001600160a01b038116600090815260208052604081205460ff16801561115957506115b283836125e0565b806111595750506001600160a01b039081166000908152601e60209081526040808320958352948152848220939092168152919052205460ff1690565b6000610df583836125e0565b336000908152602080526040902054600b9060ff16156116745760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b50601f805460018181019092557fa03837a25210ee280c2113ff4b77ca23440b19d4866cca721c801278fd08d8070180546001600160a01b0319163390811790915560008181526020808052604091829020805460ff19169094179093558051918252517f2d9629b61129967906b4b31b246507fe09b2b62e2c963a3b9e4d1aff6d4af75b929181900390910190a1565b6000838152601d60209081526040808320338085529083528184206001600160a01b0387168552909252822054610df19186918690610f4b908763ffffffff61253116565b6023546001600160a01b031681565b6001600160a01b0391821660009081527f0a51588b1664495f089dd83d2d26f247920f94a57a4a09f20cf068efc8f82bd46020908152604080832093909416825291909152205490565b6117ab6112e8565b6001600160a01b0316336001600160a01b0316146005906118255760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b506001600160e01b03198216600090815260226020526040902054600d9060ff16156118aa5760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b50600e6001600160e01b0319831661191b5760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b5060606119278361262d565b90506119338183611b2c565b6021805460018082019092557f3a6357012c1a3ae0a17d304c9920310382d968ebcc4b1771f41c6b304205b5706008820401805463ffffffff60079093166004026101000a928302191660e087901c929092029190911790556001600160e01b031984166000818152602260209081526040808320805460ff1916909517909455835192835282810184815285519484019490945284516001600160a01b038716947fb1c6e929e0b0638c228622a32f1f2fb3375541d8faa4a0176173b50b4bfc75ea9489948894919360608501928601918190849084905b83811015611a24578181015183820152602001611a0c565b50505050905090810190601f168015611a515780820380516001836020036101000a031916815260200191505b50935050505060405180910390a2505050565b60076001600160a01b038216331415611ad65760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b50336000818152601c602090815260408083206001600160a01b0386168085529252808320805460ff191690555190917f50546e66e5f44d728365dc3908c63bc5cfeeab470722c1677e3073a6ac294aa191a350565b6000826040516020018082805190602001908083835b60208310611b615780518252601f199092019160209182019101611b42565b51815160209384036101000a60001901801990921691161790526040805192909401828103601f19018352808552825192909101919091206329965a1d60e01b8252306004830152602482018190526001600160a01b03881660448301529251929550731820a4b7618bde71dce8cdc73aab6c95905fad2494506329965a1d9350606480820193600093509182900301818387803b158015611c0257600080fd5b505af1158015611c16573d6000803e3d6000fd5b50505050505050565b6001600080836040516020018082805190602001908083835b60208310611c575780518252601f199092019160209182019101611c38565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b60066001600160a01b038316611d295760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b50601454611d3d908263ffffffff61253116565b601455611d4c8260008361267d565b611d7d6000801b846000858560405180602001604052806000815250604051806020016040528060008152506127c7565b604080518281526020810182905260008183015290516001600160a01b0380851692908616917fbcd28e05e57d4bcd5bfcc92a4661d412893e6112c44a2e25d96cfdfc30d5f22e9181900360800190a36040805182815290516001600160a01b038416916000917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a3604080516001600160a01b038581168252602082018490526080828401819052600090830181905260c06060840181905283018190529251908516929182917fff4e9a26af4eb73b8bacfaa4abd4fea03d9448e7b912dc5ff4019048875aa2d4918190036101000190a4505050565b60056001600160a01b038416611eec5760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b5060076001600160a01b038316611f5c5760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b506000848152601d602090815260408083206001600160a01b038088168086529184528285209087168086529084529382902085905581518581529151909288927ff061499aa77c2f6f5e25e34955a06623705344a88256cc861a121ec0bce5cfec929081900390910190a48361201957816001600160a01b0316836001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a35b50505050565b6000610df583836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612c43565b600060066001600160a01b0386166120d25760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b50866001600160a01b0316866001600160a01b03161461226b576120f788888861258b565b8061213057506000888152601d602090815260408083206001600160a01b03808b168552908352818420908b1684529091529020548411155b6004906121965760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b506000888152601d602090815260408083206001600160a01b03808b168552908352818420908b168452909152902054841161223b576000888152601d602090815260408083206001600160a01b03808b168552908352818420908b16845290915290205461220b908563ffffffff61201f16565b6000898152601d602090815260408083206001600160a01b038b168452825280832033845290915290205561226b565b6000888152601d602090815260408083206001600160a01b03808b168552908352818420908b1684529091528120555b61227a88888888888888612cda565b6001600160a01b0386166000908152601b602090815260408083208b84529091529020546003908511156123075760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b506000612314848a6130d6565b9050612321878a8761312b565b61232c86828761267d565b61233b818989898989896127c7565b856001600160a01b0316876001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef876040518082815260200191505060405180910390a3856001600160a01b0316876001600160a01b03168a7fff4e9a26af4eb73b8bacfaa4abd4fea03d9448e7b912dc5ff4019048875aa2d48b89898960405180856001600160a01b03166001600160a01b031681526020018481526020018060200180602001838103835285818151815260200191508051906020019080838360005b8381101561241f578181015183820152602001612407565b50505050905090810190601f16801561244c5780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b8381101561247f578181015183820152602001612467565b50505050905090810190601f1680156124ac5780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390a48881146124fc5760408051868152905182918b917f67c8ba31d2dd11f1384577b3405b04ed91eed1231e408432ad2458cab37b2fa19181900360200190a35b98975050505050505050565b6125296000801b868686868660405180602001604052806000815250612061565b505050505050565b600082820183811015610df5576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600061259783836125e0565b806125cf57506001600160a01b038083166000908152601e6020908152604080832088845282528083209387168352929052205460ff165b806111595750611159848484613347565b6000816001600160a01b0316836001600160a01b03161480610df55750506001600160a01b039081166000908152601c602090815260408083209490931682529290925290205460ff1690565b604080517f416d70506172746974696f6e537472617465677956616c696461746f7200000060208201526001600160e01b031992909216603d830152805180830360210181526041909201905290565b80612687576127c2565b6001600160a01b0383166000908152601560205260409020546126b0908263ffffffff61253116565b6001600160a01b038416600090815260156020908152604080832093909355601a815282822085835290522054612725576001600160a01b03831660008181526019602090815260408083208054600181018255818552838520018790559383529254601a8252838320868452909152919020555b6001600160a01b0383166000908152601b60209081526040808320858452909152902054612759908263ffffffff61253116565b6001600160a01b0384166000908152601b60209081526040808320868452825280832093909355601790522054612793576127938261343c565b6000828152601860205260409020546127b2908263ffffffff61253116565b6000838152601860205260409020555b505050565b60006127d28861347e565b6001600160e01b0319811660009081526022602052604090205490915060ff16156129d057600061280b306128068461262d565b613481565b90506001600160a01b038116156129ca57806001600160a01b031663b3c46f426000356001600160e01b0319168b8b8b8b8b8b8b6040518963ffffffff1660e01b815260040180896001600160e01b0319166001600160e01b0319168152602001888152602001876001600160a01b03166001600160a01b03168152602001866001600160a01b03166001600160a01b03168152602001856001600160a01b03166001600160a01b031681526020018481526020018060200180602001838103835285818151815260200191508051906020019080838360005b838110156128fd5781810151838201526020016128e5565b50505050905090810190601f16801561292a5780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b8381101561295d578181015183820152602001612945565b50505050905090810190601f16801561298a5780820380516001836020036101000a031916815260200191505b509a5050505050505050505050600060405180830381600087803b1580156129b157600080fd5b505af11580156129c5573d6000803e3d6000fd5b505050505b50612a43565b600c6001600160e01b0319821615612a415760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b505b6000612a798660405180604001604052806012815260200171105b5c151bdad95b9cd49958da5c1a595b9d60721b815250613481565b90506001600160a01b03811615612c3857806001600160a01b0316638240ef486000356001600160e01b0319168b8b8b8b8b8b8b6040518963ffffffff1660e01b815260040180896001600160e01b0319166001600160e01b0319168152602001888152602001876001600160a01b03166001600160a01b03168152602001866001600160a01b03166001600160a01b03168152602001856001600160a01b03166001600160a01b031681526020018481526020018060200180602001838103835285818151815260200191508051906020019080838360005b83811015612b6b578181015183820152602001612b53565b50505050905090810190601f168015612b985780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b83811015612bcb578181015183820152602001612bb3565b50505050905090810190601f168015612bf85780820380516001836020036101000a031916815260200191505b509a5050505050505050505050600060405180830381600087803b158015612c1f57600080fd5b505af1158015612c33573d6000803e3d6000fd5b505050505b505050505050505050565b60008184841115612cd25760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612c97578181015183820152602001612c7f565b50505050905090810190601f168015612cc45780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6000612d0d866040518060400160405280600f81526020016e20b6b82a37b5b2b739a9b2b73232b960891b815250613481565b90506001600160a01b03811615612ecc57806001600160a01b031663ec3bb2886000356001600160e01b0319168a8a8a8a8a8a8a6040518963ffffffff1660e01b815260040180896001600160e01b0319166001600160e01b0319168152602001888152602001876001600160a01b03166001600160a01b03168152602001866001600160a01b03166001600160a01b03168152602001856001600160a01b03166001600160a01b031681526020018481526020018060200180602001838103835285818151815260200191508051906020019080838360005b83811015612dff578181015183820152602001612de7565b50505050905090810190601f168015612e2c5780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b83811015612e5f578181015183820152602001612e47565b50505050905090810190601f168015612e8c5780820380516001836020036101000a031916815260200191505b509a5050505050505050505050600060405180830381600087803b158015612eb357600080fd5b505af1158015612ec7573d6000803e3d6000fd5b505050505b6000612ed78961347e565b6001600160e01b0319811660009081526022602052604090205490915060ff1615612c38576000612f0b306128068461262d565b90506001600160a01b038116156130ca57806001600160a01b031663dc86ad7a6000356001600160e01b0319168c8c8c8c8c8c8c6040518963ffffffff1660e01b815260040180896001600160e01b0319166001600160e01b0319168152602001888152602001876001600160a01b03166001600160a01b03168152602001866001600160a01b03166001600160a01b03168152602001856001600160a01b03166001600160a01b031681526020018481526020018060200180602001838103835285818151815260200191508051906020019080838360005b83811015612ffd578181015183820152602001612fe5565b50505050905090810190601f16801561302a5780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b8381101561305d578181015183820152602001613045565b50505050905090810190601f16801561308a5780820380516001836020036101000a031916815260200191505b509a5050505050505050505050600060405180830381600087803b1580156130b157600080fd5b505af11580156130c5573d6000803e3d6000fd5b505050505b50505050505050505050565b60006040835110156130e9575080610ce9565b60008084806020019051604081101561310157600080fd5b5080516020909101519092509050600019821415613122579150610ce99050565b50919392505050565b80613135576127c2565b6001600160a01b03831660009081526015602052604090205461315e908263ffffffff61201f16565b6001600160a01b038416600090815260156020908152604080832093909355601b81528282208583529052205461319b908263ffffffff61201f16565b6001600160a01b0384166000908152601b602090815260408083208684528252808320939093556018905220546131d8908263ffffffff61201f16565b60008381526018602052604090208190551580156131f557508115155b156132035761320382613584565b6001600160a01b0383166000908152601b602090815260408083208584529091529020546127c2576001600160a01b0383166000908152601a602090815260408083208584529091529020548061325a57506127c2565b6001600160a01b03841660009081526019602052604081208054600019810190811061328257fe5b906000526020600020015490508060196000876001600160a01b03166001600160a01b0316815260200190815260200160002060018403815481106132c357fe5b60009182526020808320909101929092556001600160a01b038716808252601a83526040808320858452845280832086905590825260199092522080548061330757fe5b6000828152602080822083016000199081018390559092019092556001600160a01b0387168252601a815260408083208784529091528120555050505050565b6000806133538561347e565b6001600160e01b0319811660009081526022602052604090205490915060ff16613381576000915050610df5565b6000613390306128068461262d565b90506001600160a01b038116156134305760408051633f0413df60e01b8152600481018890526001600160a01b0387811660248301528681166044830152915191831691633f0413df91606480820192602092909190829003018186803b1580156133fa57600080fd5b505afa15801561340e573d6000803e3d6000fd5b505050506040513d602081101561342457600080fd5b50519250610df5915050565b50600095945050505050565b601680546001810182557fd833147d7dc355ba459fc788f669e58cfaf9dc25ddcd0702e87d69c7b5124289018290555460009182526017602052604090912055565b90565b600080826040516020018082805190602001908083835b602083106134b75780518252601f199092019160209182019101613498565b51815160209384036101000a60001901801990921691161790526040805192909401828103601f1901835280855282519282019290922063555ddc6560e11b83526001600160a01b038b166004840152602483018190529351939650731820a4b7618bde71dce8cdc73aab6c95905fad24955063aabbb8ca94506044808301949193509091829003018186803b15801561355057600080fd5b505afa158015613564573d6000803e3d6000fd5b505050506040513d602081101561357a57600080fd5b5051949350505050565b6000818152601760205260409020548061359e5750613627565b601680546000919060001981019081106135b457fe5b9060005260206000200154905080601660018403815481106135d257fe5b600091825260208083209091019290925582815260179091526040902082905560168054806135fd57fe5b60008281526020808220830160001990810183905590920190925584825260179052604081205550505b5056fea264697066735822122046f1197cc0a6e3d6399ed22c3480b4059302d3180614e1c23cf41dc5ac02219764736f6c634300060a00330000000000000000000000004a57e687b9126435a9b19e4a802113e266adebde000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000003416d7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003414d500000000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106102695760003560e01c8063740ab8f411610151578063a2c1cae2116100c3578063b9d7b47111610087578063b9d7b4711461090f578063c2f89a5114610917578063dc73e49c14610949578063dd62ed3e14610951578063e30834e01461097f578063fad8b32a146109b557610269565b8063a2c1cae21461084d578063a457c2d714610855578063a9059cbb14610881578063aeb72e70146108ad578063b6363cf2146108e157610269565b80638da5cb5b116101155780638da5cb5b146107cb578063900ff16d146107d3578063959b8c3f146107fa57806395d89b4114610820578063a0cf6b8414610828578063a26734dc1461083057610269565b8063740ab8f41461072057806375deca02146107465780637e3a262d14610780578063814435af1461078857806387f4427e146107a557610269565b80632036a94d116101ea57806339509351116101ae57806339509351146106165780635481eed314610642578063556f0dc71461066657806369598efe1461066e5780636d77cad6146106c657806370a08231146106fa57610269565b80632036a94d1461048357806323b872dd1461056a578063249cb3fa146105a057806330e82803146105cc578063313ce567146105f857610269565b806314d1e62f1161023157806314d1e62f146103a5578063168ecec5146103d757806317ec83ca1461040357806318160ddd146104495780631ff6442e1461045157610269565b806303438dd01461026e57806306fdde0314610296578063095ea7b3146103135780630e0e923b14610353578063103ef9e114610379575b600080fd5b6102946004803603602081101561028457600080fd5b50356001600160a01b03166109db565b005b61029e610c41565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102d85781810151838201526020016102c0565b50505050905090810190601f1680156103055780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61033f6004803603604081101561032957600080fd5b506001600160a01b038135169060200135610cd7565b604080519115158252519081900360200190f35b61033f6004803603602081101561036957600080fd5b50356001600160a01b0316610cef565b6102946004803603604081101561038f57600080fd5b50803590602001356001600160a01b0316610d0c565b61033f600480360360608110156103bb57600080fd5b508035906001600160a01b036020820135169060400135610de3565b610294600480360360408110156103ed57600080fd5b50803590602001356001600160a01b0316610dfc565b6104376004803603606081101561041957600080fd5b508035906001600160a01b0360208201358116916040013516610ed0565b60408051918252519081900360200190f35b610437610f00565b61033f6004803603606081101561046757600080fd5b508035906001600160a01b036020820135169060400135610f06565b610437600480360360c081101561049957600080fd5b8135916001600160a01b03602082013581169260408301359091169160608101359181019060a0810160808201356401000000008111156104d957600080fd5b8201836020820111156104eb57600080fd5b8035906020019184600183028401116401000000008311171561050d57600080fd5b91939092909160208101903564010000000081111561052b57600080fd5b82018360208201111561053d57600080fd5b8035906020019184600183028401116401000000008311171561055f57600080fd5b509092509050610f50565b61033f6004803603606081101561058057600080fd5b506001600160a01b03813581169160208101359091169060400135610fd7565b610437600480360360408110156105b657600080fd5b50803590602001356001600160a01b0316610ff5565b610437600480360360408110156105e257600080fd5b50803590602001356001600160a01b0316611059565b61060061107e565b6040805160ff9092168252519081900360200190f35b61033f6004803603604081101561062c57600080fd5b506001600160a01b038135169060200135611083565b61064a6110e1565b604080516001600160a01b039092168252519081900360200190f35b6104376110f0565b6106766110f5565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156106b257818101518382015260200161069a565b505050509050019250505060405180910390f35b61033f600480360360608110156106dc57600080fd5b508035906001600160a01b036020820135811691604001351661114c565b6104376004803603602081101561071057600080fd5b50356001600160a01b0316611161565b6106766004803603602081101561073657600080fd5b50356001600160a01b031661117c565b6107636004803603602081101561075c57600080fd5b50356111e8565b604080516001600160e01b03199092168252519081900360200190f35b61043761121c565b61064a6004803603602081101561079e57600080fd5b5035611221565b610294600480360360208110156107bb57600080fd5b50356001600160a01b0316611248565b61064a6112e8565b61033f600480360360208110156107e957600080fd5b50356001600160e01b0319166112f7565b6102946004803603602081101561081057600080fd5b50356001600160a01b0316611316565b61029e6113e1565b61064a611442565b6104376004803603602081101561084657600080fd5b5035611448565b61029461145a565b61033f6004803603604081101561086b57600080fd5b506001600160a01b03813516906020013561150a565b61033f6004803603604081101561089757600080fd5b506001600160a01b038135169060200135611568565b61033f600480360360608110156108c357600080fd5b508035906001600160a01b0360208201358116916040013516611586565b61033f600480360360408110156108f757600080fd5b506001600160a01b03813581169160200135166115ef565b6102946115fb565b61033f6004803603606081101561092d57600080fd5b508035906001600160a01b036020820135169060400135611705565b61064a61174a565b6104376004803603604081101561096757600080fd5b506001600160a01b0381358116916020013516611759565b6102946004803603604081101561099557600080fd5b5080356001600160e01b03191690602001356001600160a01b03166117a3565b610294600480360360208110156109cb57600080fd5b50356001600160a01b0316611a64565b60235460408051636eb1769f60e11b81526001600160a01b0384811660048301523060248301529151600093929092169163dd62ed3e91604480820192602092909190829003018186803b158015610a3257600080fd5b505afa158015610a46573d6000803e3d6000fd5b505050506040513d6020811015610a5c57600080fd5b50519050600481610b005760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b820191906000526020600020905b815481529060010190602001808311610ad457829003601f168201915b50509250505060405180910390fd5b50602354604080516323b872dd60e01b81526001600160a01b03858116600483015261dead602483015260448201859052915191909216916323b872dd9160648083019260209291908290030181600087803b158015610b5f57600080fd5b505af1158015610b73573d6000803e3d6000fd5b505050506040513d6020811015610b8957600080fd5b5051600f90610bf15760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b50610bfd338383611cba565b6040805182815290516001600160a01b0384169133917fea368a40e9570069bb8e6511d668293ad2e1f03b0d982431fd223de9f3b70ca69181900360200190a35050565b60128054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610ccd5780601f10610ca257610100808354040283529160200191610ccd565b820191906000526020600020905b815481529060010190602001808311610cb057829003601f168201915b5050505050905090565b6000610ce581338585611e7d565b5060015b92915050565b6001600160a01b0316600090815260208052604090205460ff1690565b60076001600160a01b038216331415610d7e5760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b50336000818152601e6020908152604080832086845282528083206001600160a01b0386168085529252808320805460ff1916600117905551909185917f3646a897c70797ecc134b0adc32f471b07bf1d6f451133b0384badab531e3fd69190a45050565b6000610df184338585611e7d565b5060015b9392505050565b60076001600160a01b038216331415610e6e5760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b50336000818152601e6020908152604080832086845282528083206001600160a01b0386168085529252808320805460ff1916905551909185917f3b287c4f1bab4df949b33bceacef984f544dc5d5479930d00e4ee8c9d8dd96f29190a45050565b6000928352601d602090815260408085206001600160a01b03948516865282528085209290931684525290205490565b60145490565b6000838152601d60209081526040808320338085529083528184206001600160a01b0387168552909252822054610df19186918690610f4b908763ffffffff61201f16565b611e7d565b6000610fca89338a8a8a8a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8e018190048102820181019092528c815292508c91508b908190840183828082843760009201919091525061206192505050565b9998505050505050505050565b6000610df13385858560405180602001604052806000815250612508565b60008281526020819052604081205460ff161561105157604051602001808073455243313832305f4143434550545f4d4147494360601b8152506014019050604051602081830303815290604052805190602001209050610ce9565b506000610ce9565b6001600160a01b03166000908152601b60209081526040808320938352929052205490565b601290565b3360008181527f0a51588b1664495f089dd83d2d26f247920f94a57a4a09f20cf068efc8f82bd4602090815260408083206001600160a01b03871684529091528120549091610ce5918391908690610f4b908763ffffffff61253116565b6011546001600160a01b031690565b600190565b60606016805480602002602001604051908101604052809291908181526020018280548015610ccd57602002820191906000526020600020905b81548152602001906001019080831161112f575050505050905090565b600061115984848461258b565b949350505050565b6001600160a01b031660009081526015602052604090205490565b6001600160a01b0381166000908152601960209081526040918290208054835181840281018401909452808452606093928301828280156111dc57602002820191906000526020600020905b8154815260200190600101908083116111c8575b50505050509050919050565b602181815481106111f557fe5b9060005260206000209060089182820401919006600402915054906101000a900460e01b81565b600081565b601f818154811061122e57fe5b6000918252602090912001546001600160a01b0316905081565b6010546001600160a01b03163314611298576040805162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b21039b2b73232b960911b604482015290519081900360640190fd5b601180546001600160a01b0319166001600160a01b0383811691909117918290556040519116907fb58bcc286020502f4931905baafed22acc969c092ed724234c73361efc68839090600090a250565b6010546001600160a01b031690565b6001600160e01b03191660009081526022602052604090205460ff1690565b60076001600160a01b0382163314156113885760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b50336000818152601c602090815260408083206001600160a01b0386168085529252808320805460ff191660011790555190917ff4caeb2d6ca8932a215a353d0703c326ec2d81fc68170f320eb2ab49e9df61f991a350565b60138054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610ccd5780601f10610ca257610100808354040283529160200191610ccd565b61dead81565b60186020526000908152604090205481565b6011546001600160a01b031633146114aa576040805162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b21039b2b73232b960911b604482015290519081900360640190fd5b60108054601180546001600160a01b03198084166001600160a01b038381169190911795869055911690915560405191811692169082907f343765429aea5a34b3ff6a3785a98a5abb2597aca87bfbb58632c173d585373a90600090a350565b3360008181527f0a51588b1664495f089dd83d2d26f247920f94a57a4a09f20cf068efc8f82bd4602090815260408083206001600160a01b03871684529091528120549091610ce5918391908690610f4b908763ffffffff61201f16565b6000610ce53333858560405180602001604052806000815250612508565b6001600160a01b038116600090815260208052604081205460ff16801561115957506115b283836125e0565b806111595750506001600160a01b039081166000908152601e60209081526040808320958352948152848220939092168152919052205460ff1690565b6000610df583836125e0565b336000908152602080526040902054600b9060ff16156116745760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b50601f805460018181019092557fa03837a25210ee280c2113ff4b77ca23440b19d4866cca721c801278fd08d8070180546001600160a01b0319163390811790915560008181526020808052604091829020805460ff19169094179093558051918252517f2d9629b61129967906b4b31b246507fe09b2b62e2c963a3b9e4d1aff6d4af75b929181900390910190a1565b6000838152601d60209081526040808320338085529083528184206001600160a01b0387168552909252822054610df19186918690610f4b908763ffffffff61253116565b6023546001600160a01b031681565b6001600160a01b0391821660009081527f0a51588b1664495f089dd83d2d26f247920f94a57a4a09f20cf068efc8f82bd46020908152604080832093909416825291909152205490565b6117ab6112e8565b6001600160a01b0316336001600160a01b0316146005906118255760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b506001600160e01b03198216600090815260226020526040902054600d9060ff16156118aa5760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b50600e6001600160e01b0319831661191b5760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b5060606119278361262d565b90506119338183611b2c565b6021805460018082019092557f3a6357012c1a3ae0a17d304c9920310382d968ebcc4b1771f41c6b304205b5706008820401805463ffffffff60079093166004026101000a928302191660e087901c929092029190911790556001600160e01b031984166000818152602260209081526040808320805460ff1916909517909455835192835282810184815285519484019490945284516001600160a01b038716947fb1c6e929e0b0638c228622a32f1f2fb3375541d8faa4a0176173b50b4bfc75ea9489948894919360608501928601918190849084905b83811015611a24578181015183820152602001611a0c565b50505050905090810190601f168015611a515780820380516001836020036101000a031916815260200191505b50935050505060405180910390a2505050565b60076001600160a01b038216331415611ad65760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b50336000818152601c602090815260408083206001600160a01b0386168085529252808320805460ff191690555190917f50546e66e5f44d728365dc3908c63bc5cfeeab470722c1677e3073a6ac294aa191a350565b6000826040516020018082805190602001908083835b60208310611b615780518252601f199092019160209182019101611b42565b51815160209384036101000a60001901801990921691161790526040805192909401828103601f19018352808552825192909101919091206329965a1d60e01b8252306004830152602482018190526001600160a01b03881660448301529251929550731820a4b7618bde71dce8cdc73aab6c95905fad2494506329965a1d9350606480820193600093509182900301818387803b158015611c0257600080fd5b505af1158015611c16573d6000803e3d6000fd5b50505050505050565b6001600080836040516020018082805190602001908083835b60208310611c575780518252601f199092019160209182019101611c38565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b60066001600160a01b038316611d295760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b50601454611d3d908263ffffffff61253116565b601455611d4c8260008361267d565b611d7d6000801b846000858560405180602001604052806000815250604051806020016040528060008152506127c7565b604080518281526020810182905260008183015290516001600160a01b0380851692908616917fbcd28e05e57d4bcd5bfcc92a4661d412893e6112c44a2e25d96cfdfc30d5f22e9181900360800190a36040805182815290516001600160a01b038416916000917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a3604080516001600160a01b038581168252602082018490526080828401819052600090830181905260c06060840181905283018190529251908516929182917fff4e9a26af4eb73b8bacfaa4abd4fea03d9448e7b912dc5ff4019048875aa2d4918190036101000190a4505050565b60056001600160a01b038416611eec5760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b5060076001600160a01b038316611f5c5760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b506000848152601d602090815260408083206001600160a01b038088168086529184528285209087168086529084529382902085905581518581529151909288927ff061499aa77c2f6f5e25e34955a06623705344a88256cc861a121ec0bce5cfec929081900390910190a48361201957816001600160a01b0316836001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a35b50505050565b6000610df583836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612c43565b600060066001600160a01b0386166120d25760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b50866001600160a01b0316866001600160a01b03161461226b576120f788888861258b565b8061213057506000888152601d602090815260408083206001600160a01b03808b168552908352818420908b1684529091529020548411155b6004906121965760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b506000888152601d602090815260408083206001600160a01b03808b168552908352818420908b168452909152902054841161223b576000888152601d602090815260408083206001600160a01b03808b168552908352818420908b16845290915290205461220b908563ffffffff61201f16565b6000898152601d602090815260408083206001600160a01b038b168452825280832033845290915290205561226b565b6000888152601d602090815260408083206001600160a01b03808b168552908352818420908b1684529091528120555b61227a88888888888888612cda565b6001600160a01b0386166000908152601b602090815260408083208b84529091529020546003908511156123075760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b506000612314848a6130d6565b9050612321878a8761312b565b61232c86828761267d565b61233b818989898989896127c7565b856001600160a01b0316876001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef876040518082815260200191505060405180910390a3856001600160a01b0316876001600160a01b03168a7fff4e9a26af4eb73b8bacfaa4abd4fea03d9448e7b912dc5ff4019048875aa2d48b89898960405180856001600160a01b03166001600160a01b031681526020018481526020018060200180602001838103835285818151815260200191508051906020019080838360005b8381101561241f578181015183820152602001612407565b50505050905090810190601f16801561244c5780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b8381101561247f578181015183820152602001612467565b50505050905090810190601f1680156124ac5780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390a48881146124fc5760408051868152905182918b917f67c8ba31d2dd11f1384577b3405b04ed91eed1231e408432ad2458cab37b2fa19181900360200190a35b98975050505050505050565b6125296000801b868686868660405180602001604052806000815250612061565b505050505050565b600082820183811015610df5576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600061259783836125e0565b806125cf57506001600160a01b038083166000908152601e6020908152604080832088845282528083209387168352929052205460ff165b806111595750611159848484613347565b6000816001600160a01b0316836001600160a01b03161480610df55750506001600160a01b039081166000908152601c602090815260408083209490931682529290925290205460ff1690565b604080517f416d70506172746974696f6e537472617465677956616c696461746f7200000060208201526001600160e01b031992909216603d830152805180830360210181526041909201905290565b80612687576127c2565b6001600160a01b0383166000908152601560205260409020546126b0908263ffffffff61253116565b6001600160a01b038416600090815260156020908152604080832093909355601a815282822085835290522054612725576001600160a01b03831660008181526019602090815260408083208054600181018255818552838520018790559383529254601a8252838320868452909152919020555b6001600160a01b0383166000908152601b60209081526040808320858452909152902054612759908263ffffffff61253116565b6001600160a01b0384166000908152601b60209081526040808320868452825280832093909355601790522054612793576127938261343c565b6000828152601860205260409020546127b2908263ffffffff61253116565b6000838152601860205260409020555b505050565b60006127d28861347e565b6001600160e01b0319811660009081526022602052604090205490915060ff16156129d057600061280b306128068461262d565b613481565b90506001600160a01b038116156129ca57806001600160a01b031663b3c46f426000356001600160e01b0319168b8b8b8b8b8b8b6040518963ffffffff1660e01b815260040180896001600160e01b0319166001600160e01b0319168152602001888152602001876001600160a01b03166001600160a01b03168152602001866001600160a01b03166001600160a01b03168152602001856001600160a01b03166001600160a01b031681526020018481526020018060200180602001838103835285818151815260200191508051906020019080838360005b838110156128fd5781810151838201526020016128e5565b50505050905090810190601f16801561292a5780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b8381101561295d578181015183820152602001612945565b50505050905090810190601f16801561298a5780820380516001836020036101000a031916815260200191505b509a5050505050505050505050600060405180830381600087803b1580156129b157600080fd5b505af11580156129c5573d6000803e3d6000fd5b505050505b50612a43565b600c6001600160e01b0319821615612a415760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b505b6000612a798660405180604001604052806012815260200171105b5c151bdad95b9cd49958da5c1a595b9d60721b815250613481565b90506001600160a01b03811615612c3857806001600160a01b0316638240ef486000356001600160e01b0319168b8b8b8b8b8b8b6040518963ffffffff1660e01b815260040180896001600160e01b0319166001600160e01b0319168152602001888152602001876001600160a01b03166001600160a01b03168152602001866001600160a01b03166001600160a01b03168152602001856001600160a01b03166001600160a01b031681526020018481526020018060200180602001838103835285818151815260200191508051906020019080838360005b83811015612b6b578181015183820152602001612b53565b50505050905090810190601f168015612b985780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b83811015612bcb578181015183820152602001612bb3565b50505050905090810190601f168015612bf85780820380516001836020036101000a031916815260200191505b509a5050505050505050505050600060405180830381600087803b158015612c1f57600080fd5b505af1158015612c33573d6000803e3d6000fd5b505050505b505050505050505050565b60008184841115612cd25760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612c97578181015183820152602001612c7f565b50505050905090810190601f168015612cc45780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6000612d0d866040518060400160405280600f81526020016e20b6b82a37b5b2b739a9b2b73232b960891b815250613481565b90506001600160a01b03811615612ecc57806001600160a01b031663ec3bb2886000356001600160e01b0319168a8a8a8a8a8a8a6040518963ffffffff1660e01b815260040180896001600160e01b0319166001600160e01b0319168152602001888152602001876001600160a01b03166001600160a01b03168152602001866001600160a01b03166001600160a01b03168152602001856001600160a01b03166001600160a01b031681526020018481526020018060200180602001838103835285818151815260200191508051906020019080838360005b83811015612dff578181015183820152602001612de7565b50505050905090810190601f168015612e2c5780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b83811015612e5f578181015183820152602001612e47565b50505050905090810190601f168015612e8c5780820380516001836020036101000a031916815260200191505b509a5050505050505050505050600060405180830381600087803b158015612eb357600080fd5b505af1158015612ec7573d6000803e3d6000fd5b505050505b6000612ed78961347e565b6001600160e01b0319811660009081526022602052604090205490915060ff1615612c38576000612f0b306128068461262d565b90506001600160a01b038116156130ca57806001600160a01b031663dc86ad7a6000356001600160e01b0319168c8c8c8c8c8c8c6040518963ffffffff1660e01b815260040180896001600160e01b0319166001600160e01b0319168152602001888152602001876001600160a01b03166001600160a01b03168152602001866001600160a01b03166001600160a01b03168152602001856001600160a01b03166001600160a01b031681526020018481526020018060200180602001838103835285818151815260200191508051906020019080838360005b83811015612ffd578181015183820152602001612fe5565b50505050905090810190601f16801561302a5780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b8381101561305d578181015183820152602001613045565b50505050905090810190601f16801561308a5780820380516001836020036101000a031916815260200191505b509a5050505050505050505050600060405180830381600087803b1580156130b157600080fd5b505af11580156130c5573d6000803e3d6000fd5b505050505b50505050505050505050565b60006040835110156130e9575080610ce9565b60008084806020019051604081101561310157600080fd5b5080516020909101519092509050600019821415613122579150610ce99050565b50919392505050565b80613135576127c2565b6001600160a01b03831660009081526015602052604090205461315e908263ffffffff61201f16565b6001600160a01b038416600090815260156020908152604080832093909355601b81528282208583529052205461319b908263ffffffff61201f16565b6001600160a01b0384166000908152601b602090815260408083208684528252808320939093556018905220546131d8908263ffffffff61201f16565b60008381526018602052604090208190551580156131f557508115155b156132035761320382613584565b6001600160a01b0383166000908152601b602090815260408083208584529091529020546127c2576001600160a01b0383166000908152601a602090815260408083208584529091529020548061325a57506127c2565b6001600160a01b03841660009081526019602052604081208054600019810190811061328257fe5b906000526020600020015490508060196000876001600160a01b03166001600160a01b0316815260200190815260200160002060018403815481106132c357fe5b60009182526020808320909101929092556001600160a01b038716808252601a83526040808320858452845280832086905590825260199092522080548061330757fe5b6000828152602080822083016000199081018390559092019092556001600160a01b0387168252601a815260408083208784529091528120555050505050565b6000806133538561347e565b6001600160e01b0319811660009081526022602052604090205490915060ff16613381576000915050610df5565b6000613390306128068461262d565b90506001600160a01b038116156134305760408051633f0413df60e01b8152600481018890526001600160a01b0387811660248301528681166044830152915191831691633f0413df91606480820192602092909190829003018186803b1580156133fa57600080fd5b505afa15801561340e573d6000803e3d6000fd5b505050506040513d602081101561342457600080fd5b50519250610df5915050565b50600095945050505050565b601680546001810182557fd833147d7dc355ba459fc788f669e58cfaf9dc25ddcd0702e87d69c7b5124289018290555460009182526017602052604090912055565b90565b600080826040516020018082805190602001908083835b602083106134b75780518252601f199092019160209182019101613498565b51815160209384036101000a60001901801990921691161790526040805192909401828103601f1901835280855282519282019290922063555ddc6560e11b83526001600160a01b038b166004840152602483018190529351939650731820a4b7618bde71dce8cdc73aab6c95905fad24955063aabbb8ca94506044808301949193509091829003018186803b15801561355057600080fd5b505afa158015613564573d6000803e3d6000fd5b505050506040513d602081101561357a57600080fd5b5051949350505050565b6000818152601760205260409020548061359e5750613627565b601680546000919060001981019081106135b457fe5b9060005260206000200154905080601660018403815481106135d257fe5b600091825260208083209091019290925582815260179091526040902082905560168054806135fd57fe5b60008281526020808220830160001990810183905590920190925584825260179052604081205550505b5056fea264697066735822122046f1197cc0a6e3d6399ed22c3480b4059302d3180614e1c23cf41dc5ac02219764736f6c634300060a0033

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

0000000000000000000000004a57e687b9126435a9b19e4a802113e266adebde000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000003416d7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003414d500000000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _swapTokenAddress_ (address): 0x4a57E687b9126435a9B19E4A802113e266AdeBde
Arg [1] : _name_ (string): Amp
Arg [2] : _symbol_ (string): AMP

-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 0000000000000000000000004a57e687b9126435a9b19e4a802113e266adebde
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [2] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [4] : 416d700000000000000000000000000000000000000000000000000000000000
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [6] : 414d500000000000000000000000000000000000000000000000000000000000


Deployed Bytecode Sourcemap

23058:57148:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;44686:412;;;;;;;;;;;;;;;;-1:-1:-1;44686:412:0;-1:-1:-1;;;;;44686:412:0;;:::i;:::-;;53841:85;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;41525:192;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;41525:192:0;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;59475:184;;;;;;;;;;;;;;;;-1:-1:-1;59475:184:0;-1:-1:-1;;;;;59475:184:0;;:::i;49550:340::-;;;;;;;;;;;;;;;;-1:-1:-1;49550:340:0;;;;;;-1:-1:-1;;;;;49550:340:0;;:::i;56096:242::-;;;;;;;;;;;;;;;;-1:-1:-1;56096:242:0;;;-1:-1:-1;;;;;56096:242:0;;;;;;;;;;:::i;50357:321::-;;;;;;;;;;;;;;;;-1:-1:-1;50357:321:0;;;;;;-1:-1:-1;;;;;50357:321:0;;:::i;55462:225::-;;;;;;;;;;;;;;;;-1:-1:-1;55462:225:0;;;-1:-1:-1;;;;;55462:225:0;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;38111:102;;;:::i;58149:455::-;;;;;;;;;;;;;;;;-1:-1:-1;58149:455:0;;;-1:-1:-1;;;;;58149:455:0;;;;;;;;;;:::i;47346:492::-;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;47346:492:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;47346:492:0;;-1:-1:-1;47346:492:0;-1:-1:-1;47346:492:0;:::i;40103:237::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;40103:237:0;;;;;;;;;;;;;;;;;:::i;13005:356::-;;;;;;;;;;;;;;;;-1:-1:-1;13005:356:0;;;;;;-1:-1:-1;;;;;13005:356:0;;:::i;45585:209::-;;;;;;;;;;;;;;;;-1:-1:-1;45585:209:0;;;;;;-1:-1:-1;;;;;45585:209:0;;:::i;54301:85::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;42480:354;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;42480:354:0;;;;;;;;:::i;9249:105::-;;;:::i;:::-;;;;-1:-1:-1;;;;;9249:105:0;;;;;;;;;;;;;;54579:93;;;:::i;54798:110::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;52156:242;;;;;;;;;;;;;;;;-1:-1:-1;52156:242:0;;;-1:-1:-1;;;;;52156:242:0;;;;;;;;;;;;:::i;38884:131::-;;;;;;;;;;;;;;;;-1:-1:-1;38884:131:0;-1:-1:-1;;;;;38884:131:0;;:::i;46018:138::-;;;;;;;;;;;;;;;;-1:-1:-1;46018:138:0;-1:-1:-1;;;;;46018:138:0;;:::i;28448:35::-;;;;;;;;;;;;;;;;-1:-1:-1;28448:35:0;;:::i;:::-;;;;-1:-1:-1;;;;;;28448:35:0;;;;;;;;;;;;;;26306:118;;;:::i;28003:35::-;;;;;;;;;;;;;;;;-1:-1:-1;28003:35:0;;:::i;9750:261::-;;;;;;;;;;;;;;;;-1:-1:-1;9750:261:0;-1:-1:-1;;;;;9750:261:0;;:::i;9027:79::-;;;:::i;61116:129::-;;;;;;;;;;;;;;;;-1:-1:-1;61116:129:0;-1:-1:-1;;;;;;61116:129:0;;:::i;48350:249::-;;;;;;;;;;;;;;;;-1:-1:-1;48350:249:0;-1:-1:-1;;;;;48350:249:0;;:::i;54040:89::-;;;:::i;29101:96::-;;;:::i;25594:57::-;;;;;;;;;;;;;;;;-1:-1:-1;25594:57:0;;:::i;10152:282::-;;;:::i;43684:396::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;43684:396:0;;;;;;;;:::i;39408:189::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;39408:189:0;;;;;;;;:::i;53163:404::-;;;;;;;;;;;;;;;;-1:-1:-1;53163:404:0;;;-1:-1:-1;;;;;53163:404:0;;;;;;;;;;;;:::i;51390:184::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;51390:184:0;;;;;;;;;;:::i;58882:330::-;;;:::i;57026:384::-;;;;;;;;;;;;;;;;-1:-1:-1;57026:384:0;;;-1:-1:-1;;;;;57026:384:0;;;;;;;;;;:::i;28875:27::-;;;:::i;40811:216::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;40811:216:0;;;;;;;;;;:::i;60202:643::-;;;;;;;;;;;;;;;;-1:-1:-1;60202:643:0;;-1:-1:-1;;;;;;60202:643:0;;;;;-1:-1:-1;;;;;60202:643:0;;:::i;48944:244::-;;;;;;;;;;;;;;;;-1:-1:-1;48944:244:0;-1:-1:-1;;;;;48944:244:0;;:::i;44686:412::-;44750:9;;:41;;;-1:-1:-1;;;44750:41:0;;-1:-1:-1;;;;;44750:41:0;;;;;;;44785:4;44750:41;;;;;;44733:14;;44750:9;;;;;:19;;:41;;;;;;;;;;;;;;;:9;:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;44750:41:0;;-1:-1:-1;44822:28:0;44810:10;44802:49;;;;-1:-1:-1;;;44802:49:0;;;;;;;;;;;;-1:-1:-1;;44802:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;44886:9:0;;:57;;;-1:-1:-1;;;44886:57:0;;-1:-1:-1;;;;;44886:57:0;;;;;;;29155:42;44886:57;;;;;;;;;;;;:9;;;;;:22;;:57;;;;;;;;;;;;;;:9;;:57;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;44886:57:0;44958:27;;44864:132;;;;-1:-1:-1;;;44864:132:0;;;;;;;;;;;;-1:-1:-1;;44864:132:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;45009:32;45015:10;45027:5;45034:6;45009:5;:32::i;:::-;45059:31;;;;;;;;-1:-1:-1;;;;;45059:31:0;;;45064:10;;45059:31;;;;;;;;;44686:412;;:::o;53841:85::-;53913:5;53906:12;;;;;;;;-1:-1:-1;;53906:12:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;53880:13;;53906:12;;53913:5;;53906:12;;53913:5;53906:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;53841:85;:::o;41525:192::-;41603:4;41620:67;41603:4;41658:10;41670:8;41680:6;41620:19;:67::i;:::-;-1:-1:-1;41705:4:0;41525:192;;;;;:::o;59475:184::-;-1:-1:-1;;;;;59611:40:0;59582:4;59611:40;;;:20;:40;;;;;;;;;59475:184::o;49550:340::-;49694:22;-1:-1:-1;;;;;49669:23:0;;49682:10;49669:23;;49661:56;;;;-1:-1:-1;;;49661:56:0;;;;;;;;;;;;-1:-1:-1;;49661:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;49761:10:0;49730:42;;;;:30;:42;;;;;;;;:54;;;;;;;;-1:-1:-1;;;;;49730:65:0;;;;;;;;;;:72;;-1:-1:-1;;49730:72:0;49798:4;49730:72;;;49818:64;49730:65;;49773:10;;49818:64;;49730:42;49818:64;49550:340;;:::o;56096:242::-;56230:4;56247:61;56267:10;56279;56291:8;56301:6;56247:19;:61::i;:::-;-1:-1:-1;56326:4:0;56096:242;;;;;;:::o;50357:321::-;50484:22;-1:-1:-1;;;;;50459:23:0;;50472:10;50459:23;;50451:56;;;;-1:-1:-1;;;50451:56:0;;;;;;;;;;;;-1:-1:-1;;50451:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;50551:10:0;50588:5;50520:42;;;:30;:42;;;;;;;;:54;;;;;;;;-1:-1:-1;;;;;50520:65:0;;;;;;;;;;:73;;-1:-1:-1;;50520:73:0;;;50609:61;50520:65;;50563:10;;50609:61;;50588:5;50609:61;50357:321;;:::o;55462:225::-;55603:7;55630:31;;;:19;:31;;;;;;;;-1:-1:-1;;;;;55630:39:0;;;;;;;;;;:49;;;;;;;;;;;55462:225::o;38111:102::-;38193:12;;38111:102;:::o;58149:455::-;58303:4;58488:31;;;:19;:31;;;;;;;;58440:10;58488:43;;;;;;;;;-1:-1:-1;;;;;58488:53:0;;;;;;;;;;58381:193;;58415:10;;58465:8;;58488:75;;58546:16;58488:75;:57;:75;:::i;:::-;58381:19;:193::i;47346:492::-;47570:7;47610:220;47649:10;47678;47707:5;47731:3;47753:6;47778:5;;47610:220;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;47610:220:0;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;47802:13:0;;-1:-1:-1;47802:13:0;;;;47610:220;;47802:13;;;;47610:220;;;;;;;;;-1:-1:-1;47610:20:0;;-1:-1:-1;;;47610:220:0:i;:::-;47590:240;47346:492;-1:-1:-1;;;;;;;;;47346:492:0:o;40103:237::-;40230:4;40247:63;40275:10;40287:5;40294:3;40299:6;40247:63;;;;;;;;;;;;:27;:63::i;13005:356::-;13200:7;13224:32;;;;;;;;;;;;;13220:134;;;12235:40;;;;;;-1:-1:-1;;;12235:40:0;;;;;;;;;;;;;;;;;;;12215:67;;;;;;13273:27;;;;13220:134;-1:-1:-1;13333:9:0;;;45585:209;-1:-1:-1;;;;;45739:35:0;45707:7;45739:35;;;:21;:35;;;;;;;;:47;;;;;;;;;45585:209::o;54301:85::-;54375:2;54301:85;:::o;42480:354::-;42669:10;42582:4;42717:49;;;:37;;:49;;;:37;:49;;;-1:-1:-1;;;;;42717:59:0;;;;;;;;;;42582:4;;42604:200;;42582:4;;42669:10;42694:8;;42717:76;;42781:11;42717:76;:63;:76;:::i;9249:105::-;9327:19;;-1:-1:-1;;;;;9327:19:0;9249:105;:::o;54579:93::-;24640:1;54579:93;:::o;54798:110::-;54848:16;54884;54877:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;54798:110;:::o;52156:242::-;52306:4;52330:60;52354:10;52366:9;52377:12;52330:23;:60::i;:::-;52323:67;52156:242;-1:-1:-1;;;;52156:242:0:o;38884:131::-;-1:-1:-1;;;;;38984:23:0;38957:7;38984:23;;;:9;:23;;;;;;;38884:131::o;46018:138::-;-1:-1:-1;;;;;46121:27:0;;;;;;:13;:27;;;;;;;;;46114:34;;;;;;;;;;;;;;;;;46085:16;;46114:34;;;46121:27;46114:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;46018:138;;;:::o;28448:35::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;26306:118::-;26358:66;26306:118;:::o;28003:35::-;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;28003:35:0;;-1:-1:-1;28003:35:0;:::o;9750:261::-;9856:6;;-1:-1:-1;;;;;9856:6:0;9842:10;:20;9834:47;;;;;-1:-1:-1;;;9834:47:0;;;;;;;;;;;;-1:-1:-1;;;9834:47:0;;;;;;;;;;;;;;;9894:19;:40;;-1:-1:-1;;;;;;9894:40:0;-1:-1:-1;;;;;9894:40:0;;;;;;;;;;;9952:51;;9983:19;;;9952:51;;-1:-1:-1;;9952:51:0;9750:261;:::o;9027:79::-;9092:6;;-1:-1:-1;;;;;9092:6:0;9027:79;:::o;61116:129::-;-1:-1:-1;;;;;;61208:29:0;61184:4;61208:29;;;:20;:29;;;;;;;;;61116:129::o;48350:249::-;48449:22;-1:-1:-1;;;;;48424:23:0;;48437:10;48424:23;;48416:56;;;;-1:-1:-1;;;48416:56:0;;;;;;;;;;;;-1:-1:-1;;48416:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;48505:10:0;48485:31;;;;:19;:31;;;;;;;;-1:-1:-1;;;;;48485:42:0;;;;;;;;;;:49;;-1:-1:-1;;48485:49:0;48530:4;48485:49;;;48550:41;48485:42;;48550:41;;;48350:249;:::o;54040:89::-;54114:7;54107:14;;;;;;;;-1:-1:-1;;54107:14:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;54081:13;;54107:14;;54114:7;;54107:14;;54114:7;54107:14;;;;;;;;;;;;;;;;;;;;;;;;29101:96;29155:42;29101:96;:::o;25594:57::-;;;;;;;;;;;;;:::o;10152:282::-;10221:19;;-1:-1:-1;;;;;10221:19:0;10207:10;:33;10199:60;;;;;-1:-1:-1;;;10199:60:0;;;;;;;;;;;;-1:-1:-1;;;10199:60:0;;;;;;;;;;;;;;;10291:6;;;10317:19;;;-1:-1:-1;;;;;;10308:28:0;;;-1:-1:-1;;;;;10317:19:0;;;10308:28;;;;;;;;10347:32;;;;;10397:29;;10291:6;;;;10419;;10291;;10397:29;;10272:16;;10397:29;10152:282;:::o;43684:396::-;43878:10;43791:4;43926:49;;;:37;;:49;;;:37;:49;;;-1:-1:-1;;;;;43926:59:0;;;;;;;;;;43791:4;;43813:237;;43791:4;;43878:10;43903:8;;43926:113;;44008:16;43926:113;:63;:113;:::i;39408:189::-;39482:4;39499:68;39527:10;39539;39551:3;39556:6;39499:68;;;;;;;;;;;;:27;:68::i;53163:404::-;-1:-1:-1;;;;;53364:40:0;;53327:4;53364:40;;;:20;:40;;;;;;;;:195;;;;;53422:42;53434:9;53445:18;53422:11;:42::i;:::-;:136;;;-1:-1:-1;;;;;;;53485:50:0;;;;;;;:30;:50;;;;;;;;:62;;;;;;;;;:73;;;;;;;;;;;;;;53163:404::o;51390:184::-;51501:4;51530:36;51542:9;51553:12;51530:11;:36::i;58882:330::-;59013:10;58992:32;;;;:20;:32;;;;;;59026:22;;58992:32;;58991:33;58983:66;;;;-1:-1:-1;;;58983:66:0;;;;;;;;;;;;-1:-1:-1;;58983:66:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;59062:18:0;:35;;;;;;;;;;;;;-1:-1:-1;;;;;;59062:35:0;59086:10;59062:35;;;;;;-1:-1:-1;59108:32:0;;;59062:35;59108:32;;;;;;;;:39;;-1:-1:-1;;59108:39:0;;;;;;;59165;;;;;;;;;;;;;;;;;58882:330::o;57026:384::-;57175:4;57299:31;;;:19;:31;;;;;;;;57251:10;57299:43;;;;;;;;;-1:-1:-1;;;;;57299:53:0;;;;;;;;;;57192:188;;57226:10;;57276:8;;57299:70;;57357:11;57299:70;:57;:70;:::i;28875:27::-;;;-1:-1:-1;;;;;28875:27:0;;:::o;40811:216::-;-1:-1:-1;;;;;40964:45:0;;;40932:7;40964:45;;;:37;;:45;;;:37;:45;;;:55;;;;;;;;;;;;;40811:216::o;60202:643::-;60315:7;:5;:7::i;:::-;-1:-1:-1;;;;;60301:21:0;:10;-1:-1:-1;;;;;60301:21:0;;60324:20;60293:52;;;;;-1:-1:-1;;;60293:52:0;;;;;;;;;;;;-1:-1:-1;;60293:52:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;60365:29:0;;;;;;:20;:29;;;;;;60396:31;;60365:29;;60364:30;60356:72;;;;-1:-1:-1;;;60356:72:0;;;;;;;;;;;;-1:-1:-1;;60356:72:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;60471:32:0;-1:-1:-1;;;;;;60447:22:0;;60439:65;;;;-1:-1:-1;;;60439:65:0;;;;;;;;;;;;-1:-1:-1;;60439:65:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;60517:19;60539:59;60590:7;60539:50;:59::i;:::-;60517:81;;60611:64;60652:5;60659:15;60611:40;:64::i;:::-;60686:19;:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;60730:29:0;;-1:-1:-1;60730:29:0;;;:20;60686:33;60730:29;;;;;;;:36;;-1:-1:-1;;60730:36:0;;;;;;;60784:53;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;60784:53:0;;;;;60686:33;;60784:53;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;60202:643;;;:::o;48944:244::-;49040:22;-1:-1:-1;;;;;49015:23:0;;49028:10;49015:23;;49007:56;;;;-1:-1:-1;;;49007:56:0;;;;;;;;;;;;-1:-1:-1;;49007:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;49096:10:0;49121:5;49076:31;;;:19;:31;;;;;;;;-1:-1:-1;;;;;49076:42:0;;;;;;;;;;:50;;-1:-1:-1;;49076:50:0;;;49142:38;49076:42;;49142:38;;;48944:244;:::o;11157:360::-;11294:21;11345:15;11328:33;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;11328:33:0;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;11328:33:0;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;11328:33:0;;;;;;11318:44;;;;;;;;;;-1:-1:-1;;;11373:136:0;;11435:4;11373:136;;;;;;;;;;-1:-1:-1;;;;;11373:136:0;;;;;;;;11318:44;;-1:-1:-1;11099:42:0;;-1:-1:-1;11373:39:0;;-1:-1:-1;11373:136:0;;;;;-1:-1:-1;;;11373:136:0;;;;;;-1:-1:-1;11099:42:0;11373:136;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11157:360;;;:::o;13577:151::-;13716:4;13651:16;:62;13695:15;13678:33;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;13678:33:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13668:44;;;;;;13651:62;;;;;;;;;;;;:69;;;;;;;;;;;;;;;;;;13577:151;:::o;79525:678::-;79669:22;-1:-1:-1;;;;;79650:17:0;;79642:50;;;;-1:-1:-1;;;79642:50:0;;;;;;;;;;;;-1:-1:-1;;79642:50:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;79720:12:0;;:24;;79737:6;79720:24;:16;:24;:::i;:::-;79705:12;:39;79755:51;79776:3;26358:66;79799:6;79755:20;:51::i;:::-;79817:186;26358:66;79854:16;;79885:9;79917:1;79934:3;79952:6;79817:186;;;;;;;;;;;;;;;;;;;;;;;;:22;:186::i;:::-;80021:34;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;80021:34:0;;;;;;;;;;;;;;;;;80071:33;;;;;;;;-1:-1:-1;;;;;80071:33:0;;;80088:1;;80071:33;;;;;;;;;80120:75;;;-1:-1:-1;;;;;80120:75:0;;;;;;;;;;;;;;;;;;80171:1;80120:75;;;;;;;;;;;;;;;;;;;;;;;;80171:1;;;80120:75;;;;;;;;;79525:678;;;:::o;75089:579::-;75294:20;-1:-1:-1;;;;;75266:26:0;;75258:57;;;;-1:-1:-1;;;75258:57:0;;;;;;;;;;;;-1:-1:-1;;75258:57:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;75358:22:0;-1:-1:-1;;;;;75334:22:0;;75326:55;;;;-1:-1:-1;;;75326:55:0;;;;;;;;;;;;-1:-1:-1;;75326:55:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;75394:31:0;;;;:19;:31;;;;;;;;-1:-1:-1;;;;;75394:45:0;;;;;;;;;;;;:55;;;;;;;;;;;;;:65;;;75475:64;;;;;;;75394:45;;75414:10;;75475:64;;;;;;;;;;;75556:30;75552:109;;75631:8;-1:-1:-1;;;;;75608:41:0;75617:12;-1:-1:-1;;;;;75608:41:0;;75641:7;75608:41;;;;;;;;;;;;;;;;;;75552:109;75089:579;;;;:::o;1350:136::-;1408:7;1435:43;1439:1;1442;1435:43;;;;;;;;;;;;;;;;;:3;:43::i;62271:2553::-;62524:7;62571:22;-1:-1:-1;;;;;62552:17:0;;62544:50;;;;-1:-1:-1;;;62544:50:0;;;;;;;;;;;;-1:-1:-1;;62544:50:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;62811:9;-1:-1:-1;;;;;62802:18:0;:5;-1:-1:-1;;;;;62802:18:0;;62798:797;;62863:57;62887:14;62903:9;62914:5;62863:23;:57::i;:::-;:147;;;-1:-1:-1;62956:35:0;;;;:19;:35;;;;;;;;-1:-1:-1;;;;;62956:42:0;;;;;;;;;;;:53;;;;;;;;;;;62946:63;;;62863:147;63029:28;62837:235;;;;;-1:-1:-1;;;62837:235:0;;;;;;;;;;;;-1:-1:-1;;62837:235:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;63202:35:0;;;;:19;:35;;;;;;;;-1:-1:-1;;;;;63202:42:0;;;;;;;;;;;:53;;;;;;;;;;;:63;-1:-1:-1;63198:386:0;;63365:35;;;;:19;:35;;;;;;;;-1:-1:-1;;;;;63365:42:0;;;;;;;;;;;:53;;;;;;;;;;;:105;;63445:6;63365:105;:57;:105;:::i;:::-;63286:35;;;;:19;:35;;;;;;;;-1:-1:-1;;;;;63286:42:0;;;;;;;;;63329:32;63286:76;;;;;;;:184;63198:386;;;63567:1;63511:35;;;:19;:35;;;;;;;;-1:-1:-1;;;;;63511:42:0;;;;;;;;;;;:53;;;;;;;;;;:57;63198:386;63607:192;63643:14;63672:9;63696:5;63716:3;63734:6;63755:5;63775:13;63607:21;:192::i;:::-;-1:-1:-1;;;;;63834:28:0;;;;;;:21;:28;;;;;;;;:44;;;;;;;;;63903:26;;63834:54;-1:-1:-1;63834:54:0;63812:128;;;;-1:-1:-1;;;63812:128:0;;;;;;;;;;;;-1:-1:-1;;63812:128:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;63953:19;63975:99;64029:5;64049:14;63975:39;:99::i;:::-;63953:121;;64087:56;64113:5;64120:14;64136:6;64087:25;:56::i;:::-;64154:46;64175:3;64180:11;64193:6;64154:20;:46::i;:::-;64211:190;64248:11;64274:9;64298:5;64318:3;64336:6;64357:5;64377:13;64211:22;:190::i;:::-;64435:3;-1:-1:-1;;;;;64419:28:0;64428:5;-1:-1:-1;;;;;64419:28:0;;64440:6;64419:28;;;;;;;;;;;;;;;;;;64570:3;-1:-1:-1;;;;;64463:190:0;64550:5;-1:-1:-1;;;;;64463:190:0;64497:14;64463:190;64526:9;64588:6;64609:5;64629:13;64463:190;;;;-1:-1:-1;;;;;64463:190:0;-1:-1:-1;;;;;64463:190:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;64463:190:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;64685:14;64670:11;:29;64666:120;;64721:53;;;;;;;;64754:11;;64738:14;;64721:53;;;;;;;;;64666:120;64805:11;62271:2553;-1:-1:-1;;;;;;;;62271:2553:0:o;65339:280::-;65531:80;26358:66;65552:16;;65570:9;65581:5;65588:3;65593:6;65601:5;65531:80;;;;;;;;;;;;:20;:80::i;:::-;;65339:280;;;;;:::o;894:181::-;952:7;984:5;;;1008:6;;;;1000:46;;;;;-1:-1:-1;;;1000:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;77164:393;77315:4;77340:36;77352:9;77363:12;77340:11;:36::i;:::-;:120;;;-1:-1:-1;;;;;;77393:44:0;;;;;;;:30;:44;;;;;;;;:56;;;;;;;;:67;;;;;;;;;;;;77340:120;:208;;;;77477:71;77512:10;77524:9;77535:12;77477:34;:71::i;76355:237::-;76467:4;76510:12;-1:-1:-1;;;;;76497:25:0;:9;-1:-1:-1;;;;;76497:25:0;;:86;;;-1:-1:-1;;;;;;;76539:33:0;;;;;;;:19;:33;;;;;;;;:44;;;;;;;;;;;;;;;;76355:237::o;19288:223::-;19444:58;;;;;;;;-1:-1:-1;;;;;;19444:58:0;;;;;;;;;;;;;;;;;;;;;;;;19288:223::o;67590:809::-;67727:11;67723:50;;67755:7;;67723:50;-1:-1:-1;;;;;67802:14:0;;;;;;:9;:14;;;;;;:26;;67821:6;67802:26;:18;:26;:::i;:::-;-1:-1:-1;;;;;67785:14:0;;;;;;:9;:14;;;;;;;;:43;;;;67845:20;:25;;;;;:37;;;;;;;67841:190;;-1:-1:-1;;;;;67904:18:0;;;;;;:13;:18;;;;;;;;:35;;;;;;;;;;;;;;;;;67994:18;;;:25;;67954:20;:25;;;;;:37;;;;;;;;;:65;67841:190;-1:-1:-1;;;;;68082:26:0;;;;;;:21;:26;;;;;;;;:38;;;;;;;;;:64;;68139:6;68082:64;:56;:64;:::i;:::-;-1:-1:-1;;;;;68041:26:0;;;;;;:21;:26;;;;;;;;:38;;;;;;;;:105;;;;68163:23;:35;;;;68159:115;;68220:42;68251:10;68220:30;:42::i;:::-;68321:34;;;;:22;:34;;;;;;:70;;68374:6;68321:70;:38;:70;:::i;:::-;68284:34;;;;:22;:34;;;;;:107;67590:809;;;;:::o;72823:1717::-;73078:24;73105:48;73140:12;73105:34;:48::i;:::-;-1:-1:-1;;;;;;73168:39:0;;;;;;:20;:39;;;;;;73078:75;;-1:-1:-1;73168:39:0;;73164:880;;;73224:38;73310:148;73350:4;73374:69;73425:17;73374:50;:69::i;:::-;73310:13;:148::i;:::-;73277:181;-1:-1:-1;;;;;;73477:44:0;;;73473:460;;73573:30;-1:-1:-1;;;;;73542:112:0;;73677:7;;-1:-1:-1;;;;;;73677:7:0;73707:12;73742:9;73774:5;73802:3;73828:6;73857:5;73885:13;73542:375;;;;;;;;;;;;;-1:-1:-1;;;;;73542:375:0;;-1:-1:-1;;;;;73542:375:0;;;;;;;;;;;;-1:-1:-1;;;;;73542:375:0;-1:-1:-1;;;;;73542:375:0;;;;;;-1:-1:-1;;;;;73542:375:0;-1:-1:-1;;;;;73542:375:0;;;;;;-1:-1:-1;;;;;73542:375:0;-1:-1:-1;;;;;73542:375:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;73542:375:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;73473:460;73164:880;;;;74007:24;-1:-1:-1;;;;;;73973:32:0;;;73965:67;;;;-1:-1:-1;;;73965:67:0;;;;;;;;;;;;-1:-1:-1;;73965:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;73164:880;74056:31;74124:40;74138:3;74143:20;;;;;;;;;;;;;-1:-1:-1;;;74143:20:0;;;74124:13;:40::i;:::-;74098:66;-1:-1:-1;;;;;;74181:37:0;;;74177:356;;74255:23;-1:-1:-1;;;;;74235:59:0;;74313:7;;-1:-1:-1;;;;;;74313:7:0;74339:12;74370:9;74398:5;74422:3;74444:6;74469:5;74493:13;74235:286;;;;;;;;;;;;;-1:-1:-1;;;;;74235:286:0;;-1:-1:-1;;;;;74235:286:0;;;;;;;;;;;;-1:-1:-1;;;;;74235:286:0;-1:-1:-1;;;;;74235:286:0;;;;;;-1:-1:-1;;;;;74235:286:0;-1:-1:-1;;;;;74235:286:0;;;;;;-1:-1:-1;;;;;74235:286:0;-1:-1:-1;;;;;74235:286:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;74235:286:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;74177:356;72823:1717;;;;;;;;;:::o;1781:192::-;1867:7;1903:12;1895:6;;;;1887:29;;;;-1:-1:-1;;;1887:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;1939:5:0;;;1781:192::o;70405:1786::-;70661:28;70723:39;70737:5;70744:17;;;;;;;;;;;;;-1:-1:-1;;;70744:17:0;;;70723:13;:39::i;:::-;70700:62;-1:-1:-1;;;;;;70777:34:0;;;70773:351;;70845:20;-1:-1:-1;;;;;70828:55:0;;70902:7;;-1:-1:-1;;;;;;70902:7:0;70928:14;70961:9;70989:5;71013:3;71035:6;71060:5;71084:13;70828:284;;;;;;;;;;;;;-1:-1:-1;;;;;70828:284:0;;-1:-1:-1;;;;;70828:284:0;;;;;;;;;;;;-1:-1:-1;;;;;70828:284:0;-1:-1:-1;;;;;70828:284:0;;;;;;-1:-1:-1;;;;;70828:284:0;-1:-1:-1;;;;;70828:284:0;;;;;;-1:-1:-1;;;;;70828:284:0;-1:-1:-1;;;;;70828:284:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;70828:284:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;70773:351;71282:26;71311:50;71346:14;71311:34;:50::i;:::-;-1:-1:-1;;;;;;71376:41:0;;;;;;:20;:41;;;;;;71282:79;;-1:-1:-1;71376:41:0;;71372:812;;;71434:44;71532:150;71572:4;71596:71;71647:19;71596:50;:71::i;71532:150::-;71493:189;-1:-1:-1;;;;;;71701:50:0;;;71697:476;;71803:36;-1:-1:-1;;;;;71772:120:0;;71915:7;;-1:-1:-1;;;;;;71915:7:0;71945:14;71982:9;72014:5;72042:3;72068:6;72097:5;72125:13;71772:385;;;;;;;;;;;;;-1:-1:-1;;;;;71772:385:0;;-1:-1:-1;;;;;71772:385:0;;;;;;;;;;;;-1:-1:-1;;;;;71772:385:0;-1:-1:-1;;;;;71772:385:0;;;;;;-1:-1:-1;;;;;71772:385:0;-1:-1:-1;;;;;71772:385:0;;;;;;-1:-1:-1;;;;;71772:385:0;-1:-1:-1;;;;;71772:385:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;71772:385:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;71697:476;71372:812;70405:1786;;;;;;;;;:::o;17423:455::-;17555:7;17599:2;17584:5;:12;:17;17580:75;;;-1:-1:-1;17625:18:0;17618:25;;17580:75;17668:12;17682:19;17716:5;17705:37;;;;;;;;;;;;;;;-1:-1:-1;17705:37:0;;;;;;;;;-1:-1:-1;17705:37:0;-1:-1:-1;;;17757:29:0;;17753:80;;;17810:11;-1:-1:-1;17803:18:0;;-1:-1:-1;17803:18:0;17753:80;-1:-1:-1;17852:18:0;;17423:455;-1:-1:-1;;;17423:455:0:o;65836:1541::-;65980:11;65976:50;;66008:7;;65976:50;-1:-1:-1;;;;;66057:16:0;;;;;;:9;:16;;;;;;:28;;66078:6;66057:28;:20;:28;:::i;:::-;-1:-1:-1;;;;;66038:16:0;;;;;;:9;:16;;;;;;;;:47;;;;66141:21;:28;;;;;:40;;;;;;;:66;;66200:6;66141:66;:58;:66;:::i;:::-;-1:-1:-1;;;;;66098:28:0;;;;;;:21;:28;;;;;;;;:40;;;;;;;;:109;;;;66255:22;:34;;;;:70;;66308:6;66255:70;:38;:70;:::i;:::-;66218:34;;;;:22;:34;;;;;:107;;;66486:39;:73;;;;-1:-1:-1;66529:30:0;;;66486:73;66482:153;;;66576:47;66612:10;66576:35;:47::i;:::-;-1:-1:-1;;;;;66763:28:0;;;;;;:21;:28;;;;;;;;:40;;;;;;;;;66759:611;;-1:-1:-1;;;;;66841:27:0;;66825:13;66841:27;;;:20;:27;;;;;;;;:39;;;;;;;;;66901:10;66897:57;;66932:7;;;66897:57;-1:-1:-1;;;;;67054:20:0;;67034:17;67054:20;;;:13;:20;;;;;67075:27;;-1:-1:-1;;67075:31:0;;;67054:53;;;;;;;;;;;;;;67034:73;;67156:9;67122:13;:20;67136:5;-1:-1:-1;;;;;67122:20:0;-1:-1:-1;;;;;67122:20:0;;;;;;;;;;;;67151:1;67143:5;:9;67122:31;;;;;;;;;;;;;;;;;;;:43;;;;-1:-1:-1;;;;;67211:27:0;;;;;:20;:27;;;;;;:38;;;;;;;;:46;;;67274:20;;;:13;:20;;;;:26;;;;;;;;;;;;;;;;;-1:-1:-1;;67274:26:0;;;;;;;;;;;;-1:-1:-1;;;;;67315:27:0;;;;:20;:27;;;;;;:39;;;;;;;;:43;-1:-1:-1;;65836:1541:0;;;:::o;78094:914::-;78256:4;78273:13;78289:46;78324:10;78289:34;:46::i;:::-;-1:-1:-1;;;;;;78353:28:0;;;;;;:20;:28;;;;;;78273:62;;-1:-1:-1;78353:28:0;;78348:74;;78405:5;78398:12;;;;;78348:74;78434:39;78518:125;78554:4;78574:58;78625:6;78574:50;:58::i;78518:125::-;78484:159;-1:-1:-1;;;;;;78658:45:0;;;78654:252;;78744:150;;;-1:-1:-1;;;78744:150:0;;;;;;;;-1:-1:-1;;;;;78744:150:0;;;;;;;;;;;;;;;;:113;;;;;;:150;;;;;;;;;;;;;;;:113;:150;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;78744:150:0;;-1:-1:-1;78720:174:0;;-1:-1:-1;;78720:174:0;78654:252;-1:-1:-1;78995:5:0;;78094:914;-1:-1:-1;;;;;78094:914:0:o;68539:193::-;68619:16;:33;;;;;;;;;;;;68701:23;-1:-1:-1;68663:35:0;;;:23;68619:33;68663:35;;;;;:61;68539:193::o;18098:124::-;18203:10;18098:124::o;11525:297::-;11643:7;11668:21;11719:15;11702:33;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;11702:33:0;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;11702:33:0;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;11702:33:0;;;;;;11692:44;;;;;;;;;-1:-1:-1;;;11754:60:0;;-1:-1:-1;;;;;11754:60:0;;;;;;;;;;;;;;11692:44;;-1:-1:-1;11099:42:0;;-1:-1:-1;11754:39:0;;-1:-1:-1;11754:60:0;;;;;11702:33;;-1:-1:-1;11754:60:0;;;;;;;11099:42;11754:60;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;11754:60:0;;11525:297;-1:-1:-1;;;;11525:297:0:o;68875:562::-;68960:13;68976:35;;;:23;:35;;;;;;69028:10;69024:49;;69055:7;;;69024:49;69165:16;69182:23;;69145:17;;69165:16;-1:-1:-1;;69182:27:0;;;69165:45;;;;;;;;;;;;;;69145:65;;69251:9;69221:16;69246:1;69238:5;:9;69221:27;;;;;;;;;;;;;;;;;;;:39;;;;69302:34;;;:23;:34;;;;;;:42;;;69357:16;:22;;;;;;;;;;;;;;;;;-1:-1:-1;;69357:22:0;;;;;;;;;;;;69390:35;;;:23;:35;;;;;:39;-1:-1:-1;;68875:562:0;;:::o

Swarm Source

ipfs://46f1197cc0a6e3d6399ed22c3480b4059302d3180614e1c23cf41dc5ac022197
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.