Address Details
contract
0xe4D89845A4128bf3cD8f0b9C6939F80aAfA37488
- Contract Name
- CyberBoxMarketPlace
- Creator
- 0xd0841b–1b7705 at 0xfd0075–b57af9
- Balance
- 0 CELO ( )
- Locked CELO Balance
- 0.00 CELO
- Voting CELO Balance
- 0.00 CELO
- Pending Unlocked Gold
- 0.00 CELO
- Tokens
-
Fetching tokens...
- Transactions
- Fetching transactions...
- Transfers
- Fetching transfers...
- Gas Used
- Fetching gas used...
- Last Balance Update
- 8403350
This contract has been verified via Sourcify.
View contract in Sourcify repository
- Contract name:
- CyberBoxMarketPlace
- Optimization enabled
- false
- Compiler version
- v0.8.0+commit.c7dfd78e
- EVM Version
- istanbul
- Verified at
- 2022-08-19T06:08:19.594724Z
contracts/MarketPlaceAPI.sol
pragma solidity 0.8.0; pragma experimental ABIEncoderV2; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/utils/math/SafeMath.sol"; import "@openzeppelin/contracts/utils/Address.sol"; import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "./Interface.sol"; /** * @title NFTKEY MarketPlace contract V1 * Note: This marketplace contract is collection based. It serves one ERC721 contract only * Payment tokens usually is the chain native coin's wrapped token, e.g. WETH, WBNB */ contract CyberBoxMarketPlace is Interface, Ownable, ReentrancyGuard { using SafeMath for uint256; using Address for address; using EnumerableSet for EnumerableSet.UintSet; using EnumerableSet for EnumerableSet.AddressSet; address public dev; // developer address struct TokenBid { EnumerableSet.AddressSet bidders; mapping(address => Bid) bids; } modifier onlyDev() { require(msg.sender == dev, "auction: wrong developer"); _; } constructor( string memory erc721Name_, address _erc721Address, address _paymentTokenAddress, address _devAddress, address _ownerAddress ) public { _erc721Name = erc721Name_; _erc721 = IERC721(_erc721Address); _paymentToken = IERC20(_paymentTokenAddress); dev = _devAddress; maketPlaceFeeAddress = _ownerAddress; } string private _erc721Name; IERC721 private _erc721; IERC20 private immutable _paymentToken; bool private _isListingAndBidEnabled = true; uint256 public _feeTokenSeller = 975; uint256 public _feeTokenCreater = 0; uint256 public _feeTokenDev = 25; uint256 private _feeFraction = 25; uint256 private _feeTokenBase = 1000; uint256 private _actionTimeOutRangeMin = 86400; // 24 hours uint256 private _actionTimeOutRangeMax = 31536000; // One year - This can extend by owner is contract is working smoothly mapping(uint256 => Listing) private _tokenListings; EnumerableSet.UintSet private _tokenIdWithListing; mapping(uint256 => TokenBid) private _tokenBids; EnumerableSet.UintSet private _tokenIdWithBid; address public tokenCreaterAddress; address public maketPlaceFeeAddress; // uint8 public partnerSharePercentage = 0; // bool public hasSharePercentageProposal; // uint8 public partnerSharePercentageProposal; EnumerableSet.AddressSet private _emptyBidders; // Help initiate TokenBid struct uint256[] private _tempTokenIdStorage; // Storage to assist cleaning address[] private _tempBidderStorage; // Storage to assist cleaning bids /** * @dev only if listing and bid is enabled * This is to help contract migration in case of upgrade or bug */ modifier onlyMarketplaceOpen() { require(_isListingAndBidEnabled, "Listing and bid are not enabled"); _; } /** * @dev only if the entered timestamp is within the allowed range * This helps to not list or bid for too short or too long period of time */ modifier onlyAllowedExpireTimestamp(uint256 expireTimestamp) { require( expireTimestamp.sub(block.timestamp) >= _actionTimeOutRangeMin, "Please enter a longer period of time" ); require( expireTimestamp.sub(block.timestamp) <= _actionTimeOutRangeMax, "Please enter a shorter period of time" ); _; } /** * @dev check if the account is the owner of this erc721 token */ function _isTokenOwner(uint256 tokenId, address account) private view returns (bool) { try _erc721.ownerOf(tokenId) returns (address tokenOwner) { return tokenOwner == account; } catch { return false; } } /** * @dev check if this contract has approved to transfer this erc721 token */ function _isTokenApproved(uint256 tokenId) private view returns (bool) { try _erc721.getApproved(tokenId) returns (address tokenOperator) { return tokenOperator == address(this); } catch { return false; } } /** * @dev check if this contract has approved to all of this owner's erc721 tokens */ function _isAllTokenApproved(address owner) private view returns (bool) { return _erc721.isApprovedForAll(owner, address(this)); } /** * @dev See {INFTKEYMarketPlaceV1-tokenAddress}. */ function tokenAddress() external view override returns (address) { return address(_erc721); } /** * @dev See {INFTKEYMarketPlaceV1-paymentTokenAddress}. */ function paymentTokenAddress() external view override returns (address) { return address(_paymentToken); } /** * @dev Check if a listing is valid or not * The seller must be the owner * The seller must have give this contract allowance * The sell price must be more than 0 * The listing mustn't be expired */ function _isListingValid(Listing memory listing) private view returns (bool) { if ( _isTokenOwner(listing.tokenId, listing.seller) && (_isTokenApproved(listing.tokenId) || _isAllTokenApproved(listing.seller)) && listing.listingPrice > 0 && listing.expireTimestamp > block.timestamp ) { return true; } } /** * @dev See {INFTKEYMarketPlaceV1-getTokenListing}. */ function getTokenListing(uint256 tokenId) public view override returns (Listing memory) { Listing memory listing = _tokenListings[tokenId]; if (_isListingValid(listing)) { return listing; } } /** * @dev See {INFTKEYMarketPlaceV1-getTokenListings}. */ function getTokenListings(uint256 from, uint256 size) public view override returns (Listing[] memory) { if (from < _tokenIdWithListing.length() && size > 0) { uint256 querySize = size; if ((from + size) > _tokenIdWithListing.length()) { querySize = _tokenIdWithListing.length() - from; } Listing[] memory listings = new Listing[](querySize); for (uint256 i = 0; i < querySize; i++) { Listing memory listing = _tokenListings[_tokenIdWithListing.at(i + from)]; if (_isListingValid(listing)) { listings[i] = listing; } } return listings; } } /** * @dev See {INFTKEYMarketPlaceV1-getAllTokenListings}. */ function getAllTokenListings() external view override returns (Listing[] memory) { return getTokenListings(0, _tokenIdWithListing.length()); } /** * @dev Check if an bid is valid or not * Bidder must not be the owner * Bidder must give the contract allowance same or more than bid price * Bid price must > 0 * Bid mustn't been expired */ function _isBidValid(Bid memory bid) private view returns (bool) { if ( !_isTokenOwner(bid.tokenId, bid.bidder) && _paymentToken.allowance(bid.bidder, address(this)) >= bid.bidPrice && bid.bidPrice > 0 && bid.expireTimestamp > block.timestamp ) { return true; } } /** * @dev See {INFTKEYMarketPlaceV1-getBidderTokenBid}. */ function getBidderTokenBid(uint256 tokenId, address bidder) public view override returns (Bid memory) { Bid memory bid = _tokenBids[tokenId].bids[bidder]; if (_isBidValid(bid)) { return bid; } } /** * @dev See {INFTKEYMarketPlaceV1-getTokenBids}. */ function getTokenBids(uint256 tokenId) external view override returns (Bid[] memory) { Bid[] memory bids = new Bid[](_tokenBids[tokenId].bidders.length()); for (uint256 i; i < _tokenBids[tokenId].bidders.length(); i++) { address bidder = _tokenBids[tokenId].bidders.at(i); Bid memory bid = _tokenBids[tokenId].bids[bidder]; if (_isBidValid(bid)) { bids[i] = bid; } } return bids; } /** * @dev See {INFTKEYMarketPlaceV1-getTokenHighestBid}. */ function getTokenHighestBid(uint256 tokenId) public view override returns (Bid memory) { Bid memory highestBid = Bid(tokenId, 0, address(0), 0); for (uint256 i; i < _tokenBids[tokenId].bidders.length(); i++) { address bidder = _tokenBids[tokenId].bidders.at(i); Bid memory bid = _tokenBids[tokenId].bids[bidder]; if (_isBidValid(bid) && bid.bidPrice > highestBid.bidPrice) { highestBid = bid; } } return highestBid; } /** * @dev See {INFTKEYMarketPlaceV1-getTokenHighestBids}. */ function getTokenHighestBids(uint256 from, uint256 size) public view override returns (Bid[] memory) { if (from < _tokenIdWithBid.length() && size > 0) { uint256 querySize = size; if ((from + size) > _tokenIdWithBid.length()) { querySize = _tokenIdWithBid.length() - from; } Bid[] memory highestBids = new Bid[](querySize); for (uint256 i = 0; i < querySize; i++) { highestBids[i] = getTokenHighestBid(_tokenIdWithBid.at(i + from)); } return highestBids; } } /** * @dev See {INFTKEYMarketPlaceV1-getAllTokenHighestBids}. */ function getAllTokenHighestBids() external view override returns (Bid[] memory) { return getTokenHighestBids(0, _tokenIdWithBid.length()); } /** * @dev delist a token - remove token id record and remove listing from mapping * @param tokenId erc721 token Id */ function _delistToken(uint256 tokenId) private { if (_tokenIdWithListing.contains(tokenId)) { delete _tokenListings[tokenId]; _tokenIdWithListing.remove(tokenId); } } /** * @dev remove a bid of a bidder * @param tokenId erc721 token Id * @param bidder bidder address */ function _removeBidOfBidder(uint256 tokenId, address bidder) private { if (_tokenBids[tokenId].bidders.contains(bidder)) { // Step 1: delete the bid and the address delete _tokenBids[tokenId].bids[bidder]; _tokenBids[tokenId].bidders.remove(bidder); // Step 2: if no bid left if (_tokenBids[tokenId].bidders.length() == 0) { _tokenIdWithBid.remove(tokenId); } } } /** * @dev See {INFTKEYMarketPlaceV1-listToken}. * People can only list if listing is allowed * The timestamp set needs to be in the allowed range * Only token owner can list token * Price must be higher than 0 * This contract must be approved to transfer this token */ function listToken( uint256 tokenId, uint256 value, uint256 expireTimestamp ) external override onlyMarketplaceOpen onlyAllowedExpireTimestamp(expireTimestamp) { require(value > 0, "Please list for more than 0 or use the transfer function"); require(_isTokenOwner(tokenId, msg.sender), "Only token owner can list token"); require( _isTokenApproved(tokenId) || _isAllTokenApproved(msg.sender), "This token is not allowed to transfer by this contract" ); _tokenListings[tokenId] = Listing(tokenId, value, msg.sender, expireTimestamp); _tokenIdWithListing.add(tokenId); emit TokenListed(tokenId, msg.sender, value); } /** * @dev See {INFTKEYMarketPlaceV1-delistToken}. * msg.sender must be the seller of the listing record */ function delistToken(uint256 tokenId) external override { require(_tokenListings[tokenId].seller == msg.sender, "Only token seller can delist token"); emit TokenDelisted(tokenId, _tokenListings[tokenId].seller); _delistToken(tokenId); } /** * @dev See {INFTKEYMarketPlaceV1-buyToken}. * Must have a valid listing * msg.sender must not the owner of token * msg.value must be at least sell price plus fees */ function buyToken(uint256 tokenId) external payable override nonReentrant { Listing memory listing = getTokenListing(tokenId); // Get valid listing require(listing.seller != address(0), "Token is not for sale"); // Listing not valid require(!_isTokenOwner(tokenId, msg.sender), "Token owner can't buy their own token"); uint256 fees = listing.listingPrice.mul(_feeFraction).div(_feeTokenBase); require( msg.value >= listing.listingPrice, "The value send is below sale price plus fees" ); // Send value to token seller and fees to contract owner uint256 valueWithoutFees = msg.value.sub(fees); uint256 tOwnerFeesShare = msg.value.mul(_feeTokenCreater).div(_feeTokenBase); uint256 devFeesShare = msg.value.mul(_feeTokenDev).div(_feeTokenBase); Address.sendValue(payable(listing.seller), valueWithoutFees); Address.sendValue(payable(maketPlaceFeeAddress), devFeesShare); if (tokenCreaterAddress != address(0) && tOwnerFeesShare > 0) { Address.sendValue(payable(tokenCreaterAddress), tOwnerFeesShare); } // Send token to buyer emit TokenBought(tokenId, listing.seller, msg.sender, msg.value, valueWithoutFees, fees); _erc721.safeTransferFrom(listing.seller, msg.sender, tokenId); // Remove token listing _delistToken(tokenId); _removeBidOfBidder(tokenId, msg.sender); } /** * @dev See {INFTKEYMarketPlaceV1-enterBidForToken}. * People can only enter bid if bid is allowed * The timestamp set needs to be in the allowed range * bid price > 0 * must not be token owner * must allow this contract to spend enough payment token */ function enterBidForToken( uint256 tokenId, uint256 bidPrice, uint256 expireTimestamp ) external override onlyMarketplaceOpen onlyAllowedExpireTimestamp(expireTimestamp) { require(bidPrice > 0, "Please bid for more than 0"); require(!_isTokenOwner(tokenId, msg.sender), "This Token belongs to this address"); require( _paymentToken.allowance(msg.sender, address(this)) >= bidPrice, "Need to have enough token holding to bid on this token" ); Bid memory bid = Bid(tokenId, bidPrice, msg.sender, expireTimestamp); // if no bids of this token add a entry to both records _tokenIdWithBid and _tokenBids if (!_tokenIdWithBid.contains(tokenId)) { _tokenIdWithBid.add(tokenId); // _tokenBids[tokenId] = TokenBid(_emptyBidders); } _tokenBids[tokenId].bidders.add(msg.sender); _tokenBids[tokenId].bids[msg.sender] = bid; emit TokenBidEntered(tokenId, msg.sender, bidPrice); } /** * @dev See {INFTKEYMarketPlaceV1-withdrawBidForToken}. * There must be a bid exists * remove this bid record */ function withdrawBidForToken(uint256 tokenId) external override { Bid memory bid = _tokenBids[tokenId].bids[msg.sender]; require(bid.bidder == msg.sender, "This address doesn't have bid on this token"); emit TokenBidWithdrawn(tokenId, bid.bidder, bid.bidPrice); _removeBidOfBidder(tokenId, msg.sender); } /** * @dev See {INFTKEYMarketPlaceV1-acceptBidForToken}. * Must be owner of this token * Must have approved this contract to transfer token * Must have a valid existing bid that matches the bidder address */ function acceptBidForToken(uint256 tokenId, address bidder) external override nonReentrant { require(_isTokenOwner(tokenId, msg.sender), "Only token owner can accept bid of token"); require( _isTokenApproved(tokenId) || _isAllTokenApproved(msg.sender), "The token is not approved to transfer by the contract" ); Bid memory existingBid = getBidderTokenBid(tokenId, bidder); require( existingBid.bidPrice > 0 && existingBid.bidder == bidder, "This token doesn't have a matching bid" ); uint256 fees = existingBid.bidPrice.mul(_feeFraction).div(_feeTokenBase); uint256 valueWithoutFees = existingBid.bidPrice.sub(fees); uint256 tOwnerFeesShare = existingBid.bidPrice.mul(_feeTokenCreater).div(_feeTokenBase); uint256 devFeesShare = existingBid.bidPrice.mul(_feeTokenDev).div(_feeTokenBase); SafeERC20.safeTransferFrom(_paymentToken, existingBid.bidder, msg.sender, valueWithoutFees); SafeERC20.safeTransferFrom( _paymentToken, existingBid.bidder, maketPlaceFeeAddress, devFeesShare ); if (tokenCreaterAddress != address(0) && tOwnerFeesShare > 0) { SafeERC20.safeTransferFrom( _paymentToken, existingBid.bidder, tokenCreaterAddress, tOwnerFeesShare ); } _erc721.safeTransferFrom(msg.sender, existingBid.bidder, tokenId); emit TokenBidAccepted( tokenId, msg.sender, existingBid.bidder, existingBid.bidPrice, valueWithoutFees, fees ); // Remove token listing _delistToken(tokenId); _removeBidOfBidder(tokenId, existingBid.bidder); } /** * @dev See {INFTKEYMarketPlaceV1-getInvalidListingCount}. */ function getInvalidListingCount() external view override returns (uint256) { uint256 count = 0; for (uint256 i = 0; i < _tokenIdWithListing.length(); i++) { if (!_isListingValid(_tokenListings[_tokenIdWithListing.at(i)])) { count = count.add(1); } } return count; } /** * @dev Count how many bid records of a token are invalid now */ function _getInvalidBidOfTokenCount(uint256 tokenId) private view returns (uint256) { uint256 count = 0; for (uint256 i = 0; i < _tokenBids[tokenId].bidders.length(); i++) { address bidder = _tokenBids[tokenId].bidders.at(i); Bid memory bid = _tokenBids[tokenId].bids[bidder]; if (!_isBidValid(bid)) { count = count.add(1); } } return count; } /** * @dev See {INFTKEYMarketPlaceV1-getInvalidBidCount}. */ function getInvalidBidCount() external view override returns (uint256) { uint256 count = 0; for (uint256 i = 0; i < _tokenIdWithBid.length(); i++) { count = count.add(_getInvalidBidOfTokenCount(_tokenIdWithBid.at(i))); } return count; } /** * @dev See {INFTKEYMarketPlaceV1-cleanAllInvalidListings}. */ function cleanAllInvalidListings() external override { for (uint256 i = 0; i < _tokenIdWithListing.length(); i++) { uint256 tokenId = _tokenIdWithListing.at(i); if (!_isListingValid(_tokenListings[tokenId])) { _tempTokenIdStorage.push(tokenId); } } for (uint256 i = 0; i < _tempTokenIdStorage.length; i++) { _delistToken(_tempTokenIdStorage[i]); } delete _tempTokenIdStorage; } /** * @dev remove invalid bids of a token * @param tokenId erc721 token Id */ function _cleanInvalidBidsOfToken(uint256 tokenId) private { for (uint256 i = 0; i < _tokenBids[tokenId].bidders.length(); i++) { address bidder = _tokenBids[tokenId].bidders.at(i); Bid memory bid = _tokenBids[tokenId].bids[bidder]; if (!_isBidValid(bid)) { _tempBidderStorage.push(_tokenBids[tokenId].bidders.at(i)); } } for (uint256 i = 0; i < _tempBidderStorage.length; i++) { address bidder = _tempBidderStorage[i]; _removeBidOfBidder(tokenId, bidder); } delete _tempBidderStorage; } /** * @dev See {INFTKEYMarketPlaceV1-cleanAllInvalidBids}. */ function cleanAllInvalidBids() external override { for (uint256 i = 0; i < _tokenIdWithBid.length(); i++) { uint256 tokenId = _tokenIdWithBid.at(i); uint256 invalidCount = _getInvalidBidOfTokenCount(tokenId); if (invalidCount > 0) { _tempTokenIdStorage.push(tokenId); } } for (uint256 i = 0; i < _tempTokenIdStorage.length; i++) { _cleanInvalidBidsOfToken(_tempTokenIdStorage[i]); } delete _tempTokenIdStorage; } /** * @dev See {INFTKEYMarketPlaceV1-erc721Name}. */ function erc721Name() external view override returns (string memory) { return _erc721Name; } /** * @dev See {INFTKEYMarketPlaceV1-isListingAndBidEnabled}. */ function isListingAndBidEnabled() external view override returns (bool) { return _isListingAndBidEnabled; } /** * @dev Enable to disable Bids and Listing */ function changeMarketplaceStatus(bool enabled) external onlyDev { _isListingAndBidEnabled = enabled; } /** * @dev See {INFTKEYMarketPlaceV1-actionTimeOutRangeMin}. */ function actionTimeOutRangeMin() external view override returns (uint256) { return _actionTimeOutRangeMin; } /** * @dev See {INFTKEYMarketPlaceV1-actionTimeOutRangeMax}. */ function actionTimeOutRangeMax() external view override returns (uint256) { return _actionTimeOutRangeMax; } /** * @dev Change minimum listing and bid time range */ function changeMinActionTimeLimit(uint256 timeInSec) external onlyDev { _actionTimeOutRangeMin = timeInSec; } /** * @dev Change maximum listing and bid time range */ function changeMaxActionTimeLimit(uint256 timeInSec) external onlyDev { _actionTimeOutRangeMax = timeInSec; } /** * @dev See {INFTKEYMarketPlaceV1-serviceFee}. */ function serviceFee() external view override returns (uint256, uint256) { return (_feeFraction, _feeTokenBase); } /** * @dev Set partner address and profit share * @param _maketPlaceFeeAddress Token maket fee address * @param _maketPlaceFeePercentage Token maket place fee for 1000 */ function setMaketPlaceAddressAndFee(address _maketPlaceFeeAddress, uint256 _maketPlaceFeePercentage) external onlyDev { require( _maketPlaceFeePercentage > 0 && _maketPlaceFeePercentage <= 1000, "Allowed percentage range is 1 to 1000" ); maketPlaceFeeAddress = _maketPlaceFeeAddress; _feeTokenDev = _maketPlaceFeePercentage; _feeTokenSeller = _feeTokenBase - _feeTokenCreater - _feeTokenDev; _feeFraction = _feeTokenCreater + _feeTokenDev; } /** * @dev Set partner address and profit share * @param _tokenCreaterAddress Token maket fee address * @param _tokenCreaterFeePercentage Token maket place fee for 1000 */ function setTokenCreaterAddressAndFee(address _tokenCreaterAddress, uint256 _tokenCreaterFeePercentage) external onlyDev { // require(tokenCreaterAddress == address(0), "Owner can't change partner address once it's set"); require(_tokenCreaterAddress != address(0), "Can't set to address 0x0"); require( _tokenCreaterFeePercentage > 0 && _tokenCreaterFeePercentage <= 100, "Allowed percentage range is 1 to 1000" ); tokenCreaterAddress = _tokenCreaterAddress; _feeTokenCreater = _tokenCreaterFeePercentage; _feeTokenSeller = _feeTokenBase - _feeTokenCreater - _feeTokenDev; _feeFraction = _feeTokenCreater + _feeTokenDev; } /** * @dev Change partner address * @param _tokenCreaterAddress Partner address * Only partner can change their share address */ function changeTokenCreaterAddress(address _tokenCreaterAddress) external { // require(msg.sender == tokenCreaterAddress, "Only partner can change partner address"); tokenCreaterAddress = _tokenCreaterAddress; if (_tokenCreaterAddress == address(0)) { _feeTokenCreater = 0; } } function changeERC721Token( string memory erc721Name_, address _erc721Address ) external onlyDev { _erc721Name = erc721Name_; _erc721 = IERC721(_erc721Address); } function changeDev(address _newDev) public onlyDev { dev = _newDev; } }
/_openzeppelin/contracts/access/Ownable.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _setOwner(_msgSender()); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _setOwner(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _setOwner(newOwner); } function _setOwner(address newOwner) private { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
/_openzeppelin/contracts/security/ReentrancyGuard.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and make it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
/_openzeppelin/contracts/token/ERC20/IERC20.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
/_openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../IERC20.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
/_openzeppelin/contracts/token/ERC721/IERC721.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external; }
/_openzeppelin/contracts/utils/Address.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
/_openzeppelin/contracts/utils/Context.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
/_openzeppelin/contracts/utils/introspection/IERC165.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * 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 * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * 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); }
/_openzeppelin/contracts/utils/math/SafeMath.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; // CAUTION // This version of SafeMath should only be used with Solidity 0.8 or later, // because it relies on the compiler's built in overflow checks. /** * @dev Wrappers over Solidity's arithmetic operations. * * NOTE: `SafeMath` is no longer needed starting with Solidity 0.8. The compiler * now has built in overflow checking. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the substraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @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) { return a + b; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return a - b; } /** * @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) { return a * b; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b <= a, errorMessage); return a - b; } } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a / b; } } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a % b; } } }
/_openzeppelin/contracts/utils/structs/EnumerableSet.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ``` * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping(bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; if (lastIndex != toDeleteIndex) { bytes32 lastvalue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastvalue; // Update the index for the moved value set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex } // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { return _values(set._inner); } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values on the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; assembly { result := store } return result; } }
/contracts/Interface.sol
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity 0.8.0; pragma experimental ABIEncoderV2; interface Interface { struct Bid { uint256 tokenId; uint256 bidPrice; address bidder; uint256 expireTimestamp; } struct Listing { uint256 tokenId; uint256 listingPrice; address seller; uint256 expireTimestamp; } event TokenListed(uint256 indexed tokenId, address indexed fromAddress, uint256 minValue); event TokenDelisted(uint256 indexed tokenId, address indexed fromAddress); event TokenBidEntered(uint256 indexed tokenId, address indexed fromAddress, uint256 value); event TokenBidWithdrawn(uint256 indexed tokenId, address indexed fromAddress, uint256 value); event TokenBought( uint256 indexed tokenId, address indexed fromAddress, address indexed toAddress, uint256 total, uint256 value, uint256 fees ); event TokenBidAccepted( uint256 indexed tokenId, address indexed owner, address indexed bidder, uint256 total, uint256 value, uint256 fees ); /** * @dev surface the erc721 token contract address */ function tokenAddress() external view returns (address); /** * @dev surface the erc20 payment token contract address */ function paymentTokenAddress() external view returns (address); /** * @dev get current listing of a token * @param tokenId erc721 token Id * @return current valid listing or empty listing struct */ function getTokenListing(uint256 tokenId) external view returns (Listing memory); /** * @dev get current valid listings by size * @param from index to start * @param size size to query * @return current valid listings * This to help batch query when list gets big */ function getTokenListings(uint256 from, uint256 size) external view returns (Listing[] memory); /** * @dev get all current valid listings * @return current valid listings */ function getAllTokenListings() external view returns (Listing[] memory); /** * @dev get bidder's bid on a token * @param tokenId erc721 token Id * @param bidder address of a bidder * @return Valid bid or empty bid */ function getBidderTokenBid(uint256 tokenId, address bidder) external view returns (Bid memory); /** * @dev get all valid bids of a token * @param tokenId erc721 token Id * @return Valid bids of a token */ function getTokenBids(uint256 tokenId) external view returns (Bid[] memory); /** * @dev get highest bid of a token * @param tokenId erc721 token Id * @return Valid highest bid or empty bid */ function getTokenHighestBid(uint256 tokenId) external view returns (Bid memory); /** * @dev get current highest bids * @param from index to start * @param size size to query * @return current highest bids * This to help batch query when list gets big */ function getTokenHighestBids(uint256 from, uint256 size) external view returns (Bid[] memory); /** * @dev get all highest bids * @return All valid highest bids */ function getAllTokenHighestBids() external view returns (Bid[] memory); /** * @dev List token for sale * @param tokenId erc721 token Id * @param value min price to sell the token * @param expireTimestamp when would this listing expire */ function listToken( uint256 tokenId, uint256 value, uint256 expireTimestamp ) external; /** * @dev Delist token for sale * @param tokenId erc721 token Id */ function delistToken(uint256 tokenId) external; /** * @dev Buy token * @param tokenId erc721 token Id */ function buyToken(uint256 tokenId) external payable; /** * @dev Enter bid for token * @param tokenId erc721 token Id * @param bidPrice price in payment token * @param expireTimestamp when would this bid expire */ function enterBidForToken( uint256 tokenId, uint256 bidPrice, uint256 expireTimestamp ) external; /** * @dev Withdraw bid for token * @param tokenId erc721 token Id */ function withdrawBidForToken(uint256 tokenId) external; /** * @dev Accept a bid of token from a bidder * @param tokenId erc721 token Id * @param bidder bidder address */ function acceptBidForToken(uint256 tokenId, address bidder) external; /** * @dev Count how many listing records are invalid now * This is to help admin to decide to do a cleaning or not */ function getInvalidListingCount() external view returns (uint256); /** * @dev Count how many bids records are invalid now * This is to help admin to decide to do a cleaning or not */ function getInvalidBidCount() external view returns (uint256); /** * @dev Clean all invalid listings */ function cleanAllInvalidListings() external; /** * @dev Clean all invalid bids */ function cleanAllInvalidBids() external; /** * @dev Name of ERC721 token */ function erc721Name() external view returns (string memory); /** * @dev Show if listing and bid are enabled */ function isListingAndBidEnabled() external view returns (bool); /** * @dev Surface minimum listing and bid time range */ function actionTimeOutRangeMin() external view returns (uint256); /** * @dev Surface maximum listing and bid time range */ function actionTimeOutRangeMax() external view returns (uint256); /** * @dev Service fee * @return fee fraction and fee base */ function serviceFee() external view returns (uint256, uint256); }
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"string","name":"erc721Name_","internalType":"string"},{"type":"address","name":"_erc721Address","internalType":"address"},{"type":"address","name":"_paymentTokenAddress","internalType":"address"},{"type":"address","name":"_devAddress","internalType":"address"},{"type":"address","name":"_ownerAddress","internalType":"address"}]},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"TokenBidAccepted","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256","indexed":true},{"type":"address","name":"owner","internalType":"address","indexed":true},{"type":"address","name":"bidder","internalType":"address","indexed":true},{"type":"uint256","name":"total","internalType":"uint256","indexed":false},{"type":"uint256","name":"value","internalType":"uint256","indexed":false},{"type":"uint256","name":"fees","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"TokenBidEntered","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256","indexed":true},{"type":"address","name":"fromAddress","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"TokenBidWithdrawn","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256","indexed":true},{"type":"address","name":"fromAddress","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"TokenBought","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256","indexed":true},{"type":"address","name":"fromAddress","internalType":"address","indexed":true},{"type":"address","name":"toAddress","internalType":"address","indexed":true},{"type":"uint256","name":"total","internalType":"uint256","indexed":false},{"type":"uint256","name":"value","internalType":"uint256","indexed":false},{"type":"uint256","name":"fees","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"TokenDelisted","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256","indexed":true},{"type":"address","name":"fromAddress","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"TokenListed","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256","indexed":true},{"type":"address","name":"fromAddress","internalType":"address","indexed":true},{"type":"uint256","name":"minValue","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"_feeTokenCreater","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"_feeTokenDev","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"_feeTokenSeller","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"acceptBidForToken","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"address","name":"bidder","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"actionTimeOutRangeMax","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"actionTimeOutRangeMin","inputs":[]},{"type":"function","stateMutability":"payable","outputs":[],"name":"buyToken","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"changeDev","inputs":[{"type":"address","name":"_newDev","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"changeERC721Token","inputs":[{"type":"string","name":"erc721Name_","internalType":"string"},{"type":"address","name":"_erc721Address","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"changeMarketplaceStatus","inputs":[{"type":"bool","name":"enabled","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"changeMaxActionTimeLimit","inputs":[{"type":"uint256","name":"timeInSec","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"changeMinActionTimeLimit","inputs":[{"type":"uint256","name":"timeInSec","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"changeTokenCreaterAddress","inputs":[{"type":"address","name":"_tokenCreaterAddress","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"cleanAllInvalidBids","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"cleanAllInvalidListings","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"delistToken","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"dev","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"enterBidForToken","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"uint256","name":"bidPrice","internalType":"uint256"},{"type":"uint256","name":"expireTimestamp","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"erc721Name","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple[]","name":"","internalType":"struct Interface.Bid[]","components":[{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"uint256","name":"bidPrice","internalType":"uint256"},{"type":"address","name":"bidder","internalType":"address"},{"type":"uint256","name":"expireTimestamp","internalType":"uint256"}]}],"name":"getAllTokenHighestBids","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple[]","name":"","internalType":"struct Interface.Listing[]","components":[{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"uint256","name":"listingPrice","internalType":"uint256"},{"type":"address","name":"seller","internalType":"address"},{"type":"uint256","name":"expireTimestamp","internalType":"uint256"}]}],"name":"getAllTokenListings","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct Interface.Bid","components":[{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"uint256","name":"bidPrice","internalType":"uint256"},{"type":"address","name":"bidder","internalType":"address"},{"type":"uint256","name":"expireTimestamp","internalType":"uint256"}]}],"name":"getBidderTokenBid","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"address","name":"bidder","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getInvalidBidCount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getInvalidListingCount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple[]","name":"","internalType":"struct Interface.Bid[]","components":[{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"uint256","name":"bidPrice","internalType":"uint256"},{"type":"address","name":"bidder","internalType":"address"},{"type":"uint256","name":"expireTimestamp","internalType":"uint256"}]}],"name":"getTokenBids","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct Interface.Bid","components":[{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"uint256","name":"bidPrice","internalType":"uint256"},{"type":"address","name":"bidder","internalType":"address"},{"type":"uint256","name":"expireTimestamp","internalType":"uint256"}]}],"name":"getTokenHighestBid","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple[]","name":"","internalType":"struct Interface.Bid[]","components":[{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"uint256","name":"bidPrice","internalType":"uint256"},{"type":"address","name":"bidder","internalType":"address"},{"type":"uint256","name":"expireTimestamp","internalType":"uint256"}]}],"name":"getTokenHighestBids","inputs":[{"type":"uint256","name":"from","internalType":"uint256"},{"type":"uint256","name":"size","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct Interface.Listing","components":[{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"uint256","name":"listingPrice","internalType":"uint256"},{"type":"address","name":"seller","internalType":"address"},{"type":"uint256","name":"expireTimestamp","internalType":"uint256"}]}],"name":"getTokenListing","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple[]","name":"","internalType":"struct Interface.Listing[]","components":[{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"uint256","name":"listingPrice","internalType":"uint256"},{"type":"address","name":"seller","internalType":"address"},{"type":"uint256","name":"expireTimestamp","internalType":"uint256"}]}],"name":"getTokenListings","inputs":[{"type":"uint256","name":"from","internalType":"uint256"},{"type":"uint256","name":"size","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isListingAndBidEnabled","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"listToken","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"uint256","name":"value","internalType":"uint256"},{"type":"uint256","name":"expireTimestamp","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"maketPlaceFeeAddress","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"paymentTokenAddress","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"},{"type":"uint256","name":"","internalType":"uint256"}],"name":"serviceFee","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setMaketPlaceAddressAndFee","inputs":[{"type":"address","name":"_maketPlaceFeeAddress","internalType":"address"},{"type":"uint256","name":"_maketPlaceFeePercentage","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setTokenCreaterAddressAndFee","inputs":[{"type":"address","name":"_tokenCreaterAddress","internalType":"address"},{"type":"uint256","name":"_tokenCreaterFeePercentage","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"tokenAddress","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"tokenCreaterAddress","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"withdrawBidForToken","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"}]}]
Contract Creation Code
0x60a06040526001600460146101000a81548160ff0219169083151502179055506103cf6005556000600655601960075560196008556103e860095562015180600a556301e13380600b553480156200005657600080fd5b506040516200677b3803806200677b83398181016040528101906200007c9190620003c6565b6200009c62000090620001c160201b60201c565b620001c960201b60201c565b600180819055508460039080519060200190620000bb9291906200028d565b5083600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508273ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff1660601b8152505081600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080601360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050505050620005e0565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b8280546200029b9062000532565b90600052602060002090601f016020900481019282620002bf57600085556200030b565b82601f10620002da57805160ff19168380011785556200030b565b828001600101855582156200030b579182015b828111156200030a578251825591602001919060010190620002ed565b5b5090506200031a91906200031e565b5090565b5b80821115620003395760008160009055506001016200031f565b5090565b6000620003546200034e8462000495565b62000461565b9050828152602081018484840111156200036d57600080fd5b6200037a848285620004fc565b509392505050565b6000815190506200039381620005c6565b92915050565b600082601f830112620003ab57600080fd5b8151620003bd8482602086016200033d565b91505092915050565b600080600080600060a08688031215620003df57600080fd5b600086015167ffffffffffffffff811115620003fa57600080fd5b620004088882890162000399565b95505060206200041b8882890162000382565b94505060406200042e8882890162000382565b9350506060620004418882890162000382565b9250506080620004548882890162000382565b9150509295509295909350565b6000604051905081810181811067ffffffffffffffff821117156200048b576200048a62000597565b5b8060405250919050565b600067ffffffffffffffff821115620004b357620004b262000597565b5b601f19601f8301169050602081019050919050565b6000620004d582620004dc565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60005b838110156200051c578082015181840152602081019050620004ff565b838111156200052c576000848401525b50505050565b600060028204905060018216806200054b57607f821691505b6020821081141562000562576200056162000568565b5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b620005d181620004c8565b8114620005dd57600080fd5b50565b60805160601c61615962000622600039600081816114ad015281816114dd015281816115930152818161255301528181612c9d015261342c01526161596000f3fe6080604052600436106102515760003560e01c806388a8c95c11610139578063b6be53ba116100b6578063e15487021161007a578063e15487021461085c578063e724488114610887578063e7d585a8146108b0578063f0e6dcab146108ed578063f2fde38b14610918578063f4ecbff11461094157610251565b8063b6be53ba1461078d578063b7e6a194146107b6578063bce64a7d146107e1578063bed659bc1461080a578063d9420c2a1461083357610251565b806398792eec116100fd57806398792eec146106a65780639d76ea58146106e3578063a3c0b5f01461070e578063a6a27f3a14610737578063afb18fe71461076257610251565b806388a8c95c146105d05780638abdf5aa146105f95780638da5cb5b146106255780638ece265a1461065057806391cca3db1461067b57610251565b8063453dfc50116101d257806370d840b51161019657806370d840b5146104e6578063715018a61461051157806373885b701461052857806375ccb1f2146105535780637d7660e01461059057806385f5a92a146105a757610251565b8063453dfc50146103eb57806354b0de6a146104165780635cc2c66b1461044157806365667aaa1461047e57806370a3b390146104a957610251565b806333549d3d1161021957806333549d3d1461032a57806333623c0a14610355578063336c16c614610380578063383fba25146103a957806340a97919146103c057610251565b806315f2d5c5146102565780631d2d3ed21461027f5780631e56afe9146102a85780632426fc24146102e55780632d296bf11461030e575b600080fd5b34801561026257600080fd5b5061027d600480360381019061027891906148e3565b61096a565b005b34801561028b57600080fd5b506102a660048036038101906102a19190614971565b610b3f565b005b3480156102b457600080fd5b506102cf60048036038101906102ca91906149c5565b610c2b565b6040516102dc9190615c41565b60405180910390f35b3480156102f157600080fd5b5061030c600480360381019061030791906149c5565b610ddf565b005b610328600480360381019061032391906149c5565b610e79565b005b34801561033657600080fd5b5061033f61126b565b60405161034c9190615c77565b60405180910390f35b34801561036157600080fd5b5061036a611275565b6040516103779190615c77565b60405180910390f35b34801561038c57600080fd5b506103a760048036038101906103a29190614a17565b61127b565b005b3480156103b557600080fd5b506103be61170f565b005b3480156103cc57600080fd5b506103d5611899565b6040516103e29190615c77565b60405180910390f35b3480156103f757600080fd5b506104006118ff565b60405161040d9190615c77565b60405180910390f35b34801561042257600080fd5b5061042b611909565b6040516104389190615840565b60405180910390f35b34801561044d57600080fd5b5061046860048036038101906104639190614a53565b611924565b6040516104759190615840565b60405180910390f35b34801561048a57600080fd5b50610493611a95565b6040516104a09190615c77565b60405180910390f35b3480156104b557600080fd5b506104d060048036038101906104cb9190614a17565b611a9b565b6040516104dd9190615c41565b60405180910390f35b3480156104f257600080fd5b506104fb611b98565b60405161050891906157c5565b60405180910390f35b34801561051d57600080fd5b50610526611bbe565b005b34801561053457600080fd5b5061053d611c46565b60405161054a919061589f565b60405180910390f35b34801561055f57600080fd5b5061057a60048036038101906105759190614a53565b611cd8565b6040516105879190615862565b60405180910390f35b34801561059c57600080fd5b506105a5611ee7565b005b3480156105b357600080fd5b506105ce60048036038101906105c991906149c5565b611fea565b005b3480156105dc57600080fd5b506105f760048036038101906105f29190614891565b612197565b005b34801561060557600080fd5b5061060e61226b565b60405161061c929190615c92565b60405180910390f35b34801561063157600080fd5b5061063a61227c565b60405161064791906157c5565b60405180910390f35b34801561065c57600080fd5b506106656122a5565b6040516106729190615c77565b60405180910390f35b34801561068757600080fd5b506106906122ab565b60405161069d91906157c5565b60405180910390f35b3480156106b257600080fd5b506106cd60048036038101906106c891906149c5565b6122d1565b6040516106da9190615c5c565b60405180910390f35b3480156106ef57600080fd5b506106f861238d565b60405161070591906157c5565b60405180910390f35b34801561071a57600080fd5b50610735600480360381019061073091906149c5565b6123b7565b005b34801561074357600080fd5b5061074c612451565b6040516107599190615c77565b60405180910390f35b34801561076e57600080fd5b5061077761254f565b60405161078491906157c5565b60405180910390f35b34801561079957600080fd5b506107b460048036038101906107af919061491f565b612577565b005b3480156107c257600080fd5b506107cb612624565b6040516107d891906157c5565b60405180910390f35b3480156107ed57600080fd5b5061080860048036038101906108039190614a8f565b61264a565b005b34801561081657600080fd5b50610831600480360381019061082c91906149c5565b612948565b005b34801561083f57600080fd5b5061085a60048036038101906108559190614891565b612a72565b005b34801561086857600080fd5b50610871612af4565b60405161087e9190615862565b60405180910390f35b34801561089357600080fd5b506108ae60048036038101906108a99190614a8f565b612b0f565b005b3480156108bc57600080fd5b506108d760048036038101906108d291906149c5565b612f2b565b6040516108e49190615840565b60405180910390f35b3480156108f957600080fd5b50610902613165565b60405161090f9190615884565b60405180910390f35b34801561092457600080fd5b5061093f600480360381019061093a9190614891565b61317c565b005b34801561094d57600080fd5b50610968600480360381019061096391906148e3565b613274565b005b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146109fa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109f190615b01565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610a6a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a61906158e1565b60405180910390fd5b600081118015610a7b575060648111155b610aba576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ab190615be1565b60405180910390fd5b81601260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600681905550600754600654600954610b159190615ed8565b610b1f9190615ed8565b600581905550600754600654610b359190615df7565b6008819055505050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610bcf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bc690615b01565b60405180910390fd5b8160039080519060200190610be592919061464a565b5080600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b610c336146d0565b6000604051806080016040528084815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020016000815250905060005b610c92600f60008681526020019081526020016000206000016133da565b811015610dd5576000610cc382600f60008881526020019081526020016000206000016133ef90919063ffffffff16565b90506000600f600087815260200190815260200160002060020160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060405180608001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016003820154815250509050610da481613409565b8015610db7575083602001518160200151115b15610dc0578093505b50508080610dcd90615fc8565b915050610c74565b5080915050919050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610e6f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e6690615b01565b60405180910390fd5b80600a8190555050565b60026001541415610ebf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eb690615b81565b60405180910390fd5b60026001819055506000610ed2826122d1565b9050600073ffffffffffffffffffffffffffffffffffffffff16816040015173ffffffffffffffffffffffffffffffffffffffff161415610f48576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f3f90615a81565b60405180910390fd5b610f52823361350f565b15610f92576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f8990615921565b60405180910390fd5b6000610fc1600954610fb360085485602001516135fb90919063ffffffff16565b61361190919063ffffffff16565b9050816020015134101561100a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611001906159a1565b60405180910390fd5b600061101f823461362790919063ffffffff16565b9050600061104c60095461103e600654346135fb90919063ffffffff16565b61361190919063ffffffff16565b9050600061107960095461106b600754346135fb90919063ffffffff16565b61361190919063ffffffff16565b905061108985604001518461363d565b6110b5601360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168261363d565b600073ffffffffffffffffffffffffffffffffffffffff16601260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141580156111145750600082115b1561114657611145601260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168361363d565b5b3373ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff16877f1d83c44501b48d5dc85fea9b94506cda160418d62c65b481199bdbec265df1573487896040516111ac93929190615cbb565b60405180910390a4600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166342842e0e866040015133896040518463ffffffff1660e01b815260040161121793929190615809565b600060405180830381600087803b15801561123157600080fd5b505af1158015611245573d6000803e3d6000fd5b5050505061125286613731565b61125c86336137b8565b50505050506001808190555050565b6000600a54905090565b60055481565b600260015414156112c1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112b890615b81565b60405180910390fd5b60026001819055506112d3823361350f565b611312576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161130990615c01565b60405180910390fd5b61131b826138e4565b8061132b575061132a336139cf565b5b61136a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611361906158c1565b60405180910390fd5b60006113768383611a9b565b9050600081602001511180156113bb57508173ffffffffffffffffffffffffffffffffffffffff16816040015173ffffffffffffffffffffffffffffffffffffffff16145b6113fa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113f190615ae1565b60405180910390fd5b600061142960095461141b60085485602001516135fb90919063ffffffff16565b61361190919063ffffffff16565b9050600061144482846020015161362790919063ffffffff16565b9050600061147560095461146760065487602001516135fb90919063ffffffff16565b61361190919063ffffffff16565b905060006114a660095461149860075488602001516135fb90919063ffffffff16565b61361190919063ffffffff16565b90506114d87f000000000000000000000000000000000000000000000000000000000000000086604001513386613a85565b61152a7f00000000000000000000000000000000000000000000000000000000000000008660400151601360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684613a85565b600073ffffffffffffffffffffffffffffffffffffffff16601260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141580156115895750600082115b156115e1576115e07f00000000000000000000000000000000000000000000000000000000000000008660400151601260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1685613a85565b5b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166342842e0e3387604001518a6040518463ffffffff1660e01b815260040161164493929190615809565b600060405180830381600087803b15801561165e57600080fd5b505af1158015611672573d6000803e3d6000fd5b50505050846040015173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16887f2c907f0c6ace0ad59e44f69f6873314bb2b85cca7eeffb05ca93fa65326bfbb4886020015187896040516116e093929190615cbb565b60405180910390a46116f187613731565b6116ff8786604001516137b8565b5050505050600180819055505050565b60005b61171c600d613b0e565b81101561181757600061173982600d613b2390919063ffffffff16565b90506117d5600c600083815260200190815260200160002060405180608001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600382015481525050613b3d565b6118035760168190806001815401808255809150506001900390600052602060002001600090919091909150555b50808061180f90615fc8565b915050611712565b5060005b6016805490508110156118885761187560168281548110611865577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154613731565b808061188090615fc8565b91505061181b565b5060166000611897919061470e565b565b6000806000905060005b6118ad6010613b0e565b8110156118f7576118e26118d36118ce836010613b2390919063ffffffff16565b613bad565b83613d2190919063ffffffff16565b915080806118ef90615fc8565b9150506118a3565b508091505090565b6000600b54905090565b606061191f600061191a6010613b0e565b611924565b905090565b60606119306010613b0e565b8310801561193e5750600082115b15611a8e5760008290506119526010613b0e565b838561195e9190615df7565b111561197c578361196f6010613b0e565b6119799190615ed8565b90505b60008167ffffffffffffffff8111156119be577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519080825280602002602001820160405280156119f757816020015b6119e46146d0565b8152602001906001900390816119dc5790505b50905060005b82811015611a8357611a2c611a278783611a179190615df7565b6010613b2390919063ffffffff16565b610c2b565b828281518110611a65577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200260200101819052508080611a7b90615fc8565b9150506119fd565b508092505050611a8f565b5b92915050565b60075481565b611aa36146d0565b6000600f600085815260200190815260200160002060020160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060405180608001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016003820154815250509050611b8281613409565b15611b905780915050611b92565b505b92915050565b601260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b611bc6613d37565b73ffffffffffffffffffffffffffffffffffffffff16611be461227c565b73ffffffffffffffffffffffffffffffffffffffff1614611c3a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c3190615aa1565b60405180910390fd5b611c446000613d3f565b565b606060038054611c5590615f96565b80601f0160208091040260200160405190810160405280929190818152602001828054611c8190615f96565b8015611cce5780601f10611ca357610100808354040283529160200191611cce565b820191906000526020600020905b815481529060010190602001808311611cb157829003601f168201915b5050505050905090565b6060611ce4600d613b0e565b83108015611cf25750600082115b15611ee0576000829050611d06600d613b0e565b8385611d129190615df7565b1115611d305783611d23600d613b0e565b611d2d9190615ed8565b90505b60008167ffffffffffffffff811115611d72577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051908082528060200260200182016040528015611dab57816020015b611d9861472f565b815260200190600190039081611d905790505b50905060005b82811015611ed5576000600c6000611dde8985611dce9190615df7565b600d613b2390919063ffffffff16565b815260200190815260200160002060405180608001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016003820154815250509050611e7681613b3d565b15611ec15780838381518110611eb5577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200260200101819052505b508080611ecd90615fc8565b915050611db1565b508092505050611ee1565b5b92915050565b60005b611ef46010613b0e565b811015611f68576000611f11826010613b2390919063ffffffff16565b90506000611f1e82613bad565b90506000811115611f535760168290806001815401808255809150506001900390600052602060002001600090919091909150555b50508080611f6090615fc8565b915050611eea565b5060005b601680549050811015611fd957611fc660168281548110611fb6577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154613e03565b8080611fd190615fc8565b915050611f6c565b5060166000611fe8919061470e565b565b6000600f600083815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060405180608001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160038201548152505090503373ffffffffffffffffffffffffffffffffffffffff16816040015173ffffffffffffffffffffffffffffffffffffffff1614612132576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161212990615b21565b60405180910390fd5b806040015173ffffffffffffffffffffffffffffffffffffffff16827f4afa471ce7ab7fa67258e3afb1adf7e899e0495602eeb26d90d41e1b64dea5a683602001516040516121819190615c77565b60405180910390a361219382336137b8565b5050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612227576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161221e90615b01565b60405180910390fd5b80600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600080600854600954915091509091565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60065481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6122d961472f565b6000600c600084815260200190815260200160002060405180608001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600382015481525050905061237881613b3d565b156123865780915050612388565b505b919050565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612447576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161243e90615b01565b60405180910390fd5b80600b8190555050565b6000806000905060005b612465600d613b0e565b81101561254757612519600c600061248784600d613b2390919063ffffffff16565b815260200190815260200160002060405180608001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600382015481525050613b3d565b61253457612531600183613d2190919063ffffffff16565b91505b808061253f90615fc8565b91505061245b565b508091505090565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612607576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125fe90615b01565b60405180910390fd5b80600460146101000a81548160ff02191690831515021790555050565b601360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600460149054906101000a900460ff16612699576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161269090615941565b60405180910390fd5b80600a546126b0428361362790919063ffffffff16565b10156126f1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126e890615c21565b60405180910390fd5b600b54612707428361362790919063ffffffff16565b1115612748576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161273f90615a01565b60405180910390fd5b6000831161278b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161278290615a41565b60405180910390fd5b612795843361350f565b6127d4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127cb90615bc1565b60405180910390fd5b6127dd846138e4565b806127ed57506127ec336139cf565b5b61282c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161282390615ac1565b60405180910390fd5b60405180608001604052808581526020018481526020013373ffffffffffffffffffffffffffffffffffffffff16815260200183815250600c6000868152602001908152602001600020600082015181600001556020820151816001015560408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550606082015181600301559050506128f284600d61408490919063ffffffff16565b503373ffffffffffffffffffffffffffffffffffffffff16847f7765a1c07bdce3390c521eaeb86030b188b77cbaba2d76bd7c9c32d906bfbcba8560405161293a9190615c77565b60405180910390a350505050565b3373ffffffffffffffffffffffffffffffffffffffff16600c600083815260200190815260200160002060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146129ec576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129e390615ba1565b60405180910390fd5b600c600082815260200190815260200160002060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16817f70a382c18b6e794d86997f6e1f1efca577925cfa85c476a6ff7031f0a3dd6ed060405160405180910390a3612a6f81613731565b50565b80601260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612af15760006006819055505b50565b6060612b0a6000612b05600d613b0e565b611cd8565b905090565b600460149054906101000a900460ff16612b5e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b5590615941565b60405180910390fd5b80600a54612b75428361362790919063ffffffff16565b1015612bb6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612bad90615c21565b60405180910390fd5b600b54612bcc428361362790919063ffffffff16565b1115612c0d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c0490615a01565b60405180910390fd5b60008311612c50576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c4790615961565b60405180910390fd5b612c5a843361350f565b15612c9a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c9190615a21565b60405180910390fd5b827f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e33306040518363ffffffff1660e01b8152600401612cf69291906157e0565b60206040518083038186803b158015612d0e57600080fd5b505afa158015612d22573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4691906149ee565b1015612d87576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d7e90615a61565b60405180910390fd5b600060405180608001604052808681526020018581526020013373ffffffffffffffffffffffffffffffffffffffff168152602001848152509050612dd685601061409e90919063ffffffff16565b612df057612dee85601061408490919063ffffffff16565b505b612e1833600f60008881526020019081526020016000206000016140b890919063ffffffff16565b5080600f600087815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082015181600001556020820151816001015560408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550606082015181600301559050503373ffffffffffffffffffffffffffffffffffffffff16857f0ea16c10401e9d7c547471845914c4a904af6a01b9fa1e195eeecae9f78bcca186604051612f1c9190615c77565b60405180910390a35050505050565b60606000612f4d600f60008581526020019081526020016000206000016133da565b67ffffffffffffffff811115612f8c577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051908082528060200260200182016040528015612fc557816020015b612fb26146d0565b815260200190600190039081612faa5790505b50905060005b612fe9600f60008681526020019081526020016000206000016133da565b81101561315b57600061301a82600f60008881526020019081526020016000206000016133ef90919063ffffffff16565b90506000600f600087815260200190815260200160002060020160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060405180608001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160038201548152505090506130fb81613409565b15613146578084848151811061313a577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200260200101819052505b5050808061315390615fc8565b915050612fcb565b5080915050919050565b6000600460149054906101000a900460ff16905090565b613184613d37565b73ffffffffffffffffffffffffffffffffffffffff166131a261227c565b73ffffffffffffffffffffffffffffffffffffffff16146131f8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016131ef90615aa1565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415613268576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161325f90615901565b60405180910390fd5b61327181613d3f565b50565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614613304576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016132fb90615b01565b60405180910390fd5b60008111801561331657506103e88111155b613355576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161334c90615be1565b60405180910390fd5b81601360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550806007819055506007546006546009546133b09190615ed8565b6133ba9190615ed8565b6005819055506007546006546133d09190615df7565b6008819055505050565b60006133e8826000016140e8565b9050919050565b60006133fe83600001836140f9565b60001c905092915050565b600061341d8260000151836040015161350f565b1580156134dc575081602001517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e8460400151306040518363ffffffff1660e01b81526004016134899291906157e0565b60206040518083038186803b1580156134a157600080fd5b505afa1580156134b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134d991906149ee565b10155b80156134ec575060008260200151115b80156134fb5750428260600151115b15613509576001905061350a565b5b919050565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636352211e846040518263ffffffff1660e01b815260040161356c9190615c77565b60206040518083038186803b15801561358457600080fd5b505afa9250505080156135b557506040513d601f19601f820116820180604052508101906135b291906148ba565b60015b6135c257600090506135f5565b8273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16149150505b92915050565b600081836136099190615e7e565b905092915050565b6000818361361f9190615e4d565b905092915050565b600081836136359190615ed8565b905092915050565b80471015613680576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613677906159c1565b60405180910390fd5b60008273ffffffffffffffffffffffffffffffffffffffff16826040516136a6906157b0565b60006040518083038185875af1925050503d80600081146136e3576040519150601f19603f3d011682016040523d82523d6000602084013e6136e8565b606091505b505090508061372c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161372390615981565b60405180910390fd5b505050565b61374581600d61409e90919063ffffffff16565b156137b557600c600082815260200190815260200160002060008082016000905560018201600090556002820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600382016000905550506137b381600d61414a90919063ffffffff16565b505b50565b6137e081600f600085815260200190815260200160002060000161416490919063ffffffff16565b156138e057600f600083815260200190815260200160002060020160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008082016000905560018201600090556002820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600382016000905550506138a281600f600085815260200190815260200160002060000161419490919063ffffffff16565b5060006138c3600f60008581526020019081526020016000206000016133da565b14156138df576138dd82601061414a90919063ffffffff16565b505b5b5050565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663081812fc836040518263ffffffff1660e01b81526004016139419190615c77565b60206040518083038186803b15801561395957600080fd5b505afa92505050801561398a57506040513d601f19601f8201168201806040525081019061398791906148ba565b60015b61399757600090506139ca565b3073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16149150505b919050565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e985e9c583306040518363ffffffff1660e01b8152600401613a2e9291906157e0565b60206040518083038186803b158015613a4657600080fd5b505afa158015613a5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a7e9190614948565b9050919050565b613b08846323b872dd60e01b858585604051602401613aa693929190615809565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506141c4565b50505050565b6000613b1c826000016140e8565b9050919050565b6000613b3283600001836140f9565b60001c905092915050565b6000613b518260000151836040015161350f565b8015613b7a5750613b6582600001516138e4565b80613b795750613b7882604001516139cf565b5b5b8015613b8a575060008260200151115b8015613b995750428260600151115b15613ba75760019050613ba8565b5b919050565b6000806000905060005b613bd5600f60008681526020019081526020016000206000016133da565b811015613d17576000613c0682600f60008881526020019081526020016000206000016133ef90919063ffffffff16565b90506000600f600087815260200190815260200160002060020160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060405180608001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016003820154815250509050613ce781613409565b613d0257613cff600185613d2190919063ffffffff16565b93505b50508080613d0f90615fc8565b915050613bb7565b5080915050919050565b60008183613d2f9190615df7565b905092915050565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b60005b613e24600f60008481526020019081526020016000206000016133da565b811015613fda576000613e5582600f60008681526020019081526020016000206000016133ef90919063ffffffff16565b90506000600f600085815260200190815260200160002060020160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060405180608001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016003820154815250509050613f3681613409565b613fc5576017613f6484600f60008881526020019081526020016000206000016133ef90919063ffffffff16565b9080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b50508080613fd290615fc8565b915050613e06565b5060005b60178054905081101561407257600060178281548110614027577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905061405e83826137b8565b50808061406a90615fc8565b915050613fde565b5060176000614081919061476d565b50565b6000614096836000018360001b61428b565b905092915050565b60006140b0836000018360001b6142fb565b905092915050565b60006140e0836000018373ffffffffffffffffffffffffffffffffffffffff1660001b61428b565b905092915050565b600081600001805490509050919050565b6000826000018281548110614137577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154905092915050565b600061415c836000018360001b61431e565b905092915050565b600061418c836000018373ffffffffffffffffffffffffffffffffffffffff1660001b6142fb565b905092915050565b60006141bc836000018373ffffffffffffffffffffffffffffffffffffffff1660001b61431e565b905092915050565b6000614226826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166144a49092919063ffffffff16565b905060008151111561428657808060200190518101906142469190614948565b614285576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161427c90615b61565b60405180910390fd5b5b505050565b600061429783836142fb565b6142f05782600001829080600181540180825580915050600190039060005260206000200160009091909190915055826000018054905083600101600084815260200190815260200160002081905550600190506142f5565b600090505b92915050565b600080836001016000848152602001908152602001600020541415905092915050565b600080836001016000848152602001908152602001600020549050600081146144985760006001826143509190615ed8565b90506000600186600001805490506143689190615ed8565b90508181146144235760008660000182815481106143af577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001549050808760000184815481106143f9577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001819055508387600101600083815260200190815260200160002081905550505b8560000180548061445d577f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061449e565b60009150505b92915050565b60606144b384846000856144bc565b90509392505050565b606082471015614501576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016144f8906159e1565b60405180910390fd5b61450a856145d0565b614549576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161454090615b41565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516145729190615799565b60006040518083038185875af1925050503d80600081146145af576040519150601f19603f3d011682016040523d82523d6000602084013e6145b4565b606091505b50915091506145c48282866145e3565b92505050949350505050565b600080823b905060008111915050919050565b606083156145f357829050614643565b6000835111156146065782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161463a919061589f565b60405180910390fd5b9392505050565b82805461465690615f96565b90600052602060002090601f01602090048101928261467857600085556146bf565b82601f1061469157805160ff19168380011785556146bf565b828001600101855582156146bf579182015b828111156146be5782518255916020019190600101906146a3565b5b5090506146cc919061478e565b5090565b60405180608001604052806000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600081525090565b508054600082559060005260206000209081019061472c919061478e565b50565b60405180608001604052806000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600081525090565b508054600082559060005260206000209081019061478b919061478e565b50565b5b808211156147a757600081600090555060010161478f565b5090565b60006147be6147b984615d23565b615cf2565b9050828152602081018484840111156147d657600080fd5b6147e1848285615f54565b509392505050565b6000813590506147f8816160de565b92915050565b60008151905061480d816160de565b92915050565b600081359050614822816160f5565b92915050565b600081519050614837816160f5565b92915050565b600082601f83011261484e57600080fd5b813561485e8482602086016147ab565b91505092915050565b6000813590506148768161610c565b92915050565b60008151905061488b8161610c565b92915050565b6000602082840312156148a357600080fd5b60006148b1848285016147e9565b91505092915050565b6000602082840312156148cc57600080fd5b60006148da848285016147fe565b91505092915050565b600080604083850312156148f657600080fd5b6000614904858286016147e9565b925050602061491585828601614867565b9150509250929050565b60006020828403121561493157600080fd5b600061493f84828501614813565b91505092915050565b60006020828403121561495a57600080fd5b600061496884828501614828565b91505092915050565b6000806040838503121561498457600080fd5b600083013567ffffffffffffffff81111561499e57600080fd5b6149aa8582860161483d565b92505060206149bb858286016147e9565b9150509250929050565b6000602082840312156149d757600080fd5b60006149e584828501614867565b91505092915050565b600060208284031215614a0057600080fd5b6000614a0e8482850161487c565b91505092915050565b60008060408385031215614a2a57600080fd5b6000614a3885828601614867565b9250506020614a49858286016147e9565b9150509250929050565b60008060408385031215614a6657600080fd5b6000614a7485828601614867565b9250506020614a8585828601614867565b9150509250929050565b600080600060608486031215614aa457600080fd5b6000614ab286828701614867565b9350506020614ac386828701614867565b9250506040614ad486828701614867565b9150509250925092565b6000614aea8383615627565b60808301905092915050565b6000614b0283836156d1565b60808301905092915050565b614b1781615f0c565b82525050565b614b2681615f0c565b82525050565b6000614b3782615d73565b614b418185615db9565b9350614b4c83615d53565b8060005b83811015614b7d578151614b648882614ade565b9750614b6f83615d9f565b925050600181019050614b50565b5085935050505092915050565b6000614b9582615d7e565b614b9f8185615dca565b9350614baa83615d63565b8060005b83811015614bdb578151614bc28882614af6565b9750614bcd83615dac565b925050600181019050614bae565b5085935050505092915050565b614bf181615f1e565b82525050565b6000614c0282615d89565b614c0c8185615ddb565b9350614c1c818560208601615f63565b80840191505092915050565b6000614c3382615d94565b614c3d8185615de6565b9350614c4d818560208601615f63565b614c56816160cd565b840191505092915050565b6000614c6e603583615de6565b91507f54686520746f6b656e206973206e6f7420617070726f76656420746f2074726160008301527f6e736665722062792074686520636f6e747261637400000000000000000000006020830152604082019050919050565b6000614cd4601883615de6565b91507f43616e27742073657420746f20616464726573732030783000000000000000006000830152602082019050919050565b6000614d14602683615de6565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000614d7a602583615de6565b91507f546f6b656e206f776e65722063616e277420627579207468656972206f776e2060008301527f746f6b656e0000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000614de0601f83615de6565b91507f4c697374696e6720616e642062696420617265206e6f7420656e61626c6564006000830152602082019050919050565b6000614e20601a83615de6565b91507f506c656173652062696420666f72206d6f7265207468616e20300000000000006000830152602082019050919050565b6000614e60603a83615de6565b91507f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260008301527f6563697069656e74206d617920686176652072657665727465640000000000006020830152604082019050919050565b6000614ec6602c83615de6565b91507f5468652076616c75652073656e642069732062656c6f772073616c652070726960008301527f636520706c7573206665657300000000000000000000000000000000000000006020830152604082019050919050565b6000614f2c601d83615de6565b91507f416464726573733a20696e73756666696369656e742062616c616e63650000006000830152602082019050919050565b6000614f6c602683615de6565b91507f416464726573733a20696e73756666696369656e742062616c616e636520666f60008301527f722063616c6c00000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000614fd2602583615de6565b91507f506c6561736520656e74657220612073686f7274657220706572696f64206f6660008301527f2074696d650000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000615038602283615de6565b91507f5468697320546f6b656e2062656c6f6e677320746f207468697320616464726560008301527f73730000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b600061509e603883615de6565b91507f506c65617365206c69737420666f72206d6f7265207468616e2030206f72207560008301527f736520746865207472616e736665722066756e6374696f6e00000000000000006020830152604082019050919050565b6000615104603683615de6565b91507f4e65656420746f206861766520656e6f75676820746f6b656e20686f6c64696e60008301527f6720746f20626964206f6e207468697320746f6b656e000000000000000000006020830152604082019050919050565b600061516a601583615de6565b91507f546f6b656e206973206e6f7420666f722073616c6500000000000000000000006000830152602082019050919050565b60006151aa602083615de6565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b60006151ea603683615de6565b91507f5468697320746f6b656e206973206e6f7420616c6c6f77656420746f2074726160008301527f6e73666572206279207468697320636f6e7472616374000000000000000000006020830152604082019050919050565b6000615250602683615de6565b91507f5468697320746f6b656e20646f65736e277420686176652061206d617463686960008301527f6e672062696400000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006152b6601883615de6565b91507f61756374696f6e3a2077726f6e6720646576656c6f70657200000000000000006000830152602082019050919050565b60006152f6602b83615de6565b91507f54686973206164647265737320646f65736e2774206861766520626964206f6e60008301527f207468697320746f6b656e0000000000000000000000000000000000000000006020830152604082019050919050565b600061535c600083615ddb565b9150600082019050919050565b6000615376601d83615de6565b91507f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006000830152602082019050919050565b60006153b6602a83615de6565b91507f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008301527f6f742073756363656564000000000000000000000000000000000000000000006020830152604082019050919050565b600061541c601f83615de6565b91507f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006000830152602082019050919050565b600061545c602283615de6565b91507f4f6e6c7920746f6b656e2073656c6c65722063616e2064656c69737420746f6b60008301527f656e0000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006154c2601f83615de6565b91507f4f6e6c7920746f6b656e206f776e65722063616e206c69737420746f6b656e006000830152602082019050919050565b6000615502602583615de6565b91507f416c6c6f7765642070657263656e746167652072616e6765206973203120746f60008301527f20313030300000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000615568602883615de6565b91507f4f6e6c7920746f6b656e206f776e65722063616e20616363657074206269642060008301527f6f6620746f6b656e0000000000000000000000000000000000000000000000006020830152604082019050919050565b60006155ce602483615de6565b91507f506c6561736520656e7465722061206c6f6e67657220706572696f64206f662060008301527f74696d65000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60808201600082015161563d600085018261577b565b506020820151615650602085018261577b565b5060408201516156636040850182614b0e565b506060820151615676606085018261577b565b50505050565b608082016000820151615692600085018261577b565b5060208201516156a5602085018261577b565b5060408201516156b86040850182614b0e565b5060608201516156cb606085018261577b565b50505050565b6080820160008201516156e7600085018261577b565b5060208201516156fa602085018261577b565b50604082015161570d6040850182614b0e565b506060820151615720606085018261577b565b50505050565b60808201600082015161573c600085018261577b565b50602082015161574f602085018261577b565b5060408201516157626040850182614b0e565b506060820151615775606085018261577b565b50505050565b61578481615f4a565b82525050565b61579381615f4a565b82525050565b60006157a58284614bf7565b915081905092915050565b60006157bb8261534f565b9150819050919050565b60006020820190506157da6000830184614b1d565b92915050565b60006040820190506157f56000830185614b1d565b6158026020830184614b1d565b9392505050565b600060608201905061581e6000830186614b1d565b61582b6020830185614b1d565b615838604083018461578a565b949350505050565b6000602082019050818103600083015261585a8184614b2c565b905092915050565b6000602082019050818103600083015261587c8184614b8a565b905092915050565b60006020820190506158996000830184614be8565b92915050565b600060208201905081810360008301526158b98184614c28565b905092915050565b600060208201905081810360008301526158da81614c61565b9050919050565b600060208201905081810360008301526158fa81614cc7565b9050919050565b6000602082019050818103600083015261591a81614d07565b9050919050565b6000602082019050818103600083015261593a81614d6d565b9050919050565b6000602082019050818103600083015261595a81614dd3565b9050919050565b6000602082019050818103600083015261597a81614e13565b9050919050565b6000602082019050818103600083015261599a81614e53565b9050919050565b600060208201905081810360008301526159ba81614eb9565b9050919050565b600060208201905081810360008301526159da81614f1f565b9050919050565b600060208201905081810360008301526159fa81614f5f565b9050919050565b60006020820190508181036000830152615a1a81614fc5565b9050919050565b60006020820190508181036000830152615a3a8161502b565b9050919050565b60006020820190508181036000830152615a5a81615091565b9050919050565b60006020820190508181036000830152615a7a816150f7565b9050919050565b60006020820190508181036000830152615a9a8161515d565b9050919050565b60006020820190508181036000830152615aba8161519d565b9050919050565b60006020820190508181036000830152615ada816151dd565b9050919050565b60006020820190508181036000830152615afa81615243565b9050919050565b60006020820190508181036000830152615b1a816152a9565b9050919050565b60006020820190508181036000830152615b3a816152e9565b9050919050565b60006020820190508181036000830152615b5a81615369565b9050919050565b60006020820190508181036000830152615b7a816153a9565b9050919050565b60006020820190508181036000830152615b9a8161540f565b9050919050565b60006020820190508181036000830152615bba8161544f565b9050919050565b60006020820190508181036000830152615bda816154b5565b9050919050565b60006020820190508181036000830152615bfa816154f5565b9050919050565b60006020820190508181036000830152615c1a8161555b565b9050919050565b60006020820190508181036000830152615c3a816155c1565b9050919050565b6000608082019050615c56600083018461567c565b92915050565b6000608082019050615c716000830184615726565b92915050565b6000602082019050615c8c600083018461578a565b92915050565b6000604082019050615ca7600083018561578a565b615cb4602083018461578a565b9392505050565b6000606082019050615cd0600083018661578a565b615cdd602083018561578a565b615cea604083018461578a565b949350505050565b6000604051905081810181811067ffffffffffffffff82111715615d1957615d1861609e565b5b8060405250919050565b600067ffffffffffffffff821115615d3e57615d3d61609e565b5b601f19601f8301169050602081019050919050565b6000819050602082019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b6000615e0282615f4a565b9150615e0d83615f4a565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115615e4257615e41616011565b5b828201905092915050565b6000615e5882615f4a565b9150615e6383615f4a565b925082615e7357615e72616040565b5b828204905092915050565b6000615e8982615f4a565b9150615e9483615f4a565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615ecd57615ecc616011565b5b828202905092915050565b6000615ee382615f4a565b9150615eee83615f4a565b925082821015615f0157615f00616011565b5b828203905092915050565b6000615f1782615f2a565b9050919050565b60008115159050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b82818337600083830152505050565b60005b83811015615f81578082015181840152602081019050615f66565b83811115615f90576000848401525b50505050565b60006002820490506001821680615fae57607f821691505b60208210811415615fc257615fc161606f565b5b50919050565b6000615fd382615f4a565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561600657616005616011565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b6160e781615f0c565b81146160f257600080fd5b50565b6160fe81615f1e565b811461610957600080fd5b50565b61611581615f4a565b811461612057600080fd5b5056fea26469706673582212202960e019675b96585fec0ccae4964c47915abbeefac2d12c4113ab611318e7b564736f6c6343000800003300000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000dc24fd5175f07c7a63576062b4d8279013217a44000000000000000000000000f194afdf50b03e69bd7d057c1aa9e10c9954e4c9000000000000000000000000d0841b274231a348d352e0786afb1632a21b7705000000000000000000000000d0841b274231a348d352e0786afb1632a21b7705000000000000000000000000000000000000000000000000000000000000000444616f7300000000000000000000000000000000000000000000000000000000
Deployed ByteCode
0x6080604052600436106102515760003560e01c806388a8c95c11610139578063b6be53ba116100b6578063e15487021161007a578063e15487021461085c578063e724488114610887578063e7d585a8146108b0578063f0e6dcab146108ed578063f2fde38b14610918578063f4ecbff11461094157610251565b8063b6be53ba1461078d578063b7e6a194146107b6578063bce64a7d146107e1578063bed659bc1461080a578063d9420c2a1461083357610251565b806398792eec116100fd57806398792eec146106a65780639d76ea58146106e3578063a3c0b5f01461070e578063a6a27f3a14610737578063afb18fe71461076257610251565b806388a8c95c146105d05780638abdf5aa146105f95780638da5cb5b146106255780638ece265a1461065057806391cca3db1461067b57610251565b8063453dfc50116101d257806370d840b51161019657806370d840b5146104e6578063715018a61461051157806373885b701461052857806375ccb1f2146105535780637d7660e01461059057806385f5a92a146105a757610251565b8063453dfc50146103eb57806354b0de6a146104165780635cc2c66b1461044157806365667aaa1461047e57806370a3b390146104a957610251565b806333549d3d1161021957806333549d3d1461032a57806333623c0a14610355578063336c16c614610380578063383fba25146103a957806340a97919146103c057610251565b806315f2d5c5146102565780631d2d3ed21461027f5780631e56afe9146102a85780632426fc24146102e55780632d296bf11461030e575b600080fd5b34801561026257600080fd5b5061027d600480360381019061027891906148e3565b61096a565b005b34801561028b57600080fd5b506102a660048036038101906102a19190614971565b610b3f565b005b3480156102b457600080fd5b506102cf60048036038101906102ca91906149c5565b610c2b565b6040516102dc9190615c41565b60405180910390f35b3480156102f157600080fd5b5061030c600480360381019061030791906149c5565b610ddf565b005b610328600480360381019061032391906149c5565b610e79565b005b34801561033657600080fd5b5061033f61126b565b60405161034c9190615c77565b60405180910390f35b34801561036157600080fd5b5061036a611275565b6040516103779190615c77565b60405180910390f35b34801561038c57600080fd5b506103a760048036038101906103a29190614a17565b61127b565b005b3480156103b557600080fd5b506103be61170f565b005b3480156103cc57600080fd5b506103d5611899565b6040516103e29190615c77565b60405180910390f35b3480156103f757600080fd5b506104006118ff565b60405161040d9190615c77565b60405180910390f35b34801561042257600080fd5b5061042b611909565b6040516104389190615840565b60405180910390f35b34801561044d57600080fd5b5061046860048036038101906104639190614a53565b611924565b6040516104759190615840565b60405180910390f35b34801561048a57600080fd5b50610493611a95565b6040516104a09190615c77565b60405180910390f35b3480156104b557600080fd5b506104d060048036038101906104cb9190614a17565b611a9b565b6040516104dd9190615c41565b60405180910390f35b3480156104f257600080fd5b506104fb611b98565b60405161050891906157c5565b60405180910390f35b34801561051d57600080fd5b50610526611bbe565b005b34801561053457600080fd5b5061053d611c46565b60405161054a919061589f565b60405180910390f35b34801561055f57600080fd5b5061057a60048036038101906105759190614a53565b611cd8565b6040516105879190615862565b60405180910390f35b34801561059c57600080fd5b506105a5611ee7565b005b3480156105b357600080fd5b506105ce60048036038101906105c991906149c5565b611fea565b005b3480156105dc57600080fd5b506105f760048036038101906105f29190614891565b612197565b005b34801561060557600080fd5b5061060e61226b565b60405161061c929190615c92565b60405180910390f35b34801561063157600080fd5b5061063a61227c565b60405161064791906157c5565b60405180910390f35b34801561065c57600080fd5b506106656122a5565b6040516106729190615c77565b60405180910390f35b34801561068757600080fd5b506106906122ab565b60405161069d91906157c5565b60405180910390f35b3480156106b257600080fd5b506106cd60048036038101906106c891906149c5565b6122d1565b6040516106da9190615c5c565b60405180910390f35b3480156106ef57600080fd5b506106f861238d565b60405161070591906157c5565b60405180910390f35b34801561071a57600080fd5b50610735600480360381019061073091906149c5565b6123b7565b005b34801561074357600080fd5b5061074c612451565b6040516107599190615c77565b60405180910390f35b34801561076e57600080fd5b5061077761254f565b60405161078491906157c5565b60405180910390f35b34801561079957600080fd5b506107b460048036038101906107af919061491f565b612577565b005b3480156107c257600080fd5b506107cb612624565b6040516107d891906157c5565b60405180910390f35b3480156107ed57600080fd5b5061080860048036038101906108039190614a8f565b61264a565b005b34801561081657600080fd5b50610831600480360381019061082c91906149c5565b612948565b005b34801561083f57600080fd5b5061085a60048036038101906108559190614891565b612a72565b005b34801561086857600080fd5b50610871612af4565b60405161087e9190615862565b60405180910390f35b34801561089357600080fd5b506108ae60048036038101906108a99190614a8f565b612b0f565b005b3480156108bc57600080fd5b506108d760048036038101906108d291906149c5565b612f2b565b6040516108e49190615840565b60405180910390f35b3480156108f957600080fd5b50610902613165565b60405161090f9190615884565b60405180910390f35b34801561092457600080fd5b5061093f600480360381019061093a9190614891565b61317c565b005b34801561094d57600080fd5b50610968600480360381019061096391906148e3565b613274565b005b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146109fa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109f190615b01565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610a6a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a61906158e1565b60405180910390fd5b600081118015610a7b575060648111155b610aba576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ab190615be1565b60405180910390fd5b81601260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600681905550600754600654600954610b159190615ed8565b610b1f9190615ed8565b600581905550600754600654610b359190615df7565b6008819055505050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610bcf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bc690615b01565b60405180910390fd5b8160039080519060200190610be592919061464a565b5080600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b610c336146d0565b6000604051806080016040528084815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020016000815250905060005b610c92600f60008681526020019081526020016000206000016133da565b811015610dd5576000610cc382600f60008881526020019081526020016000206000016133ef90919063ffffffff16565b90506000600f600087815260200190815260200160002060020160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060405180608001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016003820154815250509050610da481613409565b8015610db7575083602001518160200151115b15610dc0578093505b50508080610dcd90615fc8565b915050610c74565b5080915050919050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610e6f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e6690615b01565b60405180910390fd5b80600a8190555050565b60026001541415610ebf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eb690615b81565b60405180910390fd5b60026001819055506000610ed2826122d1565b9050600073ffffffffffffffffffffffffffffffffffffffff16816040015173ffffffffffffffffffffffffffffffffffffffff161415610f48576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f3f90615a81565b60405180910390fd5b610f52823361350f565b15610f92576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f8990615921565b60405180910390fd5b6000610fc1600954610fb360085485602001516135fb90919063ffffffff16565b61361190919063ffffffff16565b9050816020015134101561100a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611001906159a1565b60405180910390fd5b600061101f823461362790919063ffffffff16565b9050600061104c60095461103e600654346135fb90919063ffffffff16565b61361190919063ffffffff16565b9050600061107960095461106b600754346135fb90919063ffffffff16565b61361190919063ffffffff16565b905061108985604001518461363d565b6110b5601360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168261363d565b600073ffffffffffffffffffffffffffffffffffffffff16601260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141580156111145750600082115b1561114657611145601260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168361363d565b5b3373ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff16877f1d83c44501b48d5dc85fea9b94506cda160418d62c65b481199bdbec265df1573487896040516111ac93929190615cbb565b60405180910390a4600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166342842e0e866040015133896040518463ffffffff1660e01b815260040161121793929190615809565b600060405180830381600087803b15801561123157600080fd5b505af1158015611245573d6000803e3d6000fd5b5050505061125286613731565b61125c86336137b8565b50505050506001808190555050565b6000600a54905090565b60055481565b600260015414156112c1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112b890615b81565b60405180910390fd5b60026001819055506112d3823361350f565b611312576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161130990615c01565b60405180910390fd5b61131b826138e4565b8061132b575061132a336139cf565b5b61136a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611361906158c1565b60405180910390fd5b60006113768383611a9b565b9050600081602001511180156113bb57508173ffffffffffffffffffffffffffffffffffffffff16816040015173ffffffffffffffffffffffffffffffffffffffff16145b6113fa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113f190615ae1565b60405180910390fd5b600061142960095461141b60085485602001516135fb90919063ffffffff16565b61361190919063ffffffff16565b9050600061144482846020015161362790919063ffffffff16565b9050600061147560095461146760065487602001516135fb90919063ffffffff16565b61361190919063ffffffff16565b905060006114a660095461149860075488602001516135fb90919063ffffffff16565b61361190919063ffffffff16565b90506114d87f000000000000000000000000f194afdf50b03e69bd7d057c1aa9e10c9954e4c986604001513386613a85565b61152a7f000000000000000000000000f194afdf50b03e69bd7d057c1aa9e10c9954e4c98660400151601360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684613a85565b600073ffffffffffffffffffffffffffffffffffffffff16601260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141580156115895750600082115b156115e1576115e07f000000000000000000000000f194afdf50b03e69bd7d057c1aa9e10c9954e4c98660400151601260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1685613a85565b5b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166342842e0e3387604001518a6040518463ffffffff1660e01b815260040161164493929190615809565b600060405180830381600087803b15801561165e57600080fd5b505af1158015611672573d6000803e3d6000fd5b50505050846040015173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16887f2c907f0c6ace0ad59e44f69f6873314bb2b85cca7eeffb05ca93fa65326bfbb4886020015187896040516116e093929190615cbb565b60405180910390a46116f187613731565b6116ff8786604001516137b8565b5050505050600180819055505050565b60005b61171c600d613b0e565b81101561181757600061173982600d613b2390919063ffffffff16565b90506117d5600c600083815260200190815260200160002060405180608001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600382015481525050613b3d565b6118035760168190806001815401808255809150506001900390600052602060002001600090919091909150555b50808061180f90615fc8565b915050611712565b5060005b6016805490508110156118885761187560168281548110611865577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154613731565b808061188090615fc8565b91505061181b565b5060166000611897919061470e565b565b6000806000905060005b6118ad6010613b0e565b8110156118f7576118e26118d36118ce836010613b2390919063ffffffff16565b613bad565b83613d2190919063ffffffff16565b915080806118ef90615fc8565b9150506118a3565b508091505090565b6000600b54905090565b606061191f600061191a6010613b0e565b611924565b905090565b60606119306010613b0e565b8310801561193e5750600082115b15611a8e5760008290506119526010613b0e565b838561195e9190615df7565b111561197c578361196f6010613b0e565b6119799190615ed8565b90505b60008167ffffffffffffffff8111156119be577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519080825280602002602001820160405280156119f757816020015b6119e46146d0565b8152602001906001900390816119dc5790505b50905060005b82811015611a8357611a2c611a278783611a179190615df7565b6010613b2390919063ffffffff16565b610c2b565b828281518110611a65577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200260200101819052508080611a7b90615fc8565b9150506119fd565b508092505050611a8f565b5b92915050565b60075481565b611aa36146d0565b6000600f600085815260200190815260200160002060020160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060405180608001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016003820154815250509050611b8281613409565b15611b905780915050611b92565b505b92915050565b601260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b611bc6613d37565b73ffffffffffffffffffffffffffffffffffffffff16611be461227c565b73ffffffffffffffffffffffffffffffffffffffff1614611c3a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c3190615aa1565b60405180910390fd5b611c446000613d3f565b565b606060038054611c5590615f96565b80601f0160208091040260200160405190810160405280929190818152602001828054611c8190615f96565b8015611cce5780601f10611ca357610100808354040283529160200191611cce565b820191906000526020600020905b815481529060010190602001808311611cb157829003601f168201915b5050505050905090565b6060611ce4600d613b0e565b83108015611cf25750600082115b15611ee0576000829050611d06600d613b0e565b8385611d129190615df7565b1115611d305783611d23600d613b0e565b611d2d9190615ed8565b90505b60008167ffffffffffffffff811115611d72577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051908082528060200260200182016040528015611dab57816020015b611d9861472f565b815260200190600190039081611d905790505b50905060005b82811015611ed5576000600c6000611dde8985611dce9190615df7565b600d613b2390919063ffffffff16565b815260200190815260200160002060405180608001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016003820154815250509050611e7681613b3d565b15611ec15780838381518110611eb5577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200260200101819052505b508080611ecd90615fc8565b915050611db1565b508092505050611ee1565b5b92915050565b60005b611ef46010613b0e565b811015611f68576000611f11826010613b2390919063ffffffff16565b90506000611f1e82613bad565b90506000811115611f535760168290806001815401808255809150506001900390600052602060002001600090919091909150555b50508080611f6090615fc8565b915050611eea565b5060005b601680549050811015611fd957611fc660168281548110611fb6577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154613e03565b8080611fd190615fc8565b915050611f6c565b5060166000611fe8919061470e565b565b6000600f600083815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060405180608001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160038201548152505090503373ffffffffffffffffffffffffffffffffffffffff16816040015173ffffffffffffffffffffffffffffffffffffffff1614612132576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161212990615b21565b60405180910390fd5b806040015173ffffffffffffffffffffffffffffffffffffffff16827f4afa471ce7ab7fa67258e3afb1adf7e899e0495602eeb26d90d41e1b64dea5a683602001516040516121819190615c77565b60405180910390a361219382336137b8565b5050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612227576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161221e90615b01565b60405180910390fd5b80600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600080600854600954915091509091565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60065481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6122d961472f565b6000600c600084815260200190815260200160002060405180608001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600382015481525050905061237881613b3d565b156123865780915050612388565b505b919050565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612447576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161243e90615b01565b60405180910390fd5b80600b8190555050565b6000806000905060005b612465600d613b0e565b81101561254757612519600c600061248784600d613b2390919063ffffffff16565b815260200190815260200160002060405180608001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600382015481525050613b3d565b61253457612531600183613d2190919063ffffffff16565b91505b808061253f90615fc8565b91505061245b565b508091505090565b60007f000000000000000000000000f194afdf50b03e69bd7d057c1aa9e10c9954e4c9905090565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612607576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125fe90615b01565b60405180910390fd5b80600460146101000a81548160ff02191690831515021790555050565b601360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600460149054906101000a900460ff16612699576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161269090615941565b60405180910390fd5b80600a546126b0428361362790919063ffffffff16565b10156126f1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126e890615c21565b60405180910390fd5b600b54612707428361362790919063ffffffff16565b1115612748576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161273f90615a01565b60405180910390fd5b6000831161278b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161278290615a41565b60405180910390fd5b612795843361350f565b6127d4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127cb90615bc1565b60405180910390fd5b6127dd846138e4565b806127ed57506127ec336139cf565b5b61282c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161282390615ac1565b60405180910390fd5b60405180608001604052808581526020018481526020013373ffffffffffffffffffffffffffffffffffffffff16815260200183815250600c6000868152602001908152602001600020600082015181600001556020820151816001015560408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550606082015181600301559050506128f284600d61408490919063ffffffff16565b503373ffffffffffffffffffffffffffffffffffffffff16847f7765a1c07bdce3390c521eaeb86030b188b77cbaba2d76bd7c9c32d906bfbcba8560405161293a9190615c77565b60405180910390a350505050565b3373ffffffffffffffffffffffffffffffffffffffff16600c600083815260200190815260200160002060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146129ec576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129e390615ba1565b60405180910390fd5b600c600082815260200190815260200160002060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16817f70a382c18b6e794d86997f6e1f1efca577925cfa85c476a6ff7031f0a3dd6ed060405160405180910390a3612a6f81613731565b50565b80601260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612af15760006006819055505b50565b6060612b0a6000612b05600d613b0e565b611cd8565b905090565b600460149054906101000a900460ff16612b5e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b5590615941565b60405180910390fd5b80600a54612b75428361362790919063ffffffff16565b1015612bb6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612bad90615c21565b60405180910390fd5b600b54612bcc428361362790919063ffffffff16565b1115612c0d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c0490615a01565b60405180910390fd5b60008311612c50576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c4790615961565b60405180910390fd5b612c5a843361350f565b15612c9a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c9190615a21565b60405180910390fd5b827f000000000000000000000000f194afdf50b03e69bd7d057c1aa9e10c9954e4c973ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e33306040518363ffffffff1660e01b8152600401612cf69291906157e0565b60206040518083038186803b158015612d0e57600080fd5b505afa158015612d22573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4691906149ee565b1015612d87576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d7e90615a61565b60405180910390fd5b600060405180608001604052808681526020018581526020013373ffffffffffffffffffffffffffffffffffffffff168152602001848152509050612dd685601061409e90919063ffffffff16565b612df057612dee85601061408490919063ffffffff16565b505b612e1833600f60008881526020019081526020016000206000016140b890919063ffffffff16565b5080600f600087815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082015181600001556020820151816001015560408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550606082015181600301559050503373ffffffffffffffffffffffffffffffffffffffff16857f0ea16c10401e9d7c547471845914c4a904af6a01b9fa1e195eeecae9f78bcca186604051612f1c9190615c77565b60405180910390a35050505050565b60606000612f4d600f60008581526020019081526020016000206000016133da565b67ffffffffffffffff811115612f8c577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051908082528060200260200182016040528015612fc557816020015b612fb26146d0565b815260200190600190039081612faa5790505b50905060005b612fe9600f60008681526020019081526020016000206000016133da565b81101561315b57600061301a82600f60008881526020019081526020016000206000016133ef90919063ffffffff16565b90506000600f600087815260200190815260200160002060020160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060405180608001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160038201548152505090506130fb81613409565b15613146578084848151811061313a577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200260200101819052505b5050808061315390615fc8565b915050612fcb565b5080915050919050565b6000600460149054906101000a900460ff16905090565b613184613d37565b73ffffffffffffffffffffffffffffffffffffffff166131a261227c565b73ffffffffffffffffffffffffffffffffffffffff16146131f8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016131ef90615aa1565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415613268576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161325f90615901565b60405180910390fd5b61327181613d3f565b50565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614613304576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016132fb90615b01565b60405180910390fd5b60008111801561331657506103e88111155b613355576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161334c90615be1565b60405180910390fd5b81601360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550806007819055506007546006546009546133b09190615ed8565b6133ba9190615ed8565b6005819055506007546006546133d09190615df7565b6008819055505050565b60006133e8826000016140e8565b9050919050565b60006133fe83600001836140f9565b60001c905092915050565b600061341d8260000151836040015161350f565b1580156134dc575081602001517f000000000000000000000000f194afdf50b03e69bd7d057c1aa9e10c9954e4c973ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e8460400151306040518363ffffffff1660e01b81526004016134899291906157e0565b60206040518083038186803b1580156134a157600080fd5b505afa1580156134b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134d991906149ee565b10155b80156134ec575060008260200151115b80156134fb5750428260600151115b15613509576001905061350a565b5b919050565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636352211e846040518263ffffffff1660e01b815260040161356c9190615c77565b60206040518083038186803b15801561358457600080fd5b505afa9250505080156135b557506040513d601f19601f820116820180604052508101906135b291906148ba565b60015b6135c257600090506135f5565b8273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16149150505b92915050565b600081836136099190615e7e565b905092915050565b6000818361361f9190615e4d565b905092915050565b600081836136359190615ed8565b905092915050565b80471015613680576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613677906159c1565b60405180910390fd5b60008273ffffffffffffffffffffffffffffffffffffffff16826040516136a6906157b0565b60006040518083038185875af1925050503d80600081146136e3576040519150601f19603f3d011682016040523d82523d6000602084013e6136e8565b606091505b505090508061372c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161372390615981565b60405180910390fd5b505050565b61374581600d61409e90919063ffffffff16565b156137b557600c600082815260200190815260200160002060008082016000905560018201600090556002820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600382016000905550506137b381600d61414a90919063ffffffff16565b505b50565b6137e081600f600085815260200190815260200160002060000161416490919063ffffffff16565b156138e057600f600083815260200190815260200160002060020160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008082016000905560018201600090556002820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600382016000905550506138a281600f600085815260200190815260200160002060000161419490919063ffffffff16565b5060006138c3600f60008581526020019081526020016000206000016133da565b14156138df576138dd82601061414a90919063ffffffff16565b505b5b5050565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663081812fc836040518263ffffffff1660e01b81526004016139419190615c77565b60206040518083038186803b15801561395957600080fd5b505afa92505050801561398a57506040513d601f19601f8201168201806040525081019061398791906148ba565b60015b61399757600090506139ca565b3073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16149150505b919050565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e985e9c583306040518363ffffffff1660e01b8152600401613a2e9291906157e0565b60206040518083038186803b158015613a4657600080fd5b505afa158015613a5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a7e9190614948565b9050919050565b613b08846323b872dd60e01b858585604051602401613aa693929190615809565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506141c4565b50505050565b6000613b1c826000016140e8565b9050919050565b6000613b3283600001836140f9565b60001c905092915050565b6000613b518260000151836040015161350f565b8015613b7a5750613b6582600001516138e4565b80613b795750613b7882604001516139cf565b5b5b8015613b8a575060008260200151115b8015613b995750428260600151115b15613ba75760019050613ba8565b5b919050565b6000806000905060005b613bd5600f60008681526020019081526020016000206000016133da565b811015613d17576000613c0682600f60008881526020019081526020016000206000016133ef90919063ffffffff16565b90506000600f600087815260200190815260200160002060020160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060405180608001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016003820154815250509050613ce781613409565b613d0257613cff600185613d2190919063ffffffff16565b93505b50508080613d0f90615fc8565b915050613bb7565b5080915050919050565b60008183613d2f9190615df7565b905092915050565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b60005b613e24600f60008481526020019081526020016000206000016133da565b811015613fda576000613e5582600f60008681526020019081526020016000206000016133ef90919063ffffffff16565b90506000600f600085815260200190815260200160002060020160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060405180608001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016003820154815250509050613f3681613409565b613fc5576017613f6484600f60008881526020019081526020016000206000016133ef90919063ffffffff16565b9080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b50508080613fd290615fc8565b915050613e06565b5060005b60178054905081101561407257600060178281548110614027577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905061405e83826137b8565b50808061406a90615fc8565b915050613fde565b5060176000614081919061476d565b50565b6000614096836000018360001b61428b565b905092915050565b60006140b0836000018360001b6142fb565b905092915050565b60006140e0836000018373ffffffffffffffffffffffffffffffffffffffff1660001b61428b565b905092915050565b600081600001805490509050919050565b6000826000018281548110614137577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154905092915050565b600061415c836000018360001b61431e565b905092915050565b600061418c836000018373ffffffffffffffffffffffffffffffffffffffff1660001b6142fb565b905092915050565b60006141bc836000018373ffffffffffffffffffffffffffffffffffffffff1660001b61431e565b905092915050565b6000614226826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166144a49092919063ffffffff16565b905060008151111561428657808060200190518101906142469190614948565b614285576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161427c90615b61565b60405180910390fd5b5b505050565b600061429783836142fb565b6142f05782600001829080600181540180825580915050600190039060005260206000200160009091909190915055826000018054905083600101600084815260200190815260200160002081905550600190506142f5565b600090505b92915050565b600080836001016000848152602001908152602001600020541415905092915050565b600080836001016000848152602001908152602001600020549050600081146144985760006001826143509190615ed8565b90506000600186600001805490506143689190615ed8565b90508181146144235760008660000182815481106143af577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001549050808760000184815481106143f9577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001819055508387600101600083815260200190815260200160002081905550505b8560000180548061445d577f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061449e565b60009150505b92915050565b60606144b384846000856144bc565b90509392505050565b606082471015614501576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016144f8906159e1565b60405180910390fd5b61450a856145d0565b614549576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161454090615b41565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516145729190615799565b60006040518083038185875af1925050503d80600081146145af576040519150601f19603f3d011682016040523d82523d6000602084013e6145b4565b606091505b50915091506145c48282866145e3565b92505050949350505050565b600080823b905060008111915050919050565b606083156145f357829050614643565b6000835111156146065782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161463a919061589f565b60405180910390fd5b9392505050565b82805461465690615f96565b90600052602060002090601f01602090048101928261467857600085556146bf565b82601f1061469157805160ff19168380011785556146bf565b828001600101855582156146bf579182015b828111156146be5782518255916020019190600101906146a3565b5b5090506146cc919061478e565b5090565b60405180608001604052806000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600081525090565b508054600082559060005260206000209081019061472c919061478e565b50565b60405180608001604052806000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600081525090565b508054600082559060005260206000209081019061478b919061478e565b50565b5b808211156147a757600081600090555060010161478f565b5090565b60006147be6147b984615d23565b615cf2565b9050828152602081018484840111156147d657600080fd5b6147e1848285615f54565b509392505050565b6000813590506147f8816160de565b92915050565b60008151905061480d816160de565b92915050565b600081359050614822816160f5565b92915050565b600081519050614837816160f5565b92915050565b600082601f83011261484e57600080fd5b813561485e8482602086016147ab565b91505092915050565b6000813590506148768161610c565b92915050565b60008151905061488b8161610c565b92915050565b6000602082840312156148a357600080fd5b60006148b1848285016147e9565b91505092915050565b6000602082840312156148cc57600080fd5b60006148da848285016147fe565b91505092915050565b600080604083850312156148f657600080fd5b6000614904858286016147e9565b925050602061491585828601614867565b9150509250929050565b60006020828403121561493157600080fd5b600061493f84828501614813565b91505092915050565b60006020828403121561495a57600080fd5b600061496884828501614828565b91505092915050565b6000806040838503121561498457600080fd5b600083013567ffffffffffffffff81111561499e57600080fd5b6149aa8582860161483d565b92505060206149bb858286016147e9565b9150509250929050565b6000602082840312156149d757600080fd5b60006149e584828501614867565b91505092915050565b600060208284031215614a0057600080fd5b6000614a0e8482850161487c565b91505092915050565b60008060408385031215614a2a57600080fd5b6000614a3885828601614867565b9250506020614a49858286016147e9565b9150509250929050565b60008060408385031215614a6657600080fd5b6000614a7485828601614867565b9250506020614a8585828601614867565b9150509250929050565b600080600060608486031215614aa457600080fd5b6000614ab286828701614867565b9350506020614ac386828701614867565b9250506040614ad486828701614867565b9150509250925092565b6000614aea8383615627565b60808301905092915050565b6000614b0283836156d1565b60808301905092915050565b614b1781615f0c565b82525050565b614b2681615f0c565b82525050565b6000614b3782615d73565b614b418185615db9565b9350614b4c83615d53565b8060005b83811015614b7d578151614b648882614ade565b9750614b6f83615d9f565b925050600181019050614b50565b5085935050505092915050565b6000614b9582615d7e565b614b9f8185615dca565b9350614baa83615d63565b8060005b83811015614bdb578151614bc28882614af6565b9750614bcd83615dac565b925050600181019050614bae565b5085935050505092915050565b614bf181615f1e565b82525050565b6000614c0282615d89565b614c0c8185615ddb565b9350614c1c818560208601615f63565b80840191505092915050565b6000614c3382615d94565b614c3d8185615de6565b9350614c4d818560208601615f63565b614c56816160cd565b840191505092915050565b6000614c6e603583615de6565b91507f54686520746f6b656e206973206e6f7420617070726f76656420746f2074726160008301527f6e736665722062792074686520636f6e747261637400000000000000000000006020830152604082019050919050565b6000614cd4601883615de6565b91507f43616e27742073657420746f20616464726573732030783000000000000000006000830152602082019050919050565b6000614d14602683615de6565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000614d7a602583615de6565b91507f546f6b656e206f776e65722063616e277420627579207468656972206f776e2060008301527f746f6b656e0000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000614de0601f83615de6565b91507f4c697374696e6720616e642062696420617265206e6f7420656e61626c6564006000830152602082019050919050565b6000614e20601a83615de6565b91507f506c656173652062696420666f72206d6f7265207468616e20300000000000006000830152602082019050919050565b6000614e60603a83615de6565b91507f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260008301527f6563697069656e74206d617920686176652072657665727465640000000000006020830152604082019050919050565b6000614ec6602c83615de6565b91507f5468652076616c75652073656e642069732062656c6f772073616c652070726960008301527f636520706c7573206665657300000000000000000000000000000000000000006020830152604082019050919050565b6000614f2c601d83615de6565b91507f416464726573733a20696e73756666696369656e742062616c616e63650000006000830152602082019050919050565b6000614f6c602683615de6565b91507f416464726573733a20696e73756666696369656e742062616c616e636520666f60008301527f722063616c6c00000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000614fd2602583615de6565b91507f506c6561736520656e74657220612073686f7274657220706572696f64206f6660008301527f2074696d650000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000615038602283615de6565b91507f5468697320546f6b656e2062656c6f6e677320746f207468697320616464726560008301527f73730000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b600061509e603883615de6565b91507f506c65617365206c69737420666f72206d6f7265207468616e2030206f72207560008301527f736520746865207472616e736665722066756e6374696f6e00000000000000006020830152604082019050919050565b6000615104603683615de6565b91507f4e65656420746f206861766520656e6f75676820746f6b656e20686f6c64696e60008301527f6720746f20626964206f6e207468697320746f6b656e000000000000000000006020830152604082019050919050565b600061516a601583615de6565b91507f546f6b656e206973206e6f7420666f722073616c6500000000000000000000006000830152602082019050919050565b60006151aa602083615de6565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b60006151ea603683615de6565b91507f5468697320746f6b656e206973206e6f7420616c6c6f77656420746f2074726160008301527f6e73666572206279207468697320636f6e7472616374000000000000000000006020830152604082019050919050565b6000615250602683615de6565b91507f5468697320746f6b656e20646f65736e277420686176652061206d617463686960008301527f6e672062696400000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006152b6601883615de6565b91507f61756374696f6e3a2077726f6e6720646576656c6f70657200000000000000006000830152602082019050919050565b60006152f6602b83615de6565b91507f54686973206164647265737320646f65736e2774206861766520626964206f6e60008301527f207468697320746f6b656e0000000000000000000000000000000000000000006020830152604082019050919050565b600061535c600083615ddb565b9150600082019050919050565b6000615376601d83615de6565b91507f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006000830152602082019050919050565b60006153b6602a83615de6565b91507f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008301527f6f742073756363656564000000000000000000000000000000000000000000006020830152604082019050919050565b600061541c601f83615de6565b91507f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006000830152602082019050919050565b600061545c602283615de6565b91507f4f6e6c7920746f6b656e2073656c6c65722063616e2064656c69737420746f6b60008301527f656e0000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006154c2601f83615de6565b91507f4f6e6c7920746f6b656e206f776e65722063616e206c69737420746f6b656e006000830152602082019050919050565b6000615502602583615de6565b91507f416c6c6f7765642070657263656e746167652072616e6765206973203120746f60008301527f20313030300000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000615568602883615de6565b91507f4f6e6c7920746f6b656e206f776e65722063616e20616363657074206269642060008301527f6f6620746f6b656e0000000000000000000000000000000000000000000000006020830152604082019050919050565b60006155ce602483615de6565b91507f506c6561736520656e7465722061206c6f6e67657220706572696f64206f662060008301527f74696d65000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60808201600082015161563d600085018261577b565b506020820151615650602085018261577b565b5060408201516156636040850182614b0e565b506060820151615676606085018261577b565b50505050565b608082016000820151615692600085018261577b565b5060208201516156a5602085018261577b565b5060408201516156b86040850182614b0e565b5060608201516156cb606085018261577b565b50505050565b6080820160008201516156e7600085018261577b565b5060208201516156fa602085018261577b565b50604082015161570d6040850182614b0e565b506060820151615720606085018261577b565b50505050565b60808201600082015161573c600085018261577b565b50602082015161574f602085018261577b565b5060408201516157626040850182614b0e565b506060820151615775606085018261577b565b50505050565b61578481615f4a565b82525050565b61579381615f4a565b82525050565b60006157a58284614bf7565b915081905092915050565b60006157bb8261534f565b9150819050919050565b60006020820190506157da6000830184614b1d565b92915050565b60006040820190506157f56000830185614b1d565b6158026020830184614b1d565b9392505050565b600060608201905061581e6000830186614b1d565b61582b6020830185614b1d565b615838604083018461578a565b949350505050565b6000602082019050818103600083015261585a8184614b2c565b905092915050565b6000602082019050818103600083015261587c8184614b8a565b905092915050565b60006020820190506158996000830184614be8565b92915050565b600060208201905081810360008301526158b98184614c28565b905092915050565b600060208201905081810360008301526158da81614c61565b9050919050565b600060208201905081810360008301526158fa81614cc7565b9050919050565b6000602082019050818103600083015261591a81614d07565b9050919050565b6000602082019050818103600083015261593a81614d6d565b9050919050565b6000602082019050818103600083015261595a81614dd3565b9050919050565b6000602082019050818103600083015261597a81614e13565b9050919050565b6000602082019050818103600083015261599a81614e53565b9050919050565b600060208201905081810360008301526159ba81614eb9565b9050919050565b600060208201905081810360008301526159da81614f1f565b9050919050565b600060208201905081810360008301526159fa81614f5f565b9050919050565b60006020820190508181036000830152615a1a81614fc5565b9050919050565b60006020820190508181036000830152615a3a8161502b565b9050919050565b60006020820190508181036000830152615a5a81615091565b9050919050565b60006020820190508181036000830152615a7a816150f7565b9050919050565b60006020820190508181036000830152615a9a8161515d565b9050919050565b60006020820190508181036000830152615aba8161519d565b9050919050565b60006020820190508181036000830152615ada816151dd565b9050919050565b60006020820190508181036000830152615afa81615243565b9050919050565b60006020820190508181036000830152615b1a816152a9565b9050919050565b60006020820190508181036000830152615b3a816152e9565b9050919050565b60006020820190508181036000830152615b5a81615369565b9050919050565b60006020820190508181036000830152615b7a816153a9565b9050919050565b60006020820190508181036000830152615b9a8161540f565b9050919050565b60006020820190508181036000830152615bba8161544f565b9050919050565b60006020820190508181036000830152615bda816154b5565b9050919050565b60006020820190508181036000830152615bfa816154f5565b9050919050565b60006020820190508181036000830152615c1a8161555b565b9050919050565b60006020820190508181036000830152615c3a816155c1565b9050919050565b6000608082019050615c56600083018461567c565b92915050565b6000608082019050615c716000830184615726565b92915050565b6000602082019050615c8c600083018461578a565b92915050565b6000604082019050615ca7600083018561578a565b615cb4602083018461578a565b9392505050565b6000606082019050615cd0600083018661578a565b615cdd602083018561578a565b615cea604083018461578a565b949350505050565b6000604051905081810181811067ffffffffffffffff82111715615d1957615d1861609e565b5b8060405250919050565b600067ffffffffffffffff821115615d3e57615d3d61609e565b5b601f19601f8301169050602081019050919050565b6000819050602082019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b6000615e0282615f4a565b9150615e0d83615f4a565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115615e4257615e41616011565b5b828201905092915050565b6000615e5882615f4a565b9150615e6383615f4a565b925082615e7357615e72616040565b5b828204905092915050565b6000615e8982615f4a565b9150615e9483615f4a565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615ecd57615ecc616011565b5b828202905092915050565b6000615ee382615f4a565b9150615eee83615f4a565b925082821015615f0157615f00616011565b5b828203905092915050565b6000615f1782615f2a565b9050919050565b60008115159050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b82818337600083830152505050565b60005b83811015615f81578082015181840152602081019050615f66565b83811115615f90576000848401525b50505050565b60006002820490506001821680615fae57607f821691505b60208210811415615fc257615fc161606f565b5b50919050565b6000615fd382615f4a565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561600657616005616011565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b6160e781615f0c565b81146160f257600080fd5b50565b6160fe81615f1e565b811461610957600080fd5b50565b61611581615f4a565b811461612057600080fd5b5056fea26469706673582212202960e019675b96585fec0ccae4964c47915abbeefac2d12c4113ab611318e7b564736f6c63430008000033