Overview
FTM Balance
0 FTM
FTM Value
$0.00More Info
Private Name Tags
ContractCreator:
Sponsored
Latest 1 internal transaction
Parent Txn Hash | Block | From | To | Value | ||
---|---|---|---|---|---|---|
44997031 | 590 days ago | Contract Creation | 0 FTM |
Loading...
Loading
Contract Name:
FantomMarketplace
Compiler Version
v0.6.12+commit.27d51765
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.6.12; import "@openzeppelin/contracts/introspection/IERC165.sol"; import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; import "@openzeppelin/contracts/math/SafeMath.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol"; interface IFantomAddressRegistry { function artion() external view returns (address); function bundleMarketplace() external view returns (address); function auction() external view returns (address); function factory() external view returns (address); function privateFactory() external view returns (address); function artFactory() external view returns (address); function privateArtFactory() external view returns (address); function tokenRegistry() external view returns (address); function priceFeed() external view returns (address); } interface IFantomAuction { function auctions(address, uint256) external view returns ( address, address, uint256, uint256, uint256, bool ); } interface IFantomBundleMarketplace { function validateItemSold( address, uint256, uint256 ) external; } interface IFantomNFTFactory { function exists(address) external view returns (bool); } interface IFantomTokenRegistry { function enabled(address) external view returns (bool); } interface IFantomPriceFeed { function wFTM() external view returns (address); function getPrice(address) external view returns (int256, uint8); } contract FantomMarketplace is OwnableUpgradeable, ReentrancyGuardUpgradeable { using SafeMath for uint256; using AddressUpgradeable for address payable; using SafeERC20 for IERC20; /// @notice Events for the contract event ItemListed( address indexed owner, address indexed nft, uint256 tokenId, uint256 quantity, address payToken, uint256 pricePerItem, uint256 startingTime ); event ItemSold( address indexed seller, address indexed buyer, address indexed nft, uint256 tokenId, uint256 quantity, address payToken, uint256 pricePerItem ); //int256 unitPrice, event ItemUpdated( address indexed owner, address indexed nft, uint256 tokenId, address payToken, uint256 newPrice ); event ItemCanceled( address indexed owner, address indexed nft, uint256 tokenId ); event OfferCreated( address indexed creator, address indexed nft, uint256 tokenId, uint256 quantity, address payToken, uint256 pricePerItem, uint256 deadline ); event OfferCanceled( address indexed creator, address indexed nft, uint256 tokenId ); event UpdatePlatformFee(uint16 platformFee); event UpdatePlatformFeeRecipient(address payable platformFeeRecipient); /// @notice Structure for listed items struct Listing { uint256 quantity; address payToken; uint256 pricePerItem; uint256 startingTime; } /// @notice Structure for offer struct Offer { IERC20 payToken; uint256 quantity; uint256 pricePerItem; uint256 deadline; } struct CollectionRoyalty { uint16 royalty; address creator; address feeRecipient; } bytes4 private constant INTERFACE_ID_ERC721 = 0x80ac58cd; bytes4 private constant INTERFACE_ID_ERC1155 = 0xd9b67a26; /// @notice NftAddress -> Token ID -> Minter mapping(address => mapping(uint256 => address)) public minters; /// @notice NftAddress -> Token ID -> Royalty mapping(address => mapping(uint256 => uint16)) public royalties; /// @notice NftAddress -> Token ID -> Owner -> Listing item mapping(address => mapping(uint256 => mapping(address => Listing))) public listings; /// @notice NftAddress -> Token ID -> Offerer -> Offer mapping(address => mapping(uint256 => mapping(address => Offer))) public offers; /// @notice Platform fee uint16 public platformFee; /// @notice Platform fee receipient address payable public feeReceipient; /// @notice NftAddress -> Royalty mapping(address => CollectionRoyalty) public collectionRoyalties; /// @notice Address registry IFantomAddressRegistry public addressRegistry; modifier onlyMarketplace() { require( address(addressRegistry.bundleMarketplace()) == _msgSender(), "sender must be bundle marketplace" ); _; } modifier isListed( address _nftAddress, uint256 _tokenId, address _owner ) { Listing memory listing = listings[_nftAddress][_tokenId][_owner]; require(listing.quantity > 0, "not listed item"); _; } modifier notListed( address _nftAddress, uint256 _tokenId, address _owner ) { Listing memory listing = listings[_nftAddress][_tokenId][_owner]; require(listing.quantity == 0, "already listed"); _; } modifier validListing( address _nftAddress, uint256 _tokenId, address _owner ) { Listing memory listedItem = listings[_nftAddress][_tokenId][_owner]; _validOwner(_nftAddress, _tokenId, _owner, listedItem.quantity); require(_getNow() >= listedItem.startingTime, "item not buyable"); _; } modifier offerExists( address _nftAddress, uint256 _tokenId, address _creator ) { Offer memory offer = offers[_nftAddress][_tokenId][_creator]; require( offer.quantity > 0 && offer.deadline > _getNow(), "offer not exists or expired" ); _; } modifier offerNotExists( address _nftAddress, uint256 _tokenId, address _creator ) { Offer memory offer = offers[_nftAddress][_tokenId][_creator]; require( offer.quantity == 0 || offer.deadline <= _getNow(), "offer already created" ); _; } /// @notice Contract initializer function initialize(address payable _feeRecipient, uint16 _platformFee) public initializer { platformFee = _platformFee; feeReceipient = _feeRecipient; __Ownable_init(); __ReentrancyGuard_init(); } /// @notice Method for listing NFT /// @param _nftAddress Address of NFT contract /// @param _tokenId Token ID of NFT /// @param _quantity token amount to list (needed for ERC-1155 NFTs, set as 1 for ERC-721) /// @param _payToken Paying token /// @param _pricePerItem sale price for each iteam /// @param _startingTime scheduling for a future sale function listItem( address _nftAddress, uint256 _tokenId, uint256 _quantity, address _payToken, uint256 _pricePerItem, uint256 _startingTime ) external notListed(_nftAddress, _tokenId, _msgSender()) { if (IERC165(_nftAddress).supportsInterface(INTERFACE_ID_ERC721)) { IERC721 nft = IERC721(_nftAddress); require(nft.ownerOf(_tokenId) == _msgSender(), "not owning item"); require( nft.isApprovedForAll(_msgSender(), address(this)), "item not approved" ); } else if ( IERC165(_nftAddress).supportsInterface(INTERFACE_ID_ERC1155) ) { IERC1155 nft = IERC1155(_nftAddress); require( nft.balanceOf(_msgSender(), _tokenId) >= _quantity, "must hold enough nfts" ); require( nft.isApprovedForAll(_msgSender(), address(this)), "item not approved" ); } else { revert("invalid nft address"); } _validPayToken(_payToken); listings[_nftAddress][_tokenId][_msgSender()] = Listing( _quantity, _payToken, _pricePerItem, _startingTime ); emit ItemListed( _msgSender(), _nftAddress, _tokenId, _quantity, _payToken, _pricePerItem, _startingTime ); } /// @notice Method for canceling listed NFT function cancelListing(address _nftAddress, uint256 _tokenId) external nonReentrant isListed(_nftAddress, _tokenId, _msgSender()) { _cancelListing(_nftAddress, _tokenId, _msgSender()); } /// @notice Method for updating listed NFT /// @param _nftAddress Address of NFT contract /// @param _tokenId Token ID of NFT /// @param _payToken payment token /// @param _newPrice New sale price for each iteam function updateListing( address _nftAddress, uint256 _tokenId, address _payToken, uint256 _newPrice ) external nonReentrant isListed(_nftAddress, _tokenId, _msgSender()) { Listing storage listedItem = listings[_nftAddress][_tokenId][ _msgSender() ]; _validOwner(_nftAddress, _tokenId, _msgSender(), listedItem.quantity); _validPayToken(_payToken); listedItem.payToken = _payToken; listedItem.pricePerItem = _newPrice; emit ItemUpdated( _msgSender(), _nftAddress, _tokenId, _payToken, _newPrice ); } /// @notice Method for buying listed NFT /// @param _nftAddress NFT contract address /// @param _tokenId TokenId function buyItem( address _nftAddress, uint256 _tokenId, address _payToken, address _owner ) external nonReentrant isListed(_nftAddress, _tokenId, _owner) validListing(_nftAddress, _tokenId, _owner) { Listing memory listedItem = listings[_nftAddress][_tokenId][_owner]; require(listedItem.payToken == _payToken, "invalid pay token"); _buyItem(_nftAddress, _tokenId, _payToken, _owner); } function _buyItem( address _nftAddress, uint256 _tokenId, address _payToken, address _owner ) private { Listing memory listedItem = listings[_nftAddress][_tokenId][_owner]; uint256 price = listedItem.pricePerItem.mul(listedItem.quantity); uint256 feeAmount = price.mul(platformFee).div(1e3); IERC20(_payToken).safeTransferFrom( _msgSender(), feeReceipient, feeAmount ); address minter = minters[_nftAddress][_tokenId]; uint16 royalty = royalties[_nftAddress][_tokenId]; if (minter != address(0) && royalty != 0) { uint256 royaltyFee = price.sub(feeAmount); //.mul(royalty).div(10000); IERC20(_payToken).safeTransferFrom( _msgSender(), minter, royaltyFee ); feeAmount = feeAmount.add(royaltyFee); } else { minter = collectionRoyalties[_nftAddress].feeRecipient; royalty = collectionRoyalties[_nftAddress].royalty; if (minter != address(0) && royalty != 0) { // uint256 royaltyFee = price.sub(feeAmount).mul(royalty).div( // 10000 // ); // IERC20(_payToken).safeTransferFrom( // _msgSender(), // minter, // royaltyFee // ); // feeAmount = feeAmount.add(royaltyFee); } } // IERC20(_payToken).safeTransferFrom( // _msgSender(), // _owner, // price.sub(feeAmount) // ); // Transfer NFT to buyer if (IERC165(_nftAddress).supportsInterface(INTERFACE_ID_ERC721)) { IERC721(_nftAddress).safeTransferFrom( _owner, _msgSender(), _tokenId ); } else { IERC1155(_nftAddress).safeTransferFrom( _owner, _msgSender(), _tokenId, listedItem.quantity, bytes("") ); } // IFantomBundleMarketplace(addressRegistry.bundleMarketplace()) // .validateItemSold(_nftAddress, _tokenId, listedItem.quantity); emit ItemSold( _owner, _msgSender(), _nftAddress, _tokenId, listedItem.quantity, _payToken, // getPrice(_payToken), price.div(listedItem.quantity) ); delete (listings[_nftAddress][_tokenId][_owner]); } /// @notice Method for offering item /// @param _nftAddress NFT contract address /// @param _tokenId TokenId /// @param _payToken Paying token /// @param _quantity Quantity of items /// @param _pricePerItem Price per item /// @param _deadline Offer expiration function createOffer( address _nftAddress, uint256 _tokenId, IERC20 _payToken, uint256 _quantity, uint256 _pricePerItem, uint256 _deadline ) external offerNotExists(_nftAddress, _tokenId, _msgSender()) { require( IERC165(_nftAddress).supportsInterface(INTERFACE_ID_ERC721) || IERC165(_nftAddress).supportsInterface(INTERFACE_ID_ERC1155), "invalid nft address" ); IFantomAuction auction = IFantomAuction(addressRegistry.auction()); (, , , uint256 startTime, , bool resulted) = auction.auctions( _nftAddress, _tokenId ); require( startTime == 0 || resulted == true, "cannot place an offer if auction is going on" ); require(_deadline > _getNow(), "invalid expiration"); _validPayToken(address(_payToken)); offers[_nftAddress][_tokenId][_msgSender()] = Offer( _payToken, _quantity, _pricePerItem, _deadline ); emit OfferCreated( _msgSender(), _nftAddress, _tokenId, _quantity, address(_payToken), _pricePerItem, _deadline ); } /// @notice Method for canceling the offer /// @param _nftAddress NFT contract address /// @param _tokenId TokenId function cancelOffer(address _nftAddress, uint256 _tokenId) external offerExists(_nftAddress, _tokenId, _msgSender()) { delete (offers[_nftAddress][_tokenId][_msgSender()]); emit OfferCanceled(_msgSender(), _nftAddress, _tokenId); } /// @notice Method for accepting the offer /// @param _nftAddress NFT contract address /// @param _tokenId TokenId /// @param _creator Offer creator address function acceptOffer( address _nftAddress, uint256 _tokenId, address _creator ) external nonReentrant offerExists(_nftAddress, _tokenId, _creator) { Offer memory offer = offers[_nftAddress][_tokenId][_creator]; _validOwner(_nftAddress, _tokenId, _msgSender(), offer.quantity); uint256 price = offer.pricePerItem.mul(offer.quantity); uint256 feeAmount = price.mul(platformFee).div(1e3); uint256 royaltyFee; offer.payToken.safeTransferFrom(_creator, feeReceipient, feeAmount); address minter = minters[_nftAddress][_tokenId]; uint16 royalty = royalties[_nftAddress][_tokenId]; if (minter != address(0) && royalty != 0) { royaltyFee = price.sub(feeAmount).mul(royalty).div(10000); offer.payToken.safeTransferFrom(_creator, minter, royaltyFee); feeAmount = feeAmount.add(royaltyFee); } else { minter = collectionRoyalties[_nftAddress].feeRecipient; royalty = collectionRoyalties[_nftAddress].royalty; if (minter != address(0) && royalty != 0) { royaltyFee = price.sub(feeAmount).mul(royalty).div(10000); offer.payToken.safeTransferFrom(_creator, minter, royaltyFee); feeAmount = feeAmount.add(royaltyFee); } } offer.payToken.safeTransferFrom( _creator, _msgSender(), price.sub(feeAmount) ); // Transfer NFT to buyer if (IERC165(_nftAddress).supportsInterface(INTERFACE_ID_ERC721)) { IERC721(_nftAddress).safeTransferFrom( _msgSender(), _creator, _tokenId ); } else { IERC1155(_nftAddress).safeTransferFrom( _msgSender(), _creator, _tokenId, offer.quantity, bytes("") ); } IFantomBundleMarketplace(addressRegistry.bundleMarketplace()) .validateItemSold(_nftAddress, _tokenId, offer.quantity); emit ItemSold( _msgSender(), _creator, _nftAddress, _tokenId, offer.quantity, address(offer.payToken), // getPrice(address(offer.payToken)), offer.pricePerItem ); emit OfferCanceled(_creator, _nftAddress, _tokenId); delete (listings[_nftAddress][_tokenId][_msgSender()]); delete (offers[_nftAddress][_tokenId][_creator]); } /// @notice Method for setting royalty /// @param _nftAddress NFT contract address /// @param _tokenId TokenId /// @param _royalty Royalty function registerRoyalty( address _nftAddress, uint256 _tokenId, uint16 _royalty ) external { require(_royalty <= 10000, "invalid royalty"); require(_isFantomNFT(_nftAddress), "invalid nft address"); _validOwner(_nftAddress, _tokenId, _msgSender(), 1); require( minters[_nftAddress][_tokenId] == address(0), "royalty already set" ); minters[_nftAddress][_tokenId] = _msgSender(); royalties[_nftAddress][_tokenId] = _royalty; } /// @notice Method for setting royalty /// @param _nftAddress NFT contract address /// @param _royalty Royalty function registerCollectionRoyalty( address _nftAddress, address _creator, uint16 _royalty, address _feeRecipient ) external onlyOwner { require(_creator != address(0), "invalid creator address"); require(_royalty <= 10000, "invalid royalty"); require( _royalty == 0 || _feeRecipient != address(0), "invalid fee recipient address" ); require(!_isFantomNFT(_nftAddress), "invalid nft address"); if (collectionRoyalties[_nftAddress].creator == address(0)) { collectionRoyalties[_nftAddress] = CollectionRoyalty( _royalty, _creator, _feeRecipient ); } else { CollectionRoyalty storage collectionRoyalty = collectionRoyalties[ _nftAddress ]; collectionRoyalty.royalty = _royalty; collectionRoyalty.feeRecipient = _feeRecipient; collectionRoyalty.creator = _creator; } } function _isFantomNFT(address _nftAddress) internal view returns (bool) { return addressRegistry.artion() == _nftAddress || IFantomNFTFactory(addressRegistry.factory()).exists(_nftAddress) || IFantomNFTFactory(addressRegistry.privateFactory()).exists( _nftAddress ) || IFantomNFTFactory(addressRegistry.artFactory()).exists( _nftAddress ) || IFantomNFTFactory(addressRegistry.privateArtFactory()).exists( _nftAddress ); } /** @notice Method for getting price for pay token @param _payToken Paying token */ function getPrice(address _payToken) public view returns (int256) { int256 unitPrice; uint8 decimals; IFantomPriceFeed priceFeed = IFantomPriceFeed( addressRegistry.priceFeed() ); if (_payToken == address(0)) { (unitPrice, decimals) = priceFeed.getPrice(priceFeed.wFTM()); } else { (unitPrice, decimals) = priceFeed.getPrice(_payToken); } if (decimals < 18) { unitPrice = unitPrice * (int256(10)**(18 - decimals)); } else { unitPrice = unitPrice / (int256(10)**(decimals - 18)); } return unitPrice; } /** @notice Method for updating platform fee @dev Only admin @param _platformFee uint16 the platform fee to set */ function updatePlatformFee(uint16 _platformFee) external onlyOwner { platformFee = _platformFee; emit UpdatePlatformFee(_platformFee); } /** @notice Method for updating platform fee address @dev Only admin @param _platformFeeRecipient payable address the address to sends the funds to */ function updatePlatformFeeRecipient(address payable _platformFeeRecipient) external onlyOwner { feeReceipient = _platformFeeRecipient; emit UpdatePlatformFeeRecipient(_platformFeeRecipient); } /** @notice Update FantomAddressRegistry contract @dev Only admin */ function updateAddressRegistry(address _registry) external onlyOwner { addressRegistry = IFantomAddressRegistry(_registry); } /** * @notice Validate and cancel listing * @dev Only bundle marketplace can access */ function validateItemSold( address _nftAddress, uint256 _tokenId, address _seller, address _buyer ) external onlyMarketplace { Listing memory item = listings[_nftAddress][_tokenId][_seller]; if (item.quantity > 0) { _cancelListing(_nftAddress, _tokenId, _seller); } delete (offers[_nftAddress][_tokenId][_buyer]); emit OfferCanceled(_buyer, _nftAddress, _tokenId); } //////////////////////////// /// Internal and Private /// //////////////////////////// function _getNow() internal view virtual returns (uint256) { return block.timestamp; } function _validPayToken(address _payToken) internal { require( _payToken == address(0) || (addressRegistry.tokenRegistry() != address(0) && IFantomTokenRegistry(addressRegistry.tokenRegistry()) .enabled(_payToken)), "invalid pay token" ); } function _validOwner( address _nftAddress, uint256 _tokenId, address _owner, uint256 quantity ) internal { if (IERC165(_nftAddress).supportsInterface(INTERFACE_ID_ERC721)) { IERC721 nft = IERC721(_nftAddress); require(nft.ownerOf(_tokenId) == _owner, "not owning item"); } else if ( IERC165(_nftAddress).supportsInterface(INTERFACE_ID_ERC1155) ) { IERC1155 nft = IERC1155(_nftAddress); require( nft.balanceOf(_owner, _tokenId) >= quantity, "not owning item" ); } else { revert("invalid nft address"); } } function _cancelListing( address _nftAddress, uint256 _tokenId, address _owner ) private { Listing memory listedItem = listings[_nftAddress][_tokenId][_owner]; _validOwner(_nftAddress, _tokenId, _owner, listedItem.quantity); delete (listings[_nftAddress][_tokenId][_owner]); emit ItemCanceled(_owner, _nftAddress, _tokenId); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <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); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2 <0.8.0; import "../../introspection/IERC165.sol"; /** * @dev Required interface of an ERC1155 compliant contract, as defined in the * https://eips.ethereum.org/EIPS/eip-1155[EIP]. * * _Available since v3.1._ */ interface IERC1155 is IERC165 { /** * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`. */ event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); /** * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all * transfers. */ event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values); /** * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to * `approved`. */ event ApprovalForAll(address indexed account, address indexed operator, bool approved); /** * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. * * If an {URI} event was emitted for `id`, the standard * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value * returned by {IERC1155MetadataURI-uri}. */ event URI(string value, uint256 indexed id); /** * @dev Returns the amount of tokens of token type `id` owned by `account`. * * Requirements: * * - `account` cannot be the zero address. */ function balanceOf(address account, uint256 id) external view returns (uint256); /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory); /** * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`, * * Emits an {ApprovalForAll} event. * * Requirements: * * - `operator` cannot be the caller. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns true if `operator` is approved to transfer ``account``'s tokens. * * See {setApprovalForAll}. */ function isApprovedForAll(address account, address operator) external view returns (bool); /** * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}. * - `from` must have a balance of tokens of type `id` of at least `amount`. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external; /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}. * * Emits a {TransferBatch} event. * * Requirements: * * - `ids` and `amounts` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function safeBatchTransferFrom(address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data) external; }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2 <0.8.0; import "../../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; }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <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); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; import "./IERC20.sol"; import "../../math/SafeMath.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 SafeMath for uint256; 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' // solhint-disable-next-line max-line-length 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).add(value); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); _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 // solhint-disable-next-line max-line-length require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { 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) { 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) { // 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) { 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) { 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) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { require(b <= a, "SafeMath: subtraction overflow"); 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) { if (a == 0) return 0; uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, "SafeMath: division by zero"); 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) { require(b > 0, "SafeMath: modulo by zero"); 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) { 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. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryDiv}. * * 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) { 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) { require(b > 0, errorMessage); return a % b; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; import "../utils/ContextUpgradeable.sol"; import "../proxy/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal initializer { __Context_init_unchained(); __Ownable_init_unchained(); } function __Ownable_init_unchained() internal initializer { address msgSender = _msgSender(); _owner = msgSender; emit OwnershipTransferred(address(0), 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 { emit OwnershipTransferred(_owner, address(0)); _owner = 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"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } uint256[49] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2 <0.8.0; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @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; // solhint-disable-next-line no-inline-assembly 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"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (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"); // solhint-disable-next-line avoid-low-level-calls (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"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.staticcall(data); return _verifyCallResult(success, returndata, errorMessage); } function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private 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 // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; import "../proxy/Initializable.sol"; /** * @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 ReentrancyGuardUpgradeable is Initializable { // 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; function __ReentrancyGuard_init() internal initializer { __ReentrancyGuard_init_unchained(); } function __ReentrancyGuard_init_unchained() internal initializer { _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; } uint256[49] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2 <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; // solhint-disable-next-line no-inline-assembly 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"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (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"); // solhint-disable-next-line avoid-low-level-calls (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"); // solhint-disable-next-line avoid-low-level-calls (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"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.delegatecall(data); return _verifyCallResult(success, returndata, errorMessage); } function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private 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 // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; import "../proxy/Initializable.sol"; /* * @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 GSN 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 ContextUpgradeable is Initializable { function __Context_init() internal initializer { __Context_init_unchained(); } function __Context_init_unchained() internal initializer { } function _msgSender() internal view virtual returns (address payable) { return msg.sender; } function _msgData() internal view virtual returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // solhint-disable-next-line compiler-version pragma solidity >=0.4.24 <0.8.0; import "../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {UpgradeableProxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. */ bool private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Modifier to protect an initializer function from being invoked twice. */ modifier initializer() { require(_initializing || _isConstructor() || !_initialized, "Initializable: contract is already initialized"); bool isTopLevelCall = !_initializing; if (isTopLevelCall) { _initializing = true; _initialized = true; } _; if (isTopLevelCall) { _initializing = false; } } /// @dev Returns true if and only if the function is running in the constructor function _isConstructor() private view returns (bool) { return !AddressUpgradeable.isContract(address(this)); } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"nft","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ItemCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"nft","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"quantity","type":"uint256"},{"indexed":false,"internalType":"address","name":"payToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"pricePerItem","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startingTime","type":"uint256"}],"name":"ItemListed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"seller","type":"address"},{"indexed":true,"internalType":"address","name":"buyer","type":"address"},{"indexed":true,"internalType":"address","name":"nft","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"quantity","type":"uint256"},{"indexed":false,"internalType":"address","name":"payToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"pricePerItem","type":"uint256"}],"name":"ItemSold","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"nft","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"address","name":"payToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"newPrice","type":"uint256"}],"name":"ItemUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"creator","type":"address"},{"indexed":true,"internalType":"address","name":"nft","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"OfferCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"creator","type":"address"},{"indexed":true,"internalType":"address","name":"nft","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"quantity","type":"uint256"},{"indexed":false,"internalType":"address","name":"payToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"pricePerItem","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"OfferCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"platformFee","type":"uint16"}],"name":"UpdatePlatformFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address payable","name":"platformFeeRecipient","type":"address"}],"name":"UpdatePlatformFeeRecipient","type":"event"},{"inputs":[{"internalType":"address","name":"_nftAddress","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"address","name":"_creator","type":"address"}],"name":"acceptOffer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"addressRegistry","outputs":[{"internalType":"contract IFantomAddressRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_nftAddress","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"address","name":"_payToken","type":"address"},{"internalType":"address","name":"_owner","type":"address"}],"name":"buyItem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_nftAddress","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"cancelListing","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_nftAddress","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"cancelOffer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"collectionRoyalties","outputs":[{"internalType":"uint16","name":"royalty","type":"uint16"},{"internalType":"address","name":"creator","type":"address"},{"internalType":"address","name":"feeRecipient","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_nftAddress","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"contract IERC20","name":"_payToken","type":"address"},{"internalType":"uint256","name":"_quantity","type":"uint256"},{"internalType":"uint256","name":"_pricePerItem","type":"uint256"},{"internalType":"uint256","name":"_deadline","type":"uint256"}],"name":"createOffer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"feeReceipient","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_payToken","type":"address"}],"name":"getPrice","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address payable","name":"_feeRecipient","type":"address"},{"internalType":"uint16","name":"_platformFee","type":"uint16"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_nftAddress","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_quantity","type":"uint256"},{"internalType":"address","name":"_payToken","type":"address"},{"internalType":"uint256","name":"_pricePerItem","type":"uint256"},{"internalType":"uint256","name":"_startingTime","type":"uint256"}],"name":"listItem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"listings","outputs":[{"internalType":"uint256","name":"quantity","type":"uint256"},{"internalType":"address","name":"payToken","type":"address"},{"internalType":"uint256","name":"pricePerItem","type":"uint256"},{"internalType":"uint256","name":"startingTime","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"minters","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"offers","outputs":[{"internalType":"contract IERC20","name":"payToken","type":"address"},{"internalType":"uint256","name":"quantity","type":"uint256"},{"internalType":"uint256","name":"pricePerItem","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"platformFee","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_nftAddress","type":"address"},{"internalType":"address","name":"_creator","type":"address"},{"internalType":"uint16","name":"_royalty","type":"uint16"},{"internalType":"address","name":"_feeRecipient","type":"address"}],"name":"registerCollectionRoyalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_nftAddress","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint16","name":"_royalty","type":"uint16"}],"name":"registerRoyalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"royalties","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_registry","type":"address"}],"name":"updateAddressRegistry","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_nftAddress","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"address","name":"_payToken","type":"address"},{"internalType":"uint256","name":"_newPrice","type":"uint256"}],"name":"updateListing","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_platformFee","type":"uint16"}],"name":"updatePlatformFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"_platformFeeRecipient","type":"address"}],"name":"updatePlatformFeeRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_nftAddress","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"address","name":"_seller","type":"address"},{"internalType":"address","name":"_buyer","type":"address"}],"name":"validateItemSold","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b506147a6806100206000396000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80638da5cb5b116100de578063e940ebeb11610097578063f3880b6e11610071578063f3880b6e14610610578063f39e69a414610646578063f3ad65f414610676578063f5fe7f711461067e5761018e565b8063e940ebeb14610574578063e984f2eb146105b0578063f2fde38b146105ea5761018e565b80638da5cb5b1461044d578063afb0695214610455578063b2ddee0614610476578063c1661a9a146104a2578063d3f494cc146104e2578063e1e549c4146105485761018e565b806342cbb4b81161014b5780636bd3a64b116101255780636bd3a64b14610379578063715018a6146103dd57806378746d0d146103e557806385f9d345146104115761018e565b806342cbb4b8146102ba57806357b275b41461030057806368e79e89146103535761018e565b8063058a56ac1461019357806326232a2e146101c15780633740ebb3146101e05780633bbb2806146102045780633fc1cc261461023a57806341976e0914610282575b600080fd5b6101bf600480360360408110156101a957600080fd5b506001600160a01b0381351690602001356106a4565b005b6101c961083b565b6040805161ffff9092168252519081900360200190f35b6101e8610845565b604080516001600160a01b039092168252519081900360200190f35b6101bf6004803603606081101561021a57600080fd5b506001600160a01b0381358116916020810135916040909101351661085a565b6101bf600480360360c081101561025057600080fd5b506001600160a01b03813581169160208101359160408201359160608101359091169060808101359060a001356110c1565b6102a86004803603602081101561029857600080fd5b50356001600160a01b0316611657565b60408051918252519081900360200190f35b6101bf600480360360c08110156102d057600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060808101359060a00135611895565b6103266004803603602081101561031657600080fd5b50356001600160a01b0316611d7d565b6040805161ffff90941684526001600160a01b039283166020850152911682820152519081900360600190f35b6101bf6004803603602081101561036957600080fd5b50356001600160a01b0316611daf565b6103af6004803603606081101561038f57600080fd5b506001600160a01b03813581169160208101359160409091013516611e33565b604080519485526001600160a01b039093166020850152838301919091526060830152519081900360800190f35b6101bf611e75565b6101e8600480360360408110156103fb57600080fd5b506001600160a01b038135169060200135611f21565b6101bf6004803603608081101561042757600080fd5b506001600160a01b03813581169160208101359160408201358116916060013516611f47565b6101e86121e5565b6101bf6004803603602081101561046b57600080fd5b503561ffff166121f4565b6101bf6004803603604081101561048c57600080fd5b506001600160a01b0381351690602001356122a0565b6101bf600480360360808110156104b857600080fd5b506001600160a01b038135811691602081013582169161ffff6040830135169160600135166123c3565b610518600480360360608110156104f857600080fd5b506001600160a01b0381358116916020810135916040909101351661269a565b604080516001600160a01b0390951685526020850193909352838301919091526060830152519081900360800190f35b6101c96004803603604081101561055e57600080fd5b506001600160a01b0381351690602001356126dc565b6101bf6004803603608081101561058a57600080fd5b506001600160a01b038135811691602081013591604082013581169160600135166126fd565b6101bf600480360360808110156105c657600080fd5b506001600160a01b03813581169160208101359160408201351690606001356128d7565b6101bf6004803603602081101561060057600080fd5b50356001600160a01b0316612ad7565b6101bf6004803603606081101561062657600080fd5b5080356001600160a01b0316906020810135906040013561ffff16612bda565b6101bf6004803603604081101561065c57600080fd5b5080356001600160a01b0316906020013561ffff16612d65565b6101e8612e46565b6101bf6004803603602081101561069457600080fd5b50356001600160a01b0316612e55565b81816106ae612f15565b6106b66145bc565b506001600160a01b038084166000908152609a6020908152604080832086845282528083208585168452825291829020825160808101845281549094168452600181015491840182905260028101549284019290925260039091015460608301521580159061072f5750610728612f19565b8160600151115b610780576040805162461bcd60e51b815260206004820152601b60248201527f6f66666572206e6f7420657869737473206f7220657870697265640000000000604482015290519081900360640190fd5b6001600160a01b0386166000908152609a602090815260408083208884529091528120906107ac612f15565b6001600160a01b0390811682526020820192909252604001600090812080546001600160a01b031916815560018101829055600281018290556003015586166107f3612f15565b6001600160a01b03167fc6e24dcedb16cc237925b586889d0a38102c719734d6cc56acb89b013099b3a7876040518082815260200191505060405180910390a3505050505050565b609b5461ffff1681565b609b546201000090046001600160a01b031681565b600260655414156108a0576040805162461bcd60e51b815260206004820152601f602482015260008051602061461f833981519152604482015290519081900360640190fd5b60026065558282826108b06145bc565b506001600160a01b038084166000908152609a602090815260408083208684528252808320858516845282529182902082516080810184528154909416845260018101549184018290526002810154928401929092526003909101546060830152158015906109295750610922612f19565b8160600151115b61097a576040805162461bcd60e51b815260206004820152601b60248201527f6f66666572206e6f7420657869737473206f7220657870697265640000000000604482015290519081900360640190fd5b6109826145bc565b506001600160a01b038088166000908152609a602090815260408083208a8452825280832089851684528252918290208251608081018452815490941684526001810154918401919091526002810154918301919091526003015460608201526109f988886109ef612f15565b8460200151612f1d565b6000610a16826020015183604001516131b690919063ffffffff16565b609b54909150600090610a3c906103e890610a3690859061ffff166131b6565b90613218565b609b548451919250600091610a66916001600160a01b03918216918c91620100009004168561327f565b6001600160a01b03808c1660008181526097602090815260408083208f8452825280832054938352609882528083208f845290915290205491169061ffff168115801590610ab7575061ffff811615155b15610b0557610ada612710610a3661ffff8416610ad489896132d9565b906131b6565b8651909350610af4906001600160a01b03168c848661327f565b610afe8484613336565b9350610b84565b50506001600160a01b03808c166000908152609c602052604090206001810154905491169061ffff168115801590610b40575061ffff811615155b15610b8457610b5d612710610a3661ffff8416610ad489896132d9565b8651909350610b77906001600160a01b03168c848661327f565b610b818484613336565b93505b610bad8b610b90612f15565b610b9a88886132d9565b89516001600160a01b031692919061327f565b604080516301ffc9a760e01b81526380ac58cd60e01b600482015290516001600160a01b038f16916301ffc9a7916024808301926020929190829003018186803b158015610bfa57600080fd5b505afa158015610c0e573d6000803e3d6000fd5b505050506040513d6020811015610c2457600080fd5b505115610cb7578c6001600160a01b03166342842e0e610c42612f15565b8d8f6040518463ffffffff1660e01b815260040180846001600160a01b03168152602001836001600160a01b031681526020018281526020019350505050600060405180830381600087803b158015610c9a57600080fd5b505af1158015610cae573d6000803e3d6000fd5b50505050610dc4565b8c6001600160a01b031663f242432a610cce612f15565b8d8f8a60200151604051806020016040528060008152506040518663ffffffff1660e01b815260040180866001600160a01b03168152602001856001600160a01b0316815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015610d5b578181015183820152602001610d43565b50505050905090810190601f168015610d885780820380516001836020036101000a031916815260200191505b509650505050505050600060405180830381600087803b158015610dab57600080fd5b505af1158015610dbf573d6000803e3d6000fd5b505050505b609d60009054906101000a90046001600160a01b03166001600160a01b0316639e1f5b286040518163ffffffff1660e01b815260040160206040518083038186803b158015610e1257600080fd5b505afa158015610e26573d6000803e3d6000fd5b505050506040513d6020811015610e3c57600080fd5b81019080805190602001909291905050506001600160a01b03166327c1f4f48e8e89602001516040518463ffffffff1660e01b815260040180846001600160a01b031681526020018381526020018281526020019350505050600060405180830381600087803b158015610eaf57600080fd5b505af1158015610ec3573d6000803e3d6000fd5b505050508c6001600160a01b03168b6001600160a01b0316610ee3612f15565b6001600160a01b03167f33288df29d0f4a78de0aab5956626ed28d0abeb944e8f0d78dd1031efb53941f8f8a602001518b600001518c6040015160405180858152602001848152602001836001600160a01b0316815260200182815260200194505050505060405180910390a48c6001600160a01b03168b6001600160a01b03167fc6e24dcedb16cc237925b586889d0a38102c719734d6cc56acb89b013099b3a78e6040518082815260200191505060405180910390a36001600160a01b038d1660009081526099602090815260408083208f8452909152812090610fc7612f15565b6001600160a01b03166001600160a01b031681526020019081526020016000206000808201600090556001820160006101000a8154906001600160a01b030219169055600282016000905560038201600090555050609a60008e6001600160a01b03166001600160a01b0316815260200190815260200160002060008d815260200190815260200160002060008c6001600160a01b03166001600160a01b03168152602001908152602001600020600080820160006101000a8154906001600160a01b0302191690556001820160009055600282016000905560038201600090555050505050505050505050506001606581905550505050565b85856110cb612f15565b6110d36145ed565b506001600160a01b03808416600090815260996020908152604080832086845282528083208585168452825291829020825160808101845281548082526001830154909516928101929092526002810154928201929092526003909101546060820152901561117a576040805162461bcd60e51b815260206004820152600e60248201526d185b1c9958591e481b1a5cdd195960921b604482015290519081900360640190fd5b604080516301ffc9a760e01b81526380ac58cd60e01b600482015290516001600160a01b038c16916301ffc9a7916024808301926020929190829003018186803b1580156111c757600080fd5b505afa1580156111db573d6000803e3d6000fd5b505050506040513d60208110156111f157600080fd5b5051156113a35789611201612f15565b6001600160a01b0316816001600160a01b0316636352211e8c6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561124e57600080fd5b505afa158015611262573d6000803e3d6000fd5b505050506040513d602081101561127857600080fd5b50516001600160a01b0316146112c7576040805162461bcd60e51b815260206004820152600f60248201526e6e6f74206f776e696e67206974656d60881b604482015290519081900360640190fd5b806001600160a01b031663e985e9c56112de612f15565b306040518363ffffffff1660e01b815260040180836001600160a01b03168152602001826001600160a01b031681526020019250505060206040518083038186803b15801561132c57600080fd5b505afa158015611340573d6000803e3d6000fd5b505050506040513d602081101561135657600080fd5b505161139d576040805162461bcd60e51b81526020600482015260116024820152701a5d195b481b9bdd08185c1c1c9bdd9959607a1b604482015290519081900360640190fd5b50611538565b604080516301ffc9a760e01b8152636cdb3d1360e11b600482015290516001600160a01b038c16916301ffc9a7916024808301926020929190829003018186803b1580156113f057600080fd5b505afa158015611404573d6000803e3d6000fd5b505050506040513d602081101561141a57600080fd5b5051156114f55789886001600160a01b03821662fdd58e611439612f15565b8d6040518363ffffffff1660e01b815260040180836001600160a01b031681526020018281526020019250505060206040518083038186803b15801561147e57600080fd5b505afa158015611492573d6000803e3d6000fd5b505050506040513d60208110156114a857600080fd5b505110156112c7576040805162461bcd60e51b81526020600482015260156024820152746d75737420686f6c6420656e6f756768206e66747360581b604482015290519081900360640190fd5b6040805162461bcd60e51b8152602060048201526013602482015272696e76616c6964206e6674206164647265737360681b604482015290519081900360640190fd5b61154187613390565b604080516080810182528981526001600160a01b03808a166020808401919091528284018a905260608301899052908d166000908152609982528381208d82529091529182209091611591612f15565b6001600160a01b039081168252602080830193909352604091820160002084518155928401516001840180546001600160a01b0319169183169190911790559083015160028301556060909201516003909101558a166115ef612f15565b604080518c8152602081018c90526001600160a01b038b811682840152606082018b9052608082018a9052915192909116917fa0294f02f8ad82fe4744717b0f953a105547196cd3c67056200c1a4ae3aa26299181900360a00190a350505050505050505050565b600080600080609d60009054906101000a90046001600160a01b03166001600160a01b031663741bef1a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156116ab57600080fd5b505afa1580156116bf573d6000803e3d6000fd5b505050506040513d60208110156116d557600080fd5b505190506001600160a01b0385166117d957806001600160a01b03166341976e09826001600160a01b031663050d63ec6040518163ffffffff1660e01b815260040160206040518083038186803b15801561172f57600080fd5b505afa158015611743573d6000803e3d6000fd5b505050506040513d602081101561175957600080fd5b5051604080516001600160e01b031960e085901b1681526001600160a01b0390921660048301528051602480840193829003018186803b15801561179c57600080fd5b505afa1580156117b0573d6000803e3d6000fd5b505050506040513d60408110156117c657600080fd5b5080516020909101519093509150611857565b604080516341976e0960e01b81526001600160a01b0387811660048301528251908416926341976e099260248082019391829003018186803b15801561181e57600080fd5b505afa158015611832573d6000803e3d6000fd5b505050506040513d604081101561184857600080fd5b50805160209091015190935091505b60128260ff161015611876578160120360ff16600a0a8302925061188c565b6012820360ff16600a0a838161188857fe5b0592505b50909392505050565b858561189f612f15565b6118a76145bc565b506001600160a01b038084166000908152609a602090815260408083208684528252808320858516845282529182902082516080810184528154909416845260018101549184018290526002810154928401929092526003909101546060830152158061191f5750611917612f19565b816060015111155b611968576040805162461bcd60e51b81526020600482015260156024820152741bd999995c88185b1c9958591e4818dc99585d1959605a1b604482015290519081900360640190fd5b604080516301ffc9a760e01b81526380ac58cd60e01b600482015290516001600160a01b038c16916301ffc9a7916024808301926020929190829003018186803b1580156119b557600080fd5b505afa1580156119c9573d6000803e3d6000fd5b505050506040513d60208110156119df57600080fd5b505180611a615750604080516301ffc9a760e01b8152636cdb3d1360e11b600482015290516001600160a01b038c16916301ffc9a7916024808301926020929190829003018186803b158015611a3457600080fd5b505afa158015611a48573d6000803e3d6000fd5b505050506040513d6020811015611a5e57600080fd5b50515b611aa8576040805162461bcd60e51b8152602060048201526013602482015272696e76616c6964206e6674206164647265737360681b604482015290519081900360640190fd5b609d5460408051637d9f6db560e01b815290516000926001600160a01b031691637d9f6db5916004808301926020929190829003018186803b158015611aed57600080fd5b505afa158015611b01573d6000803e3d6000fd5b505050506040513d6020811015611b1757600080fd5b50516040805163227c8e0f60e11b81526001600160a01b038e81166004830152602482018e9052915192935060009283928516916344f91c1e9160448083019260c0929190829003018186803b158015611b7057600080fd5b505afa158015611b84573d6000803e3d6000fd5b505050506040513d60c0811015611b9a57600080fd5b50606081015160a0909101519092509050811580611bba57506001811515145b611bf55760405162461bcd60e51b815260040180806020018281038252602c81526020018061463f602c913960400191505060405180910390fd5b611bfd612f19565b8811611c45576040805162461bcd60e51b815260206004820152601260248201527134b73b30b634b21032bc3834b930ba34b7b760711b604482015290519081900360640190fd5b611c4e8b613390565b60405180608001604052808c6001600160a01b031681526020018b81526020018a815260200189815250609a60008f6001600160a01b03166001600160a01b0316815260200190815260200160002060008e81526020019081526020016000206000611cb8612f15565b6001600160a01b0390811682526020808301939093526040918201600020845181546001600160a01b0319169083161781559284015160018401559083015160028301556060909201516003909101558d16611d12612f15565b604080518f8152602081018e90526001600160a01b038f811682840152606082018e9052608082018d9052915192909116917f89f255157c655b5155655107b77c620998e5ad4e7485d749e4e6d7ddb63e70f69181900360a00190a350505050505050505050505050565b609c602052600090815260409020805460019091015461ffff8216916001600160a01b03620100009091048116911683565b611db7612f15565b6001600160a01b0316611dc86121e5565b6001600160a01b031614611e11576040805162461bcd60e51b81526020600482018190526024820152600080516020614706833981519152604482015290519081900360640190fd5b609d80546001600160a01b0319166001600160a01b0392909216919091179055565b6099602090815260009384526040808520825292845282842090528252902080546001820154600283015460039093015491926001600160a01b039091169184565b611e7d612f15565b6001600160a01b0316611e8e6121e5565b6001600160a01b031614611ed7576040805162461bcd60e51b81526020600482018190526024820152600080516020614706833981519152604482015290519081900360640190fd5b6033546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603380546001600160a01b0319169055565b60976020908152600092835260408084209091529082529020546001600160a01b031681565b60026065541415611f8d576040805162461bcd60e51b815260206004820152601f602482015260008051602061461f833981519152604482015290519081900360640190fd5b6002606555838382611f9d6145ed565b506001600160a01b0380841660009081526099602090815260408083208684528252808320858516845282529182902082516080810184528154808252600183015490951692810192909252600281015492820192909252600390910154606082015290612044576040805162461bcd60e51b815260206004820152600f60248201526e6e6f74206c6973746564206974656d60881b604482015290519081900360640190fd5b87878661204f6145ed565b506001600160a01b03808416600090815260996020908152604080832086845282528083208585168452825291829020825160808101845281548082526001830154909516928101929092526002810154928201929092526003909101546060820152906120c290859085908590612f1d565b80606001516120cf612f19565b1015612115576040805162461bcd60e51b815260206004820152601060248201526f6974656d206e6f742062757961626c6560801b604482015290519081900360640190fd5b61211d6145ed565b506001600160a01b03808d1660009081526099602090815260408083208f845282528083208d851684528252918290208251608081018452815481526001820154851692810183905260028201549381019390935260030154606083015290918c16146121c5576040805162461bcd60e51b815260206004820152601160248201527034b73b30b634b2103830bc903a37b5b2b760791b604482015290519081900360640190fd5b6121d18d8d8d8d61355d565b505060016065555050505050505050505050565b6033546001600160a01b031690565b6121fc612f15565b6001600160a01b031661220d6121e5565b6001600160a01b031614612256576040805162461bcd60e51b81526020600482018190526024820152600080516020614706833981519152604482015290519081900360640190fd5b609b805461ffff831661ffff19909116811790915560408051918252517fcabead39256298cdf7d1228eee68b47bc54a2192283d8d93574da08d2d7ac3039181900360200190a150565b600260655414156122e6576040805162461bcd60e51b815260206004820152601f602482015260008051602061461f833981519152604482015290519081900360640190fd5b600260655581816122f5612f15565b6122fd6145ed565b506001600160a01b03808416600090815260996020908152604080832086845282528083208585168452825291829020825160808101845281548082526001830154909516928101929092526002810154928201929092526003909101546060820152906123a4576040805162461bcd60e51b815260206004820152600f60248201526e6e6f74206c6973746564206974656d60881b604482015290519081900360640190fd5b6123b686866123b1612f15565b6139dd565b5050600160655550505050565b6123cb612f15565b6001600160a01b03166123dc6121e5565b6001600160a01b031614612425576040805162461bcd60e51b81526020600482018190526024820152600080516020614706833981519152604482015290519081900360640190fd5b6001600160a01b038316612480576040805162461bcd60e51b815260206004820152601760248201527f696e76616c69642063726561746f722061646472657373000000000000000000604482015290519081900360640190fd5b6127108261ffff1611156124cd576040805162461bcd60e51b815260206004820152600f60248201526e696e76616c696420726f79616c747960881b604482015290519081900360640190fd5b61ffff821615806124e657506001600160a01b03811615155b612537576040805162461bcd60e51b815260206004820152601d60248201527f696e76616c69642066656520726563697069656e742061646472657373000000604482015290519081900360640190fd5b61254084613ae5565b15612588576040805162461bcd60e51b8152602060048201526013602482015272696e76616c6964206e6674206164647265737360681b604482015290519081900360640190fd5b6001600160a01b038481166000908152609c60205260409020546201000090041661263a576040805160608101825261ffff80851682526001600160a01b0380871660208085019182528683168587019081528a84166000908152609c9092529590209351845491518316620100000262010000600160b01b03199190941661ffff199092169190911716919091178255915160019091018054919092166001600160a01b0319909116179055612694565b6001600160a01b038481166000908152609c6020526040902080546001820180546001600160a01b03191685851617905561ffff191661ffff85161762010000600160b01b03191662010000928616929092029190911790555b50505050565b609a60209081526000938452604080852082529284528284209052825290208054600182015460028301546003909301546001600160a01b0390921692909184565b609860209081526000928352604080842090915290825290205461ffff1681565b612705612f15565b6001600160a01b0316609d60009054906101000a90046001600160a01b03166001600160a01b0316639e1f5b286040518163ffffffff1660e01b815260040160206040518083038186803b15801561275c57600080fd5b505afa158015612770573d6000803e3d6000fd5b505050506040513d602081101561278657600080fd5b50516001600160a01b0316146127cd5760405162461bcd60e51b81526004018080602001828103825260218152602001806147266021913960400191505060405180910390fd5b6127d56145ed565b506001600160a01b038085166000908152609960209081526040808320878452825280832086851684528252918290208251608081018452815480825260018301549095169281019290925260028101549282019290925260039091015460608201529015612849576128498585856139dd565b6001600160a01b038086166000818152609a60209081526040808320898452825280832094871680845294825280832080546001600160a01b0319168155600181018490556002810184905560030192909255815188815291519293927fc6e24dcedb16cc237925b586889d0a38102c719734d6cc56acb89b013099b3a79281900390910190a35050505050565b6002606554141561291d576040805162461bcd60e51b815260206004820152601f602482015260008051602061461f833981519152604482015290519081900360640190fd5b6002606555838361292c612f15565b6129346145ed565b506001600160a01b03808416600090815260996020908152604080832086845282528083208585168452825291829020825160808101845281548082526001830154909516928101929092526002810154928201929092526003909101546060820152906129db576040805162461bcd60e51b815260206004820152600f60248201526e6e6f74206c6973746564206974656d60881b604482015290519081900360640190fd5b6001600160a01b03881660009081526099602090815260408083208a8452909152812081612a07612f15565b6001600160a01b03166001600160a01b031681526020019081526020016000209050612a3d8989612a36612f15565b8454612f1d565b612a4687613390565b6001810180546001600160a01b0319166001600160a01b0389811691909117909155600282018790558916612a79612f15565b604080518b81526001600160a01b038b811660208301528183018b9052915192909116917f60a11f1619b1716bc2857bf610d4bc631336e14d197025fd5875c1aca1ac7cbd9181900360600190a35050600160655550505050505050565b612adf612f15565b6001600160a01b0316612af06121e5565b6001600160a01b031614612b39576040805162461bcd60e51b81526020600482018190526024820152600080516020614706833981519152604482015290519081900360640190fd5b6001600160a01b038116612b7e5760405162461bcd60e51b815260040180806020018281038252602681526020018061466b6026913960400191505060405180910390fd5b6033546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603380546001600160a01b0319166001600160a01b0392909216919091179055565b6127108161ffff161115612c27576040805162461bcd60e51b815260206004820152600f60248201526e696e76616c696420726f79616c747960881b604482015290519081900360640190fd5b612c3083613ae5565b612c77576040805162461bcd60e51b8152602060048201526013602482015272696e76616c6964206e6674206164647265737360681b604482015290519081900360640190fd5b612c8b8383612c84612f15565b6001612f1d565b6001600160a01b0383811660009081526097602090815260408083208684529091529020541615612cf9576040805162461bcd60e51b81526020600482015260136024820152721c9bde585b1d1e48185b1c9958591e481cd95d606a1b604482015290519081900360640190fd5b612d01612f15565b6001600160a01b039384166000818152609760209081526040808320878452825280832080546001600160a01b03191695909816949094179096559081526098855281812093815292909352919020805461ffff191661ffff909216919091179055565b600054610100900460ff1680612d7e5750612d7e613f56565b80612d8c575060005460ff16155b612dc75760405162461bcd60e51b815260040180806020018281038252602e8152602001806146b7602e913960400191505060405180910390fd5b600054610100900460ff16158015612df2576000805460ff1961ff0019909116610100171660011790555b609b805461ffff191661ffff84161762010000600160b01b031916620100006001600160a01b03861602179055612e27613f67565b612e2f614018565b8015612e41576000805461ff00191690555b505050565b609d546001600160a01b031681565b612e5d612f15565b6001600160a01b0316612e6e6121e5565b6001600160a01b031614612eb7576040805162461bcd60e51b81526020600482018190526024820152600080516020614706833981519152604482015290519081900360640190fd5b609b80546001600160a01b03831662010000810262010000600160b01b03199092169190911790915560408051918252517fe57e7c1f36cc83fade34e32351e6eee7eb9da532662b1b5da10c631e8222aca79181900360200190a150565b3390565b4290565b604080516301ffc9a760e01b81526380ac58cd60e01b600482015290516001600160a01b038616916301ffc9a7916024808301926020929190829003018186803b158015612f6a57600080fd5b505afa158015612f7e573d6000803e3d6000fd5b505050506040513d6020811015612f9457600080fd5b50511561306d576000849050826001600160a01b0316816001600160a01b0316636352211e866040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015612fee57600080fd5b505afa158015613002573d6000803e3d6000fd5b505050506040513d602081101561301857600080fd5b50516001600160a01b031614613067576040805162461bcd60e51b815260206004820152600f60248201526e6e6f74206f776e696e67206974656d60881b604482015290519081900360640190fd5b50612694565b604080516301ffc9a760e01b8152636cdb3d1360e11b600482015290516001600160a01b038616916301ffc9a7916024808301926020929190829003018186803b1580156130ba57600080fd5b505afa1580156130ce573d6000803e3d6000fd5b505050506040513d60208110156130e457600080fd5b5051156114f557600084905081816001600160a01b031662fdd58e85876040518363ffffffff1660e01b815260040180836001600160a01b031681526020018281526020019250505060206040518083038186803b15801561314557600080fd5b505afa158015613159573d6000803e3d6000fd5b505050506040513d602081101561316f57600080fd5b50511015613067576040805162461bcd60e51b815260206004820152600f60248201526e6e6f74206f776e696e67206974656d60881b604482015290519081900360640190fd5b6000826131c557506000613212565b828202828482816131d257fe5b041461320f5760405162461bcd60e51b81526004018080602001828103825260218152602001806146e56021913960400191505060405180910390fd5b90505b92915050565b600080821161326e576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161327757fe5b049392505050565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b1790526126949085906140ad565b600082821115613330576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b60008282018381101561320f576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6001600160a01b03811615806135155750609d5460408051639d23c4c760e01b815290516000926001600160a01b031691639d23c4c7916004808301926020929190829003018186803b1580156133e657600080fd5b505afa1580156133fa573d6000803e3d6000fd5b505050506040513d602081101561341057600080fd5b50516001600160a01b0316148015906135155750609d60009054906101000a90046001600160a01b03166001600160a01b0316639d23c4c76040518163ffffffff1660e01b815260040160206040518083038186803b15801561347257600080fd5b505afa158015613486573d6000803e3d6000fd5b505050506040513d602081101561349c57600080fd5b5051604080516398afdfe360e01b81526001600160a01b038481166004830152915191909216916398afdfe3916024808301926020929190829003018186803b1580156134e857600080fd5b505afa1580156134fc573d6000803e3d6000fd5b505050506040513d602081101561351257600080fd5b50515b61355a576040805162461bcd60e51b815260206004820152601160248201527034b73b30b634b2103830bc903a37b5b2b760791b604482015290519081900360640190fd5b50565b6135656145ed565b506001600160a01b03808516600090815260996020908152604080832087845282528083208585168452825280832081516080810183528154808252600183015490961693810193909352600281015491830182905260030154606083015290926135d091906131b6565b609b549091506000906135f0906103e890610a3690859061ffff166131b6565b905061361a6135fd612f15565b609b546001600160a01b038881169291620100009004168461327f565b6001600160a01b0380881660008181526097602090815260408083208b8452825280832054938352609882528083208b845290915290205491169061ffff16811580159061366b575061ffff811615155b156136ad57600061367c85856132d9565b905061369b613689612f15565b6001600160a01b038a1690858461327f565b6136a58482613336565b9350506136ea565b50506001600160a01b038088166000908152609c602052604090206001810154905491169061ffff1681158015906136e8575061ffff811615155b505b604080516301ffc9a760e01b81526380ac58cd60e01b600482015290516001600160a01b038b16916301ffc9a7916024808301926020929190829003018186803b15801561373757600080fd5b505afa15801561374b573d6000803e3d6000fd5b505050506040513d602081101561376157600080fd5b5051156137f457886001600160a01b03166342842e0e87613780612f15565b8b6040518463ffffffff1660e01b815260040180846001600160a01b03168152602001836001600160a01b031681526020018281526020019350505050600060405180830381600087803b1580156137d757600080fd5b505af11580156137eb573d6000803e3d6000fd5b50505050613901565b886001600160a01b031663f242432a8761380c612f15565b8b8960000151604051806020016040528060008152506040518663ffffffff1660e01b815260040180866001600160a01b03168152602001856001600160a01b0316815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015613898578181015183820152602001613880565b50505050905090810190601f1680156138c55780820380516001836020036101000a031916815260200191505b509650505050505050600060405180830381600087803b1580156138e857600080fd5b505af11580156138fc573d6000803e3d6000fd5b505050505b886001600160a01b0316613913612f15565b86516001600160a01b03918216918916907f33288df29d0f4a78de0aab5956626ed28d0abeb944e8f0d78dd1031efb53941f908c908c6139538b83613218565b6040805194855260208501939093526001600160a01b03909116838301526060830152519081900360800190a45050506001600160a01b03958616600090815260996020908152604080832097835296815286822094909716815292909552509182208281556001810180546001600160a01b031916905560028101839055600301919091555050565b6139e56145ed565b506001600160a01b0380841660009081526099602090815260408083208684528252808320858516845282529182902082516080810184528154808252600183015490951692810192909252600281015492820192909252600390910154606082015290613a5890859085908590612f1d565b6001600160a01b03808516600081815260996020908152604080832088845282528083209487168084529482528083208381556001810180546001600160a01b03191690556002810184905560030192909255815187815291519293927f9ba1a3cb55ce8d63d072a886f94d2a744f50cddf82128e897d0661f5ec6231589281900390910190a350505050565b6000816001600160a01b0316609d60009054906101000a90046001600160a01b03166001600160a01b03166318944e556040518163ffffffff1660e01b815260040160206040518083038186803b158015613b3f57600080fd5b505afa158015613b53573d6000803e3d6000fd5b505050506040513d6020811015613b6957600080fd5b50516001600160a01b03161480613c6c5750609d60009054906101000a90046001600160a01b03166001600160a01b031663c45a01556040518163ffffffff1660e01b815260040160206040518083038186803b158015613bc957600080fd5b505afa158015613bdd573d6000803e3d6000fd5b505050506040513d6020811015613bf357600080fd5b505160408051637b51e92760e11b81526001600160a01b0385811660048301529151919092169163f6a3d24e916024808301926020929190829003018186803b158015613c3f57600080fd5b505afa158015613c53573d6000803e3d6000fd5b505050506040513d6020811015613c6957600080fd5b50515b80613d635750609d60009054906101000a90046001600160a01b03166001600160a01b031663735db9396040518163ffffffff1660e01b815260040160206040518083038186803b158015613cc057600080fd5b505afa158015613cd4573d6000803e3d6000fd5b505050506040513d6020811015613cea57600080fd5b505160408051637b51e92760e11b81526001600160a01b0385811660048301529151919092169163f6a3d24e916024808301926020929190829003018186803b158015613d3657600080fd5b505afa158015613d4a573d6000803e3d6000fd5b505050506040513d6020811015613d6057600080fd5b50515b80613e5a5750609d60009054906101000a90046001600160a01b03166001600160a01b0316630fb27d8c6040518163ffffffff1660e01b815260040160206040518083038186803b158015613db757600080fd5b505afa158015613dcb573d6000803e3d6000fd5b505050506040513d6020811015613de157600080fd5b505160408051637b51e92760e11b81526001600160a01b0385811660048301529151919092169163f6a3d24e916024808301926020929190829003018186803b158015613e2d57600080fd5b505afa158015613e41573d6000803e3d6000fd5b505050506040513d6020811015613e5757600080fd5b50515b806132125750609d60009054906101000a90046001600160a01b03166001600160a01b031663924db13f6040518163ffffffff1660e01b815260040160206040518083038186803b158015613eae57600080fd5b505afa158015613ec2573d6000803e3d6000fd5b505050506040513d6020811015613ed857600080fd5b505160408051637b51e92760e11b81526001600160a01b0385811660048301529151919092169163f6a3d24e916024808301926020929190829003018186803b158015613f2457600080fd5b505afa158015613f38573d6000803e3d6000fd5b505050506040513d6020811015613f4e57600080fd5b505192915050565b6000613f613061415e565b15905090565b600054610100900460ff1680613f805750613f80613f56565b80613f8e575060005460ff16155b613fc95760405162461bcd60e51b815260040180806020018281038252602e8152602001806146b7602e913960400191505060405180910390fd5b600054610100900460ff16158015613ff4576000805460ff1961ff0019909116610100171660011790555b613ffc614164565b614004614204565b801561355a576000805461ff001916905550565b600054610100900460ff16806140315750614031613f56565b8061403f575060005460ff16155b61407a5760405162461bcd60e51b815260040180806020018281038252602e8152602001806146b7602e913960400191505060405180910390fd5b600054610100900460ff161580156140a5576000805460ff1961ff0019909116610100171660011790555b6140046142fd565b6060614102826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166143a39092919063ffffffff16565b805190915015612e415780806020019051602081101561412157600080fd5b5051612e415760405162461bcd60e51b815260040180806020018281038252602a815260200180614747602a913960400191505060405180910390fd5b3b151590565b600054610100900460ff168061417d575061417d613f56565b8061418b575060005460ff16155b6141c65760405162461bcd60e51b815260040180806020018281038252602e8152602001806146b7602e913960400191505060405180910390fd5b600054610100900460ff16158015614004576000805460ff1961ff001990911661010017166001179055801561355a576000805461ff001916905550565b600054610100900460ff168061421d575061421d613f56565b8061422b575060005460ff16155b6142665760405162461bcd60e51b815260040180806020018281038252602e8152602001806146b7602e913960400191505060405180910390fd5b600054610100900460ff16158015614291576000805460ff1961ff0019909116610100171660011790555b600061429b612f15565b603380546001600160a01b0319166001600160a01b038316908117909155604051919250906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a350801561355a576000805461ff001916905550565b600054610100900460ff16806143165750614316613f56565b80614324575060005460ff16155b61435f5760405162461bcd60e51b815260040180806020018281038252602e8152602001806146b7602e913960400191505060405180910390fd5b600054610100900460ff1615801561438a576000805460ff1961ff0019909116610100171660011790555b6001606555801561355a576000805461ff001916905550565b60606143b284846000856143bc565b90505b9392505050565b6060824710156143fd5760405162461bcd60e51b81526004018080602001828103825260268152602001806146916026913960400191505060405180910390fd5b6144068561415e565b614457576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b602083106144965780518252601f199092019160209182019101614477565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d80600081146144f8576040519150601f19603f3d011682016040523d82523d6000602084013e6144fd565b606091505b509150915061450d828286614518565b979650505050505050565b606083156145275750816143b5565b8251156145375782518084602001fd5b8160405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015614581578181015183820152602001614569565b50505050905090810190601f1680156145ae5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b604051806080016040528060006001600160a01b031681526020016000815260200160008152602001600081525090565b60405180608001604052806000815260200160006001600160a01b031681526020016000815260200160008152509056fe5265656e7472616e637947756172643a207265656e7472616e742063616c6c0063616e6e6f7420706c61636520616e206f666665722069662061756374696f6e20697320676f696e67206f6e4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657273656e646572206d7573742062652062756e646c65206d61726b6574706c6163655361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a2646970667358221220662e18944b53a2243aea4448d6ea00c10cdbe1e55ac05bf1c901f7173abe8c2f64736f6c634300060c0033
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061018e5760003560e01c80638da5cb5b116100de578063e940ebeb11610097578063f3880b6e11610071578063f3880b6e14610610578063f39e69a414610646578063f3ad65f414610676578063f5fe7f711461067e5761018e565b8063e940ebeb14610574578063e984f2eb146105b0578063f2fde38b146105ea5761018e565b80638da5cb5b1461044d578063afb0695214610455578063b2ddee0614610476578063c1661a9a146104a2578063d3f494cc146104e2578063e1e549c4146105485761018e565b806342cbb4b81161014b5780636bd3a64b116101255780636bd3a64b14610379578063715018a6146103dd57806378746d0d146103e557806385f9d345146104115761018e565b806342cbb4b8146102ba57806357b275b41461030057806368e79e89146103535761018e565b8063058a56ac1461019357806326232a2e146101c15780633740ebb3146101e05780633bbb2806146102045780633fc1cc261461023a57806341976e0914610282575b600080fd5b6101bf600480360360408110156101a957600080fd5b506001600160a01b0381351690602001356106a4565b005b6101c961083b565b6040805161ffff9092168252519081900360200190f35b6101e8610845565b604080516001600160a01b039092168252519081900360200190f35b6101bf6004803603606081101561021a57600080fd5b506001600160a01b0381358116916020810135916040909101351661085a565b6101bf600480360360c081101561025057600080fd5b506001600160a01b03813581169160208101359160408201359160608101359091169060808101359060a001356110c1565b6102a86004803603602081101561029857600080fd5b50356001600160a01b0316611657565b60408051918252519081900360200190f35b6101bf600480360360c08110156102d057600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060808101359060a00135611895565b6103266004803603602081101561031657600080fd5b50356001600160a01b0316611d7d565b6040805161ffff90941684526001600160a01b039283166020850152911682820152519081900360600190f35b6101bf6004803603602081101561036957600080fd5b50356001600160a01b0316611daf565b6103af6004803603606081101561038f57600080fd5b506001600160a01b03813581169160208101359160409091013516611e33565b604080519485526001600160a01b039093166020850152838301919091526060830152519081900360800190f35b6101bf611e75565b6101e8600480360360408110156103fb57600080fd5b506001600160a01b038135169060200135611f21565b6101bf6004803603608081101561042757600080fd5b506001600160a01b03813581169160208101359160408201358116916060013516611f47565b6101e86121e5565b6101bf6004803603602081101561046b57600080fd5b503561ffff166121f4565b6101bf6004803603604081101561048c57600080fd5b506001600160a01b0381351690602001356122a0565b6101bf600480360360808110156104b857600080fd5b506001600160a01b038135811691602081013582169161ffff6040830135169160600135166123c3565b610518600480360360608110156104f857600080fd5b506001600160a01b0381358116916020810135916040909101351661269a565b604080516001600160a01b0390951685526020850193909352838301919091526060830152519081900360800190f35b6101c96004803603604081101561055e57600080fd5b506001600160a01b0381351690602001356126dc565b6101bf6004803603608081101561058a57600080fd5b506001600160a01b038135811691602081013591604082013581169160600135166126fd565b6101bf600480360360808110156105c657600080fd5b506001600160a01b03813581169160208101359160408201351690606001356128d7565b6101bf6004803603602081101561060057600080fd5b50356001600160a01b0316612ad7565b6101bf6004803603606081101561062657600080fd5b5080356001600160a01b0316906020810135906040013561ffff16612bda565b6101bf6004803603604081101561065c57600080fd5b5080356001600160a01b0316906020013561ffff16612d65565b6101e8612e46565b6101bf6004803603602081101561069457600080fd5b50356001600160a01b0316612e55565b81816106ae612f15565b6106b66145bc565b506001600160a01b038084166000908152609a6020908152604080832086845282528083208585168452825291829020825160808101845281549094168452600181015491840182905260028101549284019290925260039091015460608301521580159061072f5750610728612f19565b8160600151115b610780576040805162461bcd60e51b815260206004820152601b60248201527f6f66666572206e6f7420657869737473206f7220657870697265640000000000604482015290519081900360640190fd5b6001600160a01b0386166000908152609a602090815260408083208884529091528120906107ac612f15565b6001600160a01b0390811682526020820192909252604001600090812080546001600160a01b031916815560018101829055600281018290556003015586166107f3612f15565b6001600160a01b03167fc6e24dcedb16cc237925b586889d0a38102c719734d6cc56acb89b013099b3a7876040518082815260200191505060405180910390a3505050505050565b609b5461ffff1681565b609b546201000090046001600160a01b031681565b600260655414156108a0576040805162461bcd60e51b815260206004820152601f602482015260008051602061461f833981519152604482015290519081900360640190fd5b60026065558282826108b06145bc565b506001600160a01b038084166000908152609a602090815260408083208684528252808320858516845282529182902082516080810184528154909416845260018101549184018290526002810154928401929092526003909101546060830152158015906109295750610922612f19565b8160600151115b61097a576040805162461bcd60e51b815260206004820152601b60248201527f6f66666572206e6f7420657869737473206f7220657870697265640000000000604482015290519081900360640190fd5b6109826145bc565b506001600160a01b038088166000908152609a602090815260408083208a8452825280832089851684528252918290208251608081018452815490941684526001810154918401919091526002810154918301919091526003015460608201526109f988886109ef612f15565b8460200151612f1d565b6000610a16826020015183604001516131b690919063ffffffff16565b609b54909150600090610a3c906103e890610a3690859061ffff166131b6565b90613218565b609b548451919250600091610a66916001600160a01b03918216918c91620100009004168561327f565b6001600160a01b03808c1660008181526097602090815260408083208f8452825280832054938352609882528083208f845290915290205491169061ffff168115801590610ab7575061ffff811615155b15610b0557610ada612710610a3661ffff8416610ad489896132d9565b906131b6565b8651909350610af4906001600160a01b03168c848661327f565b610afe8484613336565b9350610b84565b50506001600160a01b03808c166000908152609c602052604090206001810154905491169061ffff168115801590610b40575061ffff811615155b15610b8457610b5d612710610a3661ffff8416610ad489896132d9565b8651909350610b77906001600160a01b03168c848661327f565b610b818484613336565b93505b610bad8b610b90612f15565b610b9a88886132d9565b89516001600160a01b031692919061327f565b604080516301ffc9a760e01b81526380ac58cd60e01b600482015290516001600160a01b038f16916301ffc9a7916024808301926020929190829003018186803b158015610bfa57600080fd5b505afa158015610c0e573d6000803e3d6000fd5b505050506040513d6020811015610c2457600080fd5b505115610cb7578c6001600160a01b03166342842e0e610c42612f15565b8d8f6040518463ffffffff1660e01b815260040180846001600160a01b03168152602001836001600160a01b031681526020018281526020019350505050600060405180830381600087803b158015610c9a57600080fd5b505af1158015610cae573d6000803e3d6000fd5b50505050610dc4565b8c6001600160a01b031663f242432a610cce612f15565b8d8f8a60200151604051806020016040528060008152506040518663ffffffff1660e01b815260040180866001600160a01b03168152602001856001600160a01b0316815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015610d5b578181015183820152602001610d43565b50505050905090810190601f168015610d885780820380516001836020036101000a031916815260200191505b509650505050505050600060405180830381600087803b158015610dab57600080fd5b505af1158015610dbf573d6000803e3d6000fd5b505050505b609d60009054906101000a90046001600160a01b03166001600160a01b0316639e1f5b286040518163ffffffff1660e01b815260040160206040518083038186803b158015610e1257600080fd5b505afa158015610e26573d6000803e3d6000fd5b505050506040513d6020811015610e3c57600080fd5b81019080805190602001909291905050506001600160a01b03166327c1f4f48e8e89602001516040518463ffffffff1660e01b815260040180846001600160a01b031681526020018381526020018281526020019350505050600060405180830381600087803b158015610eaf57600080fd5b505af1158015610ec3573d6000803e3d6000fd5b505050508c6001600160a01b03168b6001600160a01b0316610ee3612f15565b6001600160a01b03167f33288df29d0f4a78de0aab5956626ed28d0abeb944e8f0d78dd1031efb53941f8f8a602001518b600001518c6040015160405180858152602001848152602001836001600160a01b0316815260200182815260200194505050505060405180910390a48c6001600160a01b03168b6001600160a01b03167fc6e24dcedb16cc237925b586889d0a38102c719734d6cc56acb89b013099b3a78e6040518082815260200191505060405180910390a36001600160a01b038d1660009081526099602090815260408083208f8452909152812090610fc7612f15565b6001600160a01b03166001600160a01b031681526020019081526020016000206000808201600090556001820160006101000a8154906001600160a01b030219169055600282016000905560038201600090555050609a60008e6001600160a01b03166001600160a01b0316815260200190815260200160002060008d815260200190815260200160002060008c6001600160a01b03166001600160a01b03168152602001908152602001600020600080820160006101000a8154906001600160a01b0302191690556001820160009055600282016000905560038201600090555050505050505050505050506001606581905550505050565b85856110cb612f15565b6110d36145ed565b506001600160a01b03808416600090815260996020908152604080832086845282528083208585168452825291829020825160808101845281548082526001830154909516928101929092526002810154928201929092526003909101546060820152901561117a576040805162461bcd60e51b815260206004820152600e60248201526d185b1c9958591e481b1a5cdd195960921b604482015290519081900360640190fd5b604080516301ffc9a760e01b81526380ac58cd60e01b600482015290516001600160a01b038c16916301ffc9a7916024808301926020929190829003018186803b1580156111c757600080fd5b505afa1580156111db573d6000803e3d6000fd5b505050506040513d60208110156111f157600080fd5b5051156113a35789611201612f15565b6001600160a01b0316816001600160a01b0316636352211e8c6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561124e57600080fd5b505afa158015611262573d6000803e3d6000fd5b505050506040513d602081101561127857600080fd5b50516001600160a01b0316146112c7576040805162461bcd60e51b815260206004820152600f60248201526e6e6f74206f776e696e67206974656d60881b604482015290519081900360640190fd5b806001600160a01b031663e985e9c56112de612f15565b306040518363ffffffff1660e01b815260040180836001600160a01b03168152602001826001600160a01b031681526020019250505060206040518083038186803b15801561132c57600080fd5b505afa158015611340573d6000803e3d6000fd5b505050506040513d602081101561135657600080fd5b505161139d576040805162461bcd60e51b81526020600482015260116024820152701a5d195b481b9bdd08185c1c1c9bdd9959607a1b604482015290519081900360640190fd5b50611538565b604080516301ffc9a760e01b8152636cdb3d1360e11b600482015290516001600160a01b038c16916301ffc9a7916024808301926020929190829003018186803b1580156113f057600080fd5b505afa158015611404573d6000803e3d6000fd5b505050506040513d602081101561141a57600080fd5b5051156114f55789886001600160a01b03821662fdd58e611439612f15565b8d6040518363ffffffff1660e01b815260040180836001600160a01b031681526020018281526020019250505060206040518083038186803b15801561147e57600080fd5b505afa158015611492573d6000803e3d6000fd5b505050506040513d60208110156114a857600080fd5b505110156112c7576040805162461bcd60e51b81526020600482015260156024820152746d75737420686f6c6420656e6f756768206e66747360581b604482015290519081900360640190fd5b6040805162461bcd60e51b8152602060048201526013602482015272696e76616c6964206e6674206164647265737360681b604482015290519081900360640190fd5b61154187613390565b604080516080810182528981526001600160a01b03808a166020808401919091528284018a905260608301899052908d166000908152609982528381208d82529091529182209091611591612f15565b6001600160a01b039081168252602080830193909352604091820160002084518155928401516001840180546001600160a01b0319169183169190911790559083015160028301556060909201516003909101558a166115ef612f15565b604080518c8152602081018c90526001600160a01b038b811682840152606082018b9052608082018a9052915192909116917fa0294f02f8ad82fe4744717b0f953a105547196cd3c67056200c1a4ae3aa26299181900360a00190a350505050505050505050565b600080600080609d60009054906101000a90046001600160a01b03166001600160a01b031663741bef1a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156116ab57600080fd5b505afa1580156116bf573d6000803e3d6000fd5b505050506040513d60208110156116d557600080fd5b505190506001600160a01b0385166117d957806001600160a01b03166341976e09826001600160a01b031663050d63ec6040518163ffffffff1660e01b815260040160206040518083038186803b15801561172f57600080fd5b505afa158015611743573d6000803e3d6000fd5b505050506040513d602081101561175957600080fd5b5051604080516001600160e01b031960e085901b1681526001600160a01b0390921660048301528051602480840193829003018186803b15801561179c57600080fd5b505afa1580156117b0573d6000803e3d6000fd5b505050506040513d60408110156117c657600080fd5b5080516020909101519093509150611857565b604080516341976e0960e01b81526001600160a01b0387811660048301528251908416926341976e099260248082019391829003018186803b15801561181e57600080fd5b505afa158015611832573d6000803e3d6000fd5b505050506040513d604081101561184857600080fd5b50805160209091015190935091505b60128260ff161015611876578160120360ff16600a0a8302925061188c565b6012820360ff16600a0a838161188857fe5b0592505b50909392505050565b858561189f612f15565b6118a76145bc565b506001600160a01b038084166000908152609a602090815260408083208684528252808320858516845282529182902082516080810184528154909416845260018101549184018290526002810154928401929092526003909101546060830152158061191f5750611917612f19565b816060015111155b611968576040805162461bcd60e51b81526020600482015260156024820152741bd999995c88185b1c9958591e4818dc99585d1959605a1b604482015290519081900360640190fd5b604080516301ffc9a760e01b81526380ac58cd60e01b600482015290516001600160a01b038c16916301ffc9a7916024808301926020929190829003018186803b1580156119b557600080fd5b505afa1580156119c9573d6000803e3d6000fd5b505050506040513d60208110156119df57600080fd5b505180611a615750604080516301ffc9a760e01b8152636cdb3d1360e11b600482015290516001600160a01b038c16916301ffc9a7916024808301926020929190829003018186803b158015611a3457600080fd5b505afa158015611a48573d6000803e3d6000fd5b505050506040513d6020811015611a5e57600080fd5b50515b611aa8576040805162461bcd60e51b8152602060048201526013602482015272696e76616c6964206e6674206164647265737360681b604482015290519081900360640190fd5b609d5460408051637d9f6db560e01b815290516000926001600160a01b031691637d9f6db5916004808301926020929190829003018186803b158015611aed57600080fd5b505afa158015611b01573d6000803e3d6000fd5b505050506040513d6020811015611b1757600080fd5b50516040805163227c8e0f60e11b81526001600160a01b038e81166004830152602482018e9052915192935060009283928516916344f91c1e9160448083019260c0929190829003018186803b158015611b7057600080fd5b505afa158015611b84573d6000803e3d6000fd5b505050506040513d60c0811015611b9a57600080fd5b50606081015160a0909101519092509050811580611bba57506001811515145b611bf55760405162461bcd60e51b815260040180806020018281038252602c81526020018061463f602c913960400191505060405180910390fd5b611bfd612f19565b8811611c45576040805162461bcd60e51b815260206004820152601260248201527134b73b30b634b21032bc3834b930ba34b7b760711b604482015290519081900360640190fd5b611c4e8b613390565b60405180608001604052808c6001600160a01b031681526020018b81526020018a815260200189815250609a60008f6001600160a01b03166001600160a01b0316815260200190815260200160002060008e81526020019081526020016000206000611cb8612f15565b6001600160a01b0390811682526020808301939093526040918201600020845181546001600160a01b0319169083161781559284015160018401559083015160028301556060909201516003909101558d16611d12612f15565b604080518f8152602081018e90526001600160a01b038f811682840152606082018e9052608082018d9052915192909116917f89f255157c655b5155655107b77c620998e5ad4e7485d749e4e6d7ddb63e70f69181900360a00190a350505050505050505050505050565b609c602052600090815260409020805460019091015461ffff8216916001600160a01b03620100009091048116911683565b611db7612f15565b6001600160a01b0316611dc86121e5565b6001600160a01b031614611e11576040805162461bcd60e51b81526020600482018190526024820152600080516020614706833981519152604482015290519081900360640190fd5b609d80546001600160a01b0319166001600160a01b0392909216919091179055565b6099602090815260009384526040808520825292845282842090528252902080546001820154600283015460039093015491926001600160a01b039091169184565b611e7d612f15565b6001600160a01b0316611e8e6121e5565b6001600160a01b031614611ed7576040805162461bcd60e51b81526020600482018190526024820152600080516020614706833981519152604482015290519081900360640190fd5b6033546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603380546001600160a01b0319169055565b60976020908152600092835260408084209091529082529020546001600160a01b031681565b60026065541415611f8d576040805162461bcd60e51b815260206004820152601f602482015260008051602061461f833981519152604482015290519081900360640190fd5b6002606555838382611f9d6145ed565b506001600160a01b0380841660009081526099602090815260408083208684528252808320858516845282529182902082516080810184528154808252600183015490951692810192909252600281015492820192909252600390910154606082015290612044576040805162461bcd60e51b815260206004820152600f60248201526e6e6f74206c6973746564206974656d60881b604482015290519081900360640190fd5b87878661204f6145ed565b506001600160a01b03808416600090815260996020908152604080832086845282528083208585168452825291829020825160808101845281548082526001830154909516928101929092526002810154928201929092526003909101546060820152906120c290859085908590612f1d565b80606001516120cf612f19565b1015612115576040805162461bcd60e51b815260206004820152601060248201526f6974656d206e6f742062757961626c6560801b604482015290519081900360640190fd5b61211d6145ed565b506001600160a01b03808d1660009081526099602090815260408083208f845282528083208d851684528252918290208251608081018452815481526001820154851692810183905260028201549381019390935260030154606083015290918c16146121c5576040805162461bcd60e51b815260206004820152601160248201527034b73b30b634b2103830bc903a37b5b2b760791b604482015290519081900360640190fd5b6121d18d8d8d8d61355d565b505060016065555050505050505050505050565b6033546001600160a01b031690565b6121fc612f15565b6001600160a01b031661220d6121e5565b6001600160a01b031614612256576040805162461bcd60e51b81526020600482018190526024820152600080516020614706833981519152604482015290519081900360640190fd5b609b805461ffff831661ffff19909116811790915560408051918252517fcabead39256298cdf7d1228eee68b47bc54a2192283d8d93574da08d2d7ac3039181900360200190a150565b600260655414156122e6576040805162461bcd60e51b815260206004820152601f602482015260008051602061461f833981519152604482015290519081900360640190fd5b600260655581816122f5612f15565b6122fd6145ed565b506001600160a01b03808416600090815260996020908152604080832086845282528083208585168452825291829020825160808101845281548082526001830154909516928101929092526002810154928201929092526003909101546060820152906123a4576040805162461bcd60e51b815260206004820152600f60248201526e6e6f74206c6973746564206974656d60881b604482015290519081900360640190fd5b6123b686866123b1612f15565b6139dd565b5050600160655550505050565b6123cb612f15565b6001600160a01b03166123dc6121e5565b6001600160a01b031614612425576040805162461bcd60e51b81526020600482018190526024820152600080516020614706833981519152604482015290519081900360640190fd5b6001600160a01b038316612480576040805162461bcd60e51b815260206004820152601760248201527f696e76616c69642063726561746f722061646472657373000000000000000000604482015290519081900360640190fd5b6127108261ffff1611156124cd576040805162461bcd60e51b815260206004820152600f60248201526e696e76616c696420726f79616c747960881b604482015290519081900360640190fd5b61ffff821615806124e657506001600160a01b03811615155b612537576040805162461bcd60e51b815260206004820152601d60248201527f696e76616c69642066656520726563697069656e742061646472657373000000604482015290519081900360640190fd5b61254084613ae5565b15612588576040805162461bcd60e51b8152602060048201526013602482015272696e76616c6964206e6674206164647265737360681b604482015290519081900360640190fd5b6001600160a01b038481166000908152609c60205260409020546201000090041661263a576040805160608101825261ffff80851682526001600160a01b0380871660208085019182528683168587019081528a84166000908152609c9092529590209351845491518316620100000262010000600160b01b03199190941661ffff199092169190911716919091178255915160019091018054919092166001600160a01b0319909116179055612694565b6001600160a01b038481166000908152609c6020526040902080546001820180546001600160a01b03191685851617905561ffff191661ffff85161762010000600160b01b03191662010000928616929092029190911790555b50505050565b609a60209081526000938452604080852082529284528284209052825290208054600182015460028301546003909301546001600160a01b0390921692909184565b609860209081526000928352604080842090915290825290205461ffff1681565b612705612f15565b6001600160a01b0316609d60009054906101000a90046001600160a01b03166001600160a01b0316639e1f5b286040518163ffffffff1660e01b815260040160206040518083038186803b15801561275c57600080fd5b505afa158015612770573d6000803e3d6000fd5b505050506040513d602081101561278657600080fd5b50516001600160a01b0316146127cd5760405162461bcd60e51b81526004018080602001828103825260218152602001806147266021913960400191505060405180910390fd5b6127d56145ed565b506001600160a01b038085166000908152609960209081526040808320878452825280832086851684528252918290208251608081018452815480825260018301549095169281019290925260028101549282019290925260039091015460608201529015612849576128498585856139dd565b6001600160a01b038086166000818152609a60209081526040808320898452825280832094871680845294825280832080546001600160a01b0319168155600181018490556002810184905560030192909255815188815291519293927fc6e24dcedb16cc237925b586889d0a38102c719734d6cc56acb89b013099b3a79281900390910190a35050505050565b6002606554141561291d576040805162461bcd60e51b815260206004820152601f602482015260008051602061461f833981519152604482015290519081900360640190fd5b6002606555838361292c612f15565b6129346145ed565b506001600160a01b03808416600090815260996020908152604080832086845282528083208585168452825291829020825160808101845281548082526001830154909516928101929092526002810154928201929092526003909101546060820152906129db576040805162461bcd60e51b815260206004820152600f60248201526e6e6f74206c6973746564206974656d60881b604482015290519081900360640190fd5b6001600160a01b03881660009081526099602090815260408083208a8452909152812081612a07612f15565b6001600160a01b03166001600160a01b031681526020019081526020016000209050612a3d8989612a36612f15565b8454612f1d565b612a4687613390565b6001810180546001600160a01b0319166001600160a01b0389811691909117909155600282018790558916612a79612f15565b604080518b81526001600160a01b038b811660208301528183018b9052915192909116917f60a11f1619b1716bc2857bf610d4bc631336e14d197025fd5875c1aca1ac7cbd9181900360600190a35050600160655550505050505050565b612adf612f15565b6001600160a01b0316612af06121e5565b6001600160a01b031614612b39576040805162461bcd60e51b81526020600482018190526024820152600080516020614706833981519152604482015290519081900360640190fd5b6001600160a01b038116612b7e5760405162461bcd60e51b815260040180806020018281038252602681526020018061466b6026913960400191505060405180910390fd5b6033546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603380546001600160a01b0319166001600160a01b0392909216919091179055565b6127108161ffff161115612c27576040805162461bcd60e51b815260206004820152600f60248201526e696e76616c696420726f79616c747960881b604482015290519081900360640190fd5b612c3083613ae5565b612c77576040805162461bcd60e51b8152602060048201526013602482015272696e76616c6964206e6674206164647265737360681b604482015290519081900360640190fd5b612c8b8383612c84612f15565b6001612f1d565b6001600160a01b0383811660009081526097602090815260408083208684529091529020541615612cf9576040805162461bcd60e51b81526020600482015260136024820152721c9bde585b1d1e48185b1c9958591e481cd95d606a1b604482015290519081900360640190fd5b612d01612f15565b6001600160a01b039384166000818152609760209081526040808320878452825280832080546001600160a01b03191695909816949094179096559081526098855281812093815292909352919020805461ffff191661ffff909216919091179055565b600054610100900460ff1680612d7e5750612d7e613f56565b80612d8c575060005460ff16155b612dc75760405162461bcd60e51b815260040180806020018281038252602e8152602001806146b7602e913960400191505060405180910390fd5b600054610100900460ff16158015612df2576000805460ff1961ff0019909116610100171660011790555b609b805461ffff191661ffff84161762010000600160b01b031916620100006001600160a01b03861602179055612e27613f67565b612e2f614018565b8015612e41576000805461ff00191690555b505050565b609d546001600160a01b031681565b612e5d612f15565b6001600160a01b0316612e6e6121e5565b6001600160a01b031614612eb7576040805162461bcd60e51b81526020600482018190526024820152600080516020614706833981519152604482015290519081900360640190fd5b609b80546001600160a01b03831662010000810262010000600160b01b03199092169190911790915560408051918252517fe57e7c1f36cc83fade34e32351e6eee7eb9da532662b1b5da10c631e8222aca79181900360200190a150565b3390565b4290565b604080516301ffc9a760e01b81526380ac58cd60e01b600482015290516001600160a01b038616916301ffc9a7916024808301926020929190829003018186803b158015612f6a57600080fd5b505afa158015612f7e573d6000803e3d6000fd5b505050506040513d6020811015612f9457600080fd5b50511561306d576000849050826001600160a01b0316816001600160a01b0316636352211e866040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015612fee57600080fd5b505afa158015613002573d6000803e3d6000fd5b505050506040513d602081101561301857600080fd5b50516001600160a01b031614613067576040805162461bcd60e51b815260206004820152600f60248201526e6e6f74206f776e696e67206974656d60881b604482015290519081900360640190fd5b50612694565b604080516301ffc9a760e01b8152636cdb3d1360e11b600482015290516001600160a01b038616916301ffc9a7916024808301926020929190829003018186803b1580156130ba57600080fd5b505afa1580156130ce573d6000803e3d6000fd5b505050506040513d60208110156130e457600080fd5b5051156114f557600084905081816001600160a01b031662fdd58e85876040518363ffffffff1660e01b815260040180836001600160a01b031681526020018281526020019250505060206040518083038186803b15801561314557600080fd5b505afa158015613159573d6000803e3d6000fd5b505050506040513d602081101561316f57600080fd5b50511015613067576040805162461bcd60e51b815260206004820152600f60248201526e6e6f74206f776e696e67206974656d60881b604482015290519081900360640190fd5b6000826131c557506000613212565b828202828482816131d257fe5b041461320f5760405162461bcd60e51b81526004018080602001828103825260218152602001806146e56021913960400191505060405180910390fd5b90505b92915050565b600080821161326e576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161327757fe5b049392505050565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b1790526126949085906140ad565b600082821115613330576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b60008282018381101561320f576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6001600160a01b03811615806135155750609d5460408051639d23c4c760e01b815290516000926001600160a01b031691639d23c4c7916004808301926020929190829003018186803b1580156133e657600080fd5b505afa1580156133fa573d6000803e3d6000fd5b505050506040513d602081101561341057600080fd5b50516001600160a01b0316148015906135155750609d60009054906101000a90046001600160a01b03166001600160a01b0316639d23c4c76040518163ffffffff1660e01b815260040160206040518083038186803b15801561347257600080fd5b505afa158015613486573d6000803e3d6000fd5b505050506040513d602081101561349c57600080fd5b5051604080516398afdfe360e01b81526001600160a01b038481166004830152915191909216916398afdfe3916024808301926020929190829003018186803b1580156134e857600080fd5b505afa1580156134fc573d6000803e3d6000fd5b505050506040513d602081101561351257600080fd5b50515b61355a576040805162461bcd60e51b815260206004820152601160248201527034b73b30b634b2103830bc903a37b5b2b760791b604482015290519081900360640190fd5b50565b6135656145ed565b506001600160a01b03808516600090815260996020908152604080832087845282528083208585168452825280832081516080810183528154808252600183015490961693810193909352600281015491830182905260030154606083015290926135d091906131b6565b609b549091506000906135f0906103e890610a3690859061ffff166131b6565b905061361a6135fd612f15565b609b546001600160a01b038881169291620100009004168461327f565b6001600160a01b0380881660008181526097602090815260408083208b8452825280832054938352609882528083208b845290915290205491169061ffff16811580159061366b575061ffff811615155b156136ad57600061367c85856132d9565b905061369b613689612f15565b6001600160a01b038a1690858461327f565b6136a58482613336565b9350506136ea565b50506001600160a01b038088166000908152609c602052604090206001810154905491169061ffff1681158015906136e8575061ffff811615155b505b604080516301ffc9a760e01b81526380ac58cd60e01b600482015290516001600160a01b038b16916301ffc9a7916024808301926020929190829003018186803b15801561373757600080fd5b505afa15801561374b573d6000803e3d6000fd5b505050506040513d602081101561376157600080fd5b5051156137f457886001600160a01b03166342842e0e87613780612f15565b8b6040518463ffffffff1660e01b815260040180846001600160a01b03168152602001836001600160a01b031681526020018281526020019350505050600060405180830381600087803b1580156137d757600080fd5b505af11580156137eb573d6000803e3d6000fd5b50505050613901565b886001600160a01b031663f242432a8761380c612f15565b8b8960000151604051806020016040528060008152506040518663ffffffff1660e01b815260040180866001600160a01b03168152602001856001600160a01b0316815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015613898578181015183820152602001613880565b50505050905090810190601f1680156138c55780820380516001836020036101000a031916815260200191505b509650505050505050600060405180830381600087803b1580156138e857600080fd5b505af11580156138fc573d6000803e3d6000fd5b505050505b886001600160a01b0316613913612f15565b86516001600160a01b03918216918916907f33288df29d0f4a78de0aab5956626ed28d0abeb944e8f0d78dd1031efb53941f908c908c6139538b83613218565b6040805194855260208501939093526001600160a01b03909116838301526060830152519081900360800190a45050506001600160a01b03958616600090815260996020908152604080832097835296815286822094909716815292909552509182208281556001810180546001600160a01b031916905560028101839055600301919091555050565b6139e56145ed565b506001600160a01b0380841660009081526099602090815260408083208684528252808320858516845282529182902082516080810184528154808252600183015490951692810192909252600281015492820192909252600390910154606082015290613a5890859085908590612f1d565b6001600160a01b03808516600081815260996020908152604080832088845282528083209487168084529482528083208381556001810180546001600160a01b03191690556002810184905560030192909255815187815291519293927f9ba1a3cb55ce8d63d072a886f94d2a744f50cddf82128e897d0661f5ec6231589281900390910190a350505050565b6000816001600160a01b0316609d60009054906101000a90046001600160a01b03166001600160a01b03166318944e556040518163ffffffff1660e01b815260040160206040518083038186803b158015613b3f57600080fd5b505afa158015613b53573d6000803e3d6000fd5b505050506040513d6020811015613b6957600080fd5b50516001600160a01b03161480613c6c5750609d60009054906101000a90046001600160a01b03166001600160a01b031663c45a01556040518163ffffffff1660e01b815260040160206040518083038186803b158015613bc957600080fd5b505afa158015613bdd573d6000803e3d6000fd5b505050506040513d6020811015613bf357600080fd5b505160408051637b51e92760e11b81526001600160a01b0385811660048301529151919092169163f6a3d24e916024808301926020929190829003018186803b158015613c3f57600080fd5b505afa158015613c53573d6000803e3d6000fd5b505050506040513d6020811015613c6957600080fd5b50515b80613d635750609d60009054906101000a90046001600160a01b03166001600160a01b031663735db9396040518163ffffffff1660e01b815260040160206040518083038186803b158015613cc057600080fd5b505afa158015613cd4573d6000803e3d6000fd5b505050506040513d6020811015613cea57600080fd5b505160408051637b51e92760e11b81526001600160a01b0385811660048301529151919092169163f6a3d24e916024808301926020929190829003018186803b158015613d3657600080fd5b505afa158015613d4a573d6000803e3d6000fd5b505050506040513d6020811015613d6057600080fd5b50515b80613e5a5750609d60009054906101000a90046001600160a01b03166001600160a01b0316630fb27d8c6040518163ffffffff1660e01b815260040160206040518083038186803b158015613db757600080fd5b505afa158015613dcb573d6000803e3d6000fd5b505050506040513d6020811015613de157600080fd5b505160408051637b51e92760e11b81526001600160a01b0385811660048301529151919092169163f6a3d24e916024808301926020929190829003018186803b158015613e2d57600080fd5b505afa158015613e41573d6000803e3d6000fd5b505050506040513d6020811015613e5757600080fd5b50515b806132125750609d60009054906101000a90046001600160a01b03166001600160a01b031663924db13f6040518163ffffffff1660e01b815260040160206040518083038186803b158015613eae57600080fd5b505afa158015613ec2573d6000803e3d6000fd5b505050506040513d6020811015613ed857600080fd5b505160408051637b51e92760e11b81526001600160a01b0385811660048301529151919092169163f6a3d24e916024808301926020929190829003018186803b158015613f2457600080fd5b505afa158015613f38573d6000803e3d6000fd5b505050506040513d6020811015613f4e57600080fd5b505192915050565b6000613f613061415e565b15905090565b600054610100900460ff1680613f805750613f80613f56565b80613f8e575060005460ff16155b613fc95760405162461bcd60e51b815260040180806020018281038252602e8152602001806146b7602e913960400191505060405180910390fd5b600054610100900460ff16158015613ff4576000805460ff1961ff0019909116610100171660011790555b613ffc614164565b614004614204565b801561355a576000805461ff001916905550565b600054610100900460ff16806140315750614031613f56565b8061403f575060005460ff16155b61407a5760405162461bcd60e51b815260040180806020018281038252602e8152602001806146b7602e913960400191505060405180910390fd5b600054610100900460ff161580156140a5576000805460ff1961ff0019909116610100171660011790555b6140046142fd565b6060614102826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166143a39092919063ffffffff16565b805190915015612e415780806020019051602081101561412157600080fd5b5051612e415760405162461bcd60e51b815260040180806020018281038252602a815260200180614747602a913960400191505060405180910390fd5b3b151590565b600054610100900460ff168061417d575061417d613f56565b8061418b575060005460ff16155b6141c65760405162461bcd60e51b815260040180806020018281038252602e8152602001806146b7602e913960400191505060405180910390fd5b600054610100900460ff16158015614004576000805460ff1961ff001990911661010017166001179055801561355a576000805461ff001916905550565b600054610100900460ff168061421d575061421d613f56565b8061422b575060005460ff16155b6142665760405162461bcd60e51b815260040180806020018281038252602e8152602001806146b7602e913960400191505060405180910390fd5b600054610100900460ff16158015614291576000805460ff1961ff0019909116610100171660011790555b600061429b612f15565b603380546001600160a01b0319166001600160a01b038316908117909155604051919250906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a350801561355a576000805461ff001916905550565b600054610100900460ff16806143165750614316613f56565b80614324575060005460ff16155b61435f5760405162461bcd60e51b815260040180806020018281038252602e8152602001806146b7602e913960400191505060405180910390fd5b600054610100900460ff1615801561438a576000805460ff1961ff0019909116610100171660011790555b6001606555801561355a576000805461ff001916905550565b60606143b284846000856143bc565b90505b9392505050565b6060824710156143fd5760405162461bcd60e51b81526004018080602001828103825260268152602001806146916026913960400191505060405180910390fd5b6144068561415e565b614457576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b602083106144965780518252601f199092019160209182019101614477565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d80600081146144f8576040519150601f19603f3d011682016040523d82523d6000602084013e6144fd565b606091505b509150915061450d828286614518565b979650505050505050565b606083156145275750816143b5565b8251156145375782518084602001fd5b8160405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015614581578181015183820152602001614569565b50505050905090810190601f1680156145ae5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b604051806080016040528060006001600160a01b031681526020016000815260200160008152602001600081525090565b60405180608001604052806000815260200160006001600160a01b031681526020016000815260200160008152509056fe5265656e7472616e637947756172643a207265656e7472616e742063616c6c0063616e6e6f7420706c61636520616e206f666665722069662061756374696f6e20697320676f696e67206f6e4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657273656e646572206d7573742062652062756e646c65206d61726b6574706c6163655361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a2646970667358221220662e18944b53a2243aea4448d6ea00c10cdbe1e55ac05bf1c901f7173abe8c2f64736f6c634300060c0033
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.