ERC-20
Currency
Overview
Max Total Supply
99,669,232,418.619261241727531304 AMP
Holders
98,327 ( 0.004%)
Market
Price
$0.00 @ 0.000001 ETH (+2.21%)
Onchain Market Cap
$476,817,607.89
Circulating Supply Market Cap
$385,934,671.00
Other Info
Token Contract (WITH 18 Decimals)
Balance
380.632589132612705076 AMPValue
$1.82 ( ~0.000544528470635032 Eth) [0.0000%]Loading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Name:
Amp
Compiler Version
v0.6.10+commit.00c0fcaf
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
- No Contract Security Audit Submitted- Submit Audit Here
[{"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"}]
Contract Creation Code
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.