Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00Token Holdings
More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 27,946 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Request Release | 21502276 | 21 mins ago | IN | 0 ETH | 0.00017885 | ||||
Request Release | 21502094 | 58 mins ago | IN | 0 ETH | 0.00012589 | ||||
Request Release | 21502059 | 1 hr ago | IN | 0 ETH | 0.00018095 | ||||
Request Release | 21501612 | 2 hrs ago | IN | 0 ETH | 0.00013707 | ||||
Request Release | 21501367 | 3 hrs ago | IN | 0 ETH | 0.00012762 | ||||
Request Release | 21500443 | 6 hrs ago | IN | 0 ETH | 0.00008613 | ||||
Request Release | 21500441 | 6 hrs ago | IN | 0 ETH | 0.00008145 | ||||
Request Release | 21500298 | 6 hrs ago | IN | 0 ETH | 0.00009514 | ||||
Request Release | 21499659 | 9 hrs ago | IN | 0 ETH | 0.00009461 | ||||
Request Release | 21499653 | 9 hrs ago | IN | 0 ETH | 0.00009271 | ||||
Request Release | 21499650 | 9 hrs ago | IN | 0 ETH | 0.00009563 | ||||
Request Release | 21499646 | 9 hrs ago | IN | 0 ETH | 0.00008874 | ||||
Request Release | 21499577 | 9 hrs ago | IN | 0 ETH | 0.00009173 | ||||
Request Release | 21498520 | 12 hrs ago | IN | 0 ETH | 0.00009222 | ||||
Request Release | 21498447 | 13 hrs ago | IN | 0 ETH | 0.00007686 | ||||
Request Release | 21498325 | 13 hrs ago | IN | 0 ETH | 0.00009914 | ||||
Request Release | 21498040 | 14 hrs ago | IN | 0 ETH | 0.00009924 | ||||
Request Release | 21497981 | 14 hrs ago | IN | 0 ETH | 0.00009557 | ||||
Request Release | 21497874 | 15 hrs ago | IN | 0 ETH | 0.0000924 | ||||
Request Release | 21497812 | 15 hrs ago | IN | 0 ETH | 0.00008856 | ||||
Request Release | 21497480 | 16 hrs ago | IN | 0 ETH | 0.00011041 | ||||
Request Release | 21497041 | 17 hrs ago | IN | 0 ETH | 0.00015408 | ||||
Request Release | 21496681 | 19 hrs ago | IN | 0 ETH | 0.00015173 | ||||
Request Release | 21496594 | 19 hrs ago | IN | 0 ETH | 0.000152 | ||||
Request Release | 21496469 | 19 hrs ago | IN | 0 ETH | 0.0001408 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
FlexaCollateralManager
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; } } interface IAmp { function registerCollateralManager() external; } /** * @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); } } /** * @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; } /** * @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 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 FlexaCollateralManager is an implementation of IAmpTokensSender and IAmpTokensRecipient * which serves as the Amp collateral manager for the Flexa Network. */ contract FlexaCollateralManager is Ownable, IAmpTokensSender, IAmpTokensRecipient, ERC1820Client { /** * @dev AmpTokensSender interface label. */ string internal constant AMP_TOKENS_SENDER = "AmpTokensSender"; /** * @dev AmpTokensRecipient interface label. */ string internal constant AMP_TOKENS_RECIPIENT = "AmpTokensRecipient"; /** * @dev Change Partition Flag used in transfer data parameters to signal which partition * will receive the tokens. */ bytes32 internal constant CHANGE_PARTITION_FLAG = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; /** * @dev Required prefix for all registered partitions. Used to ensure the Collateral Pool * Partition Validator is used within Amp. */ bytes4 internal constant PARTITION_PREFIX = 0xCCCCCCCC; /********************************************************************************************** * Operator Data Flags *********************************************************************************************/ /** * @dev Flag used in operator data parameters to indicate the transfer is a withdrawal */ bytes32 internal constant WITHDRAWAL_FLAG = 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; /** * @dev Flag used in operator data parameters to indicate the transfer is a fallback * withdrawal */ bytes32 internal constant FALLBACK_WITHDRAWAL_FLAG = 0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; /** * @dev Flag used in operator data parameters to indicate the transfer is a supply refund */ bytes32 internal constant REFUND_FLAG = 0xcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc; /** * @dev Flag used in operator data parameters to indicate the transfer is a direct transfer */ bytes32 internal constant DIRECT_TRANSFER_FLAG = 0xdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd; /********************************************************************************************** * Configuration *********************************************************************************************/ /** * @notice Address of the Amp contract. Immutable. */ address public amp; /** * @notice Permitted partitions */ mapping(bytes32 => bool) public partitions; /********************************************************************************************** * Roles *********************************************************************************************/ /** * @notice Address authorized to publish withdrawal roots */ address public withdrawalPublisher; /** * @notice Address authorized to publish fallback withdrawal roots */ address public fallbackPublisher; /** * @notice Address authorized to adjust the withdrawal limit */ address public withdrawalLimitPublisher; /** * @notice Address authorized to directly transfer tokens */ address public directTransferer; /** * @notice Address authorized to manage permitted partition */ address public partitionManager; /** * @notice Struct used to record received tokens that can be recovered during the fallback * withdrawal period * @param supplier Token supplier * @param partition Partition which received the tokens * @param amount Number of tokens received */ struct Supply { address supplier; bytes32 partition; uint256 amount; } /********************************************************************************************** * Supply State *********************************************************************************************/ /** * @notice Supply nonce used to track incoming token transfers */ uint256 public supplyNonce = 0; /** * @notice Mapping of all incoming token transfers */ mapping(uint256 => Supply) public nonceToSupply; /********************************************************************************************** * Withdrawal State *********************************************************************************************/ /** * @notice Remaining withdrawal limit. Initially set to 100,000 Amp. */ uint256 public withdrawalLimit = 100 * 1000 * (10**18); /** * @notice Withdrawal maximum root nonce */ uint256 public maxWithdrawalRootNonce = 0; /** * @notice Active set of withdrawal roots */ mapping(bytes32 => uint256) public withdrawalRootToNonce; /** * @notice Last invoked withdrawal root for each account, per partition */ mapping(bytes32 => mapping(address => uint256)) public addressToWithdrawalNonce; /** * @notice Total amount withdrawn for each account, per partition */ mapping(bytes32 => mapping(address => uint256)) public addressToCumulativeAmountWithdrawn; /********************************************************************************************** * Fallback Withdrawal State *********************************************************************************************/ /** * @notice Withdrawal fallback delay. Initially set to one week. */ uint256 public fallbackWithdrawalDelaySeconds = 1 weeks; /** * @notice Current fallback withdrawal root */ bytes32 public fallbackRoot; /** * @notice Timestamp of when the last fallback root was published */ uint256 public fallbackSetDate = 2**200; // very far in the future /** * @notice Latest supply reflected in the fallback withdrawal authorization tree */ uint256 public fallbackMaxIncludedSupplyNonce = 0; /********************************************************************************************** * Supplier Events *********************************************************************************************/ /** * @notice Indicates a token supply has been received * @param supplier Token supplier * @param amount Number of tokens transferred * @param nonce Nonce of the supply */ event SupplyReceipt( address indexed supplier, bytes32 indexed partition, uint256 amount, uint256 indexed nonce ); /** * @notice Indicates that a withdrawal was executed * @param supplier Address whose withdrawal authorization was executed * @param partition Partition from which the tokens were transferred * @param amount Amount of tokens transferred * @param rootNonce Nonce of the withdrawal root used for authorization * @param authorizedAccountNonce Maximum previous nonce used by the account */ event Withdrawal( address indexed supplier, bytes32 indexed partition, uint256 amount, uint256 indexed rootNonce, uint256 authorizedAccountNonce ); /** * @notice Indicates a fallback withdrawal was executed * @param supplier Address whose fallback withdrawal authorization was executed * @param partition Partition from which the tokens were transferred * @param amount Amount of tokens transferred */ event FallbackWithdrawal( address indexed supplier, bytes32 indexed partition, uint256 indexed amount ); /** * @notice Indicates a release of supply is requested * @param supplier Token supplier * @param partition Parition from which the tokens should be released * @param amount Number of tokens requested to be released * @param data Metadata provided by the requestor */ event ReleaseRequest( address indexed supplier, bytes32 indexed partition, uint256 indexed amount, bytes data ); /** * @notice Indicates a supply refund was executed * @param supplier Address whose refund authorization was executed * @param partition Partition from which the tokens were transferred * @param amount Amount of tokens transferred * @param nonce Nonce of the original supply */ event SupplyRefund( address indexed supplier, bytes32 indexed partition, uint256 amount, uint256 indexed nonce ); /********************************************************************************************** * Direct Transfer Events *********************************************************************************************/ /** * @notice Emitted when tokens are directly transfered * @param operator Address that executed the direct transfer * @param from_partition Partition from which the tokens were transferred * @param to_address Address to which the tokens were transferred * @param to_partition Partition to which the tokens were transferred * @param value Amount of tokens transferred */ event DirectTransfer( address operator, bytes32 indexed from_partition, address indexed to_address, bytes32 indexed to_partition, uint256 value ); /********************************************************************************************** * Admin Configuration Events *********************************************************************************************/ /** * @notice Emitted when a partition is permitted for supply * @param partition Partition added to the permitted set */ event PartitionAdded(bytes32 indexed partition); /** * @notice Emitted when a partition is removed from the set permitted for supply * @param partition Partition removed from the permitted set */ event PartitionRemoved(bytes32 indexed partition); /********************************************************************************************** * Admin Withdrawal Management Events *********************************************************************************************/ /** * @notice Emitted when a new withdrawal root hash is added to the active set * @param rootHash Merkle root hash. * @param nonce Nonce of the Merkle root hash. */ event WithdrawalRootHashAddition(bytes32 indexed rootHash, uint256 indexed nonce); /** * @notice Emitted when a withdrawal root hash is removed from the active set * @param rootHash Merkle root hash. * @param nonce Nonce of the Merkle root hash. */ event WithdrawalRootHashRemoval(bytes32 indexed rootHash, uint256 indexed nonce); /** * @notice Emitted when the withdrawal limit is updated * @param oldValue Old limit. * @param newValue New limit. */ event WithdrawalLimitUpdate(uint256 indexed oldValue, uint256 indexed newValue); /********************************************************************************************** * Admin Fallback Management Events *********************************************************************************************/ /** * @notice Emitted when a new fallback withdrawal root hash is set * @param rootHash Merkle root hash * @param maxSupplyNonceIncluded Nonce of the last supply reflected in the tree data * @param setDate Timestamp of when the root hash was set */ event FallbackRootHashSet( bytes32 indexed rootHash, uint256 indexed maxSupplyNonceIncluded, uint256 setDate ); /** * @notice Emitted when the fallback root hash set date is reset * @param newDate Timestamp of when the fallback reset date was set */ event FallbackMechanismDateReset(uint256 indexed newDate); /** * @notice Emitted when the fallback delay is updated * @param oldValue Old delay * @param newValue New delay */ event FallbackWithdrawalDelayUpdate(uint256 indexed oldValue, uint256 indexed newValue); /********************************************************************************************** * Role Management Events *********************************************************************************************/ /** * @notice Emitted when the Withdrawal Publisher is updated * @param oldValue Old publisher * @param newValue New publisher */ event WithdrawalPublisherUpdate(address indexed oldValue, address indexed newValue); /** * @notice Emitted when the Fallback Publisher is updated * @param oldValue Old publisher * @param newValue New publisher */ event FallbackPublisherUpdate(address indexed oldValue, address indexed newValue); /** * @notice Emitted when Withdrawal Limit Publisher is updated * @param oldValue Old publisher * @param newValue New publisher */ event WithdrawalLimitPublisherUpdate(address indexed oldValue, address indexed newValue); /** * @notice Emitted when the DirectTransferer address is updated * @param oldValue Old DirectTransferer address * @param newValue New DirectTransferer address */ event DirectTransfererUpdate(address indexed oldValue, address indexed newValue); /** * @notice Emitted when the Partition Manager address is updated * @param oldValue Old Partition Manager address * @param newValue New Partition Manager address */ event PartitionManagerUpdate(address indexed oldValue, address indexed newValue); /********************************************************************************************** * Constructor *********************************************************************************************/ /** * @notice FlexaCollateralManager constructor * @param _amp Address of the Amp token contract */ constructor(address _amp) public { amp = _amp; ERC1820Client.setInterfaceImplementation(AMP_TOKENS_RECIPIENT, address(this)); ERC1820Client.setInterfaceImplementation(AMP_TOKENS_SENDER, address(this)); IAmp(amp).registerCollateralManager(); } /********************************************************************************************** * IAmpTokensRecipient Hooks *********************************************************************************************/ /** * @notice Validates where the supplied parameters are valid for a transfer of tokens to this * contract * @dev Implements IAmpTokensRecipient * @param _partition Partition from which the tokens were transferred * @param _to The destination address of the tokens. Must be this. * @param _data Optional data sent with the transfer. Used to set the destination partition. * @return true if the tokens can be received, otherwise false */ function canReceive( bytes4, /* functionSig */ bytes32 _partition, address, /* operator */ address, /* from */ address _to, uint256, /* value */ bytes calldata _data, bytes calldata /* operatorData */ ) external override view returns (bool) { if (msg.sender != amp || _to != address(this)) { return false; } bytes32 _destinationPartition = PartitionUtils._getDestinationPartition(_data, _partition); return partitions[_destinationPartition]; } /** * @notice Function called by the token contract after executing a transfer. * @dev Implements IAmpTokensRecipient * @param _partition Partition from which the tokens were transferred * @param _operator Address which triggered the transfer. This address will be credited with * the supply. * @param _to The destination address of the tokens. Must be this. * @param _value Number of tokens the token holder balance is decreased by. * @param _data Optional data sent with the transfer. Used to set the destination partition. */ function tokensReceived( bytes4, /* functionSig */ bytes32 _partition, address _operator, address, /* from */ address _to, uint256 _value, bytes calldata _data, bytes calldata /* operatorData */ ) external override { require(msg.sender == amp, "Invalid sender"); require(_to == address(this), "Invalid to address"); bytes32 _destinationPartition = PartitionUtils._getDestinationPartition(_data, _partition); require(partitions[_destinationPartition], "Invalid destination partition"); supplyNonce = SafeMath.add(supplyNonce, 1); nonceToSupply[supplyNonce].supplier = _operator; nonceToSupply[supplyNonce].partition = _destinationPartition; nonceToSupply[supplyNonce].amount = _value; emit SupplyReceipt(_operator, _destinationPartition, _value, supplyNonce); } /********************************************************************************************** * IAmpTokensSender Hooks *********************************************************************************************/ /** * @notice Validates where the supplied parameters are valid for a transfer of tokens from this * contract * @dev Implements IAmpTokensSender * @param _partition Source partition of the tokens * @param _operator Address which triggered the transfer * @param _from The source address of the tokens. Must be this. * @param _value Amount of tokens to be transferred * @param _operatorData Extra information attached by the operator. Must include the transfer * operation flag and additional authorization data custom for each transfer operation type. * @return true if the token transfer would succeed, otherwise false */ function canTransfer( bytes4, /*functionSig*/ bytes32 _partition, address _operator, address _from, address, /* to */ uint256 _value, bytes calldata, /* data */ bytes calldata _operatorData ) external override view returns (bool) { if (msg.sender != amp || _from != address(this)) { return false; } bytes32 flag = _decodeOperatorDataFlag(_operatorData); if (flag == WITHDRAWAL_FLAG) { return _validateWithdrawal(_partition, _operator, _value, _operatorData); } if (flag == FALLBACK_WITHDRAWAL_FLAG) { return _validateFallbackWithdrawal(_partition, _operator, _value, _operatorData); } if (flag == REFUND_FLAG) { return _validateRefund(_partition, _operator, _value, _operatorData); } if (flag == DIRECT_TRANSFER_FLAG) { return _validateDirectTransfer(_operator, _value); } return false; } /** * @notice Function called by the token contract when executing a transfer * @dev Implements IAmpTokensSender * @param _partition Source partition of the tokens * @param _operator Address which triggered the transfer * @param _from The source address of the tokens. Must be this. * @param _to The target address of the tokens. * @param _value Amount of tokens to be transferred * @param _data Data attached to the transfer. Typically includes partition change information. * @param _operatorData Extra information attached by the operator. Must include the transfer * operation flag and additional authorization data custom for each transfer operation type. */ function tokensToTransfer( bytes4, /* functionSig */ bytes32 _partition, address _operator, address _from, address _to, uint256 _value, bytes calldata _data, bytes calldata _operatorData ) external override { require(msg.sender == amp, "Invalid sender"); require(_from == address(this), "Invalid from address"); bytes32 flag = _decodeOperatorDataFlag(_operatorData); if (flag == WITHDRAWAL_FLAG) { _executeWithdrawal(_partition, _operator, _value, _operatorData); } else if (flag == FALLBACK_WITHDRAWAL_FLAG) { _executeFallbackWithdrawal(_partition, _operator, _value, _operatorData); } else if (flag == REFUND_FLAG) { _executeRefund(_partition, _operator, _value, _operatorData); } else if (flag == DIRECT_TRANSFER_FLAG) { _executeDirectTransfer(_partition, _operator, _to, _value, _data); } else { revert("invalid flag"); } } /********************************************************************************************** * Withdrawals *********************************************************************************************/ /** * @notice Validates withdrawal data * @param _partition Source partition of the withdrawal * @param _operator Address that is invoking the transfer * @param _value Number of tokens to be transferred * @param _operatorData Contains the withdrawal authorization data * @return true if the withdrawal data is valid, otherwise false */ function _validateWithdrawal( bytes32 _partition, address _operator, uint256 _value, bytes memory _operatorData ) internal view returns (bool) { ( address supplier, uint256 maxAuthorizedAccountNonce, uint256 withdrawalRootNonce ) = _getWithdrawalData(_partition, _value, _operatorData); return _validateWithdrawalData( _partition, _operator, _value, supplier, maxAuthorizedAccountNonce, withdrawalRootNonce ); } /** * @notice Validates the withdrawal data and updates state to reflect the transfer * @param _partition Source partition of the withdrawal * @param _operator Address that is invoking the transfer * @param _value Number of tokens to be transferred * @param _operatorData Contains the withdrawal authorization data */ function _executeWithdrawal( bytes32 _partition, address _operator, uint256 _value, bytes memory _operatorData ) internal { ( address supplier, uint256 maxAuthorizedAccountNonce, uint256 withdrawalRootNonce ) = _getWithdrawalData(_partition, _value, _operatorData); require( _validateWithdrawalData( _partition, _operator, _value, supplier, maxAuthorizedAccountNonce, withdrawalRootNonce ), "Transfer unauthorized" ); addressToCumulativeAmountWithdrawn[_partition][supplier] = SafeMath.add( _value, addressToCumulativeAmountWithdrawn[_partition][supplier] ); addressToWithdrawalNonce[_partition][supplier] = withdrawalRootNonce; withdrawalLimit = SafeMath.sub(withdrawalLimit, _value); emit Withdrawal( supplier, _partition, _value, withdrawalRootNonce, maxAuthorizedAccountNonce ); } /** * @notice Extracts withdrawal data from the supplied parameters * @param _partition Source partition of the withdrawal * @param _value Number of tokens to be transferred * @param _operatorData Contains the withdrawal authorization data, including the withdrawal * operation flag, supplier, maximum authorized account nonce, and Merkle proof. * @return supplier, the address whose account is authorized * @return maxAuthorizedAccountNonce, the maximum existing used withdrawal nonce for the * supplier and partition * @return withdrawalRootNonce, the active withdrawal root nonce found based on the supplied * data and Merkle proof */ function _getWithdrawalData( bytes32 _partition, uint256 _value, bytes memory _operatorData ) internal view returns ( address, /* supplier */ uint256, /* maxAuthorizedAccountNonce */ uint256 /* withdrawalRootNonce */ ) { ( address supplier, uint256 maxAuthorizedAccountNonce, bytes32[] memory merkleProof ) = _decodeWithdrawalOperatorData(_operatorData); bytes32 leafDataHash = _calculateWithdrawalLeaf( supplier, _partition, _value, maxAuthorizedAccountNonce ); bytes32 calculatedRoot = _calculateMerkleRoot(merkleProof, leafDataHash); uint256 withdrawalRootNonce = withdrawalRootToNonce[calculatedRoot]; return (supplier, maxAuthorizedAccountNonce, withdrawalRootNonce); } /** * @notice Validates that the parameters are valid for the requested withdrawal * @param _partition Source partition of the tokens * @param _operator Address that is executing the withdrawal * @param _value Number of tokens to be transferred * @param _supplier The address whose account is authorized * @param _maxAuthorizedAccountNonce The maximum existing used withdrawal nonce for the * supplier and partition * @param _withdrawalRootNonce The active withdrawal root nonce found based on the supplied * data and Merkle proof * @return true if the withdrawal data is valid, otherwise false */ function _validateWithdrawalData( bytes32 _partition, address _operator, uint256 _value, address _supplier, uint256 _maxAuthorizedAccountNonce, uint256 _withdrawalRootNonce ) internal view returns (bool) { return // Only owner, withdrawal publisher or supplier can invoke withdrawals (_operator == owner() || _operator == withdrawalPublisher || _operator == _supplier) && // Ensure maxAuthorizedAccountNonce has not been exceeded (addressToWithdrawalNonce[_partition][_supplier] <= _maxAuthorizedAccountNonce) && // Ensure we are within the global withdrawal limit (_value <= withdrawalLimit) && // Merkle tree proof is valid (_withdrawalRootNonce > 0) && // Ensure the withdrawal root is more recent than the maxAuthorizedAccountNonce (_withdrawalRootNonce > _maxAuthorizedAccountNonce); } /********************************************************************************************** * Fallback Withdrawals *********************************************************************************************/ /** * @notice Validates fallback withdrawal data * @param _partition Source partition of the withdrawal * @param _operator Address that is invoking the transfer * @param _value Number of tokens to be transferred * @param _operatorData Contains the fallback withdrawal authorization data * @return true if the fallback withdrawal data is valid, otherwise false */ function _validateFallbackWithdrawal( bytes32 _partition, address _operator, uint256 _value, bytes memory _operatorData ) internal view returns (bool) { ( address supplier, uint256 maxCumulativeWithdrawalAmount, uint256 newCumulativeWithdrawalAmount, bytes32 calculatedRoot ) = _getFallbackWithdrawalData(_partition, _value, _operatorData); return _validateFallbackWithdrawalData( _operator, maxCumulativeWithdrawalAmount, newCumulativeWithdrawalAmount, supplier, calculatedRoot ); } /** * @notice Validates the fallback withdrawal data and updates state to reflect the transfer * @param _partition Source partition of the withdrawal * @param _operator Address that is invoking the transfer * @param _value Number of tokens to be transferred * @param _operatorData Contains the fallback withdrawal authorization data */ function _executeFallbackWithdrawal( bytes32 _partition, address _operator, uint256 _value, bytes memory _operatorData ) internal { ( address supplier, uint256 maxCumulativeWithdrawalAmount, uint256 newCumulativeWithdrawalAmount, bytes32 calculatedRoot ) = _getFallbackWithdrawalData(_partition, _value, _operatorData); require( _validateFallbackWithdrawalData( _operator, maxCumulativeWithdrawalAmount, newCumulativeWithdrawalAmount, supplier, calculatedRoot ), "Transfer unauthorized" ); addressToCumulativeAmountWithdrawn[_partition][supplier] = newCumulativeWithdrawalAmount; addressToWithdrawalNonce[_partition][supplier] = maxWithdrawalRootNonce; emit FallbackWithdrawal(supplier, _partition, _value); } /** * @notice Extracts withdrawal data from the supplied parameters * @param _partition Source partition of the withdrawal * @param _value Number of tokens to be transferred * @param _operatorData Contains the fallback withdrawal authorization data, including the * fallback withdrawal operation flag, supplier, max cumulative withdrawal amount, and Merkle * proof. * @return supplier, the address whose account is authorized * @return maxCumulativeWithdrawalAmount, the maximum amount of tokens that can be withdrawn * for the supplier's account, including both withdrawals and fallback withdrawals * @return newCumulativeWithdrawalAmount, the new total of all withdrawals include the * current request * @return calculatedRoot, the Merkle tree root calculated based on the supplied data and proof */ function _getFallbackWithdrawalData( bytes32 _partition, uint256 _value, bytes memory _operatorData ) internal view returns ( address, /* supplier */ uint256, /* maxCumulativeWithdrawalAmount */ uint256, /* newCumulativeWithdrawalAmount */ bytes32 /* calculatedRoot */ ) { ( address supplier, uint256 maxCumulativeWithdrawalAmount, bytes32[] memory merkleProof ) = _decodeWithdrawalOperatorData(_operatorData); uint256 newCumulativeWithdrawalAmount = SafeMath.add( _value, addressToCumulativeAmountWithdrawn[_partition][supplier] ); bytes32 leafDataHash = _calculateFallbackLeaf( supplier, _partition, maxCumulativeWithdrawalAmount ); bytes32 calculatedRoot = _calculateMerkleRoot(merkleProof, leafDataHash); return ( supplier, maxCumulativeWithdrawalAmount, newCumulativeWithdrawalAmount, calculatedRoot ); } /** * @notice Validates that the parameters are valid for the requested fallback withdrawal * @param _operator Address that is executing the withdrawal * @param _maxCumulativeWithdrawalAmount, the maximum amount of tokens that can be withdrawn * for the supplier's account, including both withdrawals and fallback withdrawals * @param _newCumulativeWithdrawalAmount, the new total of all withdrawals include the * current request * @param _supplier The address whose account is authorized * @param _calculatedRoot The Merkle tree root calculated based on the supplied data and proof * @return true if the fallback withdrawal data is valid, otherwise false */ function _validateFallbackWithdrawalData( address _operator, uint256 _maxCumulativeWithdrawalAmount, uint256 _newCumulativeWithdrawalAmount, address _supplier, bytes32 _calculatedRoot ) internal view returns (bool) { return // Only owner or supplier can invoke the fallback withdrawal (_operator == owner() || _operator == _supplier) && // Ensure we have entered fallback mode (SafeMath.add(fallbackSetDate, fallbackWithdrawalDelaySeconds) <= block.timestamp) && // Check that the maximum allowable withdrawal for the supplier has not been exceeded (_newCumulativeWithdrawalAmount <= _maxCumulativeWithdrawalAmount) && // Merkle tree proof is valid (fallbackRoot == _calculatedRoot); } /********************************************************************************************** * Supply Refunds *********************************************************************************************/ /** * @notice Validates refund data * @param _partition Source partition of the refund * @param _operator Address that is invoking the transfer * @param _value Number of tokens to be transferred * @param _operatorData Contains the refund authorization data * @return true if the refund data is valid, otherwise false */ function _validateRefund( bytes32 _partition, address _operator, uint256 _value, bytes memory _operatorData ) internal view returns (bool) { (uint256 _supplyNonce, Supply memory supply) = _getRefundData(_operatorData); return _verifyRefundData(_partition, _operator, _value, _supplyNonce, supply); } /** * @notice Validates the refund data and updates state to reflect the transfer * @param _partition Source partition of the refund * @param _operator Address that is invoking the transfer * @param _value Number of tokens to be transferred * @param _operatorData Contains the refund authorization data */ function _executeRefund( bytes32 _partition, address _operator, uint256 _value, bytes memory _operatorData ) internal { (uint256 nonce, Supply memory supply) = _getRefundData(_operatorData); require( _verifyRefundData(_partition, _operator, _value, nonce, supply), "Transfer unauthorized" ); delete nonceToSupply[nonce]; emit SupplyRefund(supply.supplier, _partition, supply.amount, nonce); } /** * @notice Extracts refund data from the supplied parameters * @param _operatorData Contains the refund authorization data, including the refund * operation flag and supply nonce. * @return supplyNonce, nonce of the recorded supply * @return supply, The supplier, partition and amount of tokens in the original supply */ function _getRefundData(bytes memory _operatorData) internal view returns (uint256, Supply memory) { uint256 _supplyNonce = _decodeRefundOperatorData(_operatorData); Supply memory supply = nonceToSupply[_supplyNonce]; return (_supplyNonce, supply); } /** * @notice Validates that the parameters are valid for the requested refund * @param _partition Source partition of the tokens * @param _operator Address that is executing the refund * @param _value Number of tokens to be transferred * @param _supplyNonce nonce of the recorded supply * @param _supply The supplier, partition and amount of tokens in the original supply * @return true if the refund data is valid, otherwise false */ function _verifyRefundData( bytes32 _partition, address _operator, uint256 _value, uint256 _supplyNonce, Supply memory _supply ) internal view returns (bool) { return // Supply record exists (_supply.amount > 0) && // Only owner or supplier can invoke the refund (_operator == owner() || _operator == _supply.supplier) && // Requested partition matches the Supply record (_partition == _supply.partition) && // Requested value matches the Supply record (_value == _supply.amount) && // Ensure we have entered fallback mode (SafeMath.add(fallbackSetDate, fallbackWithdrawalDelaySeconds) <= block.timestamp) && // Supply has not already been included in the fallback withdrawal data (_supplyNonce > fallbackMaxIncludedSupplyNonce); } /********************************************************************************************** * Direct Transfers *********************************************************************************************/ /** * @notice Validates direct transfer data * @param _operator Address that is invoking the transfer * @param _value Number of tokens to be transferred * @return true if the direct transfer data is valid, otherwise false */ function _validateDirectTransfer(address _operator, uint256 _value) internal view returns (bool) { return // Only owner and directTransferer can invoke withdrawals (_operator == owner() || _operator == directTransferer) && // Ensure we are within the global withdrawal limit (_value <= withdrawalLimit); } /** * @notice Validates the direct transfer data and updates state to reflect the transfer * @param _partition Source partition of the direct transfer * @param _operator Address that is invoking the transfer * @param _to The target address of the tokens. * @param _value Number of tokens to be transferred * @param _data Data attached to the transfer. Typically includes partition change information. */ function _executeDirectTransfer( bytes32 _partition, address _operator, address _to, uint256 _value, bytes memory _data ) internal { require(_validateDirectTransfer(_operator, _value), "Transfer unauthorized"); withdrawalLimit = SafeMath.sub(withdrawalLimit, _value); bytes32 to_partition = PartitionUtils._getDestinationPartition(_data, _partition); emit DirectTransfer(_operator, _partition, _to, to_partition, _value); } /********************************************************************************************** * Release Request *********************************************************************************************/ /** * @notice Emits a release request event that can be used to trigger the release of tokens * @param _partition Parition from which the tokens should be released * @param _amount Number of tokens requested to be released * @param _data Metadata to include with the release request */ function requestRelease( bytes32 _partition, uint256 _amount, bytes memory _data ) external { emit ReleaseRequest(msg.sender, _partition, _amount, _data); } /********************************************************************************************** * Partition Management *********************************************************************************************/ /** * @notice Adds a partition to the set allowed to receive tokens * @param _partition Parition to be permitted for incoming transfers */ function addPartition(bytes32 _partition) external { require(msg.sender == owner() || msg.sender == partitionManager, "Invalid sender"); require(partitions[_partition] == false, "Partition already permitted"); (bytes4 prefix, , address partitionOwner) = PartitionUtils._splitPartition(_partition); require(prefix == PARTITION_PREFIX, "Invalid partition prefix"); require(partitionOwner == address(this), "Invalid partition owner"); partitions[_partition] = true; emit PartitionAdded(_partition); } /** * @notice Removes a partition from the set allowed to receive tokens * @param _partition Parition to be disallowed from incoming transfers */ function removePartition(bytes32 _partition) external { require(msg.sender == owner() || msg.sender == partitionManager, "Invalid sender"); require(partitions[_partition], "Partition not permitted"); delete partitions[_partition]; emit PartitionRemoved(_partition); } /********************************************************************************************** * Withdrawal Management *********************************************************************************************/ /** * @notice Modifies the withdrawal limit by the provided amount. * @param _amount Limit delta */ function modifyWithdrawalLimit(int256 _amount) external { require(msg.sender == owner() || msg.sender == withdrawalLimitPublisher, "Invalid sender"); uint256 oldLimit = withdrawalLimit; if (_amount < 0) { uint256 unsignedAmount = uint256(-_amount); withdrawalLimit = SafeMath.sub(withdrawalLimit, unsignedAmount); } else { uint256 unsignedAmount = uint256(_amount); withdrawalLimit = SafeMath.add(withdrawalLimit, unsignedAmount); } emit WithdrawalLimitUpdate(oldLimit, withdrawalLimit); } /** * @notice Adds the root hash of a Merkle tree containing authorized token withdrawals to the * active set * @param _root The root hash to be added to the active set * @param _nonce The nonce of the new root hash. Must be exactly one higher than the existing * max nonce. * @param _replacedRoots The root hashes to be removed from the repository. */ function addWithdrawalRoot( bytes32 _root, uint256 _nonce, bytes32[] calldata _replacedRoots ) external { require(msg.sender == owner() || msg.sender == withdrawalPublisher, "Invalid sender"); require(_root != 0, "Invalid root"); require(maxWithdrawalRootNonce + 1 == _nonce, "Nonce not current max plus one"); require(withdrawalRootToNonce[_root] == 0, "Nonce already used"); withdrawalRootToNonce[_root] = _nonce; maxWithdrawalRootNonce = _nonce; emit WithdrawalRootHashAddition(_root, _nonce); for (uint256 i = 0; i < _replacedRoots.length; i++) { deleteWithdrawalRoot(_replacedRoots[i]); } } /** * @notice Removes withdrawal root hashes from active set * @param _roots The root hashes to be removed from the active set */ function removeWithdrawalRoots(bytes32[] calldata _roots) external { require(msg.sender == owner() || msg.sender == withdrawalPublisher, "Invalid sender"); for (uint256 i = 0; i < _roots.length; i++) { deleteWithdrawalRoot(_roots[i]); } } /** * @notice Removes a withdrawal root hash from active set * @param _root The root hash to be removed from the active set */ function deleteWithdrawalRoot(bytes32 _root) private { uint256 nonce = withdrawalRootToNonce[_root]; require(nonce > 0, "Root not found"); delete withdrawalRootToNonce[_root]; emit WithdrawalRootHashRemoval(_root, nonce); } /********************************************************************************************** * Fallback Management *********************************************************************************************/ /** * @notice Sets the root hash of the Merkle tree containing fallback * withdrawal authorizations. * @param _root The root hash of a Merkle tree containing the fallback withdrawal * authorizations * @param _maxSupplyNonce The nonce of the latest supply whose value is reflected in the * fallback withdrawal authorizations. */ function setFallbackRoot(bytes32 _root, uint256 _maxSupplyNonce) external { require(msg.sender == owner() || msg.sender == fallbackPublisher, "Invalid sender"); require(_root != 0, "Invalid root"); require( SafeMath.add(fallbackSetDate, fallbackWithdrawalDelaySeconds) > block.timestamp, "Fallback is active" ); require( _maxSupplyNonce >= fallbackMaxIncludedSupplyNonce, "Included supply nonce decreased" ); require(_maxSupplyNonce <= supplyNonce, "Included supply nonce exceeds latest supply"); fallbackRoot = _root; fallbackMaxIncludedSupplyNonce = _maxSupplyNonce; fallbackSetDate = block.timestamp; emit FallbackRootHashSet(_root, fallbackMaxIncludedSupplyNonce, block.timestamp); } /** * @notice Resets the fallback set date to the current block's timestamp. This can be used to * delay the start of the fallback period without publishing a new root, or to deactivate the * fallback mechanism so a new fallback root may be published. */ function resetFallbackMechanismDate() external { require(msg.sender == owner() || msg.sender == fallbackPublisher, "Invalid sender"); fallbackSetDate = block.timestamp; emit FallbackMechanismDateReset(fallbackSetDate); } /** * @notice Updates the time-lock period before the fallback mechanism is activated after the * last fallback root was published. * @param _newFallbackDelaySeconds The new delay period in seconds */ function setFallbackWithdrawalDelay(uint256 _newFallbackDelaySeconds) external { require(msg.sender == owner(), "Invalid sender"); require(_newFallbackDelaySeconds != 0, "Invalid zero delay seconds"); require(_newFallbackDelaySeconds < 10 * 365 days, "Invalid delay over 10 years"); uint256 oldDelay = fallbackWithdrawalDelaySeconds; fallbackWithdrawalDelaySeconds = _newFallbackDelaySeconds; emit FallbackWithdrawalDelayUpdate(oldDelay, _newFallbackDelaySeconds); } /********************************************************************************************** * Role Management *********************************************************************************************/ /** * @notice Updates the Withdrawal Publisher address, the only address other than the owner that * can publish / remove withdrawal Merkle tree roots. * @param _newWithdrawalPublisher The address of the new Withdrawal Publisher * @dev Error invalid sender. */ function setWithdrawalPublisher(address _newWithdrawalPublisher) external { require(msg.sender == owner(), "Invalid sender"); address oldValue = withdrawalPublisher; withdrawalPublisher = _newWithdrawalPublisher; emit WithdrawalPublisherUpdate(oldValue, withdrawalPublisher); } /** * @notice Updates the Fallback Publisher address, the only address other than the owner that * can publish / remove fallback withdrawal Merkle tree roots. * @param _newFallbackPublisher The address of the new Fallback Publisher * @dev Error invalid sender. */ function setFallbackPublisher(address _newFallbackPublisher) external { require(msg.sender == owner(), "Invalid sender"); address oldValue = fallbackPublisher; fallbackPublisher = _newFallbackPublisher; emit FallbackPublisherUpdate(oldValue, fallbackPublisher); } /** * @notice Updates the Withdrawal Limit Publisher address, the only address other than the * owner that can set the withdrawal limit. * @param _newWithdrawalLimitPublisher The address of the new Withdrawal Limit Publisher * @dev Error invalid sender. */ function setWithdrawalLimitPublisher(address _newWithdrawalLimitPublisher) external { require(msg.sender == owner(), "Invalid sender"); address oldValue = withdrawalLimitPublisher; withdrawalLimitPublisher = _newWithdrawalLimitPublisher; emit WithdrawalLimitPublisherUpdate(oldValue, withdrawalLimitPublisher); } /** * @notice Updates the DirectTransferer address, the only address other than the owner that * can execute direct transfers * @param _newDirectTransferer The address of the new DirectTransferer */ function setDirectTransferer(address _newDirectTransferer) external { require(msg.sender == owner(), "Invalid sender"); address oldValue = directTransferer; directTransferer = _newDirectTransferer; emit DirectTransfererUpdate(oldValue, directTransferer); } /** * @notice Updates the Partition Manager address, the only address other than the owner that * can add and remove permitted partitions * @param _newPartitionManager The address of the new PartitionManager */ function setPartitionManager(address _newPartitionManager) external { require(msg.sender == owner(), "Invalid sender"); address oldValue = partitionManager; partitionManager = _newPartitionManager; emit PartitionManagerUpdate(oldValue, partitionManager); } /********************************************************************************************** * Operator Data Decoders *********************************************************************************************/ /** * @notice Extract flag from operatorData * @param _operatorData The operator data to be decoded * @return flag, the transfer operation type */ function _decodeOperatorDataFlag(bytes memory _operatorData) internal pure returns (bytes32) { return abi.decode(_operatorData, (bytes32)); } /** * @notice Extracts the supplier, max authorized nonce, and Merkle proof from the operator data * @param _operatorData The operator data to be decoded * @return supplier, the address whose account is authorized * @return For withdrawals: max authorized nonce, the last used withdrawal root nonce for the * supplier and partition. For fallback withdrawals: max cumulative withdrawal amount, the * maximum amount of tokens that can be withdrawn for the supplier's account, including both * withdrawals and fallback withdrawals * @return proof, the Merkle proof to be used for the authorization */ function _decodeWithdrawalOperatorData(bytes memory _operatorData) internal pure returns ( address, uint256, bytes32[] memory ) { (, address supplier, uint256 nonce, bytes32[] memory proof) = abi.decode( _operatorData, (bytes32, address, uint256, bytes32[]) ); return (supplier, nonce, proof); } /** * @notice Extracts the supply nonce from the operator data * @param _operatorData The operator data to be decoded * @return nonce, the nonce of the supply to be refunded */ function _decodeRefundOperatorData(bytes memory _operatorData) internal pure returns (uint256) { (, uint256 nonce) = abi.decode(_operatorData, (bytes32, uint256)); return nonce; } /********************************************************************************************** * Merkle Tree Verification *********************************************************************************************/ /** * @notice Hashes the supplied data and returns the hash to be used in conjunction with a proof * to calculate the Merkle tree root * @param _supplier The address whose account is authorized * @param _partition Source partition of the tokens * @param _value Number of tokens to be transferred * @param _maxAuthorizedAccountNonce The maximum existing used withdrawal nonce for the * supplier and partition * @return leaf, the hash of the supplied data */ function _calculateWithdrawalLeaf( address _supplier, bytes32 _partition, uint256 _value, uint256 _maxAuthorizedAccountNonce ) internal pure returns (bytes32) { return keccak256(abi.encodePacked(_supplier, _partition, _value, _maxAuthorizedAccountNonce)); } /** * @notice Hashes the supplied data and returns the hash to be used in conjunction with a proof * to calculate the Merkle tree root * @param _supplier The address whose account is authorized * @param _partition Source partition of the tokens * @param _maxCumulativeWithdrawalAmount, the maximum amount of tokens that can be withdrawn * for the supplier's account, including both withdrawals and fallback withdrawals * @return leaf, the hash of the supplied data */ function _calculateFallbackLeaf( address _supplier, bytes32 _partition, uint256 _maxCumulativeWithdrawalAmount ) internal pure returns (bytes32) { return keccak256(abi.encodePacked(_supplier, _partition, _maxCumulativeWithdrawalAmount)); } /** * @notice Calculates the Merkle root for the unique Merkle tree described by the provided Merkle proof and leaf hash. * @param _merkleProof The sibling node hashes at each level of the tree. * @param _leafHash The hash of the leaf data for which merkleProof is an inclusion proof. * @return The calculated Merkle root. */ function _calculateMerkleRoot(bytes32[] memory _merkleProof, bytes32 _leafHash) private pure returns (bytes32) { bytes32 computedHash = _leafHash; for (uint256 i = 0; i < _merkleProof.length; i++) { bytes32 proofElement = _merkleProof[i]; if (computedHash < proofElement) { computedHash = keccak256(abi.encodePacked(computedHash, proofElement)); } else { computedHash = keccak256(abi.encodePacked(proofElement, computedHash)); } } return computedHash; } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_amp","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"bytes32","name":"from_partition","type":"bytes32"},{"indexed":true,"internalType":"address","name":"to_address","type":"address"},{"indexed":true,"internalType":"bytes32","name":"to_partition","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"DirectTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldValue","type":"address"},{"indexed":true,"internalType":"address","name":"newValue","type":"address"}],"name":"DirectTransfererUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"newDate","type":"uint256"}],"name":"FallbackMechanismDateReset","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldValue","type":"address"},{"indexed":true,"internalType":"address","name":"newValue","type":"address"}],"name":"FallbackPublisherUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"rootHash","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"maxSupplyNonceIncluded","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"setDate","type":"uint256"}],"name":"FallbackRootHashSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"supplier","type":"address"},{"indexed":true,"internalType":"bytes32","name":"partition","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FallbackWithdrawal","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"oldValue","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"FallbackWithdrawalDelayUpdate","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":true,"internalType":"bytes32","name":"partition","type":"bytes32"}],"name":"PartitionAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldValue","type":"address"},{"indexed":true,"internalType":"address","name":"newValue","type":"address"}],"name":"PartitionManagerUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"partition","type":"bytes32"}],"name":"PartitionRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"supplier","type":"address"},{"indexed":true,"internalType":"bytes32","name":"partition","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"ReleaseRequest","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"supplier","type":"address"},{"indexed":true,"internalType":"bytes32","name":"partition","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"SupplyReceipt","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"supplier","type":"address"},{"indexed":true,"internalType":"bytes32","name":"partition","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"SupplyRefund","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"supplier","type":"address"},{"indexed":true,"internalType":"bytes32","name":"partition","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"rootNonce","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"authorizedAccountNonce","type":"uint256"}],"name":"Withdrawal","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldValue","type":"address"},{"indexed":true,"internalType":"address","name":"newValue","type":"address"}],"name":"WithdrawalLimitPublisherUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"oldValue","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"WithdrawalLimitUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldValue","type":"address"},{"indexed":true,"internalType":"address","name":"newValue","type":"address"}],"name":"WithdrawalPublisherUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"rootHash","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"WithdrawalRootHashAddition","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"rootHash","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"WithdrawalRootHashRemoval","type":"event"},{"inputs":[{"internalType":"bytes32","name":"_partition","type":"bytes32"}],"name":"addPartition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_root","type":"bytes32"},{"internalType":"uint256","name":"_nonce","type":"uint256"},{"internalType":"bytes32[]","name":"_replacedRoots","type":"bytes32[]"}],"name":"addWithdrawalRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"address","name":"","type":"address"}],"name":"addressToCumulativeAmountWithdrawn","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"address","name":"","type":"address"}],"name":"addressToWithdrawalNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"amp","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"assumeOwnership","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":"bytes4","name":"","type":"bytes4"},{"internalType":"bytes32","name":"_partition","type":"bytes32"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"canReceive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"","type":"bytes4"},{"internalType":"bytes32","name":"_partition","type":"bytes32"},{"internalType":"address","name":"_operator","type":"address"},{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"bytes","name":"_operatorData","type":"bytes"}],"name":"canTransfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"directTransferer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fallbackMaxIncludedSupplyNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fallbackPublisher","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fallbackRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fallbackSetDate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fallbackWithdrawalDelaySeconds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxWithdrawalRootNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"int256","name":"_amount","type":"int256"}],"name":"modifyWithdrawalLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"nonceToSupply","outputs":[{"internalType":"address","name":"supplier","type":"address"},{"internalType":"bytes32","name":"partition","type":"bytes32"},{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"partitionManager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"partitions","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_partition","type":"bytes32"}],"name":"removePartition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"_roots","type":"bytes32[]"}],"name":"removeWithdrawalRoots","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_partition","type":"bytes32"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"requestRelease","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"resetFallbackMechanismDate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newDirectTransferer","type":"address"}],"name":"setDirectTransferer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newFallbackPublisher","type":"address"}],"name":"setFallbackPublisher","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_root","type":"bytes32"},{"internalType":"uint256","name":"_maxSupplyNonce","type":"uint256"}],"name":"setFallbackRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newFallbackDelaySeconds","type":"uint256"}],"name":"setFallbackWithdrawalDelay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newPartitionManager","type":"address"}],"name":"setPartitionManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newWithdrawalLimitPublisher","type":"address"}],"name":"setWithdrawalLimitPublisher","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newWithdrawalPublisher","type":"address"}],"name":"setWithdrawalPublisher","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"supplyNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"","type":"bytes4"},{"internalType":"bytes32","name":"_partition","type":"bytes32"},{"internalType":"address","name":"_operator","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"tokensReceived","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"","type":"bytes4"},{"internalType":"bytes32","name":"_partition","type":"bytes32"},{"internalType":"address","name":"_operator","type":"address"},{"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":"tokensToTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawalLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawalLimitPublisher","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawalPublisher","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"withdrawalRootToNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
6080604052600060095569152d02c7e14af6800000600b556000600c5562093a8060105579010000000000000000000000000000000000000000000000000060125560006013553480156200005357600080fd5b50604051620053fb380380620053fb833981810160405260208110156200007957600080fd5b8101908080519060200190929190505050336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550620001576040518060400160405280601281526020017f416d70546f6b656e73526563697069656e740000000000000000000000000000815250306200022e60201b62003c571760201c565b620001a36040518060400160405280600f81526020017f416d70546f6b656e7353656e6465720000000000000000000000000000000000815250306200022e60201b62003c571760201c565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b9d7b4716040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156200020e57600080fd5b505af115801562000223573d6000803e3d6000fd5b505050505062000394565b6000826040516020018082805190602001908083835b6020831062000269578051825260208201915060208101905060208303925062000244565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051602081830303815290604052805190602001209050731820a4b7618bde71dce8cdc73aab6c95905fad2473ffffffffffffffffffffffffffffffffffffffff166329965a1d3083856040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019350505050600060405180830381600087803b1580156200037657600080fd5b505af11580156200038b573d6000803e3d6000fd5b50505050505050565b61505780620003a46000396000f3fe608060405234801561001057600080fd5b50600436106102485760003560e01c80636833403c1161013b5780639363a2a5116100b8578063d445781a1161007c578063d445781a14610ef8578063e44b87f914610f3e578063ec3bb28814610f82578063f18d9a70146110ee578063f24bb1c11461110c57610248565b80639363a2a514610d65578063a2c1cae214610daf578063afa2886414610db9578063c4218e6e14610dfb578063c5cfe77a14610e2957610248565b806387f4427e116100ff57806387f4427e14610c2d578063887ec0b814610c715780638da5cb5b14610cb55780638db1c3ea14610cff5780638e9cdd7d14610d2d57610248565b80636833403c146109f75780636a928f8614610a3b5780637cc17da314610a595780637ddfe78d14610aa35780638240ef4814610ac157610248565b80633a9a7e44116101c95780635481eed31161018d5780635481eed3146108c95780635bc5752a146109135780635d7892801461095d5780635fcf44d1146109bf578063628e46cb146109ed57610248565b80633a9a7e44146107bb5780633b927235146107d957806342592662146107f757806344c545071461083b57806348105b121461088557610248565b80632b15d391116102105780632b15d3911461034b5780632c95e842146103d85780632e47d5e51461045157806330e4cfba146104b357806334c341801461063757610248565b80630780895f1461024d57806308c6345d1461027b5780630973e6ba146102c55780631c8f9a171461030f5780631cef21cf1461032d575b600080fd5b6102796004803603602081101561026357600080fd5b8101908080359060200190929190505050611188565b005b610283611305565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6102cd61132b565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610317611351565b6040518082815260200191505060405180910390f35b610335611357565b6040518082815260200191505060405180910390f35b6103d66004803603606081101561036157600080fd5b8101908080359060200190929190803590602001909291908035906020019064010000000081111561039257600080fd5b8201836020820111156103a457600080fd5b803590602001918460208302840111640100000000831117156103c657600080fd5b909192939192939050505061135d565b005b61044f600480360360208110156103ee57600080fd5b810190808035906020019064010000000081111561040b57600080fd5b82018360208201111561041d57600080fd5b8035906020019184602083028401116401000000008311171561043f57600080fd5b9091929391929390505050611666565b005b61049d6004803603604081101561046757600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506117a4565b6040518082815260200191505060405180910390f35b61061d60048036036101008110156104ca57600080fd5b8101908080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561058457600080fd5b82018360208201111561059657600080fd5b803590602001918460018302840111640100000000831117156105b857600080fd5b9091929391929390803590602001906401000000008111156105d957600080fd5b8201836020820111156105eb57600080fd5b8035906020019184600183028401116401000000008311171561060d57600080fd5b90919293919293905050506117c9565b604051808215151515815260200191505060405180910390f35b6107a1600480360361010081101561064e57600080fd5b8101908080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561070857600080fd5b82018360208201111561071a57600080fd5b8035906020019184600183028401116401000000008311171561073c57600080fd5b90919293919293908035906020019064010000000081111561075d57600080fd5b82018360208201111561076f57600080fd5b8035906020019184600183028401116401000000008311171561079157600080fd5b90919293919293905050506118e7565b604051808215151515815260200191505060405180910390f35b6107c3611bab565b6040518082815260200191505060405180910390f35b6107e1611bb1565b6040518082815260200191505060405180910390f35b6108396004803603602081101561080d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611bb7565b005b610843611d47565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6108c76004803603602081101561089b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611d6d565b005b6108d1611efd565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61091b611f27565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6109a96004803603604081101561097357600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611f4d565b6040518082815260200191505060405180910390f35b6109eb600480360360208110156109d557600080fd5b8101908080359060200190929190505050611f72565b005b6109f56122d6565b005b610a3960048036036020811015610a0d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061240e565b005b610a4361259e565b6040518082815260200191505060405180910390f35b610a616125a4565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610aab6125ca565b6040518082815260200191505060405180910390f35b610c2b6004803603610100811015610ad857600080fd5b8101908080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919080359060200190640100000000811115610b9257600080fd5b820183602082011115610ba457600080fd5b80359060200191846001830284011164010000000083111715610bc657600080fd5b909192939192939080359060200190640100000000811115610be757600080fd5b820183602082011115610bf957600080fd5b80359060200191846001830284011164010000000083111715610c1b57600080fd5b90919293919293905050506125d0565b005b610c6f60048036036020811015610c4357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061291c565b005b610cb360048036036020811015610c8757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612a87565b005b610cbd612c17565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610d2b60048036036020811015610d1557600080fd5b8101908080359060200190929190505050612c40565b005b610d6360048036036040811015610d4357600080fd5b810190808035906020019092919080359060200190929190505050612e18565b005b610d6d61313a565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610db7613160565b005b610de560048036036020811015610dcf57600080fd5b810190808035906020019092919050505061336b565b6040518082815260200191505060405180910390f35b610e2760048036036020811015610e1157600080fd5b8101908080359060200190929190505050613383565b005b610ef660048036036060811015610e3f57600080fd5b81019080803590602001909291908035906020019092919080359060200190640100000000811115610e7057600080fd5b820183602082011115610e8257600080fd5b80359060200191846001830284011164010000000083111715610ea457600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050613569565b005b610f2460048036036020811015610f0e57600080fd5b8101908080359060200190929190505050613623565b604051808215151515815260200191505060405180910390f35b610f8060048036036020811015610f5457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613643565b005b6110ec6004803603610100811015610f9957600080fd5b8101908080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561105357600080fd5b82018360208201111561106557600080fd5b8035906020019184600183028401116401000000008311171561108757600080fd5b9091929391929390803590602001906401000000008111156110a857600080fd5b8201836020820111156110ba57600080fd5b803590602001918460018302840111640100000000831117156110dc57600080fd5b90919293919293905050506137d3565b005b6110f6613c07565b6040518082815260200191505060405180910390f35b6111386004803603602081101561112257600080fd5b8101908080359060200190929190505050613c0d565b604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001838152602001828152602001935050505060405180910390f35b611190612c17565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806112165750600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b611288576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f496e76616c69642073656e64657200000000000000000000000000000000000081525060200191505060405180910390fd5b6000600b54905060008212156112b85760008260000390506112ac600b5482613db9565b600b81905550506112d1565b60008290506112c9600b5482613e03565b600b81905550505b600b54817f35100bc173608e4b64e73420ef31d05adb286a999a3adaeecb20db5a8374096460405160405180910390a35050565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60125481565b60105481565b611365612c17565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806113eb5750600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b61145d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f496e76616c69642073656e64657200000000000000000000000000000000000081525060200191505060405180910390fd5b6000801b8414156114d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600c8152602001807f496e76616c696420726f6f74000000000000000000000000000000000000000081525060200191505060405180910390fd5b826001600c540114611550576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4e6f6e6365206e6f742063757272656e74206d617820706c7573206f6e65000081525060200191505060405180910390fd5b6000600d600086815260200190815260200160002054146115d9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f4e6f6e636520616c72656164792075736564000000000000000000000000000081525060200191505060405180910390fd5b82600d60008681526020019081526020016000208190555082600c8190555082847fe03adc1e77ba682eeca70bd85e61002b19d2167914a5c91673b6db229fc9abef60405160405180910390a360008090505b8282905081101561165f5761165283838381811061164657fe5b90506020020135613e8b565b808060010191505061162c565b5050505050565b61166e612c17565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806116f45750600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b611766576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f496e76616c69642073656e64657200000000000000000000000000000000000081525060200191505060405180910390fd5b60008090505b8282905081101561179f5761179283838381811061178657fe5b90506020020135613e8b565b808060010191505061176c565b505050565b600f602052816000526040600020602052806000526040600020600091509150505481565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614158061185457503073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1614155b1561186257600090506118d9565b60006118b286868080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508c613f62565b90506003600082815260200190815260200160002060009054906101000a900460ff169150505b9a9950505050505050505050565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614158061197257503073ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff1614155b156119805760009050611b9d565b60006119cf84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050613fee565b90507faaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa60001b811415611a5457611a4c8b8b8987878080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505061401d565b915050611b9d565b7fbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb60001b811415611ad757611acf8b8b8987878080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505061404f565b915050611b9d565b7fcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc60001b811415611b5a57611b528b8b8987878080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050614085565b915050611b9d565b7fdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd60001b811415611b9757611b8f8a886140b6565b915050611b9d565b60009150505b9a9950505050505050505050565b60135481565b60115481565b611bbf612c17565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611c5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f496e76616c69642073656e64657200000000000000000000000000000000000081525060200191505060405180910390fd5b6000600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600660006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f7e8156acd1ac1a836d5fa06476cd7c2bd0397675c9caeee22b3c0b969bbebf8c60405160405180910390a35050565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b611d75612c17565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611e15576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f496e76616c69642073656e64657200000000000000000000000000000000000081525060200191505060405180910390fd5b6000600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167fd2e31556fcf8b4ba79fccb734eaf55dc59bd14b78be000354f6ca30422bbe49a60405160405180910390a35050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600e602052816000526040600020602052806000526040600020600091509150505481565b611f7a612c17565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806120005750600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b612072576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f496e76616c69642073656e64657200000000000000000000000000000000000081525060200191505060405180910390fd5b600015156003600083815260200190815260200160002060009054906101000a900460ff1615151461210c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f506172746974696f6e20616c7265616479207065726d6974746564000000000081525060200191505060405180910390fd5b6000806121188361415c565b925050915063cccccccc60e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916146121d7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f496e76616c696420706172746974696f6e20707265666978000000000000000081525060200191505060405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614612278576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f496e76616c696420706172746974696f6e206f776e657200000000000000000081525060200191505060405180910390fd5b60016003600085815260200190815260200160002060006101000a81548160ff021916908315150217905550827fe0a6f722db02a2a1bda25344bf96d858349b0e5e51b2dfc0189f43c3461c4fa760405160405180910390a2505050565b6122de612c17565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806123645750600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b6123d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f496e76616c69642073656e64657200000000000000000000000000000000000081525060200191505060405180910390fd5b426012819055506012547fbe5d770f5e481394f0304d913c12a7cb92610fb29b382af9f013cc43e53c671260405160405180910390a2565b612416612c17565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146124b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f496e76616c69642073656e64657200000000000000000000000000000000000081525060200191505060405180910390fd5b6000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167fdc4f94b18c0f53480d75b5a6e13d2b2b0414d87603d97d54f383579b8fc107a360405160405180910390a35050565b600c5481565b600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600b5481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612693576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f496e76616c69642073656e64657200000000000000000000000000000000000081525060200191505060405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614612734576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f496e76616c696420746f2061646472657373000000000000000000000000000081525060200191505060405180910390fd5b600061278485858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508b613f62565b90506003600082815260200190815260200160002060009054906101000a900460ff16612819576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f496e76616c69642064657374696e6174696f6e20706172746974696f6e00000081525060200191505060405180910390fd5b6128266009546001613e03565b60098190555088600a6000600954815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600a600060095481526020019081526020016000206001018190555085600a6000600954815260200190815260200160002060020181905550600954818a73ffffffffffffffffffffffffffffffffffffffff167fa5521f7d015e07af98ded530ac91a9ccef09b2b0fe09f6a0c8742f40d88e00d1896040518082815260200191505060405180910390a45050505050505050505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146129de576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f496e76616c69642073656e64657200000000000000000000000000000000000081525060200191505060405180910390fd5b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fb58bcc286020502f4931905baafed22acc969c092ed724234c73361efc68839060405160405180910390a250565b612a8f612c17565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612b2f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f496e76616c69642073656e64657200000000000000000000000000000000000081525060200191505060405180910390fd5b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f4129b839017b7e303a7a0ca5314793dbb9b6f4f59d12205970967a8a38c10be560405160405180910390a35050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b612c48612c17565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612ce8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f496e76616c69642073656e64657200000000000000000000000000000000000081525060200191505060405180910390fd5b6000811415612d5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f496e76616c6964207a65726f2064656c6179207365636f6e647300000000000081525060200191505060405180910390fd5b6312cc03008110612dd8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f496e76616c69642064656c6179206f766572203130207965617273000000000081525060200191505060405180910390fd5b600060105490508160108190555081817fbcf7cfa26c76f9f5223a62ddebfbc7ef67d6f5cd1ef27147b47cdc11aaae1ef160405160405180910390a35050565b612e20612c17565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480612ea65750600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b612f18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f496e76616c69642073656e64657200000000000000000000000000000000000081525060200191505060405180910390fd5b6000801b821415612f91576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600c8152602001807f496e76616c696420726f6f74000000000000000000000000000000000000000081525060200191505060405180910390fd5b42612fa0601254601054613e03565b11613013576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f46616c6c6261636b20697320616374697665000000000000000000000000000081525060200191505060405180910390fd5b60135481101561308b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f496e636c7564656420737570706c79206e6f6e6365206465637265617365640081525060200191505060405180910390fd5b6009548111156130e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b815260200180614ff7602b913960400191505060405180910390fd5b816011819055508060138190555042601281905550601354827fc838e1d9f03cb7be05349642820d7e002ef8a9a1efc2fbff3292096f6d66dee8426040518082815260200191505060405180910390a35050565b600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614613223576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f496e76616c69642073656e64657200000000000000000000000000000000000081525060200191505060405180910390fd5b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f343765429aea5a34b3ff6a3785a98a5abb2597aca87bfbb58632c173d585373a60405160405180910390a350565b600d6020528060005260406000206000915090505481565b61338b612c17565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806134115750600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b613483576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f496e76616c69642073656e64657200000000000000000000000000000000000081525060200191505060405180910390fd5b6003600082815260200190815260200160002060009054906101000a900460ff16613516576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f506172746974696f6e206e6f74207065726d697474656400000000000000000081525060200191505060405180910390fd5b6003600082815260200190815260200160002060006101000a81549060ff0219169055807f4eebd21e1429831abae9d8bf8c99b5e23567b718371940b6ec713f2c53f5393860405160405180910390a250565b81833373ffffffffffffffffffffffffffffffffffffffff167f1aba60afeb70d9dd8f76ece1c94871b4c3eb1b252b32f58102e21bfb81e944bf846040518080602001828103825283818151815260200191508051906020019080838360005b838110156135e45780820151818401526020810190506135c9565b50505050905090810190601f1680156136115780820380516001836020036101000a031916815260200191505b509250505060405180910390a4505050565b60036020528060005260406000206000915054906101000a900460ff1681565b61364b612c17565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146136eb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f496e76616c69642073656e64657200000000000000000000000000000000000081525060200191505060405180910390fd5b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167fd70953def42d9e2d7e243de8cce9cd4ffc14ab08a6090965afe3922f41ae1aa360405160405180910390a35050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614613896576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f496e76616c69642073656e64657200000000000000000000000000000000000081525060200191505060405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1614613937576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f496e76616c69642066726f6d206164647265737300000000000000000000000081525060200191505060405180910390fd5b600061398683838080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050613fee565b90507faaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa60001b811415613a0857613a038a8a8886868080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050614189565b613bfa565b7fbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb60001b811415613a8857613a838a8a8886868080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050614395565b613bf9565b7fcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc60001b811415613b0857613b038a8a8886868080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050614528565b613bf8565b7fdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd60001b811415613b8957613b848a8a898989898080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505061466b565b613bf7565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600c8152602001807f696e76616c696420666c6167000000000000000000000000000000000000000081525060200191505060405180910390fd5b5b5b5b5050505050505050505050565b60095481565b600a6020528060005260406000206000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060010154908060020154905083565b6000826040516020018082805190602001908083835b60208310613c905780518252602082019150602081019050602083039250613c6d565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051602081830303815290604052805190602001209050731820a4b7618bde71dce8cdc73aab6c95905fad2473ffffffffffffffffffffffffffffffffffffffff166329965a1d3083856040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019350505050600060405180830381600087803b158015613d9c57600080fd5b505af1158015613db0573d6000803e3d6000fd5b50505050505050565b6000613dfb83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250614793565b905092915050565b600080828401905083811015613e81576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b6000600d600083815260200190815260200160002054905060008111613f19576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f526f6f74206e6f7420666f756e6400000000000000000000000000000000000081525060200191505060405180910390fd5b600d60008381526020019081526020016000206000905580827f8983ad2a9726026394d7a200a18ba3e92f424253ae3eb71d3d8e61dc8e39667c60405160405180910390a35050565b6000604083511015613f7657819050613fe8565b600080848060200190516040811015613f8e57600080fd5b810190808051906020019092919080519060200190929190505050915091507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60001b821415613fe2578092505050613fe8565b83925050505b92915050565b600081806020019051602081101561400557600080fd5b81019080805190602001909291905050509050919050565b60008060008061402e888787614853565b9250925092506140428888888686866148ba565b9350505050949350505050565b6000806000806000614062898888614a0d565b93509350935093506140778884848785614abd565b945050505050949350505050565b600080614090614fbc565b61409984614b68565b915091506140aa8787878585614c1e565b92505050949350505050565b60006140c0612c17565b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614806141465750600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16145b80156141545750600b548211155b905092915050565b6000806000808490506000602086901b905060008660001c90508282829550955095505050509193909250565b6000806000614199878686614853565b9250925092506141ad8787878686866148ba565b61421f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f5472616e7366657220756e617574686f72697a6564000000000000000000000081525060200191505060405180910390fd5b61427985600f60008a815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054613e03565b600f600089815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555080600e600089815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555061432e600b5486613db9565b600b8190555080878473ffffffffffffffffffffffffffffffffffffffff167f7c05df8754d2754df450658e6ef9fd7bc12dedd9979acddebdd93ac086b424198886604051808381526020018281526020019250505060405180910390a450505050505050565b6000806000806143a6888787614a0d565b93509350935093506143bb8784848785614abd565b61442d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f5472616e7366657220756e617574686f72697a6564000000000000000000000081525060200191505060405180910390fd5b81600f60008a815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550600c54600e60008a815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555085888573ffffffffffffffffffffffffffffffffffffffff167f55ff7b4fbb2c54e7f151ea35b8b6f4b5668e5f1795d2b26fc89fd4d09b1b6de560405160405180910390a45050505050505050565b6000614532614fbc565b61453b83614b68565b9150915061454c8686868585614c1e565b6145be576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f5472616e7366657220756e617574686f72697a6564000000000000000000000081525060200191505060405180910390fd5b600a6000838152602001908152602001600020600080820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001820160009055600282016000905550508186826000015173ffffffffffffffffffffffffffffffffffffffff167fd3ae64e25cf9949339a5916876c3341a80b5b81eb732da3642a634a7512d180884604001516040518082815260200191505060405180910390a4505050505050565b61467584836140b6565b6146e7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f5472616e7366657220756e617574686f72697a6564000000000000000000000081525060200191505060405180910390fd5b6146f3600b5483613db9565b600b8190555060006147058287613f62565b9050808473ffffffffffffffffffffffffffffffffffffffff16877f4df85043c2fcb97b502fd05c3737899069bb1b523c06beaf6999f3c1f8e5a4b58887604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a4505050505050565b6000838311158290614840576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b838110156148055780820151818401526020810190506147ea565b50505050905090810190601f1680156148325780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b6000806000806000606061486687614cee565b925092509250600061487a848b8b86614ddc565b905060006148888383614e56565b90506000600d600083815260200190815260200160002054905085858298509850985050505050505093509350939050565b60006148c4612c17565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16148061494a5750600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16145b8061498057508373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16145b80156149dc575082600e600089815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205411155b80156149ea5750600b548511155b80156149f65750600082115b8015614a0157508282115b90509695505050505050565b6000806000806000806060614a2188614cee565b9250925092506000614a838a600f60008e815260200190815260200160002060008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054613e03565b90506000614a92858d86614f0c565b90506000614aa08483614e56565b905085858483995099509950995050505050505093509350935093565b6000614ac7612c17565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff161480614b2b57508273ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16145b8015614b44575042614b41601254601054613e03565b11155b8015614b505750848411155b8015614b5d575081601154145b905095945050505050565b6000614b72614fbc565b6000614b7d84614f7d565b9050614b87614fbc565b600a60008381526020019081526020016000206040518060600160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016001820154815260200160028201548152505090508181935093505050915091565b6000808260400151118015614c9f5750614c36612c17565b73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161480614c9e5750816000015173ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16145b5b8015614cae5750816020015186145b8015614cbd5750816040015184145b8015614cd6575042614cd3601254601054613e03565b11155b8015614ce3575060135483115b905095945050505050565b60008060606000806060868060200190516080811015614d0d57600080fd5b8101908080519060200190929190805190602001909291908051906020019092919080516040519392919084640100000000821115614d4b57600080fd5b83820191506020820185811115614d6157600080fd5b8251866020820283011164010000000082111715614d7e57600080fd5b8083526020830192505050908051906020019060200280838360005b83811015614db5578082015181840152602081019050614d9a565b50505050905001604052505050935093509350508282829550955095505050509193909250565b600084848484604051602001808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b8152601401848152602001838152602001828152602001945050505050604051602081830303815290604052805190602001209050949350505050565b60008082905060008090505b8451811015614f01576000858281518110614e7957fe5b6020026020010151905080831015614ec15782816040516020018083815260200182815260200192505050604051602081830303815290604052805190602001209250614ef3565b808360405160200180838152602001828152602001925050506040516020818303038152906040528051906020012092505b508080600101915050614e62565b508091505092915050565b6000838383604051602001808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b815260140183815260200182815260200193505050506040516020818303038152906040528051906020012090509392505050565b600080828060200190516040811015614f9557600080fd5b81019080805190602001909291908051906020019092919050505091505080915050919050565b6040518060600160405280600073ffffffffffffffffffffffffffffffffffffffff1681526020016000801916815260200160008152509056fe496e636c7564656420737570706c79206e6f6e63652065786365656473206c617465737420737570706c79a26469706673582212207434a8a187fdf6b2bb9d572324a4795d279acd4909615e386e4190bcb0fe3e0764736f6c634300060a0033000000000000000000000000ff20817765cb7f73d4bde2e66e067e58d11095c2
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102485760003560e01c80636833403c1161013b5780639363a2a5116100b8578063d445781a1161007c578063d445781a14610ef8578063e44b87f914610f3e578063ec3bb28814610f82578063f18d9a70146110ee578063f24bb1c11461110c57610248565b80639363a2a514610d65578063a2c1cae214610daf578063afa2886414610db9578063c4218e6e14610dfb578063c5cfe77a14610e2957610248565b806387f4427e116100ff57806387f4427e14610c2d578063887ec0b814610c715780638da5cb5b14610cb55780638db1c3ea14610cff5780638e9cdd7d14610d2d57610248565b80636833403c146109f75780636a928f8614610a3b5780637cc17da314610a595780637ddfe78d14610aa35780638240ef4814610ac157610248565b80633a9a7e44116101c95780635481eed31161018d5780635481eed3146108c95780635bc5752a146109135780635d7892801461095d5780635fcf44d1146109bf578063628e46cb146109ed57610248565b80633a9a7e44146107bb5780633b927235146107d957806342592662146107f757806344c545071461083b57806348105b121461088557610248565b80632b15d391116102105780632b15d3911461034b5780632c95e842146103d85780632e47d5e51461045157806330e4cfba146104b357806334c341801461063757610248565b80630780895f1461024d57806308c6345d1461027b5780630973e6ba146102c55780631c8f9a171461030f5780631cef21cf1461032d575b600080fd5b6102796004803603602081101561026357600080fd5b8101908080359060200190929190505050611188565b005b610283611305565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6102cd61132b565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610317611351565b6040518082815260200191505060405180910390f35b610335611357565b6040518082815260200191505060405180910390f35b6103d66004803603606081101561036157600080fd5b8101908080359060200190929190803590602001909291908035906020019064010000000081111561039257600080fd5b8201836020820111156103a457600080fd5b803590602001918460208302840111640100000000831117156103c657600080fd5b909192939192939050505061135d565b005b61044f600480360360208110156103ee57600080fd5b810190808035906020019064010000000081111561040b57600080fd5b82018360208201111561041d57600080fd5b8035906020019184602083028401116401000000008311171561043f57600080fd5b9091929391929390505050611666565b005b61049d6004803603604081101561046757600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506117a4565b6040518082815260200191505060405180910390f35b61061d60048036036101008110156104ca57600080fd5b8101908080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561058457600080fd5b82018360208201111561059657600080fd5b803590602001918460018302840111640100000000831117156105b857600080fd5b9091929391929390803590602001906401000000008111156105d957600080fd5b8201836020820111156105eb57600080fd5b8035906020019184600183028401116401000000008311171561060d57600080fd5b90919293919293905050506117c9565b604051808215151515815260200191505060405180910390f35b6107a1600480360361010081101561064e57600080fd5b8101908080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561070857600080fd5b82018360208201111561071a57600080fd5b8035906020019184600183028401116401000000008311171561073c57600080fd5b90919293919293908035906020019064010000000081111561075d57600080fd5b82018360208201111561076f57600080fd5b8035906020019184600183028401116401000000008311171561079157600080fd5b90919293919293905050506118e7565b604051808215151515815260200191505060405180910390f35b6107c3611bab565b6040518082815260200191505060405180910390f35b6107e1611bb1565b6040518082815260200191505060405180910390f35b6108396004803603602081101561080d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611bb7565b005b610843611d47565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6108c76004803603602081101561089b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611d6d565b005b6108d1611efd565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61091b611f27565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6109a96004803603604081101561097357600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611f4d565b6040518082815260200191505060405180910390f35b6109eb600480360360208110156109d557600080fd5b8101908080359060200190929190505050611f72565b005b6109f56122d6565b005b610a3960048036036020811015610a0d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061240e565b005b610a4361259e565b6040518082815260200191505060405180910390f35b610a616125a4565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610aab6125ca565b6040518082815260200191505060405180910390f35b610c2b6004803603610100811015610ad857600080fd5b8101908080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919080359060200190640100000000811115610b9257600080fd5b820183602082011115610ba457600080fd5b80359060200191846001830284011164010000000083111715610bc657600080fd5b909192939192939080359060200190640100000000811115610be757600080fd5b820183602082011115610bf957600080fd5b80359060200191846001830284011164010000000083111715610c1b57600080fd5b90919293919293905050506125d0565b005b610c6f60048036036020811015610c4357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061291c565b005b610cb360048036036020811015610c8757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612a87565b005b610cbd612c17565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610d2b60048036036020811015610d1557600080fd5b8101908080359060200190929190505050612c40565b005b610d6360048036036040811015610d4357600080fd5b810190808035906020019092919080359060200190929190505050612e18565b005b610d6d61313a565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610db7613160565b005b610de560048036036020811015610dcf57600080fd5b810190808035906020019092919050505061336b565b6040518082815260200191505060405180910390f35b610e2760048036036020811015610e1157600080fd5b8101908080359060200190929190505050613383565b005b610ef660048036036060811015610e3f57600080fd5b81019080803590602001909291908035906020019092919080359060200190640100000000811115610e7057600080fd5b820183602082011115610e8257600080fd5b80359060200191846001830284011164010000000083111715610ea457600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050613569565b005b610f2460048036036020811015610f0e57600080fd5b8101908080359060200190929190505050613623565b604051808215151515815260200191505060405180910390f35b610f8060048036036020811015610f5457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613643565b005b6110ec6004803603610100811015610f9957600080fd5b8101908080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561105357600080fd5b82018360208201111561106557600080fd5b8035906020019184600183028401116401000000008311171561108757600080fd5b9091929391929390803590602001906401000000008111156110a857600080fd5b8201836020820111156110ba57600080fd5b803590602001918460018302840111640100000000831117156110dc57600080fd5b90919293919293905050506137d3565b005b6110f6613c07565b6040518082815260200191505060405180910390f35b6111386004803603602081101561112257600080fd5b8101908080359060200190929190505050613c0d565b604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001838152602001828152602001935050505060405180910390f35b611190612c17565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806112165750600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b611288576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f496e76616c69642073656e64657200000000000000000000000000000000000081525060200191505060405180910390fd5b6000600b54905060008212156112b85760008260000390506112ac600b5482613db9565b600b81905550506112d1565b60008290506112c9600b5482613e03565b600b81905550505b600b54817f35100bc173608e4b64e73420ef31d05adb286a999a3adaeecb20db5a8374096460405160405180910390a35050565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60125481565b60105481565b611365612c17565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806113eb5750600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b61145d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f496e76616c69642073656e64657200000000000000000000000000000000000081525060200191505060405180910390fd5b6000801b8414156114d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600c8152602001807f496e76616c696420726f6f74000000000000000000000000000000000000000081525060200191505060405180910390fd5b826001600c540114611550576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4e6f6e6365206e6f742063757272656e74206d617820706c7573206f6e65000081525060200191505060405180910390fd5b6000600d600086815260200190815260200160002054146115d9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f4e6f6e636520616c72656164792075736564000000000000000000000000000081525060200191505060405180910390fd5b82600d60008681526020019081526020016000208190555082600c8190555082847fe03adc1e77ba682eeca70bd85e61002b19d2167914a5c91673b6db229fc9abef60405160405180910390a360008090505b8282905081101561165f5761165283838381811061164657fe5b90506020020135613e8b565b808060010191505061162c565b5050505050565b61166e612c17565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806116f45750600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b611766576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f496e76616c69642073656e64657200000000000000000000000000000000000081525060200191505060405180910390fd5b60008090505b8282905081101561179f5761179283838381811061178657fe5b90506020020135613e8b565b808060010191505061176c565b505050565b600f602052816000526040600020602052806000526040600020600091509150505481565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614158061185457503073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1614155b1561186257600090506118d9565b60006118b286868080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508c613f62565b90506003600082815260200190815260200160002060009054906101000a900460ff169150505b9a9950505050505050505050565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614158061197257503073ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff1614155b156119805760009050611b9d565b60006119cf84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050613fee565b90507faaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa60001b811415611a5457611a4c8b8b8987878080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505061401d565b915050611b9d565b7fbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb60001b811415611ad757611acf8b8b8987878080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505061404f565b915050611b9d565b7fcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc60001b811415611b5a57611b528b8b8987878080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050614085565b915050611b9d565b7fdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd60001b811415611b9757611b8f8a886140b6565b915050611b9d565b60009150505b9a9950505050505050505050565b60135481565b60115481565b611bbf612c17565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611c5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f496e76616c69642073656e64657200000000000000000000000000000000000081525060200191505060405180910390fd5b6000600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600660006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f7e8156acd1ac1a836d5fa06476cd7c2bd0397675c9caeee22b3c0b969bbebf8c60405160405180910390a35050565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b611d75612c17565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611e15576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f496e76616c69642073656e64657200000000000000000000000000000000000081525060200191505060405180910390fd5b6000600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167fd2e31556fcf8b4ba79fccb734eaf55dc59bd14b78be000354f6ca30422bbe49a60405160405180910390a35050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600e602052816000526040600020602052806000526040600020600091509150505481565b611f7a612c17565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806120005750600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b612072576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f496e76616c69642073656e64657200000000000000000000000000000000000081525060200191505060405180910390fd5b600015156003600083815260200190815260200160002060009054906101000a900460ff1615151461210c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f506172746974696f6e20616c7265616479207065726d6974746564000000000081525060200191505060405180910390fd5b6000806121188361415c565b925050915063cccccccc60e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916146121d7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f496e76616c696420706172746974696f6e20707265666978000000000000000081525060200191505060405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614612278576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f496e76616c696420706172746974696f6e206f776e657200000000000000000081525060200191505060405180910390fd5b60016003600085815260200190815260200160002060006101000a81548160ff021916908315150217905550827fe0a6f722db02a2a1bda25344bf96d858349b0e5e51b2dfc0189f43c3461c4fa760405160405180910390a2505050565b6122de612c17565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806123645750600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b6123d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f496e76616c69642073656e64657200000000000000000000000000000000000081525060200191505060405180910390fd5b426012819055506012547fbe5d770f5e481394f0304d913c12a7cb92610fb29b382af9f013cc43e53c671260405160405180910390a2565b612416612c17565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146124b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f496e76616c69642073656e64657200000000000000000000000000000000000081525060200191505060405180910390fd5b6000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167fdc4f94b18c0f53480d75b5a6e13d2b2b0414d87603d97d54f383579b8fc107a360405160405180910390a35050565b600c5481565b600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600b5481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612693576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f496e76616c69642073656e64657200000000000000000000000000000000000081525060200191505060405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614612734576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f496e76616c696420746f2061646472657373000000000000000000000000000081525060200191505060405180910390fd5b600061278485858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508b613f62565b90506003600082815260200190815260200160002060009054906101000a900460ff16612819576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f496e76616c69642064657374696e6174696f6e20706172746974696f6e00000081525060200191505060405180910390fd5b6128266009546001613e03565b60098190555088600a6000600954815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600a600060095481526020019081526020016000206001018190555085600a6000600954815260200190815260200160002060020181905550600954818a73ffffffffffffffffffffffffffffffffffffffff167fa5521f7d015e07af98ded530ac91a9ccef09b2b0fe09f6a0c8742f40d88e00d1896040518082815260200191505060405180910390a45050505050505050505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146129de576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f496e76616c69642073656e64657200000000000000000000000000000000000081525060200191505060405180910390fd5b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fb58bcc286020502f4931905baafed22acc969c092ed724234c73361efc68839060405160405180910390a250565b612a8f612c17565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612b2f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f496e76616c69642073656e64657200000000000000000000000000000000000081525060200191505060405180910390fd5b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f4129b839017b7e303a7a0ca5314793dbb9b6f4f59d12205970967a8a38c10be560405160405180910390a35050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b612c48612c17565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612ce8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f496e76616c69642073656e64657200000000000000000000000000000000000081525060200191505060405180910390fd5b6000811415612d5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f496e76616c6964207a65726f2064656c6179207365636f6e647300000000000081525060200191505060405180910390fd5b6312cc03008110612dd8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f496e76616c69642064656c6179206f766572203130207965617273000000000081525060200191505060405180910390fd5b600060105490508160108190555081817fbcf7cfa26c76f9f5223a62ddebfbc7ef67d6f5cd1ef27147b47cdc11aaae1ef160405160405180910390a35050565b612e20612c17565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480612ea65750600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b612f18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f496e76616c69642073656e64657200000000000000000000000000000000000081525060200191505060405180910390fd5b6000801b821415612f91576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600c8152602001807f496e76616c696420726f6f74000000000000000000000000000000000000000081525060200191505060405180910390fd5b42612fa0601254601054613e03565b11613013576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f46616c6c6261636b20697320616374697665000000000000000000000000000081525060200191505060405180910390fd5b60135481101561308b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f496e636c7564656420737570706c79206e6f6e6365206465637265617365640081525060200191505060405180910390fd5b6009548111156130e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b815260200180614ff7602b913960400191505060405180910390fd5b816011819055508060138190555042601281905550601354827fc838e1d9f03cb7be05349642820d7e002ef8a9a1efc2fbff3292096f6d66dee8426040518082815260200191505060405180910390a35050565b600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614613223576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f496e76616c69642073656e64657200000000000000000000000000000000000081525060200191505060405180910390fd5b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f343765429aea5a34b3ff6a3785a98a5abb2597aca87bfbb58632c173d585373a60405160405180910390a350565b600d6020528060005260406000206000915090505481565b61338b612c17565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806134115750600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b613483576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f496e76616c69642073656e64657200000000000000000000000000000000000081525060200191505060405180910390fd5b6003600082815260200190815260200160002060009054906101000a900460ff16613516576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f506172746974696f6e206e6f74207065726d697474656400000000000000000081525060200191505060405180910390fd5b6003600082815260200190815260200160002060006101000a81549060ff0219169055807f4eebd21e1429831abae9d8bf8c99b5e23567b718371940b6ec713f2c53f5393860405160405180910390a250565b81833373ffffffffffffffffffffffffffffffffffffffff167f1aba60afeb70d9dd8f76ece1c94871b4c3eb1b252b32f58102e21bfb81e944bf846040518080602001828103825283818151815260200191508051906020019080838360005b838110156135e45780820151818401526020810190506135c9565b50505050905090810190601f1680156136115780820380516001836020036101000a031916815260200191505b509250505060405180910390a4505050565b60036020528060005260406000206000915054906101000a900460ff1681565b61364b612c17565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146136eb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f496e76616c69642073656e64657200000000000000000000000000000000000081525060200191505060405180910390fd5b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167fd70953def42d9e2d7e243de8cce9cd4ffc14ab08a6090965afe3922f41ae1aa360405160405180910390a35050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614613896576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f496e76616c69642073656e64657200000000000000000000000000000000000081525060200191505060405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1614613937576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f496e76616c69642066726f6d206164647265737300000000000000000000000081525060200191505060405180910390fd5b600061398683838080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050613fee565b90507faaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa60001b811415613a0857613a038a8a8886868080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050614189565b613bfa565b7fbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb60001b811415613a8857613a838a8a8886868080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050614395565b613bf9565b7fcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc60001b811415613b0857613b038a8a8886868080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050614528565b613bf8565b7fdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd60001b811415613b8957613b848a8a898989898080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505061466b565b613bf7565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600c8152602001807f696e76616c696420666c6167000000000000000000000000000000000000000081525060200191505060405180910390fd5b5b5b5b5050505050505050505050565b60095481565b600a6020528060005260406000206000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060010154908060020154905083565b6000826040516020018082805190602001908083835b60208310613c905780518252602082019150602081019050602083039250613c6d565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051602081830303815290604052805190602001209050731820a4b7618bde71dce8cdc73aab6c95905fad2473ffffffffffffffffffffffffffffffffffffffff166329965a1d3083856040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019350505050600060405180830381600087803b158015613d9c57600080fd5b505af1158015613db0573d6000803e3d6000fd5b50505050505050565b6000613dfb83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250614793565b905092915050565b600080828401905083811015613e81576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b6000600d600083815260200190815260200160002054905060008111613f19576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f526f6f74206e6f7420666f756e6400000000000000000000000000000000000081525060200191505060405180910390fd5b600d60008381526020019081526020016000206000905580827f8983ad2a9726026394d7a200a18ba3e92f424253ae3eb71d3d8e61dc8e39667c60405160405180910390a35050565b6000604083511015613f7657819050613fe8565b600080848060200190516040811015613f8e57600080fd5b810190808051906020019092919080519060200190929190505050915091507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60001b821415613fe2578092505050613fe8565b83925050505b92915050565b600081806020019051602081101561400557600080fd5b81019080805190602001909291905050509050919050565b60008060008061402e888787614853565b9250925092506140428888888686866148ba565b9350505050949350505050565b6000806000806000614062898888614a0d565b93509350935093506140778884848785614abd565b945050505050949350505050565b600080614090614fbc565b61409984614b68565b915091506140aa8787878585614c1e565b92505050949350505050565b60006140c0612c17565b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614806141465750600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16145b80156141545750600b548211155b905092915050565b6000806000808490506000602086901b905060008660001c90508282829550955095505050509193909250565b6000806000614199878686614853565b9250925092506141ad8787878686866148ba565b61421f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f5472616e7366657220756e617574686f72697a6564000000000000000000000081525060200191505060405180910390fd5b61427985600f60008a815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054613e03565b600f600089815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555080600e600089815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555061432e600b5486613db9565b600b8190555080878473ffffffffffffffffffffffffffffffffffffffff167f7c05df8754d2754df450658e6ef9fd7bc12dedd9979acddebdd93ac086b424198886604051808381526020018281526020019250505060405180910390a450505050505050565b6000806000806143a6888787614a0d565b93509350935093506143bb8784848785614abd565b61442d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f5472616e7366657220756e617574686f72697a6564000000000000000000000081525060200191505060405180910390fd5b81600f60008a815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550600c54600e60008a815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555085888573ffffffffffffffffffffffffffffffffffffffff167f55ff7b4fbb2c54e7f151ea35b8b6f4b5668e5f1795d2b26fc89fd4d09b1b6de560405160405180910390a45050505050505050565b6000614532614fbc565b61453b83614b68565b9150915061454c8686868585614c1e565b6145be576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f5472616e7366657220756e617574686f72697a6564000000000000000000000081525060200191505060405180910390fd5b600a6000838152602001908152602001600020600080820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001820160009055600282016000905550508186826000015173ffffffffffffffffffffffffffffffffffffffff167fd3ae64e25cf9949339a5916876c3341a80b5b81eb732da3642a634a7512d180884604001516040518082815260200191505060405180910390a4505050505050565b61467584836140b6565b6146e7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f5472616e7366657220756e617574686f72697a6564000000000000000000000081525060200191505060405180910390fd5b6146f3600b5483613db9565b600b8190555060006147058287613f62565b9050808473ffffffffffffffffffffffffffffffffffffffff16877f4df85043c2fcb97b502fd05c3737899069bb1b523c06beaf6999f3c1f8e5a4b58887604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a4505050505050565b6000838311158290614840576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b838110156148055780820151818401526020810190506147ea565b50505050905090810190601f1680156148325780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b6000806000806000606061486687614cee565b925092509250600061487a848b8b86614ddc565b905060006148888383614e56565b90506000600d600083815260200190815260200160002054905085858298509850985050505050505093509350939050565b60006148c4612c17565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16148061494a5750600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16145b8061498057508373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16145b80156149dc575082600e600089815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205411155b80156149ea5750600b548511155b80156149f65750600082115b8015614a0157508282115b90509695505050505050565b6000806000806000806060614a2188614cee565b9250925092506000614a838a600f60008e815260200190815260200160002060008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054613e03565b90506000614a92858d86614f0c565b90506000614aa08483614e56565b905085858483995099509950995050505050505093509350935093565b6000614ac7612c17565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff161480614b2b57508273ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16145b8015614b44575042614b41601254601054613e03565b11155b8015614b505750848411155b8015614b5d575081601154145b905095945050505050565b6000614b72614fbc565b6000614b7d84614f7d565b9050614b87614fbc565b600a60008381526020019081526020016000206040518060600160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016001820154815260200160028201548152505090508181935093505050915091565b6000808260400151118015614c9f5750614c36612c17565b73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161480614c9e5750816000015173ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16145b5b8015614cae5750816020015186145b8015614cbd5750816040015184145b8015614cd6575042614cd3601254601054613e03565b11155b8015614ce3575060135483115b905095945050505050565b60008060606000806060868060200190516080811015614d0d57600080fd5b8101908080519060200190929190805190602001909291908051906020019092919080516040519392919084640100000000821115614d4b57600080fd5b83820191506020820185811115614d6157600080fd5b8251866020820283011164010000000082111715614d7e57600080fd5b8083526020830192505050908051906020019060200280838360005b83811015614db5578082015181840152602081019050614d9a565b50505050905001604052505050935093509350508282829550955095505050509193909250565b600084848484604051602001808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b8152601401848152602001838152602001828152602001945050505050604051602081830303815290604052805190602001209050949350505050565b60008082905060008090505b8451811015614f01576000858281518110614e7957fe5b6020026020010151905080831015614ec15782816040516020018083815260200182815260200192505050604051602081830303815290604052805190602001209250614ef3565b808360405160200180838152602001828152602001925050506040516020818303038152906040528051906020012092505b508080600101915050614e62565b508091505092915050565b6000838383604051602001808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b815260140183815260200182815260200193505050506040516020818303038152906040528051906020012090509392505050565b600080828060200190516040811015614f9557600080fd5b81019080805190602001909291908051906020019092919050505091505080915050919050565b6040518060600160405280600073ffffffffffffffffffffffffffffffffffffffff1681526020016000801916815260200160008152509056fe496e636c7564656420737570706c79206e6f6e63652065786365656473206c617465737420737570706c79a26469706673582212207434a8a187fdf6b2bb9d572324a4795d279acd4909615e386e4190bcb0fe3e0764736f6c634300060a0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000ff20817765cb7f73d4bde2e66e067e58d11095c2
-----Decoded View---------------
Arg [0] : _amp (address): 0xfF20817765cB7f73d4bde2e66e067E58D11095C2
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000ff20817765cb7f73d4bde2e66e067e58d11095c2
Deployed Bytecode Sourcemap
14431:55881:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;56719:600;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;17268:34;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;16836:18;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;20276:39;;;:::i;:::-;;;;;;;;;;;;;;;;;;;20020:55;;;:::i;:::-;;;;;;;;;;;;;;;;;;;57727:734;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;58622:285;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;19596:89;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;29792:578;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;32833:1049;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;20454:49;;;:::i;:::-;;;;;;;;;;;;;;;;;;;20151:27;;;:::i;:::-;;;;;;;;;;;;;;;;;;;63879:357;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;17778:31;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;64472:301;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;6611:105;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;17401:32;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;19419:79;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;55292:573;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;61089:254;;;:::i;:::-;;65021:301;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;19144:41;;;:::i;:::-;;;;;;;;;;;;;;;;;;;17655:31;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;19017:54;;;:::i;:::-;;;;;;;;;;;;;;;;;;;30966:931;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;7112:261;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;63271:308;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;6389:79;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;61581:529;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;59950:847;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;17526:39;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;7514:282;;;:::i;:::-;;19259:56;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;56042:312;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;54687:202;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;16918:42;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;62642:322;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;34625:1059;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;18527:30;;;:::i;:::-;;;;;;;;;;;;;;;;;;;18640:47;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;56719:600;56808:7;:5;:7::i;:::-;56794:21;;:10;:21;;;:63;;;;56833:24;;;;;;;;;;;56819:38;;:10;:38;;;56794:63;56786:90;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;56887:16;56906:15;;56887:34;;56946:1;56936:7;:11;56932:316;;;56964:22;56998:7;56997:8;;56964:42;;57039:45;57052:15;;57069:14;57039:12;:45::i;:::-;57021:15;:63;;;;56932:316;;;;57117:22;57150:7;57117:41;;57191:45;57204:15;;57221:14;57191:12;:45::i;:::-;57173:15;:63;;;;56932:316;;57295:15;;57285:8;57263:48;;;;;;;;;;56719:600;;:::o;17268:34::-;;;;;;;;;;;;;:::o;16836:18::-;;;;;;;;;;;;;:::o;20276:39::-;;;;:::o;20020:55::-;;;;:::o;57727:734::-;57896:7;:5;:7::i;:::-;57882:21;;:10;:21;;;:58;;;;57921:19;;;;;;;;;;;57907:33;;:10;:33;;;57882:58;57874:85;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;57989:1;57980:10;;:5;:10;;57972:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;58056:6;58051:1;58026:22;;:26;:36;58018:79;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;58148:1;58116:21;:28;58138:5;58116:28;;;;;;;;;;;;:33;58108:64;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;58216:6;58185:21;:28;58207:5;58185:28;;;;;;;;;;;:37;;;;58258:6;58233:22;:31;;;;58316:6;58309:5;58282:41;;;;;;;;;;58341:9;58353:1;58341:13;;58336:118;58360:14;;:21;;58356:1;:25;58336:118;;;58403:39;58424:14;;58439:1;58424:17;;;;;;;;;;;;;58403:20;:39::i;:::-;58383:3;;;;;;;58336:118;;;;57727:734;;;;:::o;58622:285::-;58722:7;:5;:7::i;:::-;58708:21;;:10;:21;;;:58;;;;58747:19;;;;;;;;;;;58733:33;;:10;:33;;;58708:58;58700:85;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;58803:9;58815:1;58803:13;;58798:102;58822:6;;:13;;58818:1;:17;58798:102;;;58857:31;58878:6;;58885:1;58878:9;;;;;;;;;;;;;58857:20;:31::i;:::-;58837:3;;;;;;;58798:102;;;;58622:285;;:::o;19596:89::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;29792:578::-;30104:4;30139:3;;;;;;;;;;;30125:17;;:10;:17;;;;:41;;;;30161:4;30146:20;;:3;:20;;;;30125:41;30121:86;;;30190:5;30183:12;;;;30121:86;30219:29;30251:58;30291:5;;30251:58;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30298:10;30251:39;:58::i;:::-;30219:90;;30329:10;:33;30340:21;30329:33;;;;;;;;;;;;;;;;;;;;;30322:40;;;29792:578;;;;;;;;;;;;;:::o;32833:1049::-;33134:4;33169:3;;;;;;;;;;;33155:17;;:10;:17;;;;:43;;;;33193:4;33176:22;;:5;:22;;;;33155:43;33151:88;;;33222:5;33215:12;;;;33151:88;33251:12;33266:38;33290:13;;33266:38;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:23;:38::i;:::-;33251:53;;15712:66;33329:15;;33321:4;:23;33317:128;;;33368:65;33388:10;33400:9;33411:6;33419:13;;33368:65;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:19;:65::i;:::-;33361:72;;;;;33317:128;15976:66;33467:24;;33459:4;:32;33455:145;;;33515:73;33543:10;33555:9;33566:6;33574:13;;33515:73;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:27;:73::i;:::-;33508:80;;;;;33455:145;16213:66;33622:11;;33614:4;:19;33610:120;;;33657:61;33673:10;33685:9;33696:6;33704:13;;33657:61;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:15;:61::i;:::-;33650:68;;;;;33610:120;16461:66;33752:20;;33744:4;:28;33740:110;;;33796:42;33820:9;33831:6;33796:23;:42::i;:::-;33789:49;;;;;33740:110;33869:5;33862:12;;;32833:1049;;;;;;;;;;;;;:::o;20454:49::-;;;;:::o;20151:27::-;;;;:::o;63879:357::-;63996:7;:5;:7::i;:::-;63982:21;;:10;:21;;;63974:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;64035:16;64054:24;;;;;;;;;;;64035:43;;64116:28;64089:24;;:55;;;;;;;;;;;;;;;;;;64203:24;;;;;;;;;;;64162:66;;64193:8;64162:66;;;;;;;;;;;;63879:357;;:::o;17778:31::-;;;;;;;;;;;;;:::o;64472:301::-;64573:7;:5;:7::i;:::-;64559:21;;:10;:21;;;64551:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;64612:16;64631;;;;;;;;;;;64612:35;;64677:20;64658:16;;:39;;;;;;;;;;;;;;;;;;64748:16;;;;;;;;;;;64715:50;;64738:8;64715:50;;;;;;;;;;;;64472:301;;:::o;6611:105::-;6662:7;6689:19;;;;;;;;;;;6682:26;;6611:105;:::o;17401:32::-;;;;;;;;;;;;;:::o;19419:79::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;55292:573::-;55376:7;:5;:7::i;:::-;55362:21;;:10;:21;;;:55;;;;55401:16;;;;;;;;;;;55387:30;;:10;:30;;;55362:55;55354:82;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;55481:5;55455:31;;:10;:22;55466:10;55455:22;;;;;;;;;;;;;;;;;;;;;:31;;;55447:71;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;55532:13;55549:22;55575:42;55606:10;55575:30;:42::i;:::-;55531:86;;;;;15298:10;55648:16;;55638:26;;;:6;:26;;;;55630:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;55738:4;55712:31;;:14;:31;;;55704:67;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;55809:4;55784:10;:22;55795:10;55784:22;;;;;;;;;;;;:29;;;;;;;;;;;;;;;;;;55846:10;55831:26;;;;;;;;;;55292:573;;;:::o;61089:254::-;61169:7;:5;:7::i;:::-;61155:21;;:10;:21;;;:56;;;;61194:17;;;;;;;;;;;61180:31;;:10;:31;;;61155:56;61147:83;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;61259:15;61241;:33;;;;61319:15;;61292:43;;;;;;;;;;61089:254::o;65021:301::-;65122:7;:5;:7::i;:::-;65108:21;;:10;:21;;;65100:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;65161:16;65180;;;;;;;;;;;65161:35;;65226:20;65207:16;;:39;;;;;;;;;;;;;;;;;;65297:16;;;;;;;;;;;65264:50;;65287:8;65264:50;;;;;;;;;;;;65021:301;;:::o;19144:41::-;;;;:::o;17655:31::-;;;;;;;;;;;;;:::o;19017:54::-;;;;:::o;30966:931::-;31291:3;;;;;;;;;;;31277:17;;:10;:17;;;31269:44;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;31347:4;31332:20;;:3;:20;;;31324:51;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;31388:29;31420:58;31460:5;;31420:58;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;31467:10;31420:39;:58::i;:::-;31388:90;;31499:10;:33;31510:21;31499:33;;;;;;;;;;;;;;;;;;;;;31491:75;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;31593:28;31606:11;;31619:1;31593:12;:28::i;:::-;31579:11;:42;;;;31670:9;31632:13;:26;31646:11;;31632:26;;;;;;;;;;;:35;;;:47;;;;;;;;;;;;;;;;;;31729:21;31690:13;:26;31704:11;;31690:26;;;;;;;;;;;:36;;:60;;;;31797:6;31761:13;:26;31775:11;;31761:26;;;;;;;;;;;:33;;:42;;;;31877:11;;31846:21;31835:9;31821:68;;;31869:6;31821:68;;;;;;;;;;;;;;;;;;30966:931;;;;;;;;;;;:::o;7112:261::-;7218:6;;;;;;;;;;;7204:20;;:10;:20;;;7196:47;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7278:18;7256:19;;:40;;;;;;;;;;;;;;;;;;7345:19;;;;;;;;;;;7314:51;;;;;;;;;;;;7112:261;:::o;63271:308::-;63374:7;:5;:7::i;:::-;63360:21;;:10;:21;;;63352:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;63413:16;63432:17;;;;;;;;;;;63413:36;;63480:21;63460:17;;:41;;;;;;;;;;;;;;;;;;63553:17;;;;;;;;;;;63519:52;;63543:8;63519:52;;;;;;;;;;;;63271:308;;:::o;6389:79::-;6427:7;6454:6;;;;;;;;;;;6447:13;;6389:79;:::o;61581:529::-;61693:7;:5;:7::i;:::-;61679:21;;:10;:21;;;61671:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;61766:1;61738:24;:29;;61730:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;61844:13;61817:24;:40;61809:80;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;61902:16;61921:30;;61902:49;;61995:24;61962:30;:57;;;;62077:24;62067:8;62037:65;;;;;;;;;;61581:529;;:::o;59950:847::-;60057:7;:5;:7::i;:::-;60043:21;;:10;:21;;;:56;;;;60082:17;;;;;;;;;;;60068:31;;:10;:31;;;60043:56;60035:83;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;60146:1;60137:10;;:5;:10;;60129:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;60261:15;60197:61;60210:15;;60227:30;;60197:12;:61::i;:::-;:79;60175:147;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;60374:30;;60355:15;:49;;60333:130;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;60501:11;;60482:15;:30;;60474:86;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;60588:5;60573:12;:20;;;;60637:15;60604:30;:48;;;;60681:15;60663;:33;;;;60741:30;;60734:5;60714:75;60773:15;60714:75;;;;;;;;;;;;;;;;;;59950:847;;:::o;17526:39::-;;;;;;;;;;;;;:::o;7514:282::-;7583:19;;;;;;;;;;;7569:33;;:10;:33;;;7561:60;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7634:16;7653:6;;;;;;;;;;;7634:25;;7679:19;;;;;;;;;;;7670:6;;:28;;;;;;;;;;;;;;;;;;7739:1;7709:19;;:32;;;;;;;;;;;;;;;;;;7781:6;;;;;;;;;;;7759:29;;7771:8;7759:29;;;;;;;;;;;;7514:282;:::o;19259:56::-;;;;;;;;;;;;;;;;;:::o;56042:312::-;56129:7;:5;:7::i;:::-;56115:21;;:10;:21;;;:55;;;;56154:16;;;;;;;;;;;56140:30;;:10;:30;;;56115:55;56107:82;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;56208:10;:22;56219:10;56208:22;;;;;;;;;;;;;;;;;;;;;56200:58;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;56278:10;:22;56289:10;56278:22;;;;;;;;;;;;56271:29;;;;;;;;;;;56335:10;56318:28;;;;;;;;;;56042:312;:::o;54687:202::-;54866:7;54854:10;54842;54827:54;;;54875:5;54827:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;54687:202;;;:::o;16918:42::-;;;;;;;;;;;;;;;;;;;;;;:::o;62642:322::-;62749:7;:5;:7::i;:::-;62735:21;;:10;:21;;;62727:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;62788:16;62807:19;;;;;;;;;;;62788:38;;62859:23;62837:19;;:45;;;;;;;;;;;;;;;;;;62936:19;;;;;;;;;;;62900:56;;62926:8;62900:56;;;;;;;;;;;;62642:322;;:::o;34625:1059::-;34942:3;;;;;;;;;;;34928:17;;:10;:17;;;34920:44;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;35000:4;34983:22;;:5;:22;;;34975:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;35043:12;35058:38;35082:13;;35058:38;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:23;:38::i;:::-;35043:53;;15712:66;35121:15;;35113:4;:23;35109:568;;;35153:64;35172:10;35184:9;35195:6;35203:13;;35153:64;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:18;:64::i;:::-;35109:568;;;15976:66;35247:24;;35239:4;:32;35235:442;;;35288:72;35315:10;35327:9;35338:6;35346:13;;35288:72;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:26;:72::i;:::-;35235:442;;;16213:66;35390:11;;35382:4;:19;35378:299;;;35418:60;35433:10;35445:9;35456:6;35464:13;;35418:60;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:14;:60::i;:::-;35378:299;;;16461:66;35508:20;;35500:4;:28;35496:181;;;35545:65;35568:10;35580:9;35591:3;35596:6;35604:5;;35545:65;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:22;:65::i;:::-;35496:181;;;35643:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;35496:181;35378:299;35235:442;35109:568;34625:1059;;;;;;;;;;;:::o;18527:30::-;;;;:::o;18640:47::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;8519:360::-;8656:21;8707:15;8690:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8680:44;;;;;;8656:68;;8461:42;8735:39;;;8797:4;8817:13;8845:15;8735:136;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8519:360;;;:::o;1350:136::-;1408:7;1435:43;1439:1;1442;1435:43;;;;;;;;;;;;;;;;;:3;:43::i;:::-;1428:50;;1350:136;;;;:::o;894:181::-;952:7;972:9;988:1;984;:5;972:17;;1013:1;1008;:6;;1000:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1066:1;1059:8;;;894:181;;;;:::o;59065:270::-;59129:13;59145:21;:28;59167:5;59145:28;;;;;;;;;;;;59129:44;;59202:1;59194:5;:9;59186:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;59242:21;:28;59264:5;59242:28;;;;;;;;;;;59235:35;;;59321:5;59314;59288:39;;;;;;;;;;59065:270;;:::o;12157:455::-;12289:7;12333:2;12318:5;:12;:17;12314:75;;;12359:18;12352:25;;;;12314:75;12402:12;12416:19;12450:5;12439:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12401:75;;;;11234:66;12499:21;;12491:4;:29;12487:80;;;12544:11;12537:18;;;;;;12487:80;12586:18;12579:25;;;;12157:455;;;;;:::o;65741:155::-;65825:7;65863:13;65852:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;65845:43;;65741:155;;;:::o;36299:653::-;36477:4;36509:16;36540:33;36588:27;36629:53;36648:10;36660:6;36668:13;36629:18;:53::i;:::-;36494:188;;;;;;36715:229;36757:10;36786:9;36814:6;36839:8;36866:25;36910:19;36715:23;:229::i;:::-;36695:249;;;;;36299:653;;;;;;:::o;42509:721::-;42695:4;42727:16;42758:37;42810;42862:22;42898:61;42925:10;42937:6;42945:13;42898:26;:61::i;:::-;42712:247;;;;;;;;42992:230;43042:9;43070:29;43118;43166:8;43193:14;42992:31;:230::i;:::-;42972:250;;;;;;42509:721;;;;;;:::o;48879:365::-;49053:4;49071:20;49093;;:::i;:::-;49117:29;49132:13;49117:14;:29::i;:::-;49070:76;;;;49166:70;49184:10;49196:9;49207:6;49215:12;49229:6;49166:17;:70::i;:::-;49159:77;;;;48879:365;;;;;;:::o;52748:403::-;52866:4;52993:7;:5;:7::i;:::-;52980:20;;:9;:20;;;:53;;;;53017:16;;;;;;;;;;;53004:29;;:9;:29;;;52980:53;52979:164;;;;;53127:15;;53117:6;:25;;52979:164;52888:255;;52748:403;;;;:::o;13286:408::-;13395:6;13416;13437:7;13472:13;13495:10;13472:34;;13517:19;13560:2;13546:10;:16;;13517:46;;13574:19;13620:10;13612:19;;13574:59;;13652:6;13660:12;13674:11;13644:42;;;;;;;;;13286:408;;;;;:::o;37319:1201::-;37508:16;37539:33;37587:27;37628:53;37647:10;37659:6;37667:13;37628:18;:53::i;:::-;37493:188;;;;;;37716:229;37758:10;37787:9;37815:6;37840:8;37867:25;37911:19;37716:23;:229::i;:::-;37694:300;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;38066:115;38093:6;38114:34;:46;38149:10;38114:46;;;;;;;;;;;:56;38161:8;38114:56;;;;;;;;;;;;;;;;38066:12;:115::i;:::-;38007:34;:46;38042:10;38007:46;;;;;;;;;;;:56;38054:8;38007:56;;;;;;;;;;;;;;;:174;;;;38243:19;38194:24;:36;38219:10;38194:36;;;;;;;;;;;:46;38231:8;38194:46;;;;;;;;;;;;;;;:68;;;;38293:37;38306:15;;38323:6;38293:12;:37::i;:::-;38275:15;:55;;;;38442:19;38396:10;38373:8;38348:164;;;38421:6;38476:25;38348:164;;;;;;;;;;;;;;;;;;;;;;;;37319:1201;;;;;;;:::o;43615:1002::-;43812:16;43843:37;43895;43947:22;43983:61;44010:10;44022:6;44030:13;43983:26;:61::i;:::-;43797:247;;;;;;;;44079:230;44129:9;44157:29;44205;44253:8;44280:14;44079:31;:230::i;:::-;44057:301;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;44430:29;44371:34;:46;44406:10;44371:46;;;;;;;;;;;:56;44418:8;44371:56;;;;;;;;;;;;;;;:88;;;;44521:22;;44472:24;:36;44497:10;44472:36;;;;;;;;;;;:46;44509:8;44472:46;;;;;;;;;;;;;;;:71;;;;44602:6;44590:10;44580:8;44561:48;;;;;;;;;;;;43615:1002;;;;;;;;:::o;49599:515::-;49770:13;49785:20;;:::i;:::-;49809:29;49824:13;49809:14;:29::i;:::-;49769:69;;;;49873:63;49891:10;49903:9;49914:6;49922:5;49929:6;49873:17;:63::i;:::-;49851:134;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;50005:13;:20;50019:5;50005:20;;;;;;;;;;;;49998:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;50100:5;50073:10;50056:6;:15;;;50043:63;;;50085:6;:13;;;50043:63;;;;;;;;;;;;;;;;;;49599:515;;;;;;:::o;53610:520::-;53810:42;53834:9;53845:6;53810:23;:42::i;:::-;53802:76;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;53909:37;53922:15;;53939:6;53909:12;:37::i;:::-;53891:15;:55;;;;53959:20;53982:58;54022:5;54029:10;53982:39;:58::i;:::-;53959:81;;54101:12;54096:3;54058:64;;54084:10;54058:64;54073:9;54115:6;54058:64;;;;;;;;;;;;;;;;;;;;;;;;;;;;53610:520;;;;;;:::o;1781:192::-;1867:7;1900:1;1895;:6;;1903:12;1887:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1927:9;1943:1;1939;:5;1927:17;;1964:1;1957:8;;;1781:192;;;;;:::o;39237:951::-;39427:7;39464;39518;39594:16;39625:33;39673:28;39715:44;39745:13;39715:29;:44::i;:::-;39579:180;;;;;;39772:20;39795:144;39834:8;39857:10;39882:6;39903:25;39795:24;:144::i;:::-;39772:167;;39952:22;39977:47;39998:11;40011:12;39977:20;:47::i;:::-;39952:72;;40035:27;40065:21;:37;40087:14;40065:37;;;;;;;;;;;;40035:67;;40123:8;40133:25;40160:19;40115:65;;;;;;;;;;;;39237:951;;;;;;;:::o;40865:993::-;41122:4;41257:7;:5;:7::i;:::-;41244:20;;:9;:20;;;:56;;;;41281:19;;;;;;;;;;;41268:32;;:9;:32;;;41244:56;:82;;;;41317:9;41304:22;;:9;:22;;;41244:82;41243:251;;;;;41467:26;41416:24;:36;41441:10;41416:36;;;;;;;;;;;:47;41453:9;41416:47;;;;;;;;;;;;;;;;:77;;41243:251;:360;;;;;41587:15;;41577:6;:25;;41243:360;:446;;;;;41687:1;41664:20;:24;41243:446;:607;;;;;41823:26;41800:20;:49;41243:607;41139:711;;40865:993;;;;;;;;:::o;45510:1182::-;45708:7;45745;45803;45861;45932:16;45963:37;46015:28;46057:44;46087:13;46057:29;:44::i;:::-;45917:184;;;;;;46114:37;46154:115;46181:6;46202:34;:46;46237:10;46202:46;;;;;;;;;;;:56;46249:8;46202:56;;;;;;;;;;;;;;;;46154:12;:115::i;:::-;46114:155;;46282:20;46305:125;46342:8;46365:10;46390:29;46305:22;:125::i;:::-;46282:148;;46441:22;46466:47;46487:11;46500:12;46466:20;:47::i;:::-;46441:72;;46548:8;46571:29;46615;46659:14;46526:158;;;;;;;;;;;;;;45510:1182;;;;;;;:::o;47424:853::-;47683:4;47808:7;:5;:7::i;:::-;47795:20;;:9;:20;;;:46;;;;47832:9;47819:22;;:9;:22;;;47795:46;47794:200;;;;;47978:15;47913:61;47926:15;;47943:30;;47913:12;:61::i;:::-;:80;;47794:200;:382;;;;;48145:30;48111;:64;;47794:382;:475;;;;;48253:15;48237:12;;:31;47794:475;47700:569;;47424:853;;;;;;;:::o;50487:316::-;50589:7;50598:13;;:::i;:::-;50629:20;50652:40;50678:13;50652:25;:40::i;:::-;50629:63;;50703:20;;:::i;:::-;50726:13;:27;50740:12;50726:27;;;;;;;;;;;50703:50;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;50774:12;50788:6;50766:29;;;;;;50487:316;;;:::o;51300:951::-;51502:4;51594:1;51577:7;:14;;;:18;51576:153;;;;;51688:7;:5;:7::i;:::-;51675:20;;:9;:20;;;:53;;;;51712:7;:16;;;51699:29;;:9;:29;;;51675:53;51576:153;:265;;;;;51823:7;:17;;;51809:10;:31;51576:265;:366;;;;;51927:7;:14;;;51917:6;:24;51576:366;:518;;;;;52078:15;52013:61;52026:15;;52043:30;;52013:12;:61::i;:::-;:80;;51576:518;:667;;;;;52212:30;;52197:12;:45;51576:667;51519:724;;51300:951;;;;;;;:::o;66561:435::-;66692:7;66714;66736:16;66783;66801:13;66816:22;66867:13;66842:102;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;66780:164;;;;;;;66965:8;66975:5;66982;66957:31;;;;;;;;;66561:435;;;;;:::o;68175:325::-;68366:7;68433:9;68444:10;68456:6;68464:26;68416:75;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;68406:86;;;;;;68386:106;;68175:325;;;;;;:::o;69691:618::-;69820:7;69845:20;69868:9;69845:32;;69895:9;69907:1;69895:13;;69890:380;69914:12;:19;69910:1;:23;69890:380;;;69955:20;69978:12;69991:1;69978:15;;;;;;;;;;;;;;69955:38;;70029:12;70014;:27;70010:249;;;70104:12;70118;70087:44;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;70077:55;;;;;;70062:70;;70010:249;;;70215:12;70229;70198:44;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;70188:55;;;;;;70173:70;;70010:249;69890:380;69935:3;;;;;;;69890:380;;;;70289:12;70282:19;;;69691:618;;;;:::o;69029:285::-;69197:7;69251:9;69262:10;69274:30;69234:71;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;69224:82;;;;;;69217:89;;69029:285;;;;;:::o;67210:204::-;67296:7;67319:13;67347;67336:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;67316:65;;;67401:5;67394:12;;;67210:204;;;:::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o
Swarm Source
ipfs://7434a8a187fdf6b2bb9d572324a4795d279acd4909615e386e4190bcb0fe3e07
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.