ERC-721
Overview
Max Total Supply
124 KEY
Holders
124
Market
Volume (24H)
N/A
Min Price (24H)
N/A
Max Price (24H)
N/A
Other Info
Token Contract
Balance
1 KEYLoading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Similar Match Source Code This contract matches the deployed Bytecode of the Source Code for Contract 0x75fA3Aa7...543dAb465 The constructor portion of the code might be different and could alter the actual behaviour of the contract
Contract Name:
PublicLock
Compiler Version
v0.5.9+commit.e560f70d
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2019-06-27 */ // File: contracts/interfaces/IERC721.sol pragma solidity 0.5.9; /// @title ERC-721 Non-Fungible Token Standard /// @dev See https://eips.ethereum.org/EIPS/eip-721 /// Note: the ERC-165 identifier for this interface is 0x80ac58cd interface IERC721 { /// @dev This emits when ownership of any NFT changes by any mechanism. /// This event emits when NFTs are created (`from` == 0) and destroyed /// (`to` == 0). Exception: during contract creation, any number of NFTs /// may be created and assigned without emitting Transfer. At the time of /// any transfer, the approved address for that NFT (if any) is reset to none. event Transfer(address indexed _from, address indexed _to, uint indexed _tokenId); /// @dev This emits when the approved address for an NFT is changed or /// reaffirmed. The zero address indicates there is no approved address. /// When a Transfer event emits, this also indicates that the approved /// address for that NFT (if any) is reset to none. event Approval(address indexed _owner, address indexed _approved, uint indexed _tokenId); /// @dev This emits when an operator is enabled or disabled for an owner. /// The operator can manage all NFTs of the owner. event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved); /// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE /// TO CONFIRM THAT `_to` IS CAPABLE OF RECEIVING NFTS OR ELSE /// THEY MAY BE PERMANENTLY LOST /// @dev Throws unless `msg.sender` is the current owner, an authorized /// operator, or the approved address for this NFT. Throws if `_from` is /// not the current owner. Throws if `_to` is the zero address. Throws if /// `_tokenId` is not a valid NFT. /// @param _from The current owner of the NFT /// @param _to The new owner /// @param _tokenId The NFT to transfer function transferFrom(address _from, address _to, uint _tokenId) external payable; /// @notice Set or reaffirm the approved address for an NFT /// @dev The zero address indicates there is no approved address. /// @dev Throws unless `msg.sender` is the current NFT owner, or an authorized /// operator of the current owner. /// @param _approved The new approved NFT controller /// @param _tokenId The NFT to approve function approve(address _approved, uint _tokenId) external payable; /// @notice Transfers the ownership of an NFT from one address to another address /// @dev Throws unless `msg.sender` is the current owner, an authorized /// operator, or the approved address for this NFT. Throws if `_from` is /// not the current owner. Throws if `_to` is the zero address. Throws if /// `_tokenId` is not a valid NFT. When transfer is complete, this function /// checks if `_to` is a smart contract (code size > 0). If so, it calls /// `onERC721Received` on `_to` and throws if the return value is not /// `bytes4(keccak256('onERC721Received(address,address,uint,bytes)'))`. /// @param _from The current owner of the NFT /// @param _to The new owner /// @param _tokenId The NFT to transfer /// @param data Additional data with no specified format, sent in call to `_to` function safeTransferFrom(address _from, address _to, uint _tokenId, bytes calldata data) external payable; /// @notice Transfers the ownership of an NFT from one address to another address /// @dev This works identically to the other function with an extra data parameter, /// except this function just sets data to '' /// @param _from The current owner of the NFT /// @param _to The new owner /// @param _tokenId The NFT to transfer function safeTransferFrom(address _from, address _to, uint _tokenId) external payable; /// @notice Enable or disable approval for a third party ('operator') to manage /// all of `msg.sender`'s assets. /// @dev Emits the ApprovalForAll event. The contract MUST allow /// multiple operators per owner. /// @param _operator Address to add to the set of authorized operators. /// @param _approved True if the operator is approved, false to revoke approval function setApprovalForAll(address _operator, bool _approved) external; /// @notice Count all NFTs assigned to an owner /// @dev NFTs assigned to the zero address are considered invalid, and this /// function throws for queries about the zero address. /// @param _owner An address for whom to query the balance /// @return The number of NFTs owned by `_owner`, possibly zero function balanceOf(address _owner) external view returns (uint); /// @notice Find the owner of an NFT /// @dev NFTs assigned to zero address are considered invalid, and queries /// about them do throw. /// @param _tokenId The identifier for an NFT /// @return The address of the owner of the NFT function ownerOf(uint _tokenId) external view returns (address); /// @notice Get the approved address for a single NFT /// @dev Throws if `_tokenId` is not a valid NFT /// @param _tokenId The NFT to find the approved address for /// @return The approved address for this NFT, or the zero address if there is none function getApproved(uint _tokenId) external view returns (address); /// @notice Query if an address is an authorized operator for another address /// @param _owner The address that owns the NFTs /// @param _operator The address that acts on behalf of the owner /// @return True if `_operator` is an approved operator for `_owner`, false otherwise function isApprovedForAll(address _owner, address _operator) external view returns (bool); /// @notice A descriptive name for a collection of NFTs in this contract function name() external view returns (string memory _name); } // File: zos-lib/contracts/Initializable.sol pragma solidity >=0.4.24 <0.6.0; /** * @title Initializable * * @dev Helper contract to support initializer functions. To use it, replace * the constructor with a function that has the `initializer` modifier. * WARNING: Unlike constructors, initializer functions must be manually * invoked. This applies both to deploying an Initializable contract, as well * as extending an Initializable contract via inheritance. * WARNING: When used with inheritance, manual care must be taken to not invoke * a parent initializer twice, or ensure that all initializers are idempotent, * because this is not dealt with automatically as with constructors. */ contract Initializable { /** * @dev Indicates that the contract has been initialized. */ bool private initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private initializing; /** * @dev Modifier to use in the initializer function of a contract. */ modifier initializer() { require(initializing || isConstructor() || !initialized, "Contract instance has already been initialized"); bool isTopLevelCall = !initializing; if (isTopLevelCall) { initializing = true; initialized = true; } _; if (isTopLevelCall) { initializing = false; } } /// @dev Returns true if and only if the function is running in the constructor function isConstructor() private view returns (bool) { // extcodesize checks the size of the code stored in an address, and // address returns the current address. Since the code is still not // deployed when running a constructor, any checks on its code size will // yield zero, making it an effective way to detect if a contract is // under construction or not. uint256 cs; assembly { cs := extcodesize(address) } return cs == 0; } // Reserved storage space to allow for layout changes in the future. uint256[50] private ______gap; } // File: openzeppelin-eth/contracts/ownership/Ownable.sol pragma solidity ^0.5.0; /** * @title Ownable * @dev The Ownable contract has an owner address, and provides basic authorization control * functions, this simplifies the implementation of "user permissions". */ contract Ownable is Initializable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev The Ownable constructor sets the original `owner` of the contract to the sender * account. */ function initialize(address sender) public initializer { _owner = sender; emit OwnershipTransferred(address(0), _owner); } /** * @return the address of the owner. */ function owner() public view returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(isOwner()); _; } /** * @return true if `msg.sender` is the owner of the contract. */ function isOwner() public view returns (bool) { return msg.sender == _owner; } /** * @dev Allows the current owner to relinquish control of the contract. * @notice Renouncing to ownership will leave the contract without an owner. * It will not be possible to call the functions with the `onlyOwner` * modifier anymore. */ function renounceOwnership() public onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } /** * @dev Allows the current owner to transfer control of the contract to a newOwner. * @param newOwner The address to transfer ownership to. */ function transferOwnership(address newOwner) public onlyOwner { _transferOwnership(newOwner); } /** * @dev Transfers control of the contract to a newOwner. * @param newOwner The address to transfer ownership to. */ function _transferOwnership(address newOwner) internal { require(newOwner != address(0)); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } uint256[50] private ______gap; } // File: openzeppelin-solidity/contracts/introspection/IERC165.sol pragma solidity ^0.5.0; /** * @dev Interface of the ERC165 standard, as defined in the * [EIP](https://eips.ethereum.org/EIPS/eip-165). * * Implementers can declare support of contract interfaces, which can then be * queried by others (`ERC165Checker`). * * For an implementation, see `ERC165`. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified) * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); } // File: openzeppelin-solidity/contracts/introspection/ERC165.sol pragma solidity ^0.5.0; /** * @dev Implementation of the `IERC165` interface. * * Contracts may inherit from this and call `_registerInterface` to declare * their support of an interface. */ contract ERC165 is IERC165 { /* * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7 */ bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7; /** * @dev Mapping of interface ids to whether or not it's supported. */ mapping(bytes4 => bool) private _supportedInterfaces; constructor () internal { // Derived contracts need only register support for their own interfaces, // we register support for ERC165 itself here _registerInterface(_INTERFACE_ID_ERC165); } /** * @dev See `IERC165.supportsInterface`. * * Time complexity O(1), guaranteed to always use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool) { return _supportedInterfaces[interfaceId]; } /** * @dev Registers the contract as an implementer of the interface defined by * `interfaceId`. Support of the actual ERC165 interface is automatic and * registering its interface id is not required. * * See `IERC165.supportsInterface`. * * Requirements: * * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`). */ function _registerInterface(bytes4 interfaceId) internal { require(interfaceId != 0xffffffff, "ERC165: invalid interface id"); _supportedInterfaces[interfaceId] = true; } } // File: openzeppelin-solidity/contracts/token/ERC721/IERC721Receiver.sol pragma solidity ^0.5.0; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ contract IERC721Receiver { /** * @notice Handle the receipt of an NFT * @dev The ERC721 smart contract calls this function on the recipient * after a `safeTransfer`. This function MUST return the function selector, * otherwise the caller will revert the transaction. The selector to be * returned can be obtained as `this.onERC721Received.selector`. This * function MAY throw to revert and reject the transfer. * Note: the ERC721 contract address is always the message sender. * @param operator The address which called `safeTransferFrom` function * @param from The address which previously owned the token * @param tokenId The NFT identifier which is being transferred * @param data Additional data with no specified format * @return bytes4 `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` */ function onERC721Received(address operator, address from, uint256 tokenId, bytes memory data) public returns (bytes4); } // File: openzeppelin-solidity/contracts/token/ERC721/ERC721Holder.sol pragma solidity ^0.5.0; contract ERC721Holder is IERC721Receiver { function onERC721Received(address, address, uint256, bytes memory) public returns (bytes4) { return this.onERC721Received.selector; } } // File: openzeppelin-solidity/contracts/token/ERC20/IERC20.sol pragma solidity ^0.5.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. Does not include * the optional functions; to access them see `ERC20Detailed`. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a `Transfer` event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through `transferFrom`. This is * zero by default. * * This value changes when `approve` or `transferFrom` are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * > Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an `Approval` event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a `Transfer` event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to `approve`. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); } // File: contracts/mixins/MixinFunds.sol pragma solidity 0.5.9; /** * @title An implementation of the money related functions. * @author HardlyDifficult (unlock-protocol.com) */ contract MixinFunds { /** * The token-type that this Lock is priced in. If 0, then use ETH, else this is * a ERC20 token address. */ address public tokenAddress; constructor( address _tokenAddress ) public { require( _tokenAddress == address(0) || IERC20(_tokenAddress).totalSupply() > 0, 'INVALID_TOKEN' ); tokenAddress = _tokenAddress; } /** * Gets the current balance of the account provided. */ function getBalance( address _account ) public view returns (uint) { if(tokenAddress == address(0)) { return _account.balance; } else { return IERC20(tokenAddress).balanceOf(_account); } } /** * Ensures that the msg.sender has paid at least the price stated. * * With ETH, this means the function originally called was `payable` and the * transaction included at least the amount requested. * * Security: be wary of re-entrancy when calling this function. */ function _chargeAtLeast( uint _price ) internal { if(_price > 0) { if(tokenAddress == address(0)) { require(msg.value >= _price, 'NOT_ENOUGH_FUNDS'); } else { IERC20 token = IERC20(tokenAddress); uint balanceBefore = token.balanceOf(address(this)); token.transferFrom(msg.sender, address(this), _price); // There are known bugs in popular ERC20 implements which means we cannot // trust the return value of `transferFrom`. This require statement ensures // that a transfer occurred. require(token.balanceOf(address(this)) > balanceBefore, 'TRANSFER_FAILED'); } } } /** * Transfers funds from the contract to the account provided. * * Security: be wary of re-entrancy when calling this function. */ function _transfer( address _to, uint _amount ) internal { if(_amount > 0) { if(tokenAddress == address(0)) { address(uint160(_to)).transfer(_amount); } else { IERC20 token = IERC20(tokenAddress); uint balanceBefore = token.balanceOf(_to); token.transfer(_to, _amount); // There are known bugs in popular ERC20 implements which means we cannot // trust the return value of `transferFrom`. This require statement ensures // that a transfer occurred. require(token.balanceOf(_to) > balanceBefore, 'TRANSFER_FAILED'); } } } } // File: contracts/mixins/MixinDisableAndDestroy.sol pragma solidity 0.5.9; /** * @title Mixin allowing the Lock owner to disable a Lock (preventing new purchases) * and then destroy it. * @author HardlyDifficult * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply * separates logically groupings of code to ease readability. */ contract MixinDisableAndDestroy is IERC721, Ownable, MixinFunds { // Used to disable payable functions when deprecating an old lock bool public isAlive; event Destroy( uint balance, address indexed owner ); event Disable(); constructor( ) internal { isAlive = true; } // Only allow usage when contract is Alive modifier onlyIfAlive() { require(isAlive, 'LOCK_DEPRECATED'); _; } /** * @dev Used to disable lock before migrating keys and/or destroying contract */ function disableLock() external onlyOwner onlyIfAlive { emit Disable(); isAlive = false; } /** * @dev Used to clean up old lock contracts from the blockchain * TODO: add a check to ensure all keys are INVALID! */ function destroyLock() external onlyOwner { require(isAlive == false, 'DISABLE_FIRST'); emit Destroy(address(this).balance, msg.sender); // this will send any ETH or ERC20 held by the lock to the owner _transfer(msg.sender, getBalance(address(this))); selfdestruct(msg.sender); // Note we don't clean up the `locks` data in Unlock.sol as it should not be necessary // and leaves some data behind ('Unlock.LockBalances') which may be helpful. } } // File: contracts/interfaces/IUnlock.sol pragma solidity 0.5.9; /** * @title The Unlock Interface * @author Nick Furfaro (unlock-protocol.com) **/ interface IUnlock { // Events event NewLock( address indexed lockOwner, address indexed newLockAddress ); event NewTokenURI( string tokenURI ); event NewGlobalTokenSymbol( string tokenSymbol ); // Use initialize instead of a constructor to support proxies (for upgradeability via zos). function initialize(address _owner) external; /** * @dev Create lock * This deploys a lock for a creator. It also keeps track of the deployed lock. * @param _tokenAddress set to the ERC20 token address, or 0 for ETH. */ function createLock( uint _expirationDuration, address _tokenAddress, uint _keyPrice, uint _maxNumberOfKeys, string calldata _lockName ) external; /** * This function keeps track of the added GDP, as well as grants of discount tokens * to the referrer, if applicable. * The number of discount tokens granted is based on the value of the referal, * the current growth rate and the lock's discount token distribution rate * This function is invoked by a previously deployed lock only. */ function recordKeyPurchase( uint _value, address _referrer // solhint-disable-line no-unused-vars ) external; /** * This function will keep track of consumed discounts by a given user. * It will also grant discount tokens to the creator who is granting the discount based on the * amount of discount and compensation rate. * This function is invoked by a previously deployed lock only. */ function recordConsumedDiscount( uint _discount, uint _tokens // solhint-disable-line no-unused-vars ) external; /** * This function returns the discount available for a user, when purchasing a * a key from a lock. * This does not modify the state. It returns both the discount and the number of tokens * consumed to grant that discount. */ function computeAvailableDiscountFor( address _purchaser, // solhint-disable-line no-unused-vars uint _keyPrice // solhint-disable-line no-unused-vars ) external view returns (uint discount, uint tokens); // Function to read the globalTokenURI field. function getGlobalBaseTokenURI() external view returns (string memory); /** Function to set the globalTokenURI field. * Should throw if called by other than owner */ function setGlobalBaseTokenURI( string calldata _URI ) external; // Function to read the globalTokenSymbol field. function getGlobalTokenSymbol() external view returns (string memory); /** Function to set the globalTokenSymbol field. * Should throw if called by other than owner. */ function setGlobalTokenSymbol( string calldata _symbol ) external; } // File: contracts/mixins/MixinLockCore.sol pragma solidity 0.5.9; /** * @title Mixin for core lock data and functions. * @author HardlyDifficult * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply * separates logically groupings of code to ease readability. */ contract MixinLockCore is Ownable, MixinFunds, MixinDisableAndDestroy { event PriceChanged( uint oldKeyPrice, uint keyPrice ); event Withdrawal( address indexed sender, address indexed beneficiary, uint amount ); // Unlock Protocol address // TODO: should we make that private/internal? IUnlock public unlockProtocol; // Duration in seconds for which the keys are valid, after creation // should we take a smaller type use less gas? // TODO: add support for a timestamp instead of duration uint public expirationDuration; // price in wei of the next key // TODO: allow support for a keyPriceCalculator which could set prices dynamically uint public keyPrice; // Max number of keys sold if the keyReleaseMechanism is public uint public maxNumberOfKeys; // A count of how many new key purchases there have been uint public numberOfKeysSold; // The account which will receive funds on withdrawal address public beneficiary; // Ensure that the Lock has not sold all of its keys. modifier notSoldOut() { require(maxNumberOfKeys > numberOfKeysSold, 'LOCK_SOLD_OUT'); _; } modifier onlyOwnerOrBeneficiary() { require( msg.sender == owner() || msg.sender == beneficiary, 'ONLY_LOCK_OWNER_OR_BENEFICIARY' ); _; } constructor( address _beneficiary, uint _expirationDuration, uint _keyPrice, uint _maxNumberOfKeys ) internal { require(_expirationDuration <= 100 * 365 * 24 * 60 * 60, 'MAX_EXPIRATION_100_YEARS'); unlockProtocol = IUnlock(msg.sender); // Make sure we link back to Unlock's smart contract. beneficiary = _beneficiary; expirationDuration = _expirationDuration; keyPrice = _keyPrice; maxNumberOfKeys = _maxNumberOfKeys; } /** * @dev Called by owner to withdraw all funds from the lock and send them to the `beneficiary`. * @param _amount specifies the max amount to withdraw, which may be reduced when * considering the available balance. Set to 0 or MAX_UINT to withdraw everything. * * TODO: consider allowing anybody to trigger this as long as it goes to owner anyway? * -- however be wary of draining funds as it breaks the `cancelAndRefund` use case. */ function withdraw( uint _amount ) external onlyOwnerOrBeneficiary { uint balance = getBalance(address(this)); uint amount; if(_amount == 0 || _amount > balance) { require(balance > 0, 'NOT_ENOUGH_FUNDS'); amount = balance; } else { amount = _amount; } emit Withdrawal(msg.sender, beneficiary, amount); // Security: re-entrancy not a risk as this is the last line of an external function _transfer(beneficiary, amount); } /** * A function which lets the owner of the lock to change the price for future purchases. */ function updateKeyPrice( uint _keyPrice ) external onlyOwner onlyIfAlive { uint oldKeyPrice = keyPrice; keyPrice = _keyPrice; emit PriceChanged(oldKeyPrice, keyPrice); } /** * A function which lets the owner of the lock update the beneficiary account, * which receives funds on withdrawal. */ function updateBeneficiary( address _beneficiary ) external onlyOwnerOrBeneficiary { require(_beneficiary != address(0), 'INVALID_ADDRESS'); beneficiary = _beneficiary; } /** * Public function which returns the total number of unique keys sold (both * expired and valid) */ function totalSupply() public view returns (uint) { return numberOfKeysSold; } } // File: contracts/mixins/MixinKeys.sol pragma solidity 0.5.9; /** * @title Mixin for managing `Key` data. * @author HardlyDifficult * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply * separates logically groupings of code to ease readability. */ contract MixinKeys is Ownable, MixinLockCore { // The struct for a key struct Key { uint tokenId; uint expirationTimestamp; } // Called when the Lock owner expires a user's Key event ExpireKey(uint tokenId); // Keys // Each owner can have at most exactly one key // TODO: could we use public here? (this could be confusing though because it getter will // return 0 values when missing a key) mapping (address => Key) private keyByOwner; // Each tokenId can have at most exactly one owner at a time. // Returns 0 if the token does not exist // TODO: once we decouple tokenId from owner address (incl in js), then we can consider // merging this with numberOfKeysSold into an array instead. mapping (uint => address) private ownerByTokenId; // Addresses of owners are also stored in an array. // Addresses are never removed by design to avoid abuses around referals address[] public owners; // Ensures that an owner owns or has owned a key in the past modifier ownsOrHasOwnedKey( address _owner ) { require( keyByOwner[_owner].expirationTimestamp > 0, 'HAS_NEVER_OWNED_KEY' ); _; } // Ensures that an owner has a valid key modifier hasValidKey( address _owner ) { require( getHasValidKey(_owner), 'KEY_NOT_VALID' ); _; } // Ensures that a key has an owner modifier isKey( uint _tokenId ) { require( ownerByTokenId[_tokenId] != address(0), 'NO_SUCH_KEY' ); _; } // Ensure that the caller owns the key modifier onlyKeyOwner( uint _tokenId ) { require( isKeyOwner(_tokenId, msg.sender), 'ONLY_KEY_OWNER' ); _; } /** * A function which lets the owner of the lock expire a users' key. */ function expireKeyFor( address _owner ) public onlyOwner hasValidKey(_owner) { Key storage key = keyByOwner[_owner]; key.expirationTimestamp = block.timestamp; // Effectively expiring the key emit ExpireKey(key.tokenId); } /** * In the specific case of a Lock, each owner can own only at most 1 key. * @return The number of NFTs owned by `_owner`, either 0 or 1. */ function balanceOf( address _owner ) external view returns (uint) { require(_owner != address(0), 'INVALID_ADDRESS'); return getHasValidKey(_owner) ? 1 : 0; } /** * Checks if the user has a non-expired key. */ function getHasValidKey( address _owner ) public view returns (bool) { return keyByOwner[_owner].expirationTimestamp > block.timestamp; } /** * @notice Find the tokenId for a given user * @return The tokenId of the NFT, else revert */ function getTokenIdFor( address _account ) external view hasValidKey(_account) returns (uint) { return keyByOwner[_account].tokenId; } /** * A function which returns a subset of the keys for this Lock as an array * @param _page the page of key owners requested when faceted by page size * @param _pageSize the number of Key Owners requested per page */ function getOwnersByPage(uint _page, uint _pageSize) public view returns (address[] memory) { require(owners.length > 0, 'NO_OUTSTANDING_KEYS'); uint pageSize = _pageSize; uint _startIndex = _page * pageSize; uint endOfPageIndex; if (_startIndex + pageSize > owners.length) { endOfPageIndex = owners.length; pageSize = owners.length - _startIndex; } else { endOfPageIndex = (_startIndex + pageSize); } // new temp in-memory array to hold pageSize number of requested owners: address[] memory ownersByPage = new address[](pageSize); uint pageIndex = 0; // Build the requested set of owners into a new temporary array: for (uint i = _startIndex; i < endOfPageIndex; i++) { ownersByPage[pageIndex] = owners[i]; pageIndex++; } return ownersByPage; } /** * Checks if the given address owns the given tokenId. */ function isKeyOwner( uint _tokenId, address _owner ) public view returns (bool) { return ownerByTokenId[_tokenId] == _owner; } /** * @dev Returns the key's ExpirationTimestamp field for a given owner. * @param _owner address of the user for whom we search the key */ function keyExpirationTimestampFor( address _owner ) public view ownsOrHasOwnedKey(_owner) returns (uint timestamp) { return keyByOwner[_owner].expirationTimestamp; } /** * Public function which returns the total number of unique owners (both expired * and valid). This may be larger than totalSupply. */ function numberOfOwners() public view returns (uint) { return owners.length; } /** * @notice ERC721: Find the owner of an NFT * @return The address of the owner of the NFT, if applicable */ function ownerOf( uint _tokenId ) public view isKey(_tokenId) returns (address) { return ownerByTokenId[_tokenId]; } /** * Assigns the key a new tokenId (from numberOfKeysSold) if it does not already have * one assigned. */ function _assignNewTokenId( Key storage _key ) internal { if (_key.tokenId == 0) { // This is a brand new owner, else an owner of an expired key buying an extension. // We increment the tokenId counter numberOfKeysSold++; // we assign the incremented `numberOfKeysSold` as the tokenId for the new key _key.tokenId = numberOfKeysSold; } } /** * Records the owner of a given tokenId */ function _recordOwner( address _owner, uint _tokenId ) internal { if (ownerByTokenId[_tokenId] != _owner) { // TODO: this may include duplicate entries owners.push(_owner); // We register the owner of the tokenID ownerByTokenId[_tokenId] = _owner; } } /** * Returns the Key struct for the given owner. */ function _getKeyFor( address _owner ) internal view returns (Key storage) { return keyByOwner[_owner]; } } // File: contracts/mixins/MixinApproval.sol pragma solidity 0.5.9; /** * @title Mixin for the Approval related functions needed to meet the ERC721 * standard. * @author HardlyDifficult * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply * separates logically groupings of code to ease readability. */ contract MixinApproval is IERC721, MixinDisableAndDestroy, MixinKeys { // Keeping track of approved transfers // This is a mapping of addresses which have approved // the transfer of a key to another address where their key can be transfered // Note: the approver may actually NOT have a key... and there can only // be a single approved beneficiary // Note 2: for transfer, both addresses will be different // Note 3: for sales (new keys on restricted locks), both addresses will be the same mapping (uint => address) private approved; // Keeping track of approved operators for a Key owner. // Since an owner can have up to 1 Key, this is similiar to above // but the approval does not reset when a transfer occurs. mapping (address => mapping (address => bool)) private ownerToOperatorApproved; // Ensure that the caller has a key // or that the caller has been approved // for ownership of that key modifier onlyKeyOwnerOrApproved( uint _tokenId ) { require( isKeyOwner(_tokenId, msg.sender) || _isApproved(_tokenId, msg.sender) || isApprovedForAll(ownerOf(_tokenId), msg.sender), 'ONLY_KEY_OWNER_OR_APPROVED'); _; } /** * This approves _approved to get ownership of _tokenId. * Note: that since this is used for both purchase and transfer approvals * the approved token may not exist. */ function approve( address _approved, uint _tokenId ) external payable onlyIfAlive onlyKeyOwnerOrApproved(_tokenId) { require(msg.sender != _approved, 'APPROVE_SELF'); approved[_tokenId] = _approved; emit Approval(ownerOf(_tokenId), _approved, _tokenId); } /** * @dev Sets or unsets the approval of a given operator * An operator is allowed to transfer all tokens of the sender on their behalf * @param _to operator address to set the approval * @param _approved representing the status of the approval to be set */ function setApprovalForAll( address _to, bool _approved ) external onlyIfAlive { require(_to != msg.sender, 'APPROVE_SELF'); ownerToOperatorApproved[msg.sender][_to] = _approved; emit ApprovalForAll(msg.sender, _to, _approved); } /** * external version * Will return the approved recipient for a key, if any. */ function getApproved( uint _tokenId ) external view returns (address) { return _getApproved(_tokenId); } /** * @dev Tells whether an operator is approved by a given owner * @param _owner owner address which you want to query the approval of * @param _operator operator address which you want to query the approval of * @return bool whether the given operator is approved by the given owner */ function isApprovedForAll( address _owner, address _operator ) public view returns (bool) { return ownerToOperatorApproved[_owner][_operator]; } /** * @dev Checks if the given user is approved to transfer the tokenId. */ function _isApproved( uint _tokenId, address _user ) internal view returns (bool) { return approved[_tokenId] == _user; } /** * Will return the approved recipient for a key transfer or ownership. * Note: this does not check that a corresponding key * actually exists. */ function _getApproved( uint _tokenId ) internal view returns (address) { address approvedRecipient = approved[_tokenId]; require(approvedRecipient != address(0), 'NONE_APPROVED'); return approvedRecipient; } /** * @dev Function to clear current approval of a given token ID * @param _tokenId uint256 ID of the token to be transferred */ function _clearApproval( uint256 _tokenId ) internal { if (approved[_tokenId] != address(0)) { approved[_tokenId] = address(0); } } } // File: contracts/mixins/MixinGrantKeys.sol pragma solidity 0.5.9; /** * @title Mixin allowing the Lock owner to grant / gift keys to users. * @author HardlyDifficult * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply * separates logically groupings of code to ease readability. */ contract MixinGrantKeys is IERC721, Ownable, MixinKeys { /** * Allows the Lock owner to give a user a key with no charge. */ function grantKey( address _recipient, uint _expirationTimestamp ) external onlyOwner { _grantKey(_recipient, _expirationTimestamp); } /** * Allows the Lock owner to give a collection of users a key with no charge. * All keys granted have the same expiration date. */ function grantKeys( address[] calldata _recipients, uint _expirationTimestamp ) external onlyOwner { for(uint i = 0; i < _recipients.length; i++) { _grantKey(_recipients[i], _expirationTimestamp); } } /** * Allows the Lock owner to give a collection of users a key with no charge. * Each key may be assigned a different expiration date. */ function grantKeys( address[] calldata _recipients, uint[] calldata _expirationTimestamps ) external onlyOwner { for(uint i = 0; i < _recipients.length; i++) { _grantKey(_recipients[i], _expirationTimestamps[i]); } } /** * Give a key to the given user */ function _grantKey( address _recipient, uint _expirationTimestamp ) private { require(_recipient != address(0), 'INVALID_ADDRESS'); Key storage toKey = _getKeyFor(_recipient); require(_expirationTimestamp > toKey.expirationTimestamp, 'ALREADY_OWNS_KEY'); _assignNewTokenId(toKey); _recordOwner(_recipient, toKey.tokenId); toKey.expirationTimestamp = _expirationTimestamp; // trigger event emit Transfer( address(0), // This is a creation. _recipient, toKey.tokenId ); } } // File: contracts/UnlockUtils.sol pragma solidity 0.5.9; // This contract provides some utility methods for use with the unlock protocol smart contracts. // Borrowed from: // https://github.com/oraclize/ethereum-api/blob/master/oraclizeAPI_0.5.sol#L943 contract UnlockUtils { function strConcat( string memory _a, string memory _b, string memory _c, string memory _d ) public pure returns (string memory _concatenatedString) { bytes memory _ba = bytes(_a); bytes memory _bb = bytes(_b); bytes memory _bc = bytes(_c); bytes memory _bd = bytes(_d); string memory abcd = new string(_ba.length + _bb.length + _bc.length + _bd.length); bytes memory babcd = bytes(abcd); uint k = 0; uint i = 0; for (i = 0; i < _ba.length; i++) { babcd[k++] = _ba[i]; } for (i = 0; i < _bb.length; i++) { babcd[k++] = _bb[i]; } for (i = 0; i < _bc.length; i++) { babcd[k++] = _bc[i]; } for (i = 0; i < _bd.length; i++) { babcd[k++] = _bd[i]; } return string(babcd); } function uint2Str( uint _i ) public pure returns (string memory _uintAsString) { // make a copy of the param to avoid security/no-assign-params error uint c = _i; if (_i == 0) { return '0'; } uint j = _i; uint len; while (j != 0) { len++; j /= 10; } bytes memory bstr = new bytes(len); uint k = len - 1; while (c != 0) { bstr[k--] = byte(uint8(48 + c % 10)); c /= 10; } return string(bstr); } function address2Str( address _addr ) public pure returns(string memory) { bytes32 value = bytes32(uint256(_addr)); bytes memory alphabet = '0123456789abcdef'; bytes memory str = new bytes(42); str[0] = '0'; str[1] = 'x'; for (uint i = 0; i < 20; i++) { str[2+i*2] = alphabet[uint8(value[i + 12] >> 4)]; str[3+i*2] = alphabet[uint8(value[i + 12] & 0x0f)]; } return string(str); } } // File: contracts/mixins/MixinLockMetadata.sol pragma solidity 0.5.9; /** * @title Mixin for metadata about the Lock. * @author HardlyDifficult * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply * separates logically groupings of code to ease readability. */ contract MixinLockMetadata is IERC721, ERC165, Ownable, MixinLockCore, UnlockUtils, MixinKeys { /// A descriptive name for a collection of NFTs in this contract.Defaults to "Unlock-Protocol" but is settable by lock owner string private lockName; /// An abbreviated name for NFTs in this contract. Defaults to "KEY" but is settable by lock owner string private lockSymbol; // the base Token URI for this Lock. If not set by lock owner, the global URI stored in Unlock is used. string private baseTokenURI; event NewLockSymbol( string symbol ); constructor( string memory _lockName ) internal { lockName = _lockName; // registering the optional erc721 metadata interface with ERC165.sol using // the ID specified in the standard: https://eips.ethereum.org/EIPS/eip-721 _registerInterface(0x5b5e139f); } /** * Allows the Lock owner to assign a descriptive name for this Lock. */ function updateLockName( string calldata _lockName ) external onlyOwner { lockName = _lockName; } /** * @dev Gets the token name * @return string representing the token name */ function name( ) external view returns (string memory) { return lockName; } /** * Allows the Lock owner to assign a Symbol for this Lock. */ function updateLockSymbol( string calldata _lockSymbol ) external onlyOwner { lockSymbol = _lockSymbol; emit NewLockSymbol(_lockSymbol); } /** * @dev Gets the token symbol * @return string representing the token name */ function symbol() external view returns(string memory) { if(bytes(lockSymbol).length == 0) { return unlockProtocol.getGlobalTokenSymbol(); } else { return lockSymbol; } } /** * Allows the Lock owner to update the baseTokenURI for this Lock. */ function setBaseTokenURI( string calldata _baseTokenURI ) external onlyOwner { baseTokenURI = _baseTokenURI; } /** @notice A distinct Uniform Resource Identifier (URI) for a given asset. * @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC * 3986. The URI may point to a JSON file that conforms to the "ERC721 * Metadata JSON Schema". * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md */ function tokenURI( uint256 _tokenId ) external view isKey(_tokenId) returns(string memory) { string memory URI; if(bytes(baseTokenURI).length == 0) { URI = unlockProtocol.getGlobalBaseTokenURI(); } else { URI = baseTokenURI; } return UnlockUtils.strConcat( URI, UnlockUtils.address2Str(address(this)), '/', UnlockUtils.uint2Str(_tokenId) ); } } // File: contracts/mixins/MixinNoFallback.sol pragma solidity 0.5.9; /** * @title Mixin for the fallback function implementation, which simply reverts. * @author HardlyDifficult * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply * separates logically groupings of code to ease readability. */ contract MixinNoFallback { /** * @dev the fallback function should not be used. This explicitly reverts * to ensure it's never used. */ function() external { revert('NO_FALLBACK'); } } // File: openzeppelin-solidity/contracts/math/SafeMath.sol pragma solidity ^0.5.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { require(b <= a, "SafeMath: subtraction overflow"); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 require(b > 0, "SafeMath: division by zero"); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { require(b != 0, "SafeMath: modulo by zero"); return a % b; } } // File: contracts/mixins/MixinPurchase.sol pragma solidity 0.5.9; /** * @title Mixin for the purchase-related functions. * @author HardlyDifficult * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply * separates logically groupings of code to ease readability. */ contract MixinPurchase is MixinFunds, MixinDisableAndDestroy, MixinLockCore, MixinKeys { using SafeMath for uint; /** * @dev Purchase function, public version, with no referrer. * @param _recipient address of the recipient of the purchased key */ function purchaseFor( address _recipient ) external payable onlyIfAlive { return _purchaseFor(_recipient, address(0)); } /** * @dev Purchase function, public version, with referrer. * @param _recipient address of the recipient of the purchased key * @param _referrer address of the user making the referral */ function purchaseForFrom( address _recipient, address _referrer ) external payable onlyIfAlive hasValidKey(_referrer) { return _purchaseFor(_recipient, _referrer); } /** * @dev Purchase function: this lets a user purchase a key from the lock for another user * @param _recipient address of the recipient of the purchased key * This will fail if * - the keyReleaseMechanism is private * - the keyReleaseMechanism is Approved and the recipient has not been previously approved * - the amount value is smaller than the price * - the recipient already owns a key * TODO: next version of solidity will allow for message to be added to require. */ function _purchaseFor( address _recipient, address _referrer ) private notSoldOut() { // solhint-disable-line function-max-lines require(_recipient != address(0), 'INVALID_ADDRESS'); // Let's get the actual price for the key from the Unlock smart contract uint discount; uint tokens; uint inMemoryKeyPrice = keyPrice; (discount, tokens) = unlockProtocol.computeAvailableDiscountFor(_recipient, inMemoryKeyPrice); uint netPrice = inMemoryKeyPrice; if (discount > inMemoryKeyPrice) { netPrice = 0; } else { // SafeSub not required as the if statement already confirmed `inMemoryKeyPrice - discount` cannot underflow netPrice = inMemoryKeyPrice - discount; } // Assign the key Key storage toKey = _getKeyFor(_recipient); if (toKey.tokenId == 0) { // Assign a new tokenId (if a new owner or previously transfered) _assignNewTokenId(toKey); _recordOwner(_recipient, toKey.tokenId); } if (toKey.expirationTimestamp >= block.timestamp) { // This is an existing owner trying to extend their key toKey.expirationTimestamp = toKey.expirationTimestamp.add(expirationDuration); } else { // SafeAdd is not required here since expirationDuration is capped to a tiny value // (relative to the size of a uint) toKey.expirationTimestamp = block.timestamp + expirationDuration; } if (discount > 0) { unlockProtocol.recordConsumedDiscount(discount, tokens); } unlockProtocol.recordKeyPurchase(netPrice, _referrer); // trigger event emit Transfer( address(0), // This is a creation. _recipient, numberOfKeysSold ); // We explicitly allow for greater amounts of ETH to allow 'donations' // Security: last line to minimize risk of re-entrancy _chargeAtLeast(netPrice); } } // File: openzeppelin-solidity/contracts/cryptography/ECDSA.sol pragma solidity ^0.5.0; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * (.note) This call _does not revert_ if the signature is invalid, or * if the signer is otherwise unable to be retrieved. In those scenarios, * the zero address is returned. * * (.warning) `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise) * be too long), and then calling `toEthSignedMessageHash` on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { // Check the signature length if (signature.length != 65) { return (address(0)); } // Divide the signature in r, s and v variables bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. // solhint-disable-next-line no-inline-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return address(0); } if (v != 27 && v != 28) { return address(0); } // If the signature is valid (and not malleable), return the signer address return ecrecover(hash, v, r, s); } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * replicates the behavior of the * [`eth_sign`](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign) * JSON-RPC method. * * See `recover`. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { // 32 is the length in bytes of hash, // enforced by the type signature above return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); } } // File: contracts/mixins/MixinRefunds.sol pragma solidity 0.5.9; contract MixinRefunds is Ownable, MixinFunds, MixinLockCore, MixinKeys { using SafeMath for uint; // CancelAndRefund will return funds based on time remaining minus this penalty. // This is calculated as `proRatedRefund * refundPenaltyNumerator / refundPenaltyDenominator`. uint public refundPenaltyNumerator = 1; uint public refundPenaltyDenominator = 10; // Stores a nonce per user to use for signed messages mapping(address => uint) public keyOwnerToNonce; event CancelKey( uint indexed tokenId, address indexed owner, address indexed sendTo, uint refund ); event RefundPenaltyChanged( uint oldRefundPenaltyNumerator, uint oldRefundPenaltyDenominator, uint refundPenaltyNumerator, uint refundPenaltyDenominator ); /** * @dev Destroys the user's key and sends a refund based on the amount of time remaining. */ function cancelAndRefund() external { _cancelAndRefund(msg.sender); } /** * @dev Cancels a key owned by a different user and sends the funds to the msg.sender. * @param _keyOwner this user's key will be canceled * @param _signature getCancelAndRefundApprovalHash signed by the _keyOwner */ function cancelAndRefundFor( address _keyOwner, bytes calldata _signature ) external { require( ECDSA.recover( ECDSA.toEthSignedMessageHash( getCancelAndRefundApprovalHash(_keyOwner, msg.sender) ), _signature ) == _keyOwner, 'INVALID_SIGNATURE' ); keyOwnerToNonce[_keyOwner]++; _cancelAndRefund(_keyOwner); } /** * @dev Increments the current nonce for the msg.sender. * This can be used to invalidate a previously signed message. */ function incrementNonce( ) external { keyOwnerToNonce[msg.sender]++; } /** * Allow the owner to change the refund penalty. */ function updateRefundPenalty( uint _refundPenaltyNumerator, uint _refundPenaltyDenominator ) external onlyOwner { require(_refundPenaltyDenominator != 0, 'INVALID_RATE'); emit RefundPenaltyChanged( refundPenaltyNumerator, refundPenaltyDenominator, _refundPenaltyNumerator, _refundPenaltyDenominator ); refundPenaltyNumerator = _refundPenaltyNumerator; refundPenaltyDenominator = _refundPenaltyDenominator; } /** * @dev Determines how much of a refund a key owner would receive if they issued * a cancelAndRefund block.timestamp. * Note that due to the time required to mine a tx, the actual refund amount will be lower * than what the user reads from this call. */ function getCancelAndRefundValueFor( address _owner ) external view returns (uint refund) { return _getCancelAndRefundValue(_owner); } /** * @dev returns the hash to sign in order to allow another user to cancel on your behalf. */ function getCancelAndRefundApprovalHash( address _keyOwner, address _txSender ) public view returns (bytes32 approvalHash) { return keccak256( abi.encodePacked( // Approval is specific to this Lock address(this), // Approval enables only one cancel call keyOwnerToNonce[_keyOwner], // Approval allows only one account to broadcast the tx _txSender ) ); } /** * @dev cancels the key for the given keyOwner and sends the refund to the msg.sender. */ function _cancelAndRefund( address _keyOwner ) internal { Key storage key = _getKeyFor(_keyOwner); uint refund = _getCancelAndRefundValue(_keyOwner); emit CancelKey(key.tokenId, _keyOwner, msg.sender, refund); // expirationTimestamp is a proxy for hasKey, setting this to `block.timestamp` instead // of 0 so that we can still differentiate hasKey from hasValidKey. key.expirationTimestamp = block.timestamp; if (refund > 0) { // Security: doing this last to avoid re-entrancy concerns _transfer(msg.sender, refund); } } /** * @dev Determines how much of a refund a key owner would receive if they issued * a cancelAndRefund now. * @param _owner The owner of the key check the refund value for. */ function _getCancelAndRefundValue( address _owner ) private view hasValidKey(_owner) returns (uint refund) { Key storage key = _getKeyFor(_owner); // Math: safeSub is not required since `hasValidKey` confirms timeRemaining is positive uint timeRemaining = key.expirationTimestamp - block.timestamp; if(timeRemaining >= expirationDuration) { refund = keyPrice; } else { // Math: using safeMul in case keyPrice or timeRemaining is very large refund = keyPrice.mul(timeRemaining) / expirationDuration; } uint penalty = keyPrice.mul(refundPenaltyNumerator) / refundPenaltyDenominator; if (refund > penalty) { // Math: safeSub is not required since the if confirms this won't underflow refund -= penalty; } else { refund = 0; } } } // File: openzeppelin-solidity/contracts/utils/Address.sol pragma solidity ^0.5.0; /** * @dev Collection of functions related to the address type, */ library Address { /** * @dev Returns true if `account` is a contract. * * This test is non-exhaustive, and there may be false-negatives: during the * execution of a contract's constructor, its address will be reported as * not containing a contract. * * > It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. */ function isContract(address account) internal view returns (bool) { // This method relies in extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; // solhint-disable-next-line no-inline-assembly assembly { size := extcodesize(account) } return size > 0; } } // File: contracts/mixins/MixinTransfer.sol pragma solidity 0.5.9; /** * @title Mixin for the transfer-related functions needed to meet the ERC721 * standard. * @author Nick Furfaro * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply * separates logically groupings of code to ease readability. */ contract MixinTransfer is MixinFunds, MixinLockCore, MixinKeys, MixinApproval { using SafeMath for uint; using Address for address; event TransferFeeChanged( uint oldTransferFeeNumerator, uint oldTransferFeeDenominator, uint transferFeeNumerator, uint transferFeeDenominator ); // 0x150b7a02 == bytes4(keccak256('onERC721Received(address,address,uint256,bytes)')) bytes4 private constant _ERC721_RECEIVED = 0x150b7a02; // The fee relative to keyPrice to charge when transfering a Key to another account // (potentially on a 0x marketplace). // This is calculated as `keyPrice * transferFeeNumerator / transferFeeDenominator`. uint public transferFeeNumerator = 0; uint public transferFeeDenominator = 100; /** * This is payable because at some point we want to allow the LOCK to capture a fee on 2ndary * market transactions... */ function transferFrom( address _from, address _recipient, uint _tokenId ) public payable onlyIfAlive hasValidKey(_from) onlyKeyOwnerOrApproved(_tokenId) { require(_recipient != address(0), 'INVALID_ADDRESS'); _chargeAtLeast(getTransferFee(_from)); Key storage fromKey = _getKeyFor(_from); Key storage toKey = _getKeyFor(_recipient); uint previousExpiration = toKey.expirationTimestamp; if (toKey.tokenId == 0) { toKey.tokenId = fromKey.tokenId; _recordOwner(_recipient, toKey.tokenId); } if (previousExpiration <= block.timestamp) { // The recipient did not have a key, or had a key but it expired. The new expiration is the // sender's key expiration // an expired key is no longer a valid key, so the new tokenID is the sender's tokenID toKey.expirationTimestamp = fromKey.expirationTimestamp; toKey.tokenId = fromKey.tokenId; _recordOwner(_recipient, _tokenId); } else { // The recipient has a non expired key. We just add them the corresponding remaining time // SafeSub is not required since the if confirms `previousExpiration - block.timestamp` cannot underflow toKey.expirationTimestamp = fromKey .expirationTimestamp.add(previousExpiration - block.timestamp); } // Effectively expiring the key for the previous owner fromKey.expirationTimestamp = block.timestamp; // Set the tokenID to 0 for the previous owner to avoid duplicates fromKey.tokenId = 0; // Clear any previous approvals _clearApproval(_tokenId); // trigger event emit Transfer( _from, _recipient, _tokenId ); } /** * @notice Transfers the ownership of an NFT from one address to another address * @dev This works identically to the other function with an extra data parameter, * except this function just sets data to '' * @param _from The current owner of the NFT * @param _to The new owner * @param _tokenId The NFT to transfer */ function safeTransferFrom( address _from, address _to, uint _tokenId ) external payable { safeTransferFrom(_from, _to, _tokenId, ''); } /** * @notice Transfers the ownership of an NFT from one address to another address. * When transfer is complete, this functions * checks if `_to` is a smart contract (code size > 0). If so, it calls * `onERC721Received` on `_to` and throws if the return value is not * `bytes4(keccak256('onERC721Received(address,address,uint,bytes)'))`. * @param _from The current owner of the NFT * @param _to The new owner * @param _tokenId The NFT to transfer * @param _data Additional data with no specified format, sent in call to `_to` */ function safeTransferFrom( address _from, address _to, uint _tokenId, bytes memory _data ) public payable onlyIfAlive onlyKeyOwnerOrApproved(_tokenId) hasValidKey(ownerOf(_tokenId)) { transferFrom(_from, _to, _tokenId); require(_checkOnERC721Received(_from, _to, _tokenId, _data), 'NON_COMPLIANT_ERC721_RECEIVER'); } /** * Allow the Lock owner to change the transfer fee. */ function updateTransferFee( uint _transferFeeNumerator, uint _transferFeeDenominator ) external onlyOwner { require(_transferFeeDenominator != 0, 'INVALID_RATE'); emit TransferFeeChanged( transferFeeNumerator, transferFeeDenominator, _transferFeeNumerator, _transferFeeDenominator ); transferFeeNumerator = _transferFeeNumerator; transferFeeDenominator = _transferFeeDenominator; } /** * Determines how much of a fee a key owner would need to pay in order to * transfer the key to another account. This is pro-rated so the fee goes down * overtime. * @param _owner The owner of the key check the transfer fee for. */ function getTransferFee( address _owner ) public view hasValidKey(_owner) returns (uint) { Key storage key = _getKeyFor(_owner); // Math: safeSub is not required since `hasValidKey` confirms timeRemaining is positive uint timeRemaining = key.expirationTimestamp - block.timestamp; uint fee; if(timeRemaining >= expirationDuration) { // Max the potential impact of this fee for keys with long durations remaining fee = keyPrice; } else { // Math: using safeMul in case keyPrice or timeRemaining is very large fee = keyPrice.mul(timeRemaining) / expirationDuration; } return fee.mul(transferFeeNumerator) / transferFeeDenominator; } /** * @dev Internal function to invoke `onERC721Received` on a target address * The call is not executed if the target address is not a contract * @param from address representing the previous owner of the given token ID * @param to target address that will receive the tokens * @param tokenId uint256 ID of the token to be transferred * @param _data bytes optional data to send along with the call * @return whether the call correctly returned the expected magic value */ function _checkOnERC721Received( address from, address to, uint256 tokenId, bytes memory _data ) internal returns (bool) { if (!to.isContract()) { return true; } bytes4 retval = IERC721Receiver(to).onERC721Received( msg.sender, from, tokenId, _data); return (retval == _ERC721_RECEIVED); } } // File: contracts/PublicLock.sol pragma solidity 0.5.9; /** * @title The Lock contract * @author Julien Genestoux (unlock-protocol.com) * Eventually: implement ERC721. * @dev ERC165 allows our contract to be queried to determine whether it implements a given interface. * Every ERC-721 compliant contract must implement the ERC165 interface. * https://eips.ethereum.org/EIPS/eip-721 */ contract PublicLock is IERC721, MixinNoFallback, ERC165, Ownable, ERC721Holder, MixinFunds, MixinDisableAndDestroy, MixinLockCore, MixinKeys, MixinLockMetadata, MixinGrantKeys, MixinPurchase, MixinApproval, MixinTransfer, MixinRefunds { constructor( address _owner, uint _expirationDuration, address _tokenAddress, uint _keyPrice, uint _maxNumberOfKeys, string memory _lockName ) public MixinFunds(_tokenAddress) MixinLockCore(_owner, _expirationDuration, _keyPrice, _maxNumberOfKeys) MixinLockMetadata(_lockName) { // registering the interface for erc721 with ERC165.sol using // the ID specified in the standard: https://eips.ethereum.org/EIPS/eip-721 _registerInterface(0x80ac58cd); // We must manually initialize Ownable.sol Ownable.initialize(_owner); } // The version number of the current implementation on this network function publicLockVersion( ) external pure returns (uint16) { return 4; } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"constant":true,"inputs":[{"name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"owners","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_approved","type":"address"},{"name":"_tokenId","type":"uint256"}],"name":"approve","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"_beneficiary","type":"address"}],"name":"updateBeneficiary","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"refundPenaltyDenominator","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"refundPenaltyNumerator","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"unlockProtocol","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_page","type":"uint256"},{"name":"_pageSize","type":"uint256"}],"name":"getOwnersByPage","outputs":[{"name":"","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"keyPrice","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"expirationDuration","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"},{"name":"","type":"uint256"},{"name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"name":"","type":"bytes4"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_keyPrice","type":"uint256"}],"name":"updateKeyPrice","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"cancelAndRefund","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_recipient","type":"address"},{"name":"_tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"_amount","type":"uint256"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_baseTokenURI","type":"string"}],"name":"setBaseTokenURI","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"beneficiary","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_refundPenaltyNumerator","type":"uint256"},{"name":"_refundPenaltyDenominator","type":"uint256"}],"name":"updateRefundPenalty","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"numberOfKeysSold","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_transferFeeNumerator","type":"uint256"},{"name":"_transferFeeDenominator","type":"uint256"}],"name":"updateTransferFee","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"isAlive","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"_a","type":"string"},{"name":"_b","type":"string"},{"name":"_c","type":"string"},{"name":"_d","type":"string"}],"name":"strConcat","outputs":[{"name":"_concatenatedString","type":"string"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"keyOwnerToNonce","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_i","type":"uint256"}],"name":"uint2Str","outputs":[{"name":"_uintAsString","type":"string"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"getCancelAndRefundValueFor","outputs":[{"name":"refund","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_lockName","type":"string"}],"name":"updateLockName","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_addr","type":"address"}],"name":"address2Str","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[],"name":"incrementNonce","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"getHasValidKey","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_recipient","type":"address"},{"name":"_referrer","type":"address"}],"name":"purchaseForFrom","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"maxNumberOfKeys","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_lockSymbol","type":"string"}],"name":"updateLockSymbol","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_recipients","type":"address[]"},{"name":"_expirationTimestamps","type":"uint256[]"}],"name":"grantKeys","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"getTransferFee","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_keyOwner","type":"address"},{"name":"_txSender","type":"address"}],"name":"getCancelAndRefundApprovalHash","outputs":[{"name":"approvalHash","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isOwner","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"transferFeeNumerator","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"numberOfOwners","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_account","type":"address"}],"name":"getTokenIdFor","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"},{"name":"_owner","type":"address"}],"name":"isKeyOwner","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_recipient","type":"address"},{"name":"_expirationTimestamp","type":"uint256"}],"name":"grantKey","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"tokenAddress","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_owner","type":"address"}],"name":"expireKeyFor","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"destroyLock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"keyExpirationTimestampFor","outputs":[{"name":"timestamp","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_tokenId","type":"uint256"},{"name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"_keyOwner","type":"address"},{"name":"_signature","type":"bytes"}],"name":"cancelAndRefundFor","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"disableLock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"sender","type":"address"}],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"publicLockVersion","outputs":[{"name":"","type":"uint16"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"transferFeeDenominator","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_recipient","type":"address"}],"name":"purchaseFor","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"_account","type":"address"}],"name":"getBalance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_recipients","type":"address[]"},{"name":"_expirationTimestamp","type":"uint256"}],"name":"grantKeys","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_owner","type":"address"},{"name":"_expirationDuration","type":"uint256"},{"name":"_tokenAddress","type":"address"},{"name":"_keyPrice","type":"uint256"},{"name":"_maxNumberOfKeys","type":"uint256"},{"name":"_lockName","type":"string"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":false,"stateMutability":"nonpayable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"tokenId","type":"uint256"},{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"sendTo","type":"address"},{"indexed":false,"name":"refund","type":"uint256"}],"name":"CancelKey","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"oldRefundPenaltyNumerator","type":"uint256"},{"indexed":false,"name":"oldRefundPenaltyDenominator","type":"uint256"},{"indexed":false,"name":"refundPenaltyNumerator","type":"uint256"},{"indexed":false,"name":"refundPenaltyDenominator","type":"uint256"}],"name":"RefundPenaltyChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"oldTransferFeeNumerator","type":"uint256"},{"indexed":false,"name":"oldTransferFeeDenominator","type":"uint256"},{"indexed":false,"name":"transferFeeNumerator","type":"uint256"},{"indexed":false,"name":"transferFeeDenominator","type":"uint256"}],"name":"TransferFeeChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"symbol","type":"string"}],"name":"NewLockSymbol","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"tokenId","type":"uint256"}],"name":"ExpireKey","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"oldKeyPrice","type":"uint256"},{"indexed":false,"name":"keyPrice","type":"uint256"}],"name":"PriceChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"sender","type":"address"},{"indexed":true,"name":"beneficiary","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"Withdrawal","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"balance","type":"uint256"},{"indexed":true,"name":"owner","type":"address"}],"name":"Destroy","type":"event"},{"anonymous":false,"inputs":[],"name":"Disable","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":true,"name":"_tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_approved","type":"address"},{"indexed":true,"name":"_tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_operator","type":"address"},{"indexed":false,"name":"_approved","type":"bool"}],"name":"ApprovalForAll","type":"event"}]
Contract Creation Code
6080604052600060765560646077556001607855600a6079553480156200002557600080fd5b5060405162004af138038062004af1833981810160405260c08110156200004b57600080fd5b8151602083015160408401516060850151608086015160a087018051959794969395929491938201926401000000008111156200008757600080fd5b820160208101848111156200009b57600080fd5b8151640100000000811182820187101715620000b657600080fd5b50909350839250889150879050858588620000fa7f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b036200037316565b6001600160a01b03811615806200017857506000816001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156200014857600080fd5b505afa1580156200015d573d6000803e3d6000fd5b505050506040513d60208110156200017457600080fd5b5051115b620001e457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f494e56414c49445f544f4b454e00000000000000000000000000000000000000604482015290519081900360640190fd5b6067805460ff60a01b196001600160a01b039093166001600160a01b031990911617919091167401000000000000000000000000000000000000000017905563bbf81e008311156200029757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4d41585f45585049524154494f4e5f3130305f59454152530000000000000000604482015290519081900360640190fd5b60688054336001600160a01b031991821617909155606d80549091166001600160a01b039590951694909417909355606991909155606a55606b558051620002e790607190602084019062000565565b506200031c7f5b5e139f000000000000000000000000000000000000000000000000000000006001600160e01b036200037316565b50620003517f80ac58cd000000000000000000000000000000000000000000000000000000006001600160e01b036200037316565b62000367866200044260201b620030891760201c565b50505050505062000607565b7fffffffff0000000000000000000000000000000000000000000000000000000080821614156200040557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4552433136353a20696e76616c696420696e7465726661636520696400000000604482015290519081900360640190fd5b7fffffffff00000000000000000000000000000000000000000000000000000000166000908152602081905260409020805460ff19166001179055565b600154610100900460ff1680620004675750620004676001600160e01b036200055e16565b8062000476575060015460ff16155b620004cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e81526020018062004ac3602e913960400191505060405180910390fd5b600154610100900460ff16158015620004f8576001805460ff1961ff00199091166101001716811790555b603480546001600160a01b0319166001600160a01b0384811691909117918290556040519116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a380156200055a576001805461ff00191690555b5050565b303b155b90565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620005a857805160ff1916838001178555620005d8565b82800160010185558215620005d8579182015b82811115620005d8578251825591602001919060010190620005bb565b50620005e6929150620005ea565b5090565b6200056291905b80821115620005e65760008155600101620005f1565b6144ac80620006176000396000f3fe6080604052600436106103e45760003560e01c80636d8ea5b4116102085780639d76ea5811610118578063c4d66de8116100ab578063e985e9c51161007a578063e985e9c5146113c6578063f2fde38b14611401578063f6e4641f14611434578063f8b2cb4f1461145a578063f8faf9421461148d576103e4565b8063c4d66de814611328578063c87b56dd1461135b578063d1bbd49c14611385578063d42cfc41146113b1576103e4565b8063abdf82ce116100e7578063abdf82ce14611191578063b88d4fde146111c4578063b8968bb414611288578063c1c98d0314611313576103e4565b80639d76ea58146110f95780639f98d3cb1461110e578063a22cb46514611141578063a843a4e71461117c576103e4565b80638d0361fc1161019b57806393fd18441161016a57806393fd18441461102a57806395d89b411461103f578063970aaeb714611054578063994a8a71146110875780639b3f0b17146110c0576103e4565b80638d0361fc14610fb05780638da5cb5b14610feb5780638f32d59b146110005780638f98ce8f14611015576103e4565b806374b6c106116101d757806374b6c10614610e22578063782a4ade14610e375780637c7c425314610eb257806383cb0fa914610f7d576103e4565b80636d8ea5b414610d7957806370a0823114610dac57806370efb77014610ddf578063715018a614610e0d576103e4565b806323b872dd1161030357806342842e0e1161029657806352d6a8e41161026557806352d6a8e414610c59578063550ef3a814610c8c5780635fdb97e114610d07578063627cdcb914610d3a5780636352211e14610d4f576103e4565b806342842e0e1461098657806345e965cd146109bc5780634bc5a13514610bfc5780634c7a12a014610c2f576103e4565b806339f46986116102d257806339f46986146108fc5780633ba70e311461092c5780633d3359cb146109415780634136aa3514610971576103e4565b806323b872dd1461080c5780632e1a7d4d1461084257806330176e131461086c57806338af3eed146108e7576103e4565b80630f15023b1161037b578063150b7a021161034a578063150b7a02146106ca57806318160ddd146107b85780631f1ec029146107cd5780632009dc65146107f7576103e4565b80630f15023b1461060b57806310803b721461062057806310e56973146106a057806311a4c03a146106b5576103e4565b8063095ea7b3116103b7578063095ea7b31461056e5780630aaffd2a1461059c5780630c79130f146105cf5780630ed3e2cc146105f6576103e4565b806301ffc9a71461042c578063025e7c271461047457806306fdde03146104ba578063081812fc14610544575b3480156103f057600080fd5b506040805162461bcd60e51b815260206004820152600b60248201526a4e4f5f46414c4c4241434b60a81b604482015290519081900360640190fd5b34801561043857600080fd5b506104606004803603602081101561044f57600080fd5b50356001600160e01b031916611508565b604080519115158252519081900360200190f35b34801561048057600080fd5b5061049e6004803603602081101561049757600080fd5b503561152b565b604080516001600160a01b039092168252519081900360200190f35b3480156104c657600080fd5b506104cf611552565b6040805160208082528351818301528351919283929083019185019080838360005b838110156105095781810151838201526020016104f1565b50505050905090810190601f1680156105365780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561055057600080fd5b5061049e6004803603602081101561056757600080fd5b50356115e9565b61059a6004803603604081101561058457600080fd5b506001600160a01b0381351690602001356115fa565b005b3480156105a857600080fd5b5061059a600480360360208110156105bf57600080fd5b50356001600160a01b0316611787565b3480156105db57600080fd5b506105e4611878565b60408051918252519081900360200190f35b34801561060257600080fd5b506105e461187e565b34801561061757600080fd5b5061049e611884565b34801561062c57600080fd5b506106506004803603604081101561064357600080fd5b5080359060200135611893565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561068c578181015183820152602001610674565b505050509050019250505060405180910390f35b3480156106ac57600080fd5b506105e46119ab565b3480156106c157600080fd5b506105e46119b1565b3480156106d657600080fd5b5061079b600480360360808110156106ed57600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b81111561072757600080fd5b82018360208201111561073957600080fd5b803590602001918460018302840111600160201b8311171561075a57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506119b7945050505050565b604080516001600160e01b03199092168252519081900360200190f35b3480156107c457600080fd5b506105e46119c8565b3480156107d957600080fd5b5061059a600480360360208110156107f057600080fd5b50356119ce565b34801561080357600080fd5b5061059a611a76565b61059a6004803603606081101561082257600080fd5b506001600160a01b03813581169160208101359091169060400135611a81565b34801561084e57600080fd5b5061059a6004803603602081101561086557600080fd5b5035611ccb565b34801561087857600080fd5b5061059a6004803603602081101561088f57600080fd5b810190602081018135600160201b8111156108a957600080fd5b8201836020820111156108bb57600080fd5b803590602001918460018302840111600160201b831117156108dc57600080fd5b509092509050611e1f565b3480156108f357600080fd5b5061049e611e3c565b34801561090857600080fd5b5061059a6004803603604081101561091f57600080fd5b5080359060200135611e4b565b34801561093857600080fd5b506105e4611ef5565b34801561094d57600080fd5b5061059a6004803603604081101561096457600080fd5b5080359060200135611efb565b34801561097d57600080fd5b50610460611fa5565b61059a6004803603606081101561099c57600080fd5b506001600160a01b03813581169160208101359091169060400135611fb5565b3480156109c857600080fd5b506104cf600480360360808110156109df57600080fd5b810190602081018135600160201b8111156109f957600080fd5b820183602082011115610a0b57600080fd5b803590602001918460018302840111600160201b83111715610a2c57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b811115610a7e57600080fd5b820183602082011115610a9057600080fd5b803590602001918460018302840111600160201b83111715610ab157600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b811115610b0357600080fd5b820183602082011115610b1557600080fd5b803590602001918460018302840111600160201b83111715610b3657600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b811115610b8857600080fd5b820183602082011115610b9a57600080fd5b803590602001918460018302840111600160201b83111715610bbb57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611fd0945050505050565b348015610c0857600080fd5b506105e460048036036020811015610c1f57600080fd5b50356001600160a01b0316612185565b348015610c3b57600080fd5b506104cf60048036036020811015610c5257600080fd5b5035612197565b348015610c6557600080fd5b506105e460048036036020811015610c7c57600080fd5b50356001600160a01b031661225b565b348015610c9857600080fd5b5061059a60048036036020811015610caf57600080fd5b810190602081018135600160201b811115610cc957600080fd5b820183602082011115610cdb57600080fd5b803590602001918460018302840111600160201b83111715610cfc57600080fd5b509092509050612266565b348015610d1357600080fd5b506104cf60048036036020811015610d2a57600080fd5b50356001600160a01b0316612283565b348015610d4657600080fd5b5061059a6123ff565b348015610d5b57600080fd5b5061049e60048036036020811015610d7257600080fd5b5035612417565b348015610d8557600080fd5b5061046060048036036020811015610d9c57600080fd5b50356001600160a01b031661248d565b348015610db857600080fd5b506105e460048036036020811015610dcf57600080fd5b50356001600160a01b03166124ad565b61059a60048036036040811015610df557600080fd5b506001600160a01b038135811691602001351661251c565b348015610e1957600080fd5b5061059a6125c1565b348015610e2e57600080fd5b506105e461261c565b348015610e4357600080fd5b5061059a60048036036020811015610e5a57600080fd5b810190602081018135600160201b811115610e7457600080fd5b820183602082011115610e8657600080fd5b803590602001918460018302840111600160201b83111715610ea757600080fd5b509092509050612622565b348015610ebe57600080fd5b5061059a60048036036040811015610ed557600080fd5b810190602081018135600160201b811115610eef57600080fd5b820183602082011115610f0157600080fd5b803590602001918460208302840111600160201b83111715610f2257600080fd5b919390929091602081019035600160201b811115610f3f57600080fd5b820183602082011115610f5157600080fd5b803590602001918460208302840111600160201b83111715610f7257600080fd5b5090925090506126a4565b348015610f8957600080fd5b506105e460048036036020811015610fa057600080fd5b50356001600160a01b0316612706565b348015610fbc57600080fd5b506105e460048036036040811015610fd357600080fd5b506001600160a01b03813581169160200135166127c9565b348015610ff757600080fd5b5061049e61282d565b34801561100c57600080fd5b5061046061283c565b34801561102157600080fd5b506105e461284d565b34801561103657600080fd5b506105e4612853565b34801561104b57600080fd5b506104cf612859565b34801561106057600080fd5b506105e46004803603602081101561107757600080fd5b50356001600160a01b03166129e4565b34801561109357600080fd5b50610460600480360360408110156110aa57600080fd5b50803590602001356001600160a01b0316612a4e565b3480156110cc57600080fd5b5061059a600480360360408110156110e357600080fd5b506001600160a01b038135169060200135612a6f565b34801561110557600080fd5b5061049e612a8e565b34801561111a57600080fd5b5061059a6004803603602081101561113157600080fd5b50356001600160a01b0316612a9d565b34801561114d57600080fd5b5061059a6004803603604081101561116457600080fd5b506001600160a01b0381351690602001351515612b54565b34801561118857600080fd5b5061059a612c5f565b34801561119d57600080fd5b506105e4600480360360208110156111b457600080fd5b50356001600160a01b0316612d0b565b61059a600480360360808110156111da57600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b81111561121457600080fd5b82018360208201111561122657600080fd5b803590602001918460018302840111600160201b8311171561124757600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612d90945050505050565b34801561129457600080fd5b5061059a600480360360408110156112ab57600080fd5b6001600160a01b038235169190810190604081016020820135600160201b8111156112d557600080fd5b8201836020820111156112e757600080fd5b803590602001918460018302840111600160201b8311171561130857600080fd5b509092509050612f1e565b34801561131f57600080fd5b5061059a612ff0565b34801561133457600080fd5b5061059a6004803603602081101561134b57600080fd5b50356001600160a01b0316613089565b34801561136757600080fd5b506104cf6004803603602081101561137e57600080fd5b5035613179565b34801561139157600080fd5b5061139a613391565b6040805161ffff9092168252519081900360200190f35b3480156113bd57600080fd5b506105e4613396565b3480156113d257600080fd5b50610460600480360360408110156113e957600080fd5b506001600160a01b038135811691602001351661339c565b34801561140d57600080fd5b5061059a6004803603602081101561142457600080fd5b50356001600160a01b03166133ca565b61059a6004803603602081101561144a57600080fd5b50356001600160a01b03166133e7565b34801561146657600080fd5b506105e46004803603602081101561147d57600080fd5b50356001600160a01b0316613442565b34801561149957600080fd5b5061059a600480360360408110156114b057600080fd5b810190602081018135600160201b8111156114ca57600080fd5b8201836020820111156114dc57600080fd5b803590602001918460208302840111600160201b831117156114fd57600080fd5b9193509150356134e6565b6001600160e01b0319811660009081526020819052604090205460ff165b919050565b6070818154811061153857fe5b6000918252602090912001546001600160a01b0316905081565b60718054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156115de5780601f106115b3576101008083540402835291602001916115de565b820191906000526020600020905b8154815290600101906020018083116115c157829003601f168201915b505050505090505b90565b60006115f482613535565b92915050565b606754600160a01b900460ff1661164a576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b806116558133612a4e565b806116655750611665813361358f565b8061167d575061167d61167782612417565b3361339c565b6116cb576040805162461bcd60e51b815260206004820152601a60248201527913d3931657d2d15657d3d5d3915497d3d497d054141493d5915160321b604482015290519081900360640190fd5b336001600160a01b0384161415611718576040805162461bcd60e51b815260206004820152600c60248201526b20a8282927ab22afa9a2a62360a11b604482015290519081900360640190fd5b600082815260746020526040902080546001600160a01b0319166001600160a01b038516908117909155829061174d82612417565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b61178f61282d565b6001600160a01b0316336001600160a01b031614806117b85750606d546001600160a01b031633145b611809576040805162461bcd60e51b815260206004820152601e60248201527f4f4e4c595f4c4f434b5f4f574e45525f4f525f42454e45464943494152590000604482015290519081900360640190fd5b6001600160a01b038116611856576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b606d80546001600160a01b0319166001600160a01b0392909216919091179055565b60795481565b60785481565b6068546001600160a01b031681565b6070546060906118e0576040805162461bcd60e51b81526020600482015260136024820152724e4f5f4f55545354414e44494e475f4b45595360681b604482015290519081900360640190fd5b607054829084820290600090828401111561190357506070548181039250611908565b508082015b606083604051908082528060200260200182016040528015611934578160200160208202803883390190505b5090506000835b8381101561199e576070818154811061195057fe5b9060005260206000200160009054906101000a90046001600160a01b031683838151811061197a57fe5b6001600160a01b03909216602092830291909101909101526001918201910161193b565b5090979650505050505050565b606a5481565b60695481565b630a85bd0160e11b5b949350505050565b606c5490565b6119d661283c565b6119df57600080fd5b606754600160a01b900460ff16611a2f576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b606a805490829055604080518281526020810184905281517f8aa4fa52648a6d15edce8a179c792c86f3719d0cc3c572cf90f91948f0f2cb68929181900390910190a15050565b611a7f336135b0565b565b606754600160a01b900460ff16611ad1576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b82611adb8161248d565b611b1c576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b81611b278133612a4e565b80611b375750611b37813361358f565b80611b495750611b4961167782612417565b611b97576040805162461bcd60e51b815260206004820152601a60248201527913d3931657d2d15657d3d5d3915497d3d497d054141493d5915160321b604482015290519081900360640190fd5b6001600160a01b038416611be4576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b611bf5611bf086612706565b613625565b6000611c0086613842565b90506000611c0d86613842565b6001810154815491925090611c2c578254808355611c2c90889061385c565b428111611c50576001808401549083015582548255611c4b878761385c565b611c6d565b6001830154611c679042830363ffffffff6138e316565b60018301555b42600184015560008355611c8086613944565b85876001600160a01b0316896001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050505050505050565b611cd361282d565b6001600160a01b0316336001600160a01b03161480611cfc5750606d546001600160a01b031633145b611d4d576040805162461bcd60e51b815260206004820152601e60248201527f4f4e4c595f4c4f434b5f4f574e45525f4f525f42454e45464943494152590000604482015290519081900360640190fd5b6000611d5830613442565b90506000821580611d6857508183115b15611dbc5760008211611db5576040805162461bcd60e51b815260206004820152601060248201526f4e4f545f454e4f5547485f46554e445360801b604482015290519081900360640190fd5b5080611dbf565b50815b606d546040805183815290516001600160a01b039092169133917f2717ead6b9200dd235aad468c9809ea400fe33ac69b5bfaa6d3e90fc922b6398919081900360200190a3606d54611e1a906001600160a01b03168261397f565b505050565b611e2761283c565b611e3057600080fd5b611e1a60738383614390565b606d546001600160a01b031681565b611e5361283c565b611e5c57600080fd5b80611e9d576040805162461bcd60e51b815260206004820152600c60248201526b494e56414c49445f5241544560a01b604482015290519081900360640190fd5b60785460795460408051928352602083019190915281810184905260608201839052517fa7d13855fe99b8c8b2780f36ff9e06133878b66a664a951b2375fe2296cc00089181900360800190a1607891909155607955565b606c5481565b611f0361283c565b611f0c57600080fd5b80611f4d576040805162461bcd60e51b815260206004820152600c60248201526b494e56414c49445f5241544560a01b604482015290519081900360640190fd5b60765460775460408051928352602083019190915281810184905260608201839052517ff0cc3b8bd450a20cce7720453e064b35cf490baa5d53c7c6ef8b2e1b02898a7d9181900360800190a1607691909155607755565b606754600160a01b900460ff1681565b611e1a83838360405180602001604052806000815250612d90565b606080859050606085905060608590506060859050606081518351855187510101016040519080825280601f01601f19166020018201604052801561201c576020820181803883390190505b509050806000805b87518110156120755787818151811061203957fe5b602001015160f81c60f81b83838060010194508151811061205657fe5b60200101906001600160f81b031916908160001a905350600101612024565b5060005b86518110156120ca5786818151811061208e57fe5b602001015160f81c60f81b8383806001019450815181106120ab57fe5b60200101906001600160f81b031916908160001a905350600101612079565b5060005b855181101561211f578581815181106120e357fe5b602001015160f81c60f81b83838060010194508151811061210057fe5b60200101906001600160f81b031916908160001a9053506001016120ce565b5060005b84518110156121745784818151811061213857fe5b602001015160f81c60f81b83838060010194508151811061215557fe5b60200101906001600160f81b031916908160001a905350600101612123565b50909b9a5050505050505050505050565b607a6020526000908152604090205481565b606081806121be5750506040805180820190915260018152600360fc1b6020820152611526565b8260005b81156121d657600101600a820491506121c2565b6060816040519080825280601f01601f191660200182016040528015612203576020820181803883390190505b50905060001982015b841561225157600a850660300160f81b8282806001900393508151811061222f57fe5b60200101906001600160f81b031916908160001a905350600a8504945061220c565b5095945050505050565b60006115f482613b8b565b61226e61283c565b61227757600080fd5b611e1a60718383614390565b604080518082018252601081526f181899199a1a9b1b9c1cb0b131b232b360811b60208201528151602a80825260608281019094526001600160a01b03851692918491602082018180388339019050509050600360fc1b816000815181106122e757fe5b60200101906001600160f81b031916908160001a905350600f60fb1b8160018151811061231057fe5b60200101906001600160f81b031916908160001a90535060005b60148110156123f6578260048583600c016020811061234557fe5b1a60f81b6001600160f81b031916901c60f81c60ff168151811061236557fe5b602001015160f81c60f81b82826002026002018151811061238257fe5b60200101906001600160f81b031916908160001a905350828482600c01602081106123a957fe5b825191901a600f169081106123ba57fe5b602001015160f81c60f81b8282600202600301815181106123d757fe5b60200101906001600160f81b031916908160001a90535060010161232a565b50949350505050565b336000908152607a6020526040902080546001019055565b6000818152606f602052604081205482906001600160a01b0316612470576040805162461bcd60e51b815260206004820152600b60248201526a4e4f5f535543485f4b455960a81b604482015290519081900360640190fd5b50506000908152606f60205260409020546001600160a01b031690565b6001600160a01b03166000908152606e6020526040902060010154421090565b60006001600160a01b0382166124fc576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6125058261248d565b612510576000612513565b60015b60ff1692915050565b606754600160a01b900460ff1661256c576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b806125768161248d565b6125b7576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b611e1a8383613c6a565b6125c961283c565b6125d257600080fd5b6034546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603480546001600160a01b0319169055565b606b5481565b61262a61283c565b61263357600080fd5b61263f60728383614390565b507f8868e22e84ebf32da89b2ebcb0ac642816304ea3863b257f240df9098719cb97828260405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a15050565b6126ac61283c565b6126b557600080fd5b60005b838110156126ff576126f78585838181106126cf57fe5b905060200201356001600160a01b03168484848181106126eb57fe5b90506020020135613f35565b6001016126b8565b5050505050565b6000816127128161248d565b612753576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b600061275e84613842565b905060004282600101540390506000606954821061277f5750606a546127a0565b606954606a54612795908463ffffffff61403516565b8161279c57fe5b0490505b6077546076546127b790839063ffffffff61403516565b816127be57fe5b049695505050505050565b6001600160a01b03919091166000908152607a602090815260409182902054825130606090811b82850152603482019290925293901b6bffffffffffffffffffffffff19166054840152815180840360480181526068909301909152815191012090565b6034546001600160a01b031690565b6034546001600160a01b0316331490565b60765481565b60705490565b6072546060906002600019610100600184161502019091160461295257606860009054906101000a90046001600160a01b03166001600160a01b03166335a750de6040518163ffffffff1660e01b815260040160006040518083038186803b1580156128c457600080fd5b505afa1580156128d8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561290157600080fd5b810190808051600160201b81111561291857600080fd5b8201602081018481111561292b57600080fd5b8151600160201b81118282018710171561294457600080fd5b509094506115e69350505050565b6072805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156129d85780601f106129ad576101008083540402835291602001916129d8565b820191906000526020600020905b8154815290600101906020018083116129bb57829003601f168201915b505050505090506115e6565b6000816129f08161248d565b612a31576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b50506001600160a01b03166000908152606e602052604090205490565b6000918252606f6020526040909120546001600160a01b0391821691161490565b612a7761283c565b612a8057600080fd5b612a8a8282613f35565b5050565b6067546001600160a01b031681565b612aa561283c565b612aae57600080fd5b80612ab88161248d565b612af9576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b6001600160a01b0382166000908152606e602090815260409182902042600182015580548351908152925190927f59f2fe866dd27a1c2d34115520888c3150365cbc931aab97fa88c4b9ab40b79592908290030190a1505050565b606754600160a01b900460ff16612ba4576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b6001600160a01b038216331415612bf1576040805162461bcd60e51b815260206004820152600c60248201526b20a8282927ab22afa9a2a62360a11b604482015290519081900360640190fd5b3360008181526075602090815260408083206001600160a01b03871680855290835292819020805460ff1916861515908117909155815190815290519293927f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31929181900390910190a35050565b612c6761283c565b612c7057600080fd5b606754600160a01b900460ff1615612cbf576040805162461bcd60e51b815260206004820152600d60248201526c111254d050931157d1925494d5609a1b604482015290519081900360640190fd5b6040805130318152905133917fa053f2a7eceda47dde76e5939c5adf7b771e665fc84c8ef6feffc290a1eb1feb919081900360200190a2612d0833612d0330613442565b61397f565b33ff5b6001600160a01b0381166000908152606e60205260408120600101548290612d70576040805162461bcd60e51b81526020600482015260136024820152724841535f4e455645525f4f574e45445f4b455960681b604482015290519081900360640190fd5b50506001600160a01b03166000908152606e602052604090206001015490565b606754600160a01b900460ff16612de0576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b81612deb8133612a4e565b80612dfb5750612dfb813361358f565b80612e0d5750612e0d61167782612417565b612e5b576040805162461bcd60e51b815260206004820152601a60248201527913d3931657d2d15657d3d5d3915497d3d497d054141493d5915160321b604482015290519081900360640190fd5b612e6483612417565b612e6d8161248d565b612eae576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b612eb9868686611a81565b612ec58686868661408e565b612f16576040805162461bcd60e51b815260206004820152601d60248201527f4e4f4e5f434f4d504c49414e545f4552433732315f5245434549564552000000604482015290519081900360640190fd5b505050505050565b826001600160a01b0316612f79612f3d612f3886336127c9565b6141c1565b84848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061421292505050565b6001600160a01b031614612fc8576040805162461bcd60e51b8152602060048201526011602482015270494e56414c49445f5349474e415455524560781b604482015290519081900360640190fd5b6001600160a01b0383166000908152607a6020526040902080546001019055611e1a836135b0565b612ff861283c565b61300157600080fd5b606754600160a01b900460ff16613051576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b6040517f25a311358326fb18c62efc24bc28d3126acee8d2a67fd8b2145b757dc8bd1bc190600090a16067805460ff60a01b19169055565b600154610100900460ff16806130a257506130a2614300565b806130b0575060015460ff16155b6130eb5760405162461bcd60e51b815260040180806020018281038252602e81526020018061444a602e913960400191505060405180910390fd5b600154610100900460ff16158015613115576001805460ff1961ff00199091166101001716811790555b603480546001600160a01b0319166001600160a01b0384811691909117918290556040519116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a38015612a8a576001805461ff00191690555050565b6000818152606f602052604090205460609082906001600160a01b03166131d5576040805162461bcd60e51b815260206004820152600b60248201526a4e4f5f535543485f4b455960a81b604482015290519081900360640190fd5b607354606090600260001961010060018416150201909116046132ce57606860009054906101000a90046001600160a01b03166001600160a01b0316637ff94bb26040518163ffffffff1660e01b815260040160006040518083038186803b15801561324057600080fd5b505afa158015613254573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561327d57600080fd5b810190808051600160201b81111561329457600080fd5b820160208101848111156132a757600080fd5b8151600160201b8111828201871017156132c057600080fd5b5090945061335c9350505050565b6073805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156133545780601f1061332957610100808354040283529160200191613354565b820191906000526020600020905b81548152906001019060200180831161333757829003601f168201915b505050505090505b6119c08161336930612283565b604051806040016040528060018152602001602f60f81b81525061338c88612197565b611fd0565b600490565b60775481565b6001600160a01b03918216600090815260756020908152604080832093909416825291909152205460ff1690565b6133d261283c565b6133db57600080fd5b6133e481614306565b50565b606754600160a01b900460ff16613437576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b6133e4816000613c6a565b6067546000906001600160a01b031661346657506001600160a01b03811631611526565b606754604080516370a0823160e01b81526001600160a01b038581166004830152915191909216916370a08231916024808301926020929190829003018186803b1580156134b357600080fd5b505afa1580156134c7573d6000803e3d6000fd5b505050506040513d60208110156134dd57600080fd5b50519050611526565b6134ee61283c565b6134f757600080fd5b60005b8281101561352f5761352784848381811061351157fe5b905060200201356001600160a01b031683613f35565b6001016134fa565b50505050565b6000818152607460205260408120546001600160a01b0316806115f4576040805162461bcd60e51b815260206004820152600d60248201526c1393d39157d054141493d59151609a1b604482015290519081900360640190fd5b600091825260746020526040909120546001600160a01b0391821691161490565b60006135bb82613842565b905060006135c883613b8b565b825460408051838152905192935033926001600160a01b03871692917f0a7068a9989857441c039a14a42b67ed71dd1fcfe5a9b17cc87b252e47bce528919081900360200190a44260018301558015611e1a57611e1a338261397f565b80156133e4576067546001600160a01b03166136885780341015613683576040805162461bcd60e51b815260206004820152601060248201526f4e4f545f454e4f5547485f46554e445360801b604482015290519081900360640190fd5b6133e4565b606754604080516370a0823160e01b815230600482015290516001600160a01b039092169160009183916370a0823191602480820192602092909190829003018186803b1580156136d857600080fd5b505afa1580156136ec573d6000803e3d6000fd5b505050506040513d602081101561370257600080fd5b5051604080516323b872dd60e01b81523360048201523060248201526044810186905290519192506001600160a01b038416916323b872dd916064808201926020929091908290030181600087803b15801561375d57600080fd5b505af1158015613771573d6000803e3d6000fd5b505050506040513d602081101561378757600080fd5b5050604080516370a0823160e01b8152306004820152905182916001600160a01b038516916370a0823191602480820192602092909190829003018186803b1580156137d257600080fd5b505afa1580156137e6573d6000803e3d6000fd5b505050506040513d60208110156137fc57600080fd5b505111611e1a576040805162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b604482015290519081900360640190fd5b6001600160a01b03166000908152606e6020526040902090565b6000818152606f60205260409020546001600160a01b03838116911614612a8a5760708054600181019091557f8f6b23ffa15f0465e3176e15ca644cf24f86dc1312fe715484e3c4aead5eb78b0180546001600160a01b0384166001600160a01b031991821681179092556000838152606f60205260409020805490911690911790555050565b60008282018381101561393d576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6000818152607460205260409020546001600160a01b0316156133e457600090815260746020526040902080546001600160a01b0319169055565b8015612a8a576067546001600160a01b03166139d1576040516001600160a01b0383169082156108fc029083906000818181858888f193505050501580156139cb573d6000803e3d6000fd5b50612a8a565b606754604080516370a0823160e01b81526001600160a01b0385811660048301529151919092169160009183916370a08231916024808301926020929190829003018186803b158015613a2357600080fd5b505afa158015613a37573d6000803e3d6000fd5b505050506040513d6020811015613a4d57600080fd5b50516040805163a9059cbb60e01b81526001600160a01b0387811660048301526024820187905291519293509084169163a9059cbb916044808201926020929091908290030181600087803b158015613aa557600080fd5b505af1158015613ab9573d6000803e3d6000fd5b505050506040513d6020811015613acf57600080fd5b5050604080516370a0823160e01b81526001600160a01b038681166004830152915183928516916370a08231916024808301926020929190829003018186803b158015613b1b57600080fd5b505afa158015613b2f573d6000803e3d6000fd5b505050506040513d6020811015613b4557600080fd5b50511161352f576040805162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b604482015290519081900360640190fd5b600081613b978161248d565b613bd8576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b6000613be384613842565b905060004282600101540390506069548110613c0357606a549350613c24565b606954606a54613c19908363ffffffff61403516565b81613c2057fe5b0493505b6000607954613c40607854606a5461403590919063ffffffff16565b81613c4757fe5b04905080851115613c5c578085039450613c61565b600094505b50505050919050565b606c54606b5411613cb2576040805162461bcd60e51b815260206004820152600d60248201526c1313d0d2d7d4d3d31117d3d555609a1b604482015290519081900360640190fd5b6001600160a01b038216613cff576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b606a5460685460408051630cb175e360e01b81526001600160a01b03868116600483015260248201859052825160009586959094921692630cb175e3926044808301939192829003018186803b158015613d5857600080fd5b505afa158015613d6c573d6000803e3d6000fd5b505050506040513d6040811015613d8257600080fd5b50805160209091015190935091508080841115613da157506000613da6565b508281035b6000613db187613842565b8054909150613dd157613dc381614375565b613dd187826000015461385c565b42816001015410613dfd576069546001820154613df39163ffffffff6138e316565b6001820155613e08565b606954420160018201555b8415613e7b5760685460408051633652466360e01b8152600481018890526024810187905290516001600160a01b039092169163365246639160448082019260009290919082900301818387803b158015613e6257600080fd5b505af1158015613e76573d6000803e3d6000fd5b505050505b6068546040805163939d9f1f60e01b8152600481018590526001600160a01b0389811660248301529151919092169163939d9f1f91604480830192600092919082900301818387803b158015613ed057600080fd5b505af1158015613ee4573d6000803e3d6000fd5b5050606c546040519092506001600160a01b038a1691506000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4613f2c82613625565b50505050505050565b6001600160a01b038216613f82576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6000613f8d83613842565b905080600101548211613fda576040805162461bcd60e51b815260206004820152601060248201526f414c52454144595f4f574e535f4b455960801b604482015290519081900360640190fd5b613fe381614375565b613ff183826000015461385c565b6001810182905580546040516001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4505050565b600082614044575060006115f4565b8282028284828161405157fe5b041461393d5760405162461bcd60e51b81526004018080602001828103825260218152602001806144296021913960400191505060405180910390fd5b60006140a2846001600160a01b031661438a565b6140ae575060016119c0565b604051630a85bd0160e11b815233600482018181526001600160a01b03888116602485015260448401879052608060648501908152865160848601528651600095928a169463150b7a029490938c938b938b939260a4019060208501908083838e5b83811015614128578181015183820152602001614110565b50505050905090810190601f1680156141555780820380516001836020036101000a031916815260200191505b5095505050505050602060405180830381600087803b15801561417757600080fd5b505af115801561418b573d6000803e3d6000fd5b505050506040513d60208110156141a157600080fd5b50516001600160e01b031916630a85bd0160e11b14915050949350505050565b604080517f19457468657265756d205369676e6564204d6573736167653a0a333200000000602080830191909152603c8083019490945282518083039094018452605c909101909152815191012090565b60008151604114614225575060006115f4565b60208201516040830151606084015160001a7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a082111561426b57600093505050506115f4565b8060ff16601b1415801561428357508060ff16601c14155b1561429457600093505050506115f4565b6040805160008152602080820180845289905260ff8416828401526060820186905260808201859052915160019260a0808401939192601f1981019281900390910190855afa1580156142eb573d6000803e3d6000fd5b5050604051601f190151979650505050505050565b303b1590565b6001600160a01b03811661431957600080fd5b6034546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603480546001600160a01b0319166001600160a01b0392909216919091179055565b80546133e457606c8054600101908190559055565b3b151590565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106143d15782800160ff198235161785556143fe565b828001600101855582156143fe579182015b828111156143fe5782358255916020019190600101906143e3565b5061440a92915061440e565b5090565b6115e691905b8082111561440a576000815560010161441456fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564a265627a7a7230582047f15e51181351647a87d6980e0f8f20a1f88485a060e1fd9ce02eb8828eb7b464736f6c63430005090032436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564000000000000000000000000c0f32eba9a4192d93209e83e03b95be7f81036d700000000000000000000000000000000000000000000000000000000000151800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000aad08158cd000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000094644432031204461790000000000000000000000000000000000000000000000
Deployed Bytecode
0x6080604052600436106103e45760003560e01c80636d8ea5b4116102085780639d76ea5811610118578063c4d66de8116100ab578063e985e9c51161007a578063e985e9c5146113c6578063f2fde38b14611401578063f6e4641f14611434578063f8b2cb4f1461145a578063f8faf9421461148d576103e4565b8063c4d66de814611328578063c87b56dd1461135b578063d1bbd49c14611385578063d42cfc41146113b1576103e4565b8063abdf82ce116100e7578063abdf82ce14611191578063b88d4fde146111c4578063b8968bb414611288578063c1c98d0314611313576103e4565b80639d76ea58146110f95780639f98d3cb1461110e578063a22cb46514611141578063a843a4e71461117c576103e4565b80638d0361fc1161019b57806393fd18441161016a57806393fd18441461102a57806395d89b411461103f578063970aaeb714611054578063994a8a71146110875780639b3f0b17146110c0576103e4565b80638d0361fc14610fb05780638da5cb5b14610feb5780638f32d59b146110005780638f98ce8f14611015576103e4565b806374b6c106116101d757806374b6c10614610e22578063782a4ade14610e375780637c7c425314610eb257806383cb0fa914610f7d576103e4565b80636d8ea5b414610d7957806370a0823114610dac57806370efb77014610ddf578063715018a614610e0d576103e4565b806323b872dd1161030357806342842e0e1161029657806352d6a8e41161026557806352d6a8e414610c59578063550ef3a814610c8c5780635fdb97e114610d07578063627cdcb914610d3a5780636352211e14610d4f576103e4565b806342842e0e1461098657806345e965cd146109bc5780634bc5a13514610bfc5780634c7a12a014610c2f576103e4565b806339f46986116102d257806339f46986146108fc5780633ba70e311461092c5780633d3359cb146109415780634136aa3514610971576103e4565b806323b872dd1461080c5780632e1a7d4d1461084257806330176e131461086c57806338af3eed146108e7576103e4565b80630f15023b1161037b578063150b7a021161034a578063150b7a02146106ca57806318160ddd146107b85780631f1ec029146107cd5780632009dc65146107f7576103e4565b80630f15023b1461060b57806310803b721461062057806310e56973146106a057806311a4c03a146106b5576103e4565b8063095ea7b3116103b7578063095ea7b31461056e5780630aaffd2a1461059c5780630c79130f146105cf5780630ed3e2cc146105f6576103e4565b806301ffc9a71461042c578063025e7c271461047457806306fdde03146104ba578063081812fc14610544575b3480156103f057600080fd5b506040805162461bcd60e51b815260206004820152600b60248201526a4e4f5f46414c4c4241434b60a81b604482015290519081900360640190fd5b34801561043857600080fd5b506104606004803603602081101561044f57600080fd5b50356001600160e01b031916611508565b604080519115158252519081900360200190f35b34801561048057600080fd5b5061049e6004803603602081101561049757600080fd5b503561152b565b604080516001600160a01b039092168252519081900360200190f35b3480156104c657600080fd5b506104cf611552565b6040805160208082528351818301528351919283929083019185019080838360005b838110156105095781810151838201526020016104f1565b50505050905090810190601f1680156105365780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561055057600080fd5b5061049e6004803603602081101561056757600080fd5b50356115e9565b61059a6004803603604081101561058457600080fd5b506001600160a01b0381351690602001356115fa565b005b3480156105a857600080fd5b5061059a600480360360208110156105bf57600080fd5b50356001600160a01b0316611787565b3480156105db57600080fd5b506105e4611878565b60408051918252519081900360200190f35b34801561060257600080fd5b506105e461187e565b34801561061757600080fd5b5061049e611884565b34801561062c57600080fd5b506106506004803603604081101561064357600080fd5b5080359060200135611893565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561068c578181015183820152602001610674565b505050509050019250505060405180910390f35b3480156106ac57600080fd5b506105e46119ab565b3480156106c157600080fd5b506105e46119b1565b3480156106d657600080fd5b5061079b600480360360808110156106ed57600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b81111561072757600080fd5b82018360208201111561073957600080fd5b803590602001918460018302840111600160201b8311171561075a57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506119b7945050505050565b604080516001600160e01b03199092168252519081900360200190f35b3480156107c457600080fd5b506105e46119c8565b3480156107d957600080fd5b5061059a600480360360208110156107f057600080fd5b50356119ce565b34801561080357600080fd5b5061059a611a76565b61059a6004803603606081101561082257600080fd5b506001600160a01b03813581169160208101359091169060400135611a81565b34801561084e57600080fd5b5061059a6004803603602081101561086557600080fd5b5035611ccb565b34801561087857600080fd5b5061059a6004803603602081101561088f57600080fd5b810190602081018135600160201b8111156108a957600080fd5b8201836020820111156108bb57600080fd5b803590602001918460018302840111600160201b831117156108dc57600080fd5b509092509050611e1f565b3480156108f357600080fd5b5061049e611e3c565b34801561090857600080fd5b5061059a6004803603604081101561091f57600080fd5b5080359060200135611e4b565b34801561093857600080fd5b506105e4611ef5565b34801561094d57600080fd5b5061059a6004803603604081101561096457600080fd5b5080359060200135611efb565b34801561097d57600080fd5b50610460611fa5565b61059a6004803603606081101561099c57600080fd5b506001600160a01b03813581169160208101359091169060400135611fb5565b3480156109c857600080fd5b506104cf600480360360808110156109df57600080fd5b810190602081018135600160201b8111156109f957600080fd5b820183602082011115610a0b57600080fd5b803590602001918460018302840111600160201b83111715610a2c57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b811115610a7e57600080fd5b820183602082011115610a9057600080fd5b803590602001918460018302840111600160201b83111715610ab157600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b811115610b0357600080fd5b820183602082011115610b1557600080fd5b803590602001918460018302840111600160201b83111715610b3657600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b811115610b8857600080fd5b820183602082011115610b9a57600080fd5b803590602001918460018302840111600160201b83111715610bbb57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611fd0945050505050565b348015610c0857600080fd5b506105e460048036036020811015610c1f57600080fd5b50356001600160a01b0316612185565b348015610c3b57600080fd5b506104cf60048036036020811015610c5257600080fd5b5035612197565b348015610c6557600080fd5b506105e460048036036020811015610c7c57600080fd5b50356001600160a01b031661225b565b348015610c9857600080fd5b5061059a60048036036020811015610caf57600080fd5b810190602081018135600160201b811115610cc957600080fd5b820183602082011115610cdb57600080fd5b803590602001918460018302840111600160201b83111715610cfc57600080fd5b509092509050612266565b348015610d1357600080fd5b506104cf60048036036020811015610d2a57600080fd5b50356001600160a01b0316612283565b348015610d4657600080fd5b5061059a6123ff565b348015610d5b57600080fd5b5061049e60048036036020811015610d7257600080fd5b5035612417565b348015610d8557600080fd5b5061046060048036036020811015610d9c57600080fd5b50356001600160a01b031661248d565b348015610db857600080fd5b506105e460048036036020811015610dcf57600080fd5b50356001600160a01b03166124ad565b61059a60048036036040811015610df557600080fd5b506001600160a01b038135811691602001351661251c565b348015610e1957600080fd5b5061059a6125c1565b348015610e2e57600080fd5b506105e461261c565b348015610e4357600080fd5b5061059a60048036036020811015610e5a57600080fd5b810190602081018135600160201b811115610e7457600080fd5b820183602082011115610e8657600080fd5b803590602001918460018302840111600160201b83111715610ea757600080fd5b509092509050612622565b348015610ebe57600080fd5b5061059a60048036036040811015610ed557600080fd5b810190602081018135600160201b811115610eef57600080fd5b820183602082011115610f0157600080fd5b803590602001918460208302840111600160201b83111715610f2257600080fd5b919390929091602081019035600160201b811115610f3f57600080fd5b820183602082011115610f5157600080fd5b803590602001918460208302840111600160201b83111715610f7257600080fd5b5090925090506126a4565b348015610f8957600080fd5b506105e460048036036020811015610fa057600080fd5b50356001600160a01b0316612706565b348015610fbc57600080fd5b506105e460048036036040811015610fd357600080fd5b506001600160a01b03813581169160200135166127c9565b348015610ff757600080fd5b5061049e61282d565b34801561100c57600080fd5b5061046061283c565b34801561102157600080fd5b506105e461284d565b34801561103657600080fd5b506105e4612853565b34801561104b57600080fd5b506104cf612859565b34801561106057600080fd5b506105e46004803603602081101561107757600080fd5b50356001600160a01b03166129e4565b34801561109357600080fd5b50610460600480360360408110156110aa57600080fd5b50803590602001356001600160a01b0316612a4e565b3480156110cc57600080fd5b5061059a600480360360408110156110e357600080fd5b506001600160a01b038135169060200135612a6f565b34801561110557600080fd5b5061049e612a8e565b34801561111a57600080fd5b5061059a6004803603602081101561113157600080fd5b50356001600160a01b0316612a9d565b34801561114d57600080fd5b5061059a6004803603604081101561116457600080fd5b506001600160a01b0381351690602001351515612b54565b34801561118857600080fd5b5061059a612c5f565b34801561119d57600080fd5b506105e4600480360360208110156111b457600080fd5b50356001600160a01b0316612d0b565b61059a600480360360808110156111da57600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b81111561121457600080fd5b82018360208201111561122657600080fd5b803590602001918460018302840111600160201b8311171561124757600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612d90945050505050565b34801561129457600080fd5b5061059a600480360360408110156112ab57600080fd5b6001600160a01b038235169190810190604081016020820135600160201b8111156112d557600080fd5b8201836020820111156112e757600080fd5b803590602001918460018302840111600160201b8311171561130857600080fd5b509092509050612f1e565b34801561131f57600080fd5b5061059a612ff0565b34801561133457600080fd5b5061059a6004803603602081101561134b57600080fd5b50356001600160a01b0316613089565b34801561136757600080fd5b506104cf6004803603602081101561137e57600080fd5b5035613179565b34801561139157600080fd5b5061139a613391565b6040805161ffff9092168252519081900360200190f35b3480156113bd57600080fd5b506105e4613396565b3480156113d257600080fd5b50610460600480360360408110156113e957600080fd5b506001600160a01b038135811691602001351661339c565b34801561140d57600080fd5b5061059a6004803603602081101561142457600080fd5b50356001600160a01b03166133ca565b61059a6004803603602081101561144a57600080fd5b50356001600160a01b03166133e7565b34801561146657600080fd5b506105e46004803603602081101561147d57600080fd5b50356001600160a01b0316613442565b34801561149957600080fd5b5061059a600480360360408110156114b057600080fd5b810190602081018135600160201b8111156114ca57600080fd5b8201836020820111156114dc57600080fd5b803590602001918460208302840111600160201b831117156114fd57600080fd5b9193509150356134e6565b6001600160e01b0319811660009081526020819052604090205460ff165b919050565b6070818154811061153857fe5b6000918252602090912001546001600160a01b0316905081565b60718054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156115de5780601f106115b3576101008083540402835291602001916115de565b820191906000526020600020905b8154815290600101906020018083116115c157829003601f168201915b505050505090505b90565b60006115f482613535565b92915050565b606754600160a01b900460ff1661164a576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b806116558133612a4e565b806116655750611665813361358f565b8061167d575061167d61167782612417565b3361339c565b6116cb576040805162461bcd60e51b815260206004820152601a60248201527913d3931657d2d15657d3d5d3915497d3d497d054141493d5915160321b604482015290519081900360640190fd5b336001600160a01b0384161415611718576040805162461bcd60e51b815260206004820152600c60248201526b20a8282927ab22afa9a2a62360a11b604482015290519081900360640190fd5b600082815260746020526040902080546001600160a01b0319166001600160a01b038516908117909155829061174d82612417565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b61178f61282d565b6001600160a01b0316336001600160a01b031614806117b85750606d546001600160a01b031633145b611809576040805162461bcd60e51b815260206004820152601e60248201527f4f4e4c595f4c4f434b5f4f574e45525f4f525f42454e45464943494152590000604482015290519081900360640190fd5b6001600160a01b038116611856576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b606d80546001600160a01b0319166001600160a01b0392909216919091179055565b60795481565b60785481565b6068546001600160a01b031681565b6070546060906118e0576040805162461bcd60e51b81526020600482015260136024820152724e4f5f4f55545354414e44494e475f4b45595360681b604482015290519081900360640190fd5b607054829084820290600090828401111561190357506070548181039250611908565b508082015b606083604051908082528060200260200182016040528015611934578160200160208202803883390190505b5090506000835b8381101561199e576070818154811061195057fe5b9060005260206000200160009054906101000a90046001600160a01b031683838151811061197a57fe5b6001600160a01b03909216602092830291909101909101526001918201910161193b565b5090979650505050505050565b606a5481565b60695481565b630a85bd0160e11b5b949350505050565b606c5490565b6119d661283c565b6119df57600080fd5b606754600160a01b900460ff16611a2f576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b606a805490829055604080518281526020810184905281517f8aa4fa52648a6d15edce8a179c792c86f3719d0cc3c572cf90f91948f0f2cb68929181900390910190a15050565b611a7f336135b0565b565b606754600160a01b900460ff16611ad1576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b82611adb8161248d565b611b1c576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b81611b278133612a4e565b80611b375750611b37813361358f565b80611b495750611b4961167782612417565b611b97576040805162461bcd60e51b815260206004820152601a60248201527913d3931657d2d15657d3d5d3915497d3d497d054141493d5915160321b604482015290519081900360640190fd5b6001600160a01b038416611be4576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b611bf5611bf086612706565b613625565b6000611c0086613842565b90506000611c0d86613842565b6001810154815491925090611c2c578254808355611c2c90889061385c565b428111611c50576001808401549083015582548255611c4b878761385c565b611c6d565b6001830154611c679042830363ffffffff6138e316565b60018301555b42600184015560008355611c8086613944565b85876001600160a01b0316896001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050505050505050565b611cd361282d565b6001600160a01b0316336001600160a01b03161480611cfc5750606d546001600160a01b031633145b611d4d576040805162461bcd60e51b815260206004820152601e60248201527f4f4e4c595f4c4f434b5f4f574e45525f4f525f42454e45464943494152590000604482015290519081900360640190fd5b6000611d5830613442565b90506000821580611d6857508183115b15611dbc5760008211611db5576040805162461bcd60e51b815260206004820152601060248201526f4e4f545f454e4f5547485f46554e445360801b604482015290519081900360640190fd5b5080611dbf565b50815b606d546040805183815290516001600160a01b039092169133917f2717ead6b9200dd235aad468c9809ea400fe33ac69b5bfaa6d3e90fc922b6398919081900360200190a3606d54611e1a906001600160a01b03168261397f565b505050565b611e2761283c565b611e3057600080fd5b611e1a60738383614390565b606d546001600160a01b031681565b611e5361283c565b611e5c57600080fd5b80611e9d576040805162461bcd60e51b815260206004820152600c60248201526b494e56414c49445f5241544560a01b604482015290519081900360640190fd5b60785460795460408051928352602083019190915281810184905260608201839052517fa7d13855fe99b8c8b2780f36ff9e06133878b66a664a951b2375fe2296cc00089181900360800190a1607891909155607955565b606c5481565b611f0361283c565b611f0c57600080fd5b80611f4d576040805162461bcd60e51b815260206004820152600c60248201526b494e56414c49445f5241544560a01b604482015290519081900360640190fd5b60765460775460408051928352602083019190915281810184905260608201839052517ff0cc3b8bd450a20cce7720453e064b35cf490baa5d53c7c6ef8b2e1b02898a7d9181900360800190a1607691909155607755565b606754600160a01b900460ff1681565b611e1a83838360405180602001604052806000815250612d90565b606080859050606085905060608590506060859050606081518351855187510101016040519080825280601f01601f19166020018201604052801561201c576020820181803883390190505b509050806000805b87518110156120755787818151811061203957fe5b602001015160f81c60f81b83838060010194508151811061205657fe5b60200101906001600160f81b031916908160001a905350600101612024565b5060005b86518110156120ca5786818151811061208e57fe5b602001015160f81c60f81b8383806001019450815181106120ab57fe5b60200101906001600160f81b031916908160001a905350600101612079565b5060005b855181101561211f578581815181106120e357fe5b602001015160f81c60f81b83838060010194508151811061210057fe5b60200101906001600160f81b031916908160001a9053506001016120ce565b5060005b84518110156121745784818151811061213857fe5b602001015160f81c60f81b83838060010194508151811061215557fe5b60200101906001600160f81b031916908160001a905350600101612123565b50909b9a5050505050505050505050565b607a6020526000908152604090205481565b606081806121be5750506040805180820190915260018152600360fc1b6020820152611526565b8260005b81156121d657600101600a820491506121c2565b6060816040519080825280601f01601f191660200182016040528015612203576020820181803883390190505b50905060001982015b841561225157600a850660300160f81b8282806001900393508151811061222f57fe5b60200101906001600160f81b031916908160001a905350600a8504945061220c565b5095945050505050565b60006115f482613b8b565b61226e61283c565b61227757600080fd5b611e1a60718383614390565b604080518082018252601081526f181899199a1a9b1b9c1cb0b131b232b360811b60208201528151602a80825260608281019094526001600160a01b03851692918491602082018180388339019050509050600360fc1b816000815181106122e757fe5b60200101906001600160f81b031916908160001a905350600f60fb1b8160018151811061231057fe5b60200101906001600160f81b031916908160001a90535060005b60148110156123f6578260048583600c016020811061234557fe5b1a60f81b6001600160f81b031916901c60f81c60ff168151811061236557fe5b602001015160f81c60f81b82826002026002018151811061238257fe5b60200101906001600160f81b031916908160001a905350828482600c01602081106123a957fe5b825191901a600f169081106123ba57fe5b602001015160f81c60f81b8282600202600301815181106123d757fe5b60200101906001600160f81b031916908160001a90535060010161232a565b50949350505050565b336000908152607a6020526040902080546001019055565b6000818152606f602052604081205482906001600160a01b0316612470576040805162461bcd60e51b815260206004820152600b60248201526a4e4f5f535543485f4b455960a81b604482015290519081900360640190fd5b50506000908152606f60205260409020546001600160a01b031690565b6001600160a01b03166000908152606e6020526040902060010154421090565b60006001600160a01b0382166124fc576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6125058261248d565b612510576000612513565b60015b60ff1692915050565b606754600160a01b900460ff1661256c576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b806125768161248d565b6125b7576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b611e1a8383613c6a565b6125c961283c565b6125d257600080fd5b6034546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603480546001600160a01b0319169055565b606b5481565b61262a61283c565b61263357600080fd5b61263f60728383614390565b507f8868e22e84ebf32da89b2ebcb0ac642816304ea3863b257f240df9098719cb97828260405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a15050565b6126ac61283c565b6126b557600080fd5b60005b838110156126ff576126f78585838181106126cf57fe5b905060200201356001600160a01b03168484848181106126eb57fe5b90506020020135613f35565b6001016126b8565b5050505050565b6000816127128161248d565b612753576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b600061275e84613842565b905060004282600101540390506000606954821061277f5750606a546127a0565b606954606a54612795908463ffffffff61403516565b8161279c57fe5b0490505b6077546076546127b790839063ffffffff61403516565b816127be57fe5b049695505050505050565b6001600160a01b03919091166000908152607a602090815260409182902054825130606090811b82850152603482019290925293901b6bffffffffffffffffffffffff19166054840152815180840360480181526068909301909152815191012090565b6034546001600160a01b031690565b6034546001600160a01b0316331490565b60765481565b60705490565b6072546060906002600019610100600184161502019091160461295257606860009054906101000a90046001600160a01b03166001600160a01b03166335a750de6040518163ffffffff1660e01b815260040160006040518083038186803b1580156128c457600080fd5b505afa1580156128d8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561290157600080fd5b810190808051600160201b81111561291857600080fd5b8201602081018481111561292b57600080fd5b8151600160201b81118282018710171561294457600080fd5b509094506115e69350505050565b6072805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156129d85780601f106129ad576101008083540402835291602001916129d8565b820191906000526020600020905b8154815290600101906020018083116129bb57829003601f168201915b505050505090506115e6565b6000816129f08161248d565b612a31576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b50506001600160a01b03166000908152606e602052604090205490565b6000918252606f6020526040909120546001600160a01b0391821691161490565b612a7761283c565b612a8057600080fd5b612a8a8282613f35565b5050565b6067546001600160a01b031681565b612aa561283c565b612aae57600080fd5b80612ab88161248d565b612af9576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b6001600160a01b0382166000908152606e602090815260409182902042600182015580548351908152925190927f59f2fe866dd27a1c2d34115520888c3150365cbc931aab97fa88c4b9ab40b79592908290030190a1505050565b606754600160a01b900460ff16612ba4576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b6001600160a01b038216331415612bf1576040805162461bcd60e51b815260206004820152600c60248201526b20a8282927ab22afa9a2a62360a11b604482015290519081900360640190fd5b3360008181526075602090815260408083206001600160a01b03871680855290835292819020805460ff1916861515908117909155815190815290519293927f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31929181900390910190a35050565b612c6761283c565b612c7057600080fd5b606754600160a01b900460ff1615612cbf576040805162461bcd60e51b815260206004820152600d60248201526c111254d050931157d1925494d5609a1b604482015290519081900360640190fd5b6040805130318152905133917fa053f2a7eceda47dde76e5939c5adf7b771e665fc84c8ef6feffc290a1eb1feb919081900360200190a2612d0833612d0330613442565b61397f565b33ff5b6001600160a01b0381166000908152606e60205260408120600101548290612d70576040805162461bcd60e51b81526020600482015260136024820152724841535f4e455645525f4f574e45445f4b455960681b604482015290519081900360640190fd5b50506001600160a01b03166000908152606e602052604090206001015490565b606754600160a01b900460ff16612de0576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b81612deb8133612a4e565b80612dfb5750612dfb813361358f565b80612e0d5750612e0d61167782612417565b612e5b576040805162461bcd60e51b815260206004820152601a60248201527913d3931657d2d15657d3d5d3915497d3d497d054141493d5915160321b604482015290519081900360640190fd5b612e6483612417565b612e6d8161248d565b612eae576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b612eb9868686611a81565b612ec58686868661408e565b612f16576040805162461bcd60e51b815260206004820152601d60248201527f4e4f4e5f434f4d504c49414e545f4552433732315f5245434549564552000000604482015290519081900360640190fd5b505050505050565b826001600160a01b0316612f79612f3d612f3886336127c9565b6141c1565b84848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061421292505050565b6001600160a01b031614612fc8576040805162461bcd60e51b8152602060048201526011602482015270494e56414c49445f5349474e415455524560781b604482015290519081900360640190fd5b6001600160a01b0383166000908152607a6020526040902080546001019055611e1a836135b0565b612ff861283c565b61300157600080fd5b606754600160a01b900460ff16613051576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b6040517f25a311358326fb18c62efc24bc28d3126acee8d2a67fd8b2145b757dc8bd1bc190600090a16067805460ff60a01b19169055565b600154610100900460ff16806130a257506130a2614300565b806130b0575060015460ff16155b6130eb5760405162461bcd60e51b815260040180806020018281038252602e81526020018061444a602e913960400191505060405180910390fd5b600154610100900460ff16158015613115576001805460ff1961ff00199091166101001716811790555b603480546001600160a01b0319166001600160a01b0384811691909117918290556040519116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a38015612a8a576001805461ff00191690555050565b6000818152606f602052604090205460609082906001600160a01b03166131d5576040805162461bcd60e51b815260206004820152600b60248201526a4e4f5f535543485f4b455960a81b604482015290519081900360640190fd5b607354606090600260001961010060018416150201909116046132ce57606860009054906101000a90046001600160a01b03166001600160a01b0316637ff94bb26040518163ffffffff1660e01b815260040160006040518083038186803b15801561324057600080fd5b505afa158015613254573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561327d57600080fd5b810190808051600160201b81111561329457600080fd5b820160208101848111156132a757600080fd5b8151600160201b8111828201871017156132c057600080fd5b5090945061335c9350505050565b6073805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156133545780601f1061332957610100808354040283529160200191613354565b820191906000526020600020905b81548152906001019060200180831161333757829003601f168201915b505050505090505b6119c08161336930612283565b604051806040016040528060018152602001602f60f81b81525061338c88612197565b611fd0565b600490565b60775481565b6001600160a01b03918216600090815260756020908152604080832093909416825291909152205460ff1690565b6133d261283c565b6133db57600080fd5b6133e481614306565b50565b606754600160a01b900460ff16613437576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b6133e4816000613c6a565b6067546000906001600160a01b031661346657506001600160a01b03811631611526565b606754604080516370a0823160e01b81526001600160a01b038581166004830152915191909216916370a08231916024808301926020929190829003018186803b1580156134b357600080fd5b505afa1580156134c7573d6000803e3d6000fd5b505050506040513d60208110156134dd57600080fd5b50519050611526565b6134ee61283c565b6134f757600080fd5b60005b8281101561352f5761352784848381811061351157fe5b905060200201356001600160a01b031683613f35565b6001016134fa565b50505050565b6000818152607460205260408120546001600160a01b0316806115f4576040805162461bcd60e51b815260206004820152600d60248201526c1393d39157d054141493d59151609a1b604482015290519081900360640190fd5b600091825260746020526040909120546001600160a01b0391821691161490565b60006135bb82613842565b905060006135c883613b8b565b825460408051838152905192935033926001600160a01b03871692917f0a7068a9989857441c039a14a42b67ed71dd1fcfe5a9b17cc87b252e47bce528919081900360200190a44260018301558015611e1a57611e1a338261397f565b80156133e4576067546001600160a01b03166136885780341015613683576040805162461bcd60e51b815260206004820152601060248201526f4e4f545f454e4f5547485f46554e445360801b604482015290519081900360640190fd5b6133e4565b606754604080516370a0823160e01b815230600482015290516001600160a01b039092169160009183916370a0823191602480820192602092909190829003018186803b1580156136d857600080fd5b505afa1580156136ec573d6000803e3d6000fd5b505050506040513d602081101561370257600080fd5b5051604080516323b872dd60e01b81523360048201523060248201526044810186905290519192506001600160a01b038416916323b872dd916064808201926020929091908290030181600087803b15801561375d57600080fd5b505af1158015613771573d6000803e3d6000fd5b505050506040513d602081101561378757600080fd5b5050604080516370a0823160e01b8152306004820152905182916001600160a01b038516916370a0823191602480820192602092909190829003018186803b1580156137d257600080fd5b505afa1580156137e6573d6000803e3d6000fd5b505050506040513d60208110156137fc57600080fd5b505111611e1a576040805162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b604482015290519081900360640190fd5b6001600160a01b03166000908152606e6020526040902090565b6000818152606f60205260409020546001600160a01b03838116911614612a8a5760708054600181019091557f8f6b23ffa15f0465e3176e15ca644cf24f86dc1312fe715484e3c4aead5eb78b0180546001600160a01b0384166001600160a01b031991821681179092556000838152606f60205260409020805490911690911790555050565b60008282018381101561393d576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6000818152607460205260409020546001600160a01b0316156133e457600090815260746020526040902080546001600160a01b0319169055565b8015612a8a576067546001600160a01b03166139d1576040516001600160a01b0383169082156108fc029083906000818181858888f193505050501580156139cb573d6000803e3d6000fd5b50612a8a565b606754604080516370a0823160e01b81526001600160a01b0385811660048301529151919092169160009183916370a08231916024808301926020929190829003018186803b158015613a2357600080fd5b505afa158015613a37573d6000803e3d6000fd5b505050506040513d6020811015613a4d57600080fd5b50516040805163a9059cbb60e01b81526001600160a01b0387811660048301526024820187905291519293509084169163a9059cbb916044808201926020929091908290030181600087803b158015613aa557600080fd5b505af1158015613ab9573d6000803e3d6000fd5b505050506040513d6020811015613acf57600080fd5b5050604080516370a0823160e01b81526001600160a01b038681166004830152915183928516916370a08231916024808301926020929190829003018186803b158015613b1b57600080fd5b505afa158015613b2f573d6000803e3d6000fd5b505050506040513d6020811015613b4557600080fd5b50511161352f576040805162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b604482015290519081900360640190fd5b600081613b978161248d565b613bd8576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b6000613be384613842565b905060004282600101540390506069548110613c0357606a549350613c24565b606954606a54613c19908363ffffffff61403516565b81613c2057fe5b0493505b6000607954613c40607854606a5461403590919063ffffffff16565b81613c4757fe5b04905080851115613c5c578085039450613c61565b600094505b50505050919050565b606c54606b5411613cb2576040805162461bcd60e51b815260206004820152600d60248201526c1313d0d2d7d4d3d31117d3d555609a1b604482015290519081900360640190fd5b6001600160a01b038216613cff576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b606a5460685460408051630cb175e360e01b81526001600160a01b03868116600483015260248201859052825160009586959094921692630cb175e3926044808301939192829003018186803b158015613d5857600080fd5b505afa158015613d6c573d6000803e3d6000fd5b505050506040513d6040811015613d8257600080fd5b50805160209091015190935091508080841115613da157506000613da6565b508281035b6000613db187613842565b8054909150613dd157613dc381614375565b613dd187826000015461385c565b42816001015410613dfd576069546001820154613df39163ffffffff6138e316565b6001820155613e08565b606954420160018201555b8415613e7b5760685460408051633652466360e01b8152600481018890526024810187905290516001600160a01b039092169163365246639160448082019260009290919082900301818387803b158015613e6257600080fd5b505af1158015613e76573d6000803e3d6000fd5b505050505b6068546040805163939d9f1f60e01b8152600481018590526001600160a01b0389811660248301529151919092169163939d9f1f91604480830192600092919082900301818387803b158015613ed057600080fd5b505af1158015613ee4573d6000803e3d6000fd5b5050606c546040519092506001600160a01b038a1691506000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4613f2c82613625565b50505050505050565b6001600160a01b038216613f82576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6000613f8d83613842565b905080600101548211613fda576040805162461bcd60e51b815260206004820152601060248201526f414c52454144595f4f574e535f4b455960801b604482015290519081900360640190fd5b613fe381614375565b613ff183826000015461385c565b6001810182905580546040516001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4505050565b600082614044575060006115f4565b8282028284828161405157fe5b041461393d5760405162461bcd60e51b81526004018080602001828103825260218152602001806144296021913960400191505060405180910390fd5b60006140a2846001600160a01b031661438a565b6140ae575060016119c0565b604051630a85bd0160e11b815233600482018181526001600160a01b03888116602485015260448401879052608060648501908152865160848601528651600095928a169463150b7a029490938c938b938b939260a4019060208501908083838e5b83811015614128578181015183820152602001614110565b50505050905090810190601f1680156141555780820380516001836020036101000a031916815260200191505b5095505050505050602060405180830381600087803b15801561417757600080fd5b505af115801561418b573d6000803e3d6000fd5b505050506040513d60208110156141a157600080fd5b50516001600160e01b031916630a85bd0160e11b14915050949350505050565b604080517f19457468657265756d205369676e6564204d6573736167653a0a333200000000602080830191909152603c8083019490945282518083039094018452605c909101909152815191012090565b60008151604114614225575060006115f4565b60208201516040830151606084015160001a7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a082111561426b57600093505050506115f4565b8060ff16601b1415801561428357508060ff16601c14155b1561429457600093505050506115f4565b6040805160008152602080820180845289905260ff8416828401526060820186905260808201859052915160019260a0808401939192601f1981019281900390910190855afa1580156142eb573d6000803e3d6000fd5b5050604051601f190151979650505050505050565b303b1590565b6001600160a01b03811661431957600080fd5b6034546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603480546001600160a01b0319166001600160a01b0392909216919091179055565b80546133e457606c8054600101908190559055565b3b151590565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106143d15782800160ff198235161785556143fe565b828001600101855582156143fe579182015b828111156143fe5782358255916020019190600101906143e3565b5061440a92915061440e565b5090565b6115e691905b8082111561440a576000815560010161441456fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564a265627a7a7230582047f15e51181351647a87d6980e0f8f20a1f88485a060e1fd9ce02eb8828eb7b464736f6c63430005090032
Deployed Bytecode Sourcemap
72624:1064:0:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;47743:21:0;;;-1:-1:-1;;;47743:21:0;;;;;;;;;;;;-1:-1:-1;;;47743:21:0;;;;;;;;;;;;;;12092:135;;8:9:-1;5:2;;;30:1;27;20:12;5:2;12092:135:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;12092:135:0;-1:-1:-1;;;;;;12092:135:0;;:::i;:::-;;;;;;;;;;;;;;;;;;30062:23;;8:9:-1;5:2;;;30:1;27;20:12;5:2;30062:23:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;30062:23:0;;:::i;:::-;;;;-1:-1:-1;;;;;30062:23:0;;;;;;;;;;;;;;45537:94;;8:9:-1;5:2;;;30:1;27;20:12;5:2;45537:94:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:100:-1;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;45537:94:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;38219:138;;8:9:-1;5:2;;;30:1;27;20:12;5:2;38219:138:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;38219:138:0;;:::i;37249:311::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;37249:311:0;;;;;;;;:::i;:::-;;28391:199;;8:9:-1;5:2;;;30:1;27;20:12;5:2;28391:199:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;28391:199:0;-1:-1:-1;;;;;28391:199:0;;:::i;59330:41::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;59330:41:0;;;:::i;:::-;;;;;;;;;;;;;;;;59287:38;;8:9:-1;5:2;;;30:1;27;20:12;5:2;59287:38:0;;;:::i;25420:29::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;25420:29:0;;;:::i;32352:879::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;32352:879:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;32352:879:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:100:-1;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;32352:879:0;;;;;;;;;;;;;;;;;25795:20;;8:9:-1;5:2;;;30:1;27;20:12;5:2;25795:20:0;;;:::i;25637:30::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;25637:30:0;;;:::i;14281:147::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;14281:147:0;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;14281:147:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;14281:147:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;14281:147:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;-1:-1;;;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;14281:147:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;14281:147:0;;-1:-1:-1;14281:147:0;;-1:-1:-1;;;;;14281:147:0:i;:::-;;;;-1:-1:-1;;;;;;14281:147:0;;;;;;;;;;;;;;28714:104;;8:9:-1;5:2;;;30:1;27;20:12;5:2;28714:104:0;;;:::i;28034:213::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;28034:213:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;28034:213:0;;:::i;59909:85::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;59909:85:0;;;:::i;66538:1750::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;66538:1750:0;;;;;;;;;;;;;;;;;:::i;27405:517::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;27405:517:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;27405:517:0;;:::i;46290:134::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;46290:134:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;46290:134:0;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;46290:134:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;46290:134:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;-1:-1;;;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;-1:-1;46290:134:0;;-1:-1:-1;46290:134:0;-1:-1:-1;46290:134:0;:::i;26075:26::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;26075:26:0;;;:::i;60942:491::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;60942:491:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;60942:491:0;;;;;;;:::i;25983:28::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;25983:28:0;;;:::i;69844:463::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;69844:463:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;69844:463:0;;;;;;;:::i;20553:19::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;20553:19:0;;;:::i;68641:174::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;68641:174:0;;;;;;;;;;;;;;;;;:::i;42204:820::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;42204:820:0;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;42204:820:0;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;42204:820:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;42204:820:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;-1:-1;;;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;42204:820:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;42204:820:0;;;;;;;;-1:-1:-1;42204:820:0;;-1:-1:-1;;;;;5:28;;2:2;;;46:1;43;36:12;2:2;42204:820:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;42204:820:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;-1:-1;;;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;42204:820:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;42204:820:0;;;;;;;;-1:-1:-1;42204:820:0;;-1:-1:-1;;;;;5:28;;2:2;;;46:1;43;36:12;2:2;42204:820:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;42204:820:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;-1:-1;;;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;42204:820:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;42204:820:0;;;;;;;;-1:-1:-1;42204:820:0;;-1:-1:-1;;;;;5:28;;2:2;;;46:1;43;36:12;2:2;42204:820:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;42204:820:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;-1:-1;;;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;42204:820:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;42204:820:0;;-1:-1:-1;42204:820:0;;-1:-1:-1;;;;;42204:820:0:i;59435:47::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;59435:47:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;59435:47:0;-1:-1:-1;;;;;59435:47:0;;:::i;43030:516::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;43030:516:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;43030:516:0;;:::i;61719:163::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;61719:163:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;61719:163:0;-1:-1:-1;;;;;61719:163:0;;:::i;45313:121::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;45313:121:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;45313:121:0;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;45313:121:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;45313:121:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;-1:-1;;;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;-1:-1;45313:121:0;;-1:-1:-1;45313:121:0;-1:-1:-1;45313:121:0;:::i;43552:457::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;43552:457:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;43552:457:0;-1:-1:-1;;;;;43552:457:0;;:::i;60786:84::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;60786:84:0;;;:::i;34217:150::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;34217:150:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;34217:150:0;;:::i;31653:171::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;31653:171:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;31653:171:0;-1:-1:-1;;;;;31653:171:0;;:::i;31388:197::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;31388:197:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;31388:197:0;-1:-1:-1;;;;;31388:197:0;;:::i;52435:209::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;52435:209:0;;;;;;;;;;:::i;9442:140::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;9442:140:0;;;:::i;25889:27::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;25889:27:0;;;:::i;45713:167::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;45713:167:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;45713:167:0;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;45713:167:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;45713:167:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;-1:-1;;;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;-1:-1;45713:167:0;;-1:-1:-1;45713:167:0;-1:-1:-1;45713:167:0;:::i;41032:257::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;41032:257:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;41032:257:0;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;41032:257:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;41032:257:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;41032:257:0;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;41032:257:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;41032:257:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;-1:-1;41032:257:0;;-1:-1:-1;41032:257:0;-1:-1:-1;41032:257:0;:::i;70572:727::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;70572:727:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;70572:727:0;-1:-1:-1;;;;;70572:727:0;;:::i;61995:456::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;61995:456:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;61995:456:0;;;;;;;;;;:::i;8729:79::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;8729:79:0;;;:::i;9064:92::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;9064:92:0;;;:::i;66310:36::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;66310:36:0;;;:::i;33982:104::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;33982:104:0;;;:::i;45985:215::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;45985:215:0;;;:::i;31941:173::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;31941:173:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;31941:173:0;-1:-1:-1;;;;;31941:173:0;;:::i;33309:155::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;33309:155:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;33309:155:0;;;;;;-1:-1:-1;;;;;33309:155:0;;:::i;40314:163::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;40314:163:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;40314:163:0;;;;;;;;:::i;17662:27::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;17662:27:0;;;:::i;30959:266::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;30959:266:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;30959:266:0;-1:-1:-1;;;;;30959:266:0;;:::i;37848:268::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;37848:268:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;37848:268:0;;;;;;;;;;:::i;21223:500::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;21223:500:0;;;:::i;33622:200::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;33622:200:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;33622:200:0;-1:-1:-1;;;;;33622:200:0;;:::i;69387:382::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;69387:382:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;69387:382:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;69387:382:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;-1:-1;;;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;69387:382:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;69387:382:0;;-1:-1:-1;69387:382:0;;-1:-1:-1;;;;;69387:382:0:i;60239:401::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;60239:401:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;60239:401:0;;;;;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;60239:401:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;60239:401:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;-1:-1;;;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;-1:-1;60239:401:0;;-1:-1:-1;60239:401:0;-1:-1:-1;60239:401:0;:::i;20961:121::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;20961:121:0;;;:::i;8516:145::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;8516:145:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;8516:145:0;-1:-1:-1;;;;;8516:145:0;;:::i;46765:445::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;46765:445:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;46765:445:0;;:::i;73592:93::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;73592:93:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;66351:40;;8:9:-1;5:2;;;30:1;27;20:12;5:2;66351:40:0;;;:::i;38674:173::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;38674:173:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;38674:173:0;;;;;;;;;;:::i;9759:109::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;9759:109:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;9759:109:0;-1:-1:-1;;;;;9759:109:0;;:::i;52071:154::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;52071:154:0;-1:-1:-1;;;;;52071:154:0;;:::i;17992:236::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;17992:236:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;17992:236:0;-1:-1:-1;;;;;17992:236:0;;:::i;40631:241::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;40631:241:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;40631:241:0;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;40631:241:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;40631:241:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;40631:241:0;;-1:-1:-1;40631:241:0;-1:-1:-1;40631:241:0;;:::i;12092:135::-;-1:-1:-1;;;;;;12186:33:0;;12162:4;12186:33;;;;;;;;;;;;;12092:135;;;;:::o;30062:23::-;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;30062:23:0;;-1:-1:-1;30062:23:0;:::o;45537:94::-;45617:8;45610:15;;;;;;;;-1:-1:-1;;45610:15:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;45585:13;;45610:15;;45617:8;;45610:15;;45617:8;45610:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;45537:94;;:::o;38219:138::-;38303:7;38329:22;38342:8;38329:12;:22::i;:::-;38322:29;38219:138;-1:-1:-1;;38219:138:0:o;37249:311::-;20820:7;;-1:-1:-1;;;20820:7:0;;;;20812:35;;;;;-1:-1:-1;;;20812:35:0;;;;;;;;;;;;-1:-1:-1;;;20812:35:0;;;;;;;;;;;;;;;37387:8;36862:32;36873:8;36883:10;36862;:32::i;:::-;:78;;;;36907:33;36919:8;36929:10;36907:11;:33::i;:::-;36862:138;;;;36953:47;36970:17;36978:8;36970:7;:17::i;:::-;36989:10;36953:16;:47::i;:::-;36846:192;;;;;-1:-1:-1;;;36846:192:0;;;;;;;;;;;;-1:-1:-1;;;36846:192:0;;;;;;;;;;;;;;;37415:10;-1:-1:-1;;;;;37415:23:0;;;;37407:48;;;;;-1:-1:-1;;;37407:48:0;;;;;;;;;;;;-1:-1:-1;;;37407:48:0;;;;;;;;;;;;;;;37464:18;;;;:8;:18;;;;;:30;;-1:-1:-1;;;;;;37464:30:0;-1:-1:-1;;;;;37464:30:0;;;;;;;;:18;;37515:17;37464:18;37515:7;:17::i;:::-;-1:-1:-1;;;;;37506:48:0;;;;;;;;;;;20854:1;37249:311;;:::o;28391:199::-;26348:7;:5;:7::i;:::-;-1:-1:-1;;;;;26334:21:0;:10;-1:-1:-1;;;;;26334:21:0;;:50;;;-1:-1:-1;26373:11:0;;-1:-1:-1;;;;;26373:11:0;26359:10;:25;26334:50;26318:114;;;;;-1:-1:-1;;;26318:114:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;28505:26:0;;28497:54;;;;;-1:-1:-1;;;28497:54:0;;;;;;;;;;;;-1:-1:-1;;;28497:54:0;;;;;;;;;;;;;;;28558:11;:26;;-1:-1:-1;;;;;;28558:26:0;-1:-1:-1;;;;;28558:26:0;;;;;;;;;;28391:199::o;59330:41::-;;;;:::o;59287:38::-;;;;:::o;25420:29::-;;;-1:-1:-1;;;;;25420:29:0;;:::o;32352:879::-;32477:6;:13;32441:16;;32469:49;;;;;-1:-1:-1;;;32469:49:0;;;;;;;;;;;;-1:-1:-1;;;32469:49:0;;;;;;;;;;;;;;;32656:6;:13;32541:9;;32576:16;;;;32525:13;;32631:22;;;:38;32627:202;;;-1:-1:-1;32697:6:0;:13;32730:27;;;;-1:-1:-1;32627:202:0;;;-1:-1:-1;32798:22:0;;;32627:202;32915:29;32961:8;32947:23;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;32947:23:0;-1:-1:-1;32915:55:0;-1:-1:-1;32977:14:0;33088:11;33074:124;33105:14;33101:1;:18;33074:124;;;33161:6;33168:1;33161:9;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;33161:9:0;33135:12;33148:9;33135:23;;;;;;;;-1:-1:-1;;;;;33135:35:0;;;:23;;;;;;;;;;;:35;33179:11;;;;;33121:3;33074:124;;;-1:-1:-1;33213:12:0;;32352:879;-1:-1:-1;;;;;;;32352:879:0:o;25795:20::-;;;;:::o;25637:30::-;;;;:::o;14281:147::-;-1:-1:-1;;;14281:147:0;;;;;;;:::o;28714:104::-;28796:16;;28714:104;:::o;28034:213::-;8941:9;:7;:9::i;:::-;8933:18;;;;;;20820:7;;-1:-1:-1;;;20820:7:0;;;;20812:35;;;;;-1:-1:-1;;;20812:35:0;;;;;;;;;;;;-1:-1:-1;;;20812:35:0;;;;;;;;;;;;;;;28159:8;;;28174:20;;;;28206:35;;;;;;;;;;;;;;;;;;;;;;;;;20854:1;28034:213;:::o;59909:85::-;59960:28;59977:10;59960:16;:28::i;:::-;59909:85::o;66538:1750::-;20820:7;;-1:-1:-1;;;20820:7:0;;;;20812:35;;;;;-1:-1:-1;;;20812:35:0;;;;;;;;;;;;-1:-1:-1;;;20812:35:0;;;;;;;;;;;;;;;66689:5;30438:22;30453:6;30438:14;:22::i;:::-;30422:62;;;;;-1:-1:-1;;;30422:62:0;;;;;;;;;;;;-1:-1:-1;;;30422:62:0;;;;;;;;;;;;;;;66724:8;36862:32;36873:8;36883:10;36862;:32::i;:::-;:78;;;;36907:33;36919:8;36929:10;36907:11;:33::i;:::-;36862:138;;;;36953:47;36970:17;36978:8;36970:7;:17::i;36953:47::-;36846:192;;;;;-1:-1:-1;;;36846:192:0;;;;;;;;;;;;-1:-1:-1;;;36846:192:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;66752:24:0;;66744:52;;;;;-1:-1:-1;;;66744:52:0;;;;;;;;;;;;-1:-1:-1;;;66744:52:0;;;;;;;;;;;;;;;66803:37;66818:21;66833:5;66818:14;:21::i;:::-;66803:14;:37::i;:::-;66849:19;66871:17;66882:5;66871:10;:17::i;:::-;66849:39;;66895:17;66915:22;66926:10;66915;:22::i;:::-;66972:25;;;;67010:13;;66895:42;;-1:-1:-1;66972:25:0;67006:120;;67055:15;;67039:31;;;67079:39;;67092:10;;67079:12;:39::i;:::-;67160:15;67138:18;:37;67134:764;;67441:27;;;;;67413:25;;;:55;67493:15;;67477:31;;67517:34;67530:10;67542:8;67517:12;:34::i;:::-;67134:764;;;67811:37;;;;:79;;67874:15;67853:36;;67811:79;:41;:79;:::i;:::-;67783:25;;;:107;67134:764;67996:15;67966:27;;;:45;68110:1;68092:19;;68157:24;68172:8;68157:14;:24::i;:::-;68267:8;68248:10;-1:-1:-1;;;;;68217:65:0;68234:5;-1:-1:-1;;;;;68217:65:0;;;;;;;;;;;37045:1;;;30491;20854;66538:1750;;;:::o;27405:517::-;26348:7;:5;:7::i;:::-;-1:-1:-1;;;;;26334:21:0;:10;-1:-1:-1;;;;;26334:21:0;;:50;;;-1:-1:-1;26373:11:0;;-1:-1:-1;;;;;26373:11:0;26359:10;:25;26334:50;26318:114;;;;;-1:-1:-1;;;26318:114:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;27494:12;27509:25;27528:4;27509:10;:25::i;:::-;27494:40;-1:-1:-1;27541:11:0;27562:12;;;:33;;;27588:7;27578;:17;27562:33;27559:174;;;27629:1;27619:7;:11;27611:40;;;;;-1:-1:-1;;;27611:40:0;;;;;;;;;;;;-1:-1:-1;;;27611:40:0;;;;;;;;;;;;;;;-1:-1:-1;27669:7:0;27559:174;;;-1:-1:-1;27718:7:0;27559:174;27769:11;;27746:43;;;;;;;;-1:-1:-1;;;;;27769:11:0;;;;27757:10;;27746:43;;;;;;;;;;27896:11;;27886:30;;-1:-1:-1;;;;;27896:11:0;27909:6;27886:9;:30::i;:::-;26439:1;;27405:517;:::o;46290:134::-;8941:9;:7;:9::i;:::-;8933:18;;;;;;46390:28;:12;46405:13;;46390:28;:::i;26075:26::-;;;-1:-1:-1;;;;;26075:26:0;;:::o;60942:491::-;8941:9;:7;:9::i;:::-;8933:18;;;;;;61095:30;61087:55;;;;;-1:-1:-1;;;61087:55:0;;;;;;;;;;;;-1:-1:-1;;;61087:55:0;;;;;;;;;;;;;;;61185:22;;61216:24;;61156:157;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;61320:22;:48;;;;61375:24;:52;60942:491::o;25983:28::-;;;;:::o;69844:463::-;8941:9;:7;:9::i;:::-;8933:18;;;;;;69991:28;69983:53;;;;;-1:-1:-1;;;69983:53:0;;;;;;;;;;;;-1:-1:-1;;;69983:53:0;;;;;;;;;;;;;;;70075:20;;70104:22;;70048:147;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;70202:20;:44;;;;70253:22;:48;69844:463::o;20553:19::-;;;-1:-1:-1;;;20553:19:0;;;;;:::o;68641:174::-;68767:42;68784:5;68791:3;68796:8;68767:42;;;;;;;;;;;;:16;:42::i;42204:820::-;42351:33;42396:16;42421:2;42396:28;;42431:16;42456:2;42431:28;;42466:16;42491:2;42466:28;;42501:16;42526:2;42501:28;;42536:18;42607:3;:10;42594:3;:10;42581:3;:10;42568:3;:10;:23;:36;:49;42557:61;;;;;;;;;;;;;;;;;;;;;;;;;21:6:-1;;104:10;42557:61:0;87:34:-1;135:17;;-1:-1;42557:61:0;-1:-1:-1;42536:82:0;-1:-1:-1;42536:82:0;42664:6;;42698:69;42714:3;:10;42710:1;:14;42698:69;;;42753:3;42757:1;42753:6;;;;;;;;;;;;;;;;42740:5;42746:3;;;;;;42740:10;;;;;;;;;;;:19;-1:-1:-1;;;;;42740:19:0;;;;;;;;-1:-1:-1;42726:3:0;;42698:69;;;-1:-1:-1;42782:1:0;42773:69;42789:3;:10;42785:1;:14;42773:69;;;42828:3;42832:1;42828:6;;;;;;;;;;;;;;;;42815:5;42821:3;;;;;;42815:10;;;;;;;;;;;:19;-1:-1:-1;;;;;42815:19:0;;;;;;;;-1:-1:-1;42801:3:0;;42773:69;;;-1:-1:-1;42857:1:0;42848:69;42864:3;:10;42860:1;:14;42848:69;;;42903:3;42907:1;42903:6;;;;;;;;;;;;;;;;42890:5;42896:3;;;;;;42890:10;;;;;;;;;;;:19;-1:-1:-1;;;;;42890:19:0;;;;;;;;-1:-1:-1;42876:3:0;;42848:69;;;-1:-1:-1;42932:1:0;42923:69;42939:3;:10;42935:1;:14;42923:69;;;42978:3;42982:1;42978:6;;;;;;;;;;;;;;;;42965:5;42971:3;;;;;;42965:10;;;;;;;;;;;:19;-1:-1:-1;;;;;42965:19:0;;;;;;;;-1:-1:-1;42951:3:0;;42923:69;;;-1:-1:-1;43012:5:0;;42204:820;-1:-1:-1;;;;;;;;;;;42204:820:0:o;59435:47::-;;;;;;;;;;;;;:::o;43030:516::-;43098:27;43220:2;43233:7;43229:40;;-1:-1:-1;;43251:10:0;;;;;;;;;;;;-1:-1:-1;;;43251:10:0;;;;;;43229:40;43284:2;43275:6;43308:53;43315:6;;43308:53;;43332:5;;43351:2;43346:7;;;;43308:53;;;43367:17;43397:3;43387:14;;;;;;;;;;;;;;;;;;;;;;;;;21:6:-1;;104:10;43387:14:0;87:34:-1;135:17;;-1:-1;43387:14:0;-1:-1:-1;43367:34:0;-1:-1:-1;;;43417:7:0;;43431:84;43438:6;;43431:84;;43487:2;43483:1;:6;43478:2;:11;43467:24;;43455:4;43460:3;;;;;;;43455:9;;;;;;;;;;;:36;-1:-1:-1;;;;;43455:36:0;;;;;;;;-1:-1:-1;43505:2:0;43500:7;;;;43431:84;;;-1:-1:-1;43535:4:0;43030:516;-1:-1:-1;;;;;43030:516:0:o;61719:163::-;61814:11;61844:32;61869:6;61844:24;:32::i;45313:121::-;8941:9;:7;:9::i;:::-;8933:18;;;;;;45408:20;:8;45419:9;;45408:20;:::i;43552:457::-;43699:42;;;;;;;;;;;-1:-1:-1;;;43699:42:0;;;;43767:13;;43777:2;43767:13;;;43628;43767;;;;;;-1:-1:-1;;;;;43677:14:0;;;43699:42;43628:13;;43767;;;21:6:-1;;104:10;43767:13:0;87:34:-1;135:17;;-1:-1;43767:13:0;43748:32;;-1:-1:-1;;;43787:3:0;43791:1;43787:6;;;;;;;;;;;:12;-1:-1:-1;;;;;43787:12:0;;;;;;;;;-1:-1:-1;;;43806:3:0;43810:1;43806:6;;;;;;;;;;;:12;-1:-1:-1;;;;;43806:12:0;;;;;;;;-1:-1:-1;43830:6:0;43825:154;43846:2;43842:1;:6;43825:154;;;43877:8;43909:1;43892:5;43898:1;43902:2;43898:6;43892:13;;;;;;;;;;-1:-1:-1;;;;;43892:18:0;;;;43886:25;;43877:35;;;;;;;;;;;;;;;;;;43864:3;43870:1;43872;43870:3;43868:1;:5;43864:10;;;;;;;;;;;:48;-1:-1:-1;;;;;43864:48:0;;;;;;;;;43934:8;43949:5;43955:1;43959:2;43955:6;43949:13;;;;;;;43934:37;;43949:13;;;43965:4;43943:27;;43934:37;;;;;;;;;;;;;;43921:3;43927:1;43929;43927:3;43925:1;:5;43921:10;;;;;;;;;;;:50;-1:-1:-1;;;;;43921:50:0;;;;;;;;-1:-1:-1;43850:3:0;;43825:154;;;-1:-1:-1;43999:3:0;43552:457;-1:-1:-1;;;;43552:457:0:o;60786:84::-;60851:10;60835:27;;;;:15;:27;;;;;:29;;;;;;60786:84::o;34217:150::-;34311:7;30605:24;;;:14;:24;;;;;;34287:8;;-1:-1:-1;;;;;30605:24:0;30589:76;;;;;-1:-1:-1;;;30589:76:0;;;;;;;;;;;;-1:-1:-1;;;30589:76:0;;;;;;;;;;;;;;;-1:-1:-1;;34337:24:0;;;;:14;:24;;;;;;-1:-1:-1;;;;;34337:24:0;;34217:150::o;31653:171::-;-1:-1:-1;;;;;31762:18:0;31739:4;31762:18;;;:10;:18;;;;;:38;;;31803:15;-1:-1:-1;;31653:171:0:o;31388:197::-;31471:4;-1:-1:-1;;;;;31495:20:0;;31487:48;;;;;-1:-1:-1;;;31487:48:0;;;;;;;;;;;;-1:-1:-1;;;31487:48:0;;;;;;;;;;;;;;;31549:22;31564:6;31549:14;:22::i;:::-;:30;;31578:1;31549:30;;;31574:1;31549:30;31542:37;;;31388:197;-1:-1:-1;;31388:197:0:o;52435:209::-;20820:7;;-1:-1:-1;;;20820:7:0;;;;20812:35;;;;;-1:-1:-1;;;20812:35:0;;;;;;;;;;;;-1:-1:-1;;;20812:35:0;;;;;;;;;;;;;;;52575:9;30438:22;30453:6;30438:14;:22::i;:::-;30422:62;;;;;-1:-1:-1;;;30422:62:0;;;;;;;;;;;;-1:-1:-1;;;30422:62:0;;;;;;;;;;;;;;;52603:35;52616:10;52628:9;52603:12;:35::i;9442:140::-;8941:9;:7;:9::i;:::-;8933:18;;;;;;9525:6;;9504:40;;9541:1;;-1:-1:-1;;;;;9525:6:0;;9504:40;;9541:1;;9504:40;9555:6;:19;;-1:-1:-1;;;;;;9555:19:0;;;9442:140::o;25889:27::-;;;;:::o;45713:167::-;8941:9;:7;:9::i;:::-;8933:18;;;;;;45812:24;:10;45825:11;;45812:24;:::i;:::-;;45848:26;45862:11;;45848:26;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;;74:27;45848:26:0;;137:4:-1;117:14;;;-1:-1;;113:30;157:16;;;45848:26:0;;;;-1:-1:-1;45848:26:0;;-1:-1:-1;;;;45848:26:0;45713:167;;:::o;41032:257::-;8941:9;:7;:9::i;:::-;8933:18;;;;;;41175:6;41171:113;41187:22;;;41171:113;;;41225:51;41235:11;;41247:1;41235:14;;;;;;;;;;;;;-1:-1:-1;;;;;41235:14:0;41251:21;;41273:1;41251:24;;;;;;;;;;;;;41225:9;:51::i;:::-;41211:3;;41171:113;;;;41032:257;;;;:::o;70572:727::-;70678:4;70656:6;30438:22;30453:6;30438:14;:22::i;:::-;30422:62;;;;;-1:-1:-1;;;30422:62:0;;;;;;;;;;;;-1:-1:-1;;;30422:62:0;;;;;;;;;;;;;;;70694:15;70712:18;70723:6;70712:10;:18::i;:::-;70694:36;;70830:18;70877:15;70851:3;:23;;;:41;70830:62;;70899:8;70934:18;;70917:13;:35;70914:312;;-1:-1:-1;71055:8:0;;70914:312;;;71200:18;;71170:8;;:27;;71183:13;71170:27;:12;:27;:::i;:::-;:48;;;;;;71164:54;;70914:312;71271:22;;71247:20;;71239:29;;:3;;:29;:7;:29;:::i;:::-;:54;;;;;;;70572:727;-1:-1:-1;;;;;;70572:727:0:o;61995:456::-;-1:-1:-1;;;;;62318:26:0;;;;62114:20;62318:26;;;:15;:26;;;;;;;;;;62171:267;;62252:4;62171:267;;;;;;;;;;;;;;;;;;-1:-1:-1;;62171:267:0;;;;;;;26:21:-1;;;22:32;;6:49;;62171:267:0;;;;;;;62153:292;;;;;;61995:456::o;8729:79::-;8794:6;;-1:-1:-1;;;;;8794:6:0;8729:79;:::o;9064:92::-;9142:6;;-1:-1:-1;;;;;9142:6:0;9128:10;:20;;9064:92::o;66310:36::-;;;;:::o;33982:104::-;34067:6;:13;33982:104;:::o;45985:215::-;46069:10;46063:24;46035:13;;46063:24;-1:-1:-1;;46063:24:0;;;;;;;;;;;46060:135;;46110:14;;;;;;;;;-1:-1:-1;;;;;46110:14:0;-1:-1:-1;;;;;46110:35:0;;:37;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;46110:37:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;46110:37:0;;;;;;39:16:-1;36:1;17:17;2:54;101:4;46110:37:0;80:15:-1;;;-1:-1;;76:31;65:43;;120:4;113:20;13:2;5:11;;2:2;;;29:1;26;19:12;2:2;46110:37:0;;;;;;-1:-1:-1;;;14:3;11:20;8:2;;;44:1;41;34:12;8:2;62:21;;123:4;114:14;;138:31;;;135:2;;;182:1;179;172:12;135:2;213:10;;-1:-1;;;244:29;;285:43;;;282:58;-1:-1;233:115;230:2;;;361:1;358;351:12;230:2;-1:-1;46110:37:0;;-1:-1:-1;46103:44:0;;-1:-1:-1;;;;46103:44:0;46060:135;46177:10;46170:17;;;;;;;;;;;;;-1:-1:-1;;46170:17:0;;;;;;;;;;;;;;;;;;;;;;;;;;;46177:10;46170:17;;46177:10;46170:17;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;31941:173;32057:4;32033:8;30438:22;30453:6;30438:14;:22::i;:::-;30422:62;;;;;-1:-1:-1;;;30422:62:0;;;;;;;;;;;;-1:-1:-1;;;30422:62:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;32080:20:0;;;;;:10;:20;;;;;:28;;31941:173::o;33309:155::-;33401:4;33424:24;;;:14;:24;;;;;;;-1:-1:-1;;;;;33424:34:0;;;:24;;:34;;33309:155::o;40314:163::-;8941:9;:7;:9::i;:::-;8933:18;;;;;;40428:43;40438:10;40450:20;40428:9;:43::i;:::-;40314:163;;:::o;17662:27::-;;;-1:-1:-1;;;;;17662:27:0;;:::o;30959:266::-;8941:9;:7;:9::i;:::-;8933:18;;;;;;31051:6;30438:22;30453:6;30438:14;:22::i;:::-;30422:62;;;;;-1:-1:-1;;;30422:62:0;;;;;;;;;;;;-1:-1:-1;;;30422:62:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;31087:18:0;;31069:15;31087:18;;;:10;:18;;;;;;;;;31138:15;31112:23;;;:41;31207:11;;31197:22;;;;;;;31087:18;;31197:22;;;;;;;;;30491:1;8962;30959:266;:::o;37848:268::-;20820:7;;-1:-1:-1;;;20820:7:0;;;;20812:35;;;;;-1:-1:-1;;;20812:35:0;;;;;;;;;;;;-1:-1:-1;;;20812:35:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;37963:17:0;;37970:10;37963:17;;37955:42;;;;;-1:-1:-1;;;37955:42:0;;;;;;;;;;;;-1:-1:-1;;;37955:42:0;;;;;;;;;;;;;;;38028:10;38004:35;;;;:23;:35;;;;;;;;-1:-1:-1;;;;;38004:40:0;;;;;;;;;;;;:52;;-1:-1:-1;;38004:52:0;;;;;;;;;;38068:42;;;;;;;38004:40;;38028:10;38068:42;;;;;;;;;;;37848:268;;:::o;21223:500::-;8941:9;:7;:9::i;:::-;8933:18;;;;;;21293:7;;-1:-1:-1;;;21293:7:0;;;;:16;21285:42;;;;;-1:-1:-1;;;21285:42:0;;;;;;;;;;;;-1:-1:-1;;;21285:42:0;;;;;;;;;;;;;;;21341;;;21357:4;21349:21;21341:42;;;;21372:10;;21341:42;;;;;;;;;;21462:48;21472:10;21484:25;21503:4;21484:10;:25::i;:::-;21462:9;:48::i;:::-;21530:10;21517:24;33622:200;-1:-1:-1;;;;;30232:18:0;;33745:14;30232:18;;;:10;:18;;;;;:38;;;33723:6;;30216:88;;;;;-1:-1:-1;;;30216:88:0;;;;;;;;;;;;-1:-1:-1;;;30216:88:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;33778:18:0;;;;;:10;:18;;;;;:38;;;;33622:200::o;69387:382::-;20820:7;;-1:-1:-1;;;20820:7:0;;;;20812:35;;;;;-1:-1:-1;;;20812:35:0;;;;;;;;;;;;-1:-1:-1;;;20812:35:0;;;;;;;;;;;;;;;69571:8;36862:32;36873:8;36883:10;36862;:32::i;:::-;:78;;;;36907:33;36919:8;36929:10;36907:11;:33::i;:::-;36862:138;;;;36953:47;36970:17;36978:8;36970:7;:17::i;36953:47::-;36846:192;;;;;-1:-1:-1;;;36846:192:0;;;;;;;;;;;;-1:-1:-1;;;36846:192:0;;;;;;;;;;;;;;;69598:17;69606:8;69598:7;:17::i;:::-;30438:22;30453:6;30438:14;:22::i;:::-;30422:62;;;;;-1:-1:-1;;;30422:62:0;;;;;;;;;;;;-1:-1:-1;;;30422:62:0;;;;;;;;;;;;;;;69627:34;69640:5;69647:3;69652:8;69627:12;:34::i;:::-;69676:51;69699:5;69706:3;69711:8;69721:5;69676:22;:51::i;:::-;69668:93;;;;;-1:-1:-1;;;69668:93:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;37045:1;20854;69387:382;;;;:::o;60239:401::-;60526:9;-1:-1:-1;;;;;60363:172:0;:159;60387:105;60428:53;60459:9;60470:10;60428:30;:53::i;:::-;60387:28;:105::i;:::-;60503:10;;60363:159;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;60363:13:0;;-1:-1:-1;;;60363:159:0:i;:::-;-1:-1:-1;;;;;60363:172:0;;60347:216;;;;;-1:-1:-1;;;60347:216:0;;;;;;;;;;;;-1:-1:-1;;;60347:216:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;60572:26:0;;;;;;:15;:26;;;;;:28;;;;;;60607:27;60588:9;60607:16;:27::i;20961:121::-;8941:9;:7;:9::i;:::-;8933:18;;;;;;20820:7;;-1:-1:-1;;;20820:7:0;;;;20812:35;;;;;-1:-1:-1;;;20812:35:0;;;;;;;;;;;;-1:-1:-1;;;20812:35:0;;;;;;;;;;;;;;;21045:9;;;;;;;21061:7;:15;;-1:-1:-1;;;;21061:15:0;;;20961:121::o;8516:145::-;6947:12;;;;;;;;:31;;;6963:15;:13;:15::i;:::-;6947:47;;;-1:-1:-1;6983:11:0;;;;6982:12;6947:47;6939:106;;;;-1:-1:-1;;;6939:106:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7077:12;;;;;;;7076:13;7096:83;;;;7140:4;7125:19;;-1:-1:-1;;;;7125:19:0;;;;;7153:18;;;;;7096:83;8582:6;:15;;-1:-1:-1;;;;;;8582:15:0;-1:-1:-1;;;;;8582:15:0;;;;;;;;;;;8613:40;;8646:6;;;-1:-1:-1;;8613:40:0;;-1:-1:-1;;8613:40:0;7201:14;7197:57;;;7226:12;:20;;-1:-1:-1;;7226:20:0;;;8516:145;;:::o;46765:445::-;30641:1;30605:24;;;:14;:24;;;;;;46864:13;;46841:8;;-1:-1:-1;;;;;30605:24:0;30589:76;;;;;-1:-1:-1;;;30589:76:0;;;;;;;;;;;;-1:-1:-1;;;30589:76:0;;;;;;;;;;;;;;;46922:12;46916:26;46889:17;;46916:26;-1:-1:-1;;46916:26:0;;;;;;;;;;;46913:138;;46964:14;;;;;;;;;-1:-1:-1;;;;;46964:14:0;-1:-1:-1;;;;;46964:36:0;;:38;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;46964:38:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;46964:38:0;;;;;;39:16:-1;36:1;17:17;2:54;101:4;46964:38:0;80:15:-1;;;-1:-1;;76:31;65:43;;120:4;113:20;13:2;5:11;;2:2;;;29:1;26;19:12;2:2;46964:38:0;;;;;;-1:-1:-1;;;14:3;11:20;8:2;;;44:1;41;34:12;8:2;62:21;;123:4;114:14;;138:31;;;135:2;;;182:1;179;172:12;135:2;213:10;;-1:-1;;;244:29;;285:43;;;282:58;-1:-1;233:115;230:2;;;361:1;358;351:12;230:2;-1:-1;46964:38:0;;-1:-1:-1;46913:138:0;;-1:-1:-1;;;;46913:138:0;;47031:12;47025:18;;;;;;;;;;;;;-1:-1:-1;;47025:18:0;;;;;;;;;;;;;;;;;;;;;;;;;;;47031:12;47025:18;;47031:12;47025:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;46913:138;47066;47096:3;47108:38;47140:4;47108:23;:38::i;:::-;47066:138;;;;;;;;;;;;;-1:-1:-1;;;47066:138:0;;;47167:30;47188:8;47167:20;:30::i;:::-;47066:21;:138::i;73592:93::-;73678:1;73592:93;:::o;66351:40::-;;;;:::o;38674:173::-;-1:-1:-1;;;;;38799:31:0;;;38776:4;38799:31;;;:23;:31;;;;;;;;:42;;;;;;;;;;;;;;;38674:173::o;9759:109::-;8941:9;:7;:9::i;:::-;8933:18;;;;;;9832:28;9851:8;9832:18;:28::i;:::-;9759:109;:::o;52071:154::-;20820:7;;-1:-1:-1;;;20820:7:0;;;;20812:35;;;;;-1:-1:-1;;;20812:35:0;;;;;;;;;;;;-1:-1:-1;;;20812:35:0;;;;;;;;;;;;;;;52183:36;52196:10;52216:1;52183:12;:36::i;17992:236::-;18085:12;;18066:4;;-1:-1:-1;;;;;18085:12:0;18082:141;;-1:-1:-1;;;;;;18129:16:0;;;18122:23;;18082:141;18182:12;;18175:40;;;-1:-1:-1;;;18175:40:0;;-1:-1:-1;;;;;18175:40:0;;;;;;;;;18182:12;;;;;18175:30;;:40;;;;;;;;;;;;;;18182:12;18175:40;;;5:2:-1;;;;30:1;27;20:12;5:2;18175:40:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;18175:40:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;18175:40:0;;-1:-1:-1;18168:47:0;;40631:241;8941:9;:7;:9::i;:::-;8933:18;;;;;;40762:6;40758:109;40774:22;;;40758:109;;;40812:47;40822:11;;40834:1;40822:14;;;;;;;;;;;;;-1:-1:-1;;;;;40822:14:0;40838:20;40812:9;:47::i;:::-;40798:3;;40758:109;;;;40631:241;;;:::o;39264:251::-;39349:7;39396:18;;;:8;:18;;;;;;-1:-1:-1;;;;;39396:18:0;39429:31;39421:57;;;;;-1:-1:-1;;;39421:57:0;;;;;;;;;;;;-1:-1:-1;;;39421:57:0;;;;;;;;;;;;;;38940:150;39034:4;39057:18;;;:8;:18;;;;;;;-1:-1:-1;;;;;39057:27:0;;;:18;;:27;;38940:150::o;62561:594::-;62635:15;62653:21;62664:9;62653:10;:21::i;:::-;62635:39;;62683:11;62697:35;62722:9;62697:24;:35::i;:::-;62756:11;;62746:53;;;;;;;;62683:49;;-1:-1:-1;62780:10:0;;-1:-1:-1;;;;;62746:53:0;;;62756:11;62746:53;;;;;;;;;;62998:15;62972:23;;;:41;63026:10;;63022:128;;63113:29;63123:10;63135:6;63113:9;:29::i;18535:684::-;18604:10;;18601:613;;18628:12;;-1:-1:-1;;;;;18628:12:0;18625:582;;18688:6;18675:9;:19;;18667:48;;;;;-1:-1:-1;;;18667:48:0;;;;;;;;;;;;-1:-1:-1;;;18667:48:0;;;;;;;;;;;;;;;18625:582;;;18764:12;;18809:30;;;-1:-1:-1;;;18809:30:0;;18833:4;18809:30;;;;;;-1:-1:-1;;;;;18764:12:0;;;;18742;;18764;;18809:15;;:30;;;;;;;;;;;;;;;18764:12;18809:30;;;5:2:-1;;;;30:1;27;20:12;5:2;18809:30:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;18809:30:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;18809:30:0;18850:53;;;-1:-1:-1;;;18850:53:0;;18869:10;18850:53;;;;18889:4;18850:53;;;;;;;;;;;;18809:30;;-1:-1:-1;;;;;;18850:18:0;;;;;:53;;;;;18809:30;;18850:53;;;;;;;;-1:-1:-1;18850:18:0;:53;;;5:2:-1;;;;30:1;27;20:12;5:2;18850:53:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;18850:53:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;19131:30:0;;;-1:-1:-1;;;19131:30:0;;19155:4;19131:30;;;;;;19164:13;;-1:-1:-1;;;;;19131:15:0;;;;;:30;;;;;18850:53;;19131:30;;;;;;;;:15;:30;;;5:2:-1;;;;30:1;27;20:12;5:2;19131:30:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;19131:30:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;19131:30:0;:46;19123:74;;;;;-1:-1:-1;;;19123:74:0;;;;;;;;;;;;-1:-1:-1;;;19123:74:0;;;;;;;;;;;;;;35332:128;-1:-1:-1;;;;;35436:18:0;35406:11;35436:18;;;:10;:18;;;;;;35332:128::o;34954:308::-;35045:24;;;;:14;:24;;;;;;-1:-1:-1;;;;;35045:34:0;;;:24;;:34;35041:216;;35141:6;27:10:-1;;39:1;23:18;;45:23;;;35141:19:0;;;;-1:-1:-1;;;;;35141:19:0;;-1:-1:-1;;;;;;35141:19:0;;;;;;;;-1:-1:-1;35216:24:0;;;:14;35141:19;35216:24;;;;:33;;;;;;;;;;34954:308;;:::o;48698:181::-;48756:7;48788:5;;;48812:6;;;;48804:46;;;;;-1:-1:-1;;;48804:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;48870:1;48698:181;-1:-1:-1;;;48698:181:0:o;39665:162::-;39770:1;39740:18;;;:8;:18;;;;;;-1:-1:-1;;;;;39740:18:0;:32;39736:86;;39812:1;39783:18;;;:8;:18;;;;;:31;;-1:-1:-1;;;;;;39783:31:0;;;39665:162::o;19377:645::-;19460:11;;19457:560;;19485:12;;-1:-1:-1;;;;;19485:12:0;19482:528;;19524:39;;-1:-1:-1;;;;;19524:30:0;;;:39;;;;;19555:7;;19524:39;;;;19555:7;19524:30;:39;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;19524:39:0;19482:528;;;19612:12;;19657:20;;;-1:-1:-1;;;19657:20:0;;-1:-1:-1;;;;;19657:20:0;;;;;;;;;19612:12;;;;;19590;;19612;;19657:15;;:20;;;;;;;;;;;;;;19612:12;19657:20;;;5:2:-1;;;;30:1;27;20:12;5:2;19657:20:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;19657:20:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;19657:20:0;19688:28;;;-1:-1:-1;;;19688:28:0;;-1:-1:-1;;;;;19688:28:0;;;;;;;;;;;;;;;19657:20;;-1:-1:-1;19688:14:0;;;;;;:28;;;;;19657:20;;19688:28;;;;;;;;-1:-1:-1;19688:14:0;:28;;;5:2:-1;;;;30:1;27;20:12;5:2;19688:28:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;19688:28:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;19944:20:0;;;-1:-1:-1;;;19944:20:0;;-1:-1:-1;;;;;19944:20:0;;;;;;;;;19967:13;;19944:15;;;;;:20;;;;;19688:28;;19944:20;;;;;;;:15;:20;;;5:2:-1;;;;30:1;27;20:12;5:2;19944:20:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;19944:20:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;19944:20:0;:36;19936:64;;;;;-1:-1:-1;;;19936:64:0;;;;;;;;;;;;-1:-1:-1;;;19936:64:0;;;;;;;;;;;;;;63357:845;63474:11;63452:6;30438:22;30453:6;30438:14;:22::i;:::-;30422:62;;;;;-1:-1:-1;;;30422:62:0;;;;;;;;;;;;-1:-1:-1;;;30422:62:0;;;;;;;;;;;;;;;63497:15;63515:18;63526:6;63515:10;:18::i;:::-;63497:36;;63633:18;63680:15;63654:3;:23;;;:41;63633:62;;63722:18;;63705:13;:35;63702:232;;63760:8;;63751:17;;63702:232;;;63908:18;;63878:8;;:27;;63891:13;63878:27;:12;:27;:::i;:::-;:48;;;;;;63869:57;;63702:232;63940:12;63994:24;;63955:36;63968:22;;63955:8;;:12;;:36;;;;:::i;:::-;:63;;;;;;63940:78;;64038:7;64029:6;:16;64025:172;;;64149:7;64139:17;;;;64025:172;;;64188:1;64179:10;;64025:172;30491:1;;;63357:845;;;;:::o;53160:1928::-;26220:16;;26202:15;;:34;26194:60;;;;;-1:-1:-1;;;26194:60:0;;;;;;;;;;;;-1:-1:-1;;;26194:60:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;53328:24:0;;53320:52;;;;;-1:-1:-1;;;53320:52:0;;;;;;;;;;;;-1:-1:-1;;;53320:52:0;;;;;;;;;;;;;;;53521:8;;53557:14;;:72;;;-1:-1:-1;;;53557:72:0;;-1:-1:-1;;;;;53557:72:0;;;;;;;;;;;;;;;53459:13;;;;53521:8;;53557:14;;;:42;;:72;;;;;;;;;;;;:14;:72;;;5:2:-1;;;;30:1;27;20:12;5:2;53557:72:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;53557:72:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;53557:72:0;;;;;;;;;-1:-1:-1;53557:72:0;-1:-1:-1;53652:16:0;53679:27;;;53675:239;;;-1:-1:-1;53728:1:0;53675:239;;;-1:-1:-1;53879:27:0;;;53675:239;53945:17;53965:22;53976:10;53965;:22::i;:::-;54000:13;;53945:42;;-1:-1:-1;53996:186:0;;54102:24;54120:5;54102:17;:24::i;:::-;54135:39;54148:10;54160:5;:13;;;54135:12;:39::i;:::-;54223:15;54194:5;:25;;;:44;54190:427;;54370:18;;54340:25;;;;:49;;;:29;:49;:::i;:::-;54312:25;;;:77;54190:427;;;54591:18;;54573:15;:36;54545:25;;;:64;54190:427;54629:12;;54625:90;;54652:14;;:55;;;-1:-1:-1;;;54652:55:0;;;;;;;;;;;;;;;;-1:-1:-1;;;;;54652:14:0;;;;:37;;:55;;;;;:14;;:55;;;;;;;;:14;;:55;;;5:2:-1;;;;30:1;27;20:12;5:2;54652:55:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;54652:55:0;;;;54625:90;54723:14;;:53;;;-1:-1:-1;;;54723:53:0;;;;;;;;-1:-1:-1;;;;;54723:53:0;;;;;;;;;:14;;;;;:32;;:53;;;;;:14;;:53;;;;;;;:14;;:53;;;5:2:-1;;;;30:1;27;20:12;5:2;54723:53:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;54890:16:0;;54812:101;;54890:16;;-1:-1:-1;;;;;;54812:101:0;;;-1:-1:-1;54837:1:0;;54812:101;;54837:1;;54812:101;55058:24;55073:8;55058:14;:24::i;:::-;26261:1;;;;;53160:1928;;:::o;41344:560::-;-1:-1:-1;;;;;41451:24:0;;41443:52;;;;;-1:-1:-1;;;41443:52:0;;;;;;;;;;;;-1:-1:-1;;;41443:52:0;;;;;;;;;;;;;;;41504:17;41524:22;41535:10;41524;:22::i;:::-;41504:42;;41584:5;:25;;;41561:20;:48;41553:77;;;;;-1:-1:-1;;;41553:77:0;;;;;;;;;;;;-1:-1:-1;;;41553:77:0;;;;;;;;;;;;;;;41639:24;41657:5;41639:17;:24::i;:::-;41670:39;41683:10;41695:5;:13;;;41670:12;:39::i;:::-;41716:25;;;:48;;;41878:13;;41800:98;;-1:-1:-1;;;;;41800:98:0;;;41878:13;;41800:98;;41878:13;;41800:98;41344:560;;;:::o;49589:470::-;49647:7;49891:6;49887:47;;-1:-1:-1;49921:1:0;49914:8;;49887:47;49958:5;;;49962:1;49958;:5;:1;49982:5;;;;;:10;49974:56;;;;-1:-1:-1;;;49974:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;71813:362;71961:4;71982:15;:2;-1:-1:-1;;;;;71982:13:0;;:15::i;:::-;71977:50;;-1:-1:-1;72015:4:0;72008:11;;71977:50;72049:78;;-1:-1:-1;;;72049:78:0;;72094:10;72049:78;;;;;;-1:-1:-1;;;;;72049:78:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;72033:13;;72049:36;;;;;;72094:10;;72106:4;;72112:7;;72121:5;;72049:78;;;;;;;;;;;72033:13;8:100:-1;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;72049:78:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;72049:78:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;72049:78:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;72049:78:0;-1:-1:-1;;;;;;72142:26:0;-1:-1:-1;;;72142:26:0;;-1:-1:-1;;71813:362:0;;;;;;:::o;58624:269::-;58826:58;;;;;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;58826:58:0;;;;;;;58816:69;;;;;;58624:269::o;56418:1930::-;56496:7;56559:9;:16;56579:2;56559:22;56555:74;;-1:-1:-1;56614:1:0;56598:19;;56555:74;56990:4;56975:20;;56969:27;57036:4;57021:20;;57015:27;57090:4;57075:20;;57069:27;56698:9;57061:36;58020:66;58007:79;;58003:129;;;58118:1;58103:17;;;;;;;58003:129;58148:1;:7;;58153:2;58148:7;;:18;;;;;58159:1;:7;;58164:2;58159:7;;58148:18;58144:68;;;58198:1;58183:17;;;;;;;58144:68;58316:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;58316:24:0;;;;;;;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;58316:24:0;;-1:-1:-1;;58316:24:0;;;56418:1930;-1:-1:-1;;;;;;;56418:1930:0:o;7348:476::-;7788:7;7776:20;7811:7;7348:476;:::o;10018:187::-;-1:-1:-1;;;;;10092:22:0;;10084:31;;;;;;10152:6;;10131:38;;-1:-1:-1;;;;;10131:38:0;;;;10152:6;;10131:38;;10152:6;;10131:38;10180:6;:17;;-1:-1:-1;;;;;;10180:17:0;-1:-1:-1;;;;;10180:17:0;;;;;;;;;;10018:187::o;34495:396::-;34573:12;;34569:317;;34734:16;:18;;;;;;;;34847:31;;34495:396::o;64829:422::-;65196:20;65235:8;;;64829:422::o;72624:1064::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;72624:1064:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;72624:1064:0;;;-1:-1:-1;72624:1064:0;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;
Swarm Source
bzzr://47f15e51181351647a87d6980e0f8f20a1f88485a060e1fd9ce02eb8828eb7b4
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.