Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
13316062 | 1115 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Contract Name:
FNDNFTMarket
Compiler Version
v0.7.6+commit.7338295f
Optimization Enabled:
Yes with 1337 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
/* ・ * ★ ・ 。 ・ ゚☆ 。 * ★ ゚・。 * 。 * ☆ 。・゚*.。 ゚ *.。☆。★ ・ ` .-:::::-.` `-::---...``` `-:` .:+ssssoooo++//:.` .-/+shhhhhhhhhhhhhyyyssooo: .--::. .+ossso+/////++/:://-` .////+shhhhhhhhhhhhhhhhhhhhhy `-----::. `/+////+++///+++/:--:/+/- -////+shhhhhhhhhhhhhhhhhhhhhy `------:::-` `//-.``.-/+ooosso+:-.-/oso- -////+shhhhhhhhhhhhhhhhhhhhhy .--------:::-` :+:.` .-/osyyyyyyso++syhyo.-////+shhhhhhhhhhhhhhhhhhhhhy `-----------:::-. +o+:-.-:/oyhhhhhhdhhhhhdddy:-////+shhhhhhhhhhhhhhhhhhhhhy .------------::::-- `oys+/::/+shhhhhhhdddddddddy/-////+shhhhhhhhhhhhhhhhhhhhhy .--------------:::::-` +ys+////+yhhhhhhhddddddddhy:-////+yhhhhhhhhhhhhhhhhhhhhhy `----------------::::::-`.ss+/:::+oyhhhhhhhhhhhhhhho`-////+shhhhhhhhhhhhhhhhhhhhhy .------------------:::::::.-so//::/+osyyyhhhhhhhhhys` -////+shhhhhhhhhhhhhhhhhhhhhy `.-------------------::/:::::..+o+////+oosssyyyyyyys+` .////+shhhhhhhhhhhhhhhhhhhhhy .--------------------::/:::.` -+o++++++oooosssss/. `-//+shhhhhhhhhhhhhhhhhhhhyo .------- ``````.......--` `-/+ooooosso+/-` `./++++///:::--...``hhhhyo ````` * ・ 。 ・ ゚☆ 。 * ★ ゚・。 * 。 * ☆ 。・゚*.。 ゚ *.。☆。★ ・ * ゚。·*・。 ゚* ☆゚・。°*. ゚ ・ ゚*。・゚★。 ・ *゚。 * ・゚*。★・ ☆∴。 * ・ 。 */ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.7.0; pragma abicoder v2; // solhint-disable-line import "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol"; import "./mixins/FoundationTreasuryNode.sol"; import "./mixins/roles/FoundationAdminRole.sol"; import "./mixins/roles/FoundationOperatorRole.sol"; import "./mixins/NFTMarketCore.sol"; import "./mixins/SendValueWithFallbackWithdraw.sol"; import "./mixins/NFTMarketCreators.sol"; import "./mixins/NFTMarketFees.sol"; import "./mixins/NFTMarketAuction.sol"; import "./mixins/NFTMarketReserveAuction.sol"; import "./mixins/AccountMigration.sol"; import "./mixins/NFTMarketPrivateSale.sol"; /** * @title A market for NFTs on Foundation. * @dev This top level file holds no data directly to ease future upgrades. */ contract FNDNFTMarket is FoundationTreasuryNode, FoundationAdminRole, FoundationOperatorRole, AccountMigration, NFTMarketCore, ReentrancyGuardUpgradeable, NFTMarketCreators, SendValueWithFallbackWithdraw, NFTMarketFees, NFTMarketAuction, NFTMarketReserveAuction, NFTMarketPrivateSale { /** * @notice Called once to configure the contract after the initial deployment. * @dev This farms the initialize call out to inherited contracts as needed. */ function initialize(address payable treasury) public initializer { FoundationTreasuryNode._initializeFoundationTreasuryNode(treasury); NFTMarketAuction._initializeNFTMarketAuction(); NFTMarketReserveAuction._initializeNFTMarketReserveAuction(); } /** * @notice Allows Foundation to update the market configuration. */ function adminUpdateConfig( uint256 minPercentIncrementInBasisPoints, uint256 duration, uint256 primaryF8nFeeBasisPoints, uint256 secondaryF8nFeeBasisPoints, uint256 secondaryCreatorFeeBasisPoints ) public onlyFoundationAdmin { // It's okay to call _reinitialize multiple times, but it must be called at least once after upgrade _reinitialize(); _updateReserveAuctionConfig(minPercentIncrementInBasisPoints, duration); _updateMarketFees(primaryF8nFeeBasisPoints, secondaryF8nFeeBasisPoints, secondaryCreatorFeeBasisPoints); } /** * @dev Checks who the seller for an NFT is, this will check escrow or return the current owner if not in escrow. * This is a no-op function required to avoid compile errors. */ function _getSellerFor(address nftContract, uint256 tokenId) internal view virtual override(NFTMarketCore, NFTMarketReserveAuction) returns (address payable) { return super._getSellerFor(nftContract, tokenId); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.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 OR Apache-2.0 pragma solidity ^0.7.0; import "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol"; import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol"; /** * @notice A mixin that stores a reference to the Foundation treasury contract. */ abstract contract FoundationTreasuryNode is Initializable { using AddressUpgradeable for address payable; address payable private treasury; /** * @dev Called once after the initial deployment to set the Foundation treasury address. */ function _initializeFoundationTreasuryNode(address payable _treasury) internal initializer { require(_treasury.isContract(), "FoundationTreasuryNode: Address is not a contract"); treasury = _treasury; } /** * @notice Returns the address of the Foundation treasury. */ function getFoundationTreasury() public view returns (address payable) { return treasury; } // `______gap` is added to each mixin to allow adding new data slots or additional mixins in an upgrade-safe way. uint256[2000] private __gap; }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.7.0; import "../../interfaces/IAdminRole.sol"; import "../FoundationTreasuryNode.sol"; /** * @notice Allows a contract to leverage the admin role defined by the Foundation treasury. */ abstract contract FoundationAdminRole is FoundationTreasuryNode { // This file uses 0 data slots (other than what's included via FoundationTreasuryNode) modifier onlyFoundationAdmin() { require(_isFoundationAdmin(), "FoundationAdminRole: caller does not have the Admin role"); _; } function _isFoundationAdmin() internal view returns (bool) { return IAdminRole(getFoundationTreasury()).isAdmin(msg.sender); } }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.7.0; import "../../interfaces/IOperatorRole.sol"; import "../FoundationTreasuryNode.sol"; /** * @notice Allows a contract to leverage the operator role defined by the Foundation treasury. */ abstract contract FoundationOperatorRole is FoundationTreasuryNode { // This file uses 0 data slots (other than what's included via FoundationTreasuryNode) function _isFoundationOperator() internal view returns (bool) { return IOperatorRole(getFoundationTreasury()).isOperator(msg.sender); } }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.7.0; import "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol"; /** * @notice A place for common modifiers and functions used by various NFTMarket mixins, if any. * @dev This also leaves a gap which can be used to add a new mixin to the top of the inheritance tree. */ abstract contract NFTMarketCore { /** * @dev If the auction did not have an escrowed seller to return, this falls back to return the current owner. * This allows functions to calculate the correct fees before the NFT has been listed in auction. */ function _getSellerFor(address nftContract, uint256 tokenId) internal view virtual returns (address payable) { return payable(IERC721Upgradeable(nftContract).ownerOf(tokenId)); } // 50 slots were consumed by adding ReentrancyGuardUpgradeable uint256[950] private ______gap; }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.7.0; import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol"; /** * @notice Attempt to send ETH and if the transfer fails or runs out of gas, store the balance * for future withdrawal instead. */ abstract contract SendValueWithFallbackWithdraw is ReentrancyGuardUpgradeable { using AddressUpgradeable for address payable; using SafeMathUpgradeable for uint256; mapping(address => uint256) private pendingWithdrawals; event WithdrawPending(address indexed user, uint256 amount); event Withdrawal(address indexed user, uint256 amount); /** * @notice Returns how much funds are available for manual withdraw due to failed transfers. */ function getPendingWithdrawal(address user) public view returns (uint256) { return pendingWithdrawals[user]; } /** * @notice Allows a user to manually withdraw funds which originally failed to transfer to themselves. */ function withdraw() public { withdrawFor(msg.sender); } /** * @notice Allows anyone to manually trigger a withdrawal of funds which originally failed to transfer for a user. */ function withdrawFor(address payable user) public nonReentrant { uint256 amount = pendingWithdrawals[user]; require(amount > 0, "No funds are pending withdrawal"); pendingWithdrawals[user] = 0; user.sendValue(amount); emit Withdrawal(user, amount); } /** * @dev Attempt to send a user ETH with a reasonably low gas limit of 20k, * which is enough to send to contracts as well. */ function _sendValueWithFallbackWithdrawWithLowGasLimit(address payable user, uint256 amount) internal { _sendValueWithFallbackWithdraw(user, amount, 20000); } /** * @dev Attempt to send a user or contract ETH with a moderate gas limit of 90k, * which is enough for a 5-way split. */ function _sendValueWithFallbackWithdrawWithMediumGasLimit(address payable user, uint256 amount) internal { _sendValueWithFallbackWithdraw(user, amount, 210000); } /** * @dev Attempt to send a user or contract ETH and if it fails store the amount owned for later withdrawal. */ function _sendValueWithFallbackWithdraw( address payable user, uint256 amount, uint256 gasLimit ) private { if (amount == 0) { return; } // Cap the gas to prevent consuming all available gas to block a tx from completing successfully // solhint-disable-next-line avoid-low-level-calls (bool success, ) = user.call{ value: amount, gas: gasLimit }(""); if (!success) { // Record failed sends for a withdrawal later // Transfers could fail if sent to a multisig with non-trivial receiver logic // solhint-disable-next-line reentrancy pendingWithdrawals[user] = pendingWithdrawals[user].add(amount); emit WithdrawPending(user, amount); } } uint256[499] private ______gap; }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.7.0; import "../interfaces/IFNDNFT721.sol"; import "../interfaces/ITokenCreatorPaymentAddress.sol"; import "../interfaces/ITokenCreator.sol"; import "../interfaces/IGetRoyalties.sol"; import "../interfaces/IHasSecondarySaleFees.sol"; import "../interfaces/IOwnable.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol"; import "./OZ/ERC165Checker.sol"; import "./Constants.sol"; /** * @notice A mixin for associating creators to NFTs. * @dev In the future this may store creators directly in order to support NFTs created on a different platform. */ abstract contract NFTMarketCreators is Constants, ReentrancyGuardUpgradeable // Adding this unused mixin to help with linearization { using ERC165Checker for address; /** * @dev Returns the destination address for any payments to the creator, * or address(0) if the destination is unknown. * It also checks if the current seller is the creator for isPrimary checks. */ // solhint-disable-next-line code-complexity function _getCreatorPaymentInfo( address nftContract, uint256 tokenId, address seller ) internal view returns ( address payable[] memory recipients, uint256[] memory splitPerRecipientInBasisPoints, bool isCreator ) { // All NFTs implement 165 so we skip that check, individual interfaces should return false if 165 is not implemented // 1st priority: getTokenCreatorPaymentAddress w/ 165 if (nftContract.supportsERC165Interface(type(ITokenCreatorPaymentAddress).interfaceId)) { try ITokenCreatorPaymentAddress(nftContract).getTokenCreatorPaymentAddress{ gas: READ_ONLY_GAS_LIMIT }(tokenId) returns (address payable tokenCreatorPaymentAddress) { if (tokenCreatorPaymentAddress != address(0)) { recipients = new address payable[](1); recipients[0] = tokenCreatorPaymentAddress; if (tokenCreatorPaymentAddress == seller) { // splitPerRecipientInBasisPoints is not relevant when only 1 recipient is defined return (recipients, splitPerRecipientInBasisPoints, true); } // else persist recipients but look for other isCreator definitions } } catch // solhint-disable-next-line no-empty-blocks { // Fall through } } // 2nd priority: tokenCreator w/ 165 if (nftContract.supportsERC165Interface(type(ITokenCreator).interfaceId)) { try IFNDNFT721(nftContract).tokenCreator{ gas: READ_ONLY_GAS_LIMIT }(tokenId) returns (address payable _creator) { if (_creator != address(0)) { if (recipients.length == 0) { // Only pay the tokenCreator if there wasn't a tokenCreatorPaymentAddress defined recipients = new address payable[](1); recipients[0] = _creator; } // splitPerRecipientInBasisPoints is not relevant when only 1 recipient is defined return (recipients, splitPerRecipientInBasisPoints, _creator == seller); } } catch // solhint-disable-next-line no-empty-blocks { // Fall through } } // 3rd priority: getRoyalties if (recipients.length == 0 && nftContract.supportsERC165Interface(type(IGetRoyalties).interfaceId)) { try IGetRoyalties(nftContract).getRoyalties{ gas: READ_ONLY_GAS_LIMIT }(tokenId) returns ( address payable[] memory _recipients, uint256[] memory recipientBasisPoints ) { if (_recipients.length > 0 && _recipients.length == recipientBasisPoints.length) { bool hasRecipient = false; for (uint256 i = 0; i < _recipients.length; i++) { if (_recipients[i] != address(0)) { hasRecipient = true; if (_recipients[i] == seller) { isCreator = true; } } } if (hasRecipient) { return (_recipients, recipientBasisPoints, isCreator); } } } catch // solhint-disable-next-line no-empty-blocks { // Fall through } } // 4th priority: getFee* if (recipients.length == 0 && nftContract.supportsERC165Interface(type(IHasSecondarySaleFees).interfaceId)) { try IHasSecondarySaleFees(nftContract).getFeeRecipients{ gas: READ_ONLY_GAS_LIMIT }(tokenId) returns ( address payable[] memory _recipients ) { if (_recipients.length > 0) { try IHasSecondarySaleFees(nftContract).getFeeBps{ gas: READ_ONLY_GAS_LIMIT }(tokenId) returns ( uint256[] memory recipientBasisPoints ) { if (_recipients.length == recipientBasisPoints.length) { bool hasRecipient = false; for (uint256 i = 0; i < _recipients.length; i++) { if (_recipients[i] != address(0)) { hasRecipient = true; if (_recipients[i] == seller) { isCreator = true; } } } if (hasRecipient) { return (_recipients, recipientBasisPoints, isCreator); } } } catch // solhint-disable-next-line no-empty-blocks { // Fall through } } } catch // solhint-disable-next-line no-empty-blocks { // Fall through } } // 5th priority: owner try IOwnable(nftContract).owner{ gas: READ_ONLY_GAS_LIMIT }() returns (address owner) { if (owner != address(0)) { if (recipients.length == 0) { // Only pay the owner if there wasn't a tokenCreatorPaymentAddress defined recipients = new address payable[](1); recipients[0] = payable(owner); } // splitPerRecipientInBasisPoints is not relevant when only 1 recipient is defined return (recipients, splitPerRecipientInBasisPoints, owner == seller); } } catch // solhint-disable-next-line no-empty-blocks { // Fall through } // 6th priority: tokenCreator w/o requiring 165 try IFNDNFT721(nftContract).tokenCreator{ gas: READ_ONLY_GAS_LIMIT }(tokenId) returns (address payable _creator) { if (_creator != address(0)) { if (recipients.length == 0) { // Only pay the tokenCreator if there wasn't a tokenCreatorPaymentAddress defined recipients = new address payable[](1); recipients[0] = _creator; } // splitPerRecipientInBasisPoints is not relevant when only 1 recipient is defined return (recipients, splitPerRecipientInBasisPoints, _creator == seller); } } catch // solhint-disable-next-line no-empty-blocks { // Fall through } // If no valid payment address or creator is found, return 0 recipients } // 500 slots were added via the new SendValueWithFallbackWithdraw mixin uint256[500] private ______gap; }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.7.0; import "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol"; import "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol"; import "./FoundationTreasuryNode.sol"; import "./Constants.sol"; import "./NFTMarketCore.sol"; import "./NFTMarketCreators.sol"; import "./SendValueWithFallbackWithdraw.sol"; /** * @notice A mixin to distribute funds when an NFT is sold. */ abstract contract NFTMarketFees is Constants, Initializable, FoundationTreasuryNode, NFTMarketCore, NFTMarketCreators, SendValueWithFallbackWithdraw { using SafeMathUpgradeable for uint256; uint256 private _primaryFoundationFeeBasisPoints; uint256 private _secondaryFoundationFeeBasisPoints; uint256 private _secondaryCreatorFeeBasisPoints; mapping(address => mapping(uint256 => bool)) private nftContractToTokenIdToFirstSaleCompleted; event MarketFeesUpdated( uint256 primaryFoundationFeeBasisPoints, uint256 secondaryFoundationFeeBasisPoints, uint256 secondaryCreatorFeeBasisPoints ); /** * @notice Returns true if the given NFT has not been sold in this market previously and is being sold by the creator. */ function getIsPrimary(address nftContract, uint256 tokenId) public view returns (bool isPrimary) { address payable seller = _getSellerFor(nftContract, tokenId); bool isCreator; (, , isCreator) = _getCreatorPaymentInfo(nftContract, tokenId, seller); isPrimary = isCreator && !nftContractToTokenIdToFirstSaleCompleted[nftContract][tokenId]; } /** * @notice Returns the current fee configuration in basis points. */ function getFeeConfig() public view returns ( uint256 primaryFoundationFeeBasisPoints, uint256 secondaryFoundationFeeBasisPoints, uint256 secondaryCreatorFeeBasisPoints ) { return (_primaryFoundationFeeBasisPoints, _secondaryFoundationFeeBasisPoints, _secondaryCreatorFeeBasisPoints); } /** * @notice Returns how funds will be distributed for an Auction sale at the given price point. * @dev This is required for backwards compatibility with subgraph. */ function getFees( address nftContract, uint256 tokenId, uint256 price ) public view returns ( uint256 foundationFee, uint256 creatorRev, uint256 ownerRev ) { address payable seller = _getSellerFor(nftContract, tokenId); (foundationFee, , , creatorRev, , ownerRev) = _getFees(nftContract, tokenId, seller, price); } /** * @dev Calculates how funds should be distributed for the given sale details. */ function _getFees( address nftContract, uint256 tokenId, address payable seller, uint256 price ) private view returns ( uint256 foundationFee, address payable[] memory creatorRecipients, uint256[] memory creatorShares, uint256 creatorRev, address payable ownerRevTo, uint256 ownerRev ) { bool isCreator; (creatorRecipients, creatorShares, isCreator) = _getCreatorPaymentInfo(nftContract, tokenId, seller); bool isPrimary = isCreator && !nftContractToTokenIdToFirstSaleCompleted[nftContract][tokenId]; // The SafeMath usage below should only be applicable if a huge (unrealistic) price is used // or fees are misconfigured. // Calculate the Foundation fee foundationFee = price.mul(isPrimary ? _primaryFoundationFeeBasisPoints : _secondaryFoundationFeeBasisPoints) / BASIS_POINTS; // Calculate the Creator revenue. if (isPrimary) { creatorRev = price.sub(foundationFee); // The owner is the creator so ownerRev is not broken out here. } else { if (creatorRecipients.length > 0) { if (isCreator) { // Non-primary sales by the creator should go to the payment address. creatorRev = price.sub(foundationFee); } else { creatorRev = price.mul(_secondaryCreatorFeeBasisPoints) / BASIS_POINTS; // If a secondary sale, calculate the owner revenue. ownerRevTo = seller; ownerRev = price.sub(foundationFee).sub(creatorRev); } } else { // If a secondary sale, calculate the owner revenue. ownerRevTo = seller; ownerRev = price.sub(foundationFee); } } } /** * @dev Distributes funds to foundation, creator, and NFT owner after a sale. * This call will respect the creator's payment address if defined. */ // solhint-disable-next-line code-complexity function _distributeFunds( address nftContract, uint256 tokenId, address payable seller, uint256 price ) internal returns ( uint256 foundationFee, uint256 creatorFee, uint256 ownerRev ) { address payable[] memory creatorRecipients; uint256[] memory creatorShares; address payable ownerRevTo; (foundationFee, creatorRecipients, creatorShares, creatorFee, ownerRevTo, ownerRev) = _getFees( nftContract, tokenId, seller, price ); // Anytime fees are distributed that indicates the first sale is complete, // which will not change state during a secondary sale. // This must come after the `_getFees` call above as this state is considered in the function. nftContractToTokenIdToFirstSaleCompleted[nftContract][tokenId] = true; _sendValueWithFallbackWithdrawWithLowGasLimit(getFoundationTreasury(), foundationFee); if (creatorFee > 0) { if (creatorRecipients.length > 1) { uint256 maxCreatorIndex = creatorRecipients.length - 1; if (maxCreatorIndex > MAX_CREATOR_INDEX) { maxCreatorIndex = MAX_CREATOR_INDEX; } // Determine the total shares defined so it can be leveraged to distribute below uint256 totalShares; for (uint256 i = 0; i <= maxCreatorIndex; i++) { if (creatorShares[i] > BASIS_POINTS) { // If the numbers are >100% we ignore the fee recipients and pay just the first instead maxCreatorIndex = 0; break; } totalShares = totalShares.add(creatorShares[i]); } if (totalShares == 0) { maxCreatorIndex = 0; } // Send payouts to each additional recipient if more than 1 was defined uint256 totalDistributed; for (uint256 i = 1; i <= maxCreatorIndex; i++) { uint256 share = (creatorFee.mul(creatorShares[i])) / totalShares; totalDistributed = totalDistributed.add(share); _sendValueWithFallbackWithdrawWithMediumGasLimit(creatorRecipients[i], share); } // Send the remainder to the 1st creator, rounding in their favor _sendValueWithFallbackWithdrawWithMediumGasLimit(creatorRecipients[0], creatorFee.sub(totalDistributed)); } else { _sendValueWithFallbackWithdrawWithMediumGasLimit(creatorRecipients[0], creatorFee); } } _sendValueWithFallbackWithdrawWithMediumGasLimit(ownerRevTo, ownerRev); } /** * @notice Allows Foundation to change the market fees. */ function _updateMarketFees( uint256 primaryFoundationFeeBasisPoints, uint256 secondaryFoundationFeeBasisPoints, uint256 secondaryCreatorFeeBasisPoints ) internal { require(primaryFoundationFeeBasisPoints < BASIS_POINTS, "NFTMarketFees: Fees >= 100%"); require( secondaryFoundationFeeBasisPoints.add(secondaryCreatorFeeBasisPoints) < BASIS_POINTS, "NFTMarketFees: Fees >= 100%" ); _primaryFoundationFeeBasisPoints = primaryFoundationFeeBasisPoints; _secondaryFoundationFeeBasisPoints = secondaryFoundationFeeBasisPoints; _secondaryCreatorFeeBasisPoints = secondaryCreatorFeeBasisPoints; emit MarketFeesUpdated( primaryFoundationFeeBasisPoints, secondaryFoundationFeeBasisPoints, secondaryCreatorFeeBasisPoints ); } uint256[1000] private ______gap; }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.7.0; /** * @notice An abstraction layer for auctions. * @dev This contract can be expanded with reusable calls and data as more auction types are added. */ abstract contract NFTMarketAuction { /** * @dev A global id for auctions of any type. */ uint256 private nextAuctionId; function _initializeNFTMarketAuction() internal { nextAuctionId = 1; } function _getNextAndIncrementAuctionId() internal returns (uint256) { return nextAuctionId++; } uint256[1000] private ______gap; }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.7.0; pragma abicoder v2; // solhint-disable-line import "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol"; import "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol"; import "./Constants.sol"; import "./NFTMarketCore.sol"; import "./NFTMarketFees.sol"; import "./SendValueWithFallbackWithdraw.sol"; import "./NFTMarketAuction.sol"; import "./roles/FoundationAdminRole.sol"; import "./AccountMigration.sol"; /** * @notice Manages a reserve price auction for NFTs. */ abstract contract NFTMarketReserveAuction is Constants, FoundationAdminRole, AccountMigration, NFTMarketCore, ReentrancyGuardUpgradeable, SendValueWithFallbackWithdraw, NFTMarketFees, NFTMarketAuction { using SafeMathUpgradeable for uint256; struct ReserveAuction { address nftContract; uint256 tokenId; address payable seller; uint256 duration; uint256 extensionDuration; uint256 endTime; address payable bidder; uint256 amount; } mapping(address => mapping(uint256 => uint256)) private nftContractToTokenIdToAuctionId; mapping(uint256 => ReserveAuction) private auctionIdToAuction; uint256 private _minPercentIncrementInBasisPoints; // This variable was used in an older version of the contract, left here as a gap to ensure upgrade compatibility uint256 private ______gap_was_maxBidIncrementRequirement; uint256 private _duration; // These variables were used in an older version of the contract, left here as gaps to ensure upgrade compatibility uint256 private ______gap_was_extensionDuration; uint256 private ______gap_was_goLiveDate; // Cap the max duration so that overflows will not occur uint256 private constant MAX_MAX_DURATION = 1000 days; uint256 private constant EXTENSION_DURATION = 15 minutes; event ReserveAuctionConfigUpdated( uint256 minPercentIncrementInBasisPoints, uint256 maxBidIncrementRequirement, uint256 duration, uint256 extensionDuration, uint256 goLiveDate ); event ReserveAuctionCreated( address indexed seller, address indexed nftContract, uint256 indexed tokenId, uint256 duration, uint256 extensionDuration, uint256 reservePrice, uint256 auctionId ); event ReserveAuctionUpdated(uint256 indexed auctionId, uint256 reservePrice); event ReserveAuctionCanceled(uint256 indexed auctionId); event ReserveAuctionBidPlaced(uint256 indexed auctionId, address indexed bidder, uint256 amount, uint256 endTime); event ReserveAuctionFinalized( uint256 indexed auctionId, address indexed seller, address indexed bidder, uint256 f8nFee, uint256 creatorFee, uint256 ownerRev ); event ReserveAuctionCanceledByAdmin(uint256 indexed auctionId, string reason); event ReserveAuctionSellerMigrated( uint256 indexed auctionId, address indexed originalSellerAddress, address indexed newSellerAddress ); modifier onlyValidAuctionConfig(uint256 reservePrice) { require(reservePrice > 0, "NFTMarketReserveAuction: Reserve price must be at least 1 wei"); _; } /** * @notice Returns auction details for a given auctionId. */ function getReserveAuction(uint256 auctionId) public view returns (ReserveAuction memory) { return auctionIdToAuction[auctionId]; } /** * @notice Returns the auctionId for a given NFT, or 0 if no auction is found. * @dev If an auction is canceled, it will not be returned. However the auction may be over and pending finalization. */ function getReserveAuctionIdFor(address nftContract, uint256 tokenId) public view returns (uint256) { return nftContractToTokenIdToAuctionId[nftContract][tokenId]; } /** * @dev Returns the seller that put a given NFT into escrow, * or bubbles the call up to check the current owner if the NFT is not currently in escrow. */ function _getSellerFor(address nftContract, uint256 tokenId) internal view virtual override returns (address payable seller) { seller = auctionIdToAuction[nftContractToTokenIdToAuctionId[nftContract][tokenId]].seller; if (seller == address(0)) { return super._getSellerFor(nftContract, tokenId); } } /** * @notice Returns the current configuration for reserve auctions. */ function getReserveAuctionConfig() public view returns (uint256 minPercentIncrementInBasisPoints, uint256 duration) { minPercentIncrementInBasisPoints = _minPercentIncrementInBasisPoints; duration = _duration; } function _initializeNFTMarketReserveAuction() internal { _duration = 24 hours; // A sensible default value } function _updateReserveAuctionConfig(uint256 minPercentIncrementInBasisPoints, uint256 duration) internal { require(minPercentIncrementInBasisPoints <= BASIS_POINTS, "NFTMarketReserveAuction: Min increment must be <= 100%"); // Cap the max duration so that overflows will not occur require(duration <= MAX_MAX_DURATION, "NFTMarketReserveAuction: Duration must be <= 1000 days"); require(duration >= EXTENSION_DURATION, "NFTMarketReserveAuction: Duration must be >= EXTENSION_DURATION"); _minPercentIncrementInBasisPoints = minPercentIncrementInBasisPoints; _duration = duration; // We continue to emit unused configuration variables to simplify the subgraph integration. emit ReserveAuctionConfigUpdated(minPercentIncrementInBasisPoints, 0, duration, EXTENSION_DURATION, 0); } /** * @notice Creates an auction for the given NFT. * The NFT is held in escrow until the auction is finalized or canceled. */ function createReserveAuction( address nftContract, uint256 tokenId, uint256 reservePrice ) public onlyValidAuctionConfig(reservePrice) nonReentrant { // If an auction is already in progress then the NFT would be in escrow and the modifier would have failed uint256 auctionId = _getNextAndIncrementAuctionId(); nftContractToTokenIdToAuctionId[nftContract][tokenId] = auctionId; auctionIdToAuction[auctionId] = ReserveAuction( nftContract, tokenId, msg.sender, _duration, EXTENSION_DURATION, 0, // endTime is only known once the reserve price is met address(0), // bidder is only known once a bid has been placed reservePrice ); IERC721Upgradeable(nftContract).transferFrom(msg.sender, address(this), tokenId); emit ReserveAuctionCreated( msg.sender, nftContract, tokenId, _duration, EXTENSION_DURATION, reservePrice, auctionId ); } /** * @notice If an auction has been created but has not yet received bids, the configuration * such as the reservePrice may be changed by the seller. */ function updateReserveAuction(uint256 auctionId, uint256 reservePrice) public onlyValidAuctionConfig(reservePrice) { ReserveAuction storage auction = auctionIdToAuction[auctionId]; require(auction.seller == msg.sender, "NFTMarketReserveAuction: Not your auction"); require(auction.endTime == 0, "NFTMarketReserveAuction: Auction in progress"); auction.amount = reservePrice; emit ReserveAuctionUpdated(auctionId, reservePrice); } /** * @notice If an auction has been created but has not yet received bids, it may be canceled by the seller. * The NFT is returned to the seller from escrow. */ function cancelReserveAuction(uint256 auctionId) public nonReentrant { ReserveAuction memory auction = auctionIdToAuction[auctionId]; require(auction.seller == msg.sender, "NFTMarketReserveAuction: Not your auction"); require(auction.endTime == 0, "NFTMarketReserveAuction: Auction in progress"); delete nftContractToTokenIdToAuctionId[auction.nftContract][auction.tokenId]; delete auctionIdToAuction[auctionId]; IERC721Upgradeable(auction.nftContract).transferFrom(address(this), auction.seller, auction.tokenId); emit ReserveAuctionCanceled(auctionId); } /** * @notice A bidder may place a bid which is at least the value defined by `getMinBidAmount`. * If this is the first bid on the auction, the countdown will begin. * If there is already an outstanding bid, the previous bidder will be refunded at this time * and if the bid is placed in the final moments of the auction, the countdown may be extended. */ function placeBid(uint256 auctionId) public payable nonReentrant { ReserveAuction storage auction = auctionIdToAuction[auctionId]; require(auction.amount != 0, "NFTMarketReserveAuction: Auction not found"); if (auction.endTime == 0) { // If this is the first bid, ensure it's >= the reserve price require(auction.amount <= msg.value, "NFTMarketReserveAuction: Bid must be at least the reserve price"); } else { // If this bid outbids another, confirm that the bid is at least x% greater than the last require(auction.endTime >= block.timestamp, "NFTMarketReserveAuction: Auction is over"); require(auction.bidder != msg.sender, "NFTMarketReserveAuction: You already have an outstanding bid"); uint256 minAmount = _getMinBidAmountForReserveAuction(auction.amount); require(msg.value >= minAmount, "NFTMarketReserveAuction: Bid amount too low"); } if (auction.endTime == 0) { auction.amount = msg.value; auction.bidder = msg.sender; // On the first bid, the endTime is now + duration auction.endTime = block.timestamp + auction.duration; } else { // Cache and update bidder state before a possible reentrancy (via the value transfer) uint256 originalAmount = auction.amount; address payable originalBidder = auction.bidder; auction.amount = msg.value; auction.bidder = msg.sender; // When a bid outbids another, check to see if a time extension should apply. if (auction.endTime - block.timestamp < auction.extensionDuration) { auction.endTime = block.timestamp + auction.extensionDuration; } // Refund the previous bidder _sendValueWithFallbackWithdrawWithLowGasLimit(originalBidder, originalAmount); } emit ReserveAuctionBidPlaced(auctionId, msg.sender, msg.value, auction.endTime); } /** * @notice Once the countdown has expired for an auction, anyone can settle the auction. * This will send the NFT to the highest bidder and distribute funds. */ function finalizeReserveAuction(uint256 auctionId) public nonReentrant { ReserveAuction memory auction = auctionIdToAuction[auctionId]; require(auction.endTime > 0, "NFTMarketReserveAuction: Auction was already settled"); require(auction.endTime < block.timestamp, "NFTMarketReserveAuction: Auction still in progress"); delete nftContractToTokenIdToAuctionId[auction.nftContract][auction.tokenId]; delete auctionIdToAuction[auctionId]; IERC721Upgradeable(auction.nftContract).transferFrom(address(this), auction.bidder, auction.tokenId); (uint256 f8nFee, uint256 creatorFee, uint256 ownerRev) = _distributeFunds( auction.nftContract, auction.tokenId, auction.seller, auction.amount ); emit ReserveAuctionFinalized(auctionId, auction.seller, auction.bidder, f8nFee, creatorFee, ownerRev); } /** * @notice Returns the minimum amount a bidder must spend to participate in an auction. */ function getMinBidAmount(uint256 auctionId) public view returns (uint256) { ReserveAuction storage auction = auctionIdToAuction[auctionId]; if (auction.endTime == 0) { return auction.amount; } return _getMinBidAmountForReserveAuction(auction.amount); } /** * @dev Determines the minimum bid amount when outbidding another user. */ function _getMinBidAmountForReserveAuction(uint256 currentBidAmount) private view returns (uint256) { uint256 minIncrement = currentBidAmount.mul(_minPercentIncrementInBasisPoints) / BASIS_POINTS; if (minIncrement == 0) { // The next bid must be at least 1 wei greater than the current. return currentBidAmount.add(1); } return minIncrement.add(currentBidAmount); } /** * @notice Allows Foundation to cancel an auction, refunding the bidder and returning the NFT to the seller. * This should only be used for extreme cases such as DMCA takedown requests. The reason should always be provided. */ function adminCancelReserveAuction(uint256 auctionId, string memory reason) public onlyFoundationAdmin { require(bytes(reason).length > 0, "NFTMarketReserveAuction: Include a reason for this cancellation"); ReserveAuction memory auction = auctionIdToAuction[auctionId]; require(auction.amount > 0, "NFTMarketReserveAuction: Auction not found"); delete nftContractToTokenIdToAuctionId[auction.nftContract][auction.tokenId]; delete auctionIdToAuction[auctionId]; IERC721Upgradeable(auction.nftContract).transferFrom(address(this), auction.seller, auction.tokenId); if (auction.bidder != address(0)) { _sendValueWithFallbackWithdrawWithMediumGasLimit(auction.bidder, auction.amount); } emit ReserveAuctionCanceledByAdmin(auctionId, reason); } /** * @notice Allows an NFT owner and Foundation to work together in order to update the seller * for auctions they have listed to a new account. * @param signature Message `I authorize Foundation to migrate my account to ${newAccount.address.toLowerCase()}` * signed by the original account. * @dev This will gracefully skip any auctions that have already been finalized. */ function adminAccountMigration( uint256[] calldata listedAuctionIds, address originalAddress, address payable newAddress, bytes calldata signature ) public onlyAuthorizedAccountMigration(originalAddress, newAddress, signature) { for (uint256 i = 0; i < listedAuctionIds.length; i++) { uint256 auctionId = listedAuctionIds[i]; ReserveAuction storage auction = auctionIdToAuction[auctionId]; // The seller would be 0 if it was finalized before this call if (auction.seller != address(0)) { require(auction.seller == originalAddress, "NFTMarketReserveAuction: Auction not created by that address"); auction.seller = newAddress; emit ReserveAuctionSellerMigrated(auctionId, originalAddress, newAddress); } } } uint256[1000] private ______gap; }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.7.0; import "@openzeppelin/contracts/cryptography/ECDSA.sol"; import "@openzeppelin/contracts/utils/Address.sol"; import "@openzeppelin/contracts/utils/Strings.sol"; import "./roles/FoundationOperatorRole.sol"; import "../interfaces/IERC1271.sol"; /** * @notice Checks for a valid signature authorizing the migration of an account to a new address. * @dev This is shared by both the FNDNFT721 and FNDNFTMarket, and the same signature authorizes both. */ abstract contract AccountMigration is FoundationOperatorRole { // From https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.1.0/contracts/utils/cryptography function _isValidSignatureNow( address signer, bytes32 hash, bytes memory signature ) private view returns (bool) { if (Address.isContract(signer)) { try IERC1271(signer).isValidSignature(hash, signature) returns (bytes4 magicValue) { return magicValue == IERC1271(signer).isValidSignature.selector; } catch { return false; } } else { return ECDSA.recover(hash, signature) == signer; } } // From https://ethereum.stackexchange.com/questions/8346/convert-address-to-string function _toAsciiString(address x) private pure returns (string memory) { bytes memory s = new bytes(42); s[0] = "0"; s[1] = "x"; for (uint256 i = 0; i < 20; i++) { bytes1 b = bytes1(uint8(uint256(uint160(x)) / (2**(8 * (19 - i))))); bytes1 hi = bytes1(uint8(b) / 16); bytes1 lo = bytes1(uint8(b) - 16 * uint8(hi)); s[2 * i + 2] = _char(hi); s[2 * i + 3] = _char(lo); } return string(s); } function _char(bytes1 b) private pure returns (bytes1 c) { if (uint8(b) < 10) return bytes1(uint8(b) + 0x30); else return bytes1(uint8(b) + 0x57); } // From https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.1.0/contracts/utils/cryptography/ECDSA.sol // Modified to accept messages (instead of the message hash) function _toEthSignedMessage(bytes memory message) private pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(message.length), message)); } /** * @dev Confirms the msg.sender is a Foundation operator and that the signature provided is valid. * @param signature Message `I authorize Foundation to migrate my account to ${newAccount.address.toLowerCase()}` * signed by the original account. */ modifier onlyAuthorizedAccountMigration( address originalAddress, address newAddress, bytes memory signature ) { require(_isFoundationOperator(), "AccountMigration: Caller is not an operator"); require(originalAddress != newAddress, "AccountMigration: Cannot migrate to the same account"); bytes32 hash = _toEthSignedMessage( abi.encodePacked("I authorize Foundation to migrate my account to ", _toAsciiString(newAddress)) ); require( _isValidSignatureNow(originalAddress, hash, signature), "AccountMigration: Signature must be from the original account" ); _; } }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.7.0; import "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol"; import "./NFTMarketFees.sol"; /** * @notice Adds support for a private sale of an NFT directly between two parties. */ abstract contract NFTMarketPrivateSale is NFTMarketFees { /** * @dev This name is used in the EIP-712 domain. * If multiple classes use EIP-712 signatures in the future this can move to the shared constants file. */ string private constant NAME = "FNDNFTMarket"; /** * @dev This is a hash of the method signature used in the EIP-712 signature for private sales. */ bytes32 private constant BUY_FROM_PRIVATE_SALE_TYPEHASH = keccak256("BuyFromPrivateSale(address nftContract,uint256 tokenId,address buyer,uint256 price,uint256 deadline)"); /** * @dev This is the domain used in EIP-712 signatures. * It is not a constant so that the chainId can be determined dynamically. * If multiple classes use EIP-712 signatures in the future this can move to a shared file. */ bytes32 private DOMAIN_SEPARATOR; event PrivateSaleFinalized( address indexed nftContract, uint256 indexed tokenId, address indexed seller, address buyer, uint256 f8nFee, uint256 creatorFee, uint256 ownerRev, uint256 deadline ); /** * @dev This function must be called at least once before signatures will work as expected. * It's okay to call this function many times. Subsequent calls will have no impact. */ function _reinitialize() internal { uint256 chainId; // solhint-disable-next-line no-inline-assembly assembly { chainId := chainid() } DOMAIN_SEPARATOR = keccak256( abi.encode( keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), keccak256(bytes(NAME)), keccak256(bytes("1")), chainId, address(this) ) ); } /** * @notice Allow two parties to execute a private sale. * @dev The seller signs a message approving the sale, and then the buyer calls this function * with the msg.value equal to the agreed upon price. * The sale is executed in this single on-chain call including the transfer of funds and the NFT. */ function buyFromPrivateSale( IERC721Upgradeable nftContract, uint256 tokenId, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) public payable { // The signed message from the seller is only valid for a limited time. require(deadline >= block.timestamp, "NFTMarketPrivateSale: EXPIRED"); // The seller must have the NFT in their wallet when this function is called. address payable seller = payable(nftContract.ownerOf(tokenId)); // Scoping this block to avoid a stack too deep error { bytes32 digest = keccak256( abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR, keccak256(abi.encode(BUY_FROM_PRIVATE_SALE_TYPEHASH, nftContract, tokenId, msg.sender, msg.value, deadline)) ) ); // Revert if the signature is invalid, the terms are not as expected, or if the seller transferred the NFT. require(ecrecover(digest, v, r, s) == seller, "NFTMarketPrivateSale: INVALID_SIGNATURE"); } // This will revert if the seller has not given the market contract approval. nftContract.transferFrom(seller, msg.sender, tokenId); // Pay the seller, creator, and Foundation as appropriate. (uint256 f8nFee, uint256 creatorFee, uint256 ownerRev) = _distributeFunds( address(nftContract), tokenId, seller, msg.value ); emit PrivateSaleFinalized( address(nftContract), tokenId, seller, msg.sender, f8nFee, creatorFee, ownerRev, deadline ); } uint256[1000] 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)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.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 OR Apache-2.0 pragma solidity ^0.7.0; /** * @notice Interface for AdminRole which wraps the default admin role from * OpenZeppelin's AccessControl for easy integration. */ interface IAdminRole { function isAdmin(address account) external view returns (bool); }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.7.0; /** * @notice Interface for OperatorRole which wraps a role from * OpenZeppelin's AccessControl for easy integration. */ interface IOperatorRole { function isOperator(address account) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.0; import "../../introspection/IERC165Upgradeable.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721Upgradeable is IERC165Upgradeable { /** * @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.7.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 IERC165Upgradeable { /** * @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.7.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 SafeMathUpgradeable { /** * @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 OR Apache-2.0 // solhint-disable pragma solidity ^0.7.0; interface IFNDNFT721 { function tokenCreator(uint256 tokenId) external view returns (address payable); function getTokenCreatorPaymentAddress(uint256 tokenId) external view returns (address payable); }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.7.0; interface ITokenCreatorPaymentAddress { function getTokenCreatorPaymentAddress(uint256 tokenId) external view returns (address payable tokenCreatorPaymentAddress); }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.7.0; interface ITokenCreator { function tokenCreator(uint256 tokenId) external view returns (address payable); }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.7.0; interface IGetRoyalties { function getRoyalties(uint256 tokenId) external view returns (address payable[] memory recipients, uint256[] memory feesInBasisPoints); }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.7.0; /** * @notice An interface for communicating fees to 3rd party marketplaces. * @dev Originally implemented in mainnet contract 0x44d6e8933f8271abcf253c72f9ed7e0e4c0323b3 */ interface IHasSecondarySaleFees { function getFeeRecipients(uint256 id) external view returns (address payable[] memory); function getFeeBps(uint256 id) external view returns (uint256[] memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.0; interface IOwnable { /** * @dev Returns the address of the current owner. */ function owner() external view returns (address); }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor () { 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; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.0; /** * From https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.2.0/contracts/utils/introspection/ERC165.sol * Modified to support Solidity 0.7 and allow checking multiple interfaces w/o checking general 165 support. */ import "./IERC165.sol"; /** * @dev Library used to query support of an interface declared via {IERC165}. * * Note that these functions return the actual result of the query: they do not * `revert` if an interface is not supported. It is up to the caller to decide * what to do in these cases. */ library ERC165Checker { // As per the EIP-165 spec, no interface should ever match 0xffffffff bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff; /** * @dev Returns true if `account` supports the {IERC165} interface, */ function supportsERC165(address account) internal view returns (bool) { // Any contract that implements ERC165 must explicitly indicate support of // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid return supportsERC165Interface(account, type(IERC165).interfaceId) && !supportsERC165Interface(account, _INTERFACE_ID_INVALID); } /** * @dev Returns true if `account` supports the interface defined by * `interfaceId`. Support for {IERC165} itself is queried automatically. * * See {IERC165-supportsInterface}. */ function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) { // query support of both ERC165 as per the spec and support of _interfaceId return supportsERC165(account) && supportsERC165Interface(account, interfaceId); } /** * @dev Returns a boolean array where each value corresponds to the * interfaces passed in and whether they're supported or not. This allows * you to batch check interfaces for a contract where your expectation * is that some interfaces may not be supported. * * See {IERC165-supportsInterface}. * * _Available since v3.4._ */ function getSupportedInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool[] memory) { // an array of booleans corresponding to interfaceIds and whether they're supported or not bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length); // query support of ERC165 itself if (supportsERC165(account)) { // query support of each interface in interfaceIds for (uint256 i = 0; i < interfaceIds.length; i++) { interfaceIdsSupported[i] = supportsERC165Interface(account, interfaceIds[i]); } } return interfaceIdsSupported; } /** * @dev Returns true if `account` supports all the interfaces defined in * `interfaceIds`. Support for {IERC165} itself is queried automatically. * * Batch-querying can lead to gas savings by skipping repeated checks for * {IERC165} support. * * See {IERC165-supportsInterface}. */ function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) { // query support of ERC165 itself if (!supportsERC165(account)) { return false; } // query support of each interface in _interfaceIds for (uint256 i = 0; i < interfaceIds.length; i++) { if (!supportsERC165Interface(account, interfaceIds[i])) { return false; } } // all interfaces supported return true; } /** * @notice Query if a contract implements an interface, does not check ERC165 support * @param account The address of the contract to query for support of an interface * @param interfaceId The interface identifier, as specified in ERC-165 * @return true if the contract at account indicates support of the interface with * identifier interfaceId, false otherwise * @dev Assumes that account contains a contract that supports ERC165, otherwise * the behavior of this method is undefined. This precondition can be checked * with {supportsERC165}. * Interface identification is specified in ERC-165. */ function supportsERC165Interface(address account, bytes4 interfaceId) internal view returns (bool) { bytes memory encodedParams = abi.encodeWithSelector(IERC165(account).supportsInterface.selector, interfaceId); (bool success, bytes memory result) = account.staticcall{ gas: 30000 }(encodedParams); if (result.length < 32) return false; return success && abi.decode(result, (bool)); } }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.7.0; /** * @dev Constant values shared across mixins. */ abstract contract Constants { uint256 internal constant BASIS_POINTS = 10000; uint256 internal constant READ_ONLY_GAS_LIMIT = 40000; /** * @dev Support up to 5 royalty recipients. A cap is required to ensure gas costs are not too high * when an auction is finalized. */ uint256 internal constant MAX_CREATOR_INDEX = 4; }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /* * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with 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 Context { 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; } }
// SPDX-License-Identifier: MIT /** * From https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.2.0/contracts/utils/introspection/IERC165.sol * Modified to support Solidity 0.7 */ pragma solidity ^0.7.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.7.0; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { // Check the signature length if (signature.length != 65) { revert("ECDSA: invalid signature length"); } // Divide the signature in r, s and v variables bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. // solhint-disable-next-line no-inline-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return recover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`, * `r` and `s` signature fields separately. */ function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, "ECDSA: invalid signature 's' value"); require(v == 27 || v == 28, "ECDSA: invalid signature 'v' value"); // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); require(signer != address(0), "ECDSA: invalid signature"); return signer; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * replicates the behavior of the * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`] * JSON-RPC method. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { // 32 is the length in bytes of hash, // enforced by the type signature above return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.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.7.0; /** * @dev String operations. */ library Strings { /** * @dev Converts a `uint256` to its ASCII `string` representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); uint256 index = digits - 1; temp = value; while (temp != 0) { buffer[index--] = bytes1(uint8(48 + temp % 10)); temp /= 10; } return string(buffer); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.0; /** * @dev Interface of the ERC1271 standard signature validation method for * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271]. * * from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.1.0/contracts/interfaces/IERC1271.sol */ interface IERC1271 { /** * @dev Should return whether the signature provided is valid for the provided data * @param hash Hash of the data to be signed * @param signature Signature byte array associated with _data */ function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue); }
{ "optimizer": { "enabled": true, "runs": 1337 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"primaryFoundationFeeBasisPoints","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"secondaryFoundationFeeBasisPoints","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"secondaryCreatorFeeBasisPoints","type":"uint256"}],"name":"MarketFeesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"nftContract","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"seller","type":"address"},{"indexed":false,"internalType":"address","name":"buyer","type":"address"},{"indexed":false,"internalType":"uint256","name":"f8nFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"creatorFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"ownerRev","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"PrivateSaleFinalized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"auctionId","type":"uint256"},{"indexed":true,"internalType":"address","name":"bidder","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endTime","type":"uint256"}],"name":"ReserveAuctionBidPlaced","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"auctionId","type":"uint256"}],"name":"ReserveAuctionCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"auctionId","type":"uint256"},{"indexed":false,"internalType":"string","name":"reason","type":"string"}],"name":"ReserveAuctionCanceledByAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"minPercentIncrementInBasisPoints","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"maxBidIncrementRequirement","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"duration","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"extensionDuration","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"goLiveDate","type":"uint256"}],"name":"ReserveAuctionConfigUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"seller","type":"address"},{"indexed":true,"internalType":"address","name":"nftContract","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"duration","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"extensionDuration","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"reservePrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"auctionId","type":"uint256"}],"name":"ReserveAuctionCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"auctionId","type":"uint256"},{"indexed":true,"internalType":"address","name":"seller","type":"address"},{"indexed":true,"internalType":"address","name":"bidder","type":"address"},{"indexed":false,"internalType":"uint256","name":"f8nFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"creatorFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"ownerRev","type":"uint256"}],"name":"ReserveAuctionFinalized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"auctionId","type":"uint256"},{"indexed":true,"internalType":"address","name":"originalSellerAddress","type":"address"},{"indexed":true,"internalType":"address","name":"newSellerAddress","type":"address"}],"name":"ReserveAuctionSellerMigrated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"auctionId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"reservePrice","type":"uint256"}],"name":"ReserveAuctionUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"WithdrawPending","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdrawal","type":"event"},{"inputs":[{"internalType":"uint256[]","name":"listedAuctionIds","type":"uint256[]"},{"internalType":"address","name":"originalAddress","type":"address"},{"internalType":"address payable","name":"newAddress","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"adminAccountMigration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"auctionId","type":"uint256"},{"internalType":"string","name":"reason","type":"string"}],"name":"adminCancelReserveAuction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"minPercentIncrementInBasisPoints","type":"uint256"},{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"uint256","name":"primaryF8nFeeBasisPoints","type":"uint256"},{"internalType":"uint256","name":"secondaryF8nFeeBasisPoints","type":"uint256"},{"internalType":"uint256","name":"secondaryCreatorFeeBasisPoints","type":"uint256"}],"name":"adminUpdateConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC721Upgradeable","name":"nftContract","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"buyFromPrivateSale","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"auctionId","type":"uint256"}],"name":"cancelReserveAuction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"nftContract","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"reservePrice","type":"uint256"}],"name":"createReserveAuction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"auctionId","type":"uint256"}],"name":"finalizeReserveAuction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getFeeConfig","outputs":[{"internalType":"uint256","name":"primaryFoundationFeeBasisPoints","type":"uint256"},{"internalType":"uint256","name":"secondaryFoundationFeeBasisPoints","type":"uint256"},{"internalType":"uint256","name":"secondaryCreatorFeeBasisPoints","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"nftContract","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"}],"name":"getFees","outputs":[{"internalType":"uint256","name":"foundationFee","type":"uint256"},{"internalType":"uint256","name":"creatorRev","type":"uint256"},{"internalType":"uint256","name":"ownerRev","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFoundationTreasury","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"nftContract","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getIsPrimary","outputs":[{"internalType":"bool","name":"isPrimary","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"auctionId","type":"uint256"}],"name":"getMinBidAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getPendingWithdrawal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"auctionId","type":"uint256"}],"name":"getReserveAuction","outputs":[{"components":[{"internalType":"address","name":"nftContract","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address payable","name":"seller","type":"address"},{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"uint256","name":"extensionDuration","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"address payable","name":"bidder","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct NFTMarketReserveAuction.ReserveAuction","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getReserveAuctionConfig","outputs":[{"internalType":"uint256","name":"minPercentIncrementInBasisPoints","type":"uint256"},{"internalType":"uint256","name":"duration","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"nftContract","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getReserveAuctionIdFor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address payable","name":"treasury","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"auctionId","type":"uint256"}],"name":"placeBid","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"auctionId","type":"uint256"},{"internalType":"uint256","name":"reservePrice","type":"uint256"}],"name":"updateReserveAuction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"user","type":"address"}],"name":"withdrawFor","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b506144e5806100206000396000f3fe60806040526004361061016a5760003560e01c80635ed31d8a116100cb5780637ee8b2f81161007f5780639eca672c116100595780639eca672c146103c3578063c4d66de8146103e3578063f7a2da23146104035761016a565b80637ee8b2f8146103635780639979ef45146103835780639e79b41f146103965761016a565b80636775d96a116100b05780636775d96a146103105780637430e0c61461032357806374a45126146103435761016a565b80635ed31d8a146102cc5780635fbbc0d2146102ec5761016a565b80633ccfd60b116101225780634ce6931a116101075780634ce6931a1461026c5780634d6706631461028c5780635d83d562146102ac5761016a565b80633ccfd60b1461023757806347e357401461024c5761016a565b806321506fff1161015357806321506fff146101c75780632ab2b52b146101e75780633b230bc9146102145761016a565b806303ec16d71461016f5780632047677714610191575b600080fd5b34801561017b57600080fd5b5061018f61018a366004613b37565b610425565b005b34801561019d57600080fd5b506101b16101ac366004613904565b6104f3565b6040516101be9190613bca565b60405180910390f35b3480156101d357600080fd5b5061018f6101e2366004613a7e565b61054f565b3480156101f357600080fd5b50610207610202366004613904565b61078f565b6040516101be9190614203565b34801561022057600080fd5b506102296107bb565b6040516101be92919061422f565b34801561024357600080fd5b5061018f6107c7565b34801561025857600080fd5b50610207610267366004613a7e565b6107d2565b34801561027857600080fd5b5061018f61028736600461392f565b61080b565b34801561029857600080fd5b5061018f6102a7366004613963565b610ac5565b3480156102b857600080fd5b5061018f6102c7366004613a96565b610d4f565b3480156102d857600080fd5b5061018f6102e7366004613b58565b610f9f565b3480156102f857600080fd5b50610301611006565b6040516101be9392919061423d565b61018f61031e366004613a1e565b611017565b34801561032f57600080fd5b5061018f61033e366004613a7e565b61134c565b34801561034f57600080fd5b5061030161035e36600461392f565b6115d3565b34801561036f57600080fd5b5061020761037e3660046138e8565b611604565b61018f610391366004613a7e565b611620565b3480156103a257600080fd5b506103b66103b1366004613a7e565b61185d565b6040516101be919061419b565b3480156103cf57600080fd5b5061018f6103de3660046138e8565b6118e2565b3480156103ef57600080fd5b5061018f6103fe3660046138e8565b611a1a565b34801561040f57600080fd5b50610418611ad6565b6040516101be9190613b92565b806000811161044f5760405162461bcd60e51b815260040161044690613c28565b60405180910390fd5b60008381526117776020526040902060028101546001600160a01b0316331461048a5760405162461bcd60e51b815260040161044690613d3f565b6005810154156104ac5760405162461bcd60e51b815260040161044690613f10565b828160070181905550837f0c0f2662914f0cd1e952db2aa425901cb00e7c1f507687d22cb04e836d55d9c7846040516104e59190614203565b60405180910390a250505050565b6000806105008484611aeb565b9050600061050f858584611afe565b925082915050801561054657506001600160a01b0385166000908152610fa46020908152604080832087845290915290205460ff16155b95945050505050565b6002610b875414156105a8576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002610b878190556000828152611777602090815260409182902082516101008101845281546001600160a01b0390811682526001830154938201939093529381015482169284018390526003810154606085015260048101546080850152600581015460a0850152600681015490911660c08401526007015460e083015233146106455760405162461bcd60e51b815260040161044690613d3f565b60a0810151156106675760405162461bcd60e51b815260040161044690613f10565b80516001600160a01b0390811660009081526117766020908152604080832082860180518552908352818420849055868452611777909252808320805473ffffffffffffffffffffffffffffffffffffffff199081168255600182018590556002820180548216905560038201859055600480830186905560058301869055600683018054909216909155600790910193909355845181860151925191516323b872dd60e01b81529416936323b872dd936107289330939092909101613ba6565b600060405180830381600087803b15801561074257600080fd5b505af1158015610756573d6000803e3d6000fd5b50506040518492507f14b9c40404d5b41deb481f9a40b8aeb2bf4b47679b38cf757075a66ed510f7f19150600090a250506001610b8755565b6001600160a01b0382166000908152611776602090815260408083208484529091529020545b92915050565b6117785461177a549091565b6107d0336118e2565b565b60008181526117776020526040812060058101546107f557600701549050610806565b610802816007015461240d565b9150505b919050565b806000811161082c5760405162461bcd60e51b815260040161044690613c28565b6002610b87541415610885576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002610b87556000610895612455565b9050806117766000876001600160a01b03166001600160a01b03168152602001908152602001600020600086815260200190815260200160002081905550604051806101000160405280866001600160a01b03168152602001858152602001336001600160a01b0316815260200161177a54815260200161038481526020016000815260200160006001600160a01b0316815260200184815250611777600083815260200190815260200160002060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506020820151816001015560408201518160020160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550606082015181600301556080820151816004015560a0820151816005015560c08201518160060160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060e08201518160070155905050846001600160a01b03166323b872dd3330876040518463ffffffff1660e01b8152600401610a2f93929190613ba6565b600060405180830381600087803b158015610a4957600080fd5b505af1158015610a5d573d6000803e3d6000fd5b5050505083856001600160a01b0316336001600160a01b03167f1062dd3b35f12b4064331244d00f40c1d4831965e4285654157a2409c6217cff61177a546103848887604051610ab09493929190614253565b60405180910390a450506001610b8755505050565b838383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610b079250612464915050565b610b425760405162461bcd60e51b815260040180806020018281038252602b815260200180614485602b913960400191505060405180910390fd5b816001600160a01b0316836001600160a01b03161415610b935760405162461bcd60e51b815260040180806020018281038252603481526020018061442a6034913960400191505060405180910390fd5b6000610c16610ba1846124eb565b6040516020018060306142c4823960300182805190602001908083835b60208310610bdd5780518252601f199092019160209182019101610bbe565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051602081830303815290604052612651565b9050610c23848284612743565b610c5e5760405162461bcd60e51b815260040180806020018281038252603d815260200180614287603d913960400191505060405180910390fd5b60005b89811015610d425760008b8b83818110610c7757fe5b60209081029290920135600081815261177790935260409092206002810154929350916001600160a01b0316159050610d385760028101546001600160a01b038c8116911614610cd95760405162461bcd60e51b815260040161044690613eb3565b60028101805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b038c811691821790925560405190918d169084907f099239784bcc562970bdd08339308cf1ff2a1eb4c62e47e52d5b6b064e11a55390600090a45b5050600101610c61565b5050505050505050505050565b610d5761288b565b610d925760405162461bcd60e51b81526004018080602001828103825260388152602001806143816038913960400191505060405180910390fd5b6000815111610db35760405162461bcd60e51b815260040161044690613ce2565b6000828152611777602090815260409182902082516101008101845281546001600160a01b03908116825260018301549382019390935260028201548316938101939093526003810154606084015260048101546080840152600581015460a0840152600681015490911660c08301526007015460e08201819052610e4a5760405162461bcd60e51b815260040161044690613d9c565b80516001600160a01b0390811660009081526117766020908152604080832082860180518552908352818420849055878452611777909252808320805473ffffffffffffffffffffffffffffffffffffffff199081168255600182018590556002820180548216905560038201859055600480830186905560058301869055600683018054909216909155600790910193909355845181860151925191516323b872dd60e01b81529416936323b872dd93610f0b9330939092909101613ba6565b600060405180830381600087803b158015610f2557600080fd5b505af1158015610f39573d6000803e3d6000fd5b5050505060c08101516001600160a01b031615610f6257610f628160c001518260e001516128e1565b827f1d56d378404d81e3fc5f3dfbf88359b8cb2ecafa73b3270c478bf7b2bdd1446983604051610f929190613bd5565b60405180910390a2505050565b610fa761288b565b610fe25760405162461bcd60e51b81526004018080602001828103825260388152602001806143816038913960400191505060405180910390fd5b610fea6128ef565b610ff485856129f2565b610fff838383612aad565b5050505050565b610fa154610fa254610fa354909192565b4284101561106c576040805162461bcd60e51b815260206004820152601d60248201527f4e46544d61726b65745072697661746553616c653a2045585049524544000000604482015290519081900360640190fd5b6000866001600160a01b0316636352211e876040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b1580156110b257600080fd5b505afa1580156110c6573d6000803e3d6000fd5b505050506040513d60208110156110dc57600080fd5b5051611b6554604080517f6f5a5497fcb7364f6bad56db9aad5785b6786717424e748b8bfef6e6554cd5516020828101919091526001600160a01b03808d1683850152606083018c90523360808401523460a084015260c08084018c90528451808503909101815260e0840185528051908301207f1901000000000000000000000000000000000000000000000000000000000000610100850152610102840195909552610122808401959095528351808403909501855261014283018085528551958301959095206000909552610162830180855285905260ff8a166101828401526101a283018990526101c2830188905292519495509293918516926001926101e280840193601f198301929081900390910190855afa158015611206573d6000803e3d6000fd5b505050602060405103516001600160a01b0316146112555760405162461bcd60e51b815260040180806020018281038252602781526020018061445e6027913960400191505060405180910390fd5b50604080516323b872dd60e01b81526001600160a01b038381166004830152336024830152604482018990529151918916916323b872dd9160648082019260009290919082900301818387803b1580156112ae57600080fd5b505af11580156112c2573d6000803e3d6000fd5b5050505060008060006112d78a8a8634612bb9565b604080513381526020810185905280820184905260608101839052608081018d9052905193965091945092506001600160a01b03808716928c92918e16917f6c623fa5e13aaaf28288f807e5b4f9ec6fb7ef812568e00317c552663bea918f919081900360a00190a450505050505050505050565b6002610b875414156113a5576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002610b878190556000828152611777602090815260409182902082516101008101845281546001600160a01b039081168252600183015493820193909352938101548216928401929092526003820154606084015260048201546080840152600582015460a08401819052600683015490911660c084015260079091015460e08301526114455760405162461bcd60e51b81526004016104469061413e565b428160a00151106114685760405162461bcd60e51b8152600401610446906140e1565b80516001600160a01b0390811660009081526117766020908152604080832082860180518552908352818420849055868452611777909252808320805473ffffffffffffffffffffffffffffffffffffffff199081168255600182018590556002820180548216905560038201859055600480830186905560058301869055600683018054909216909155600790910193909355845160c0860151925191516323b872dd60e01b81529416936323b872dd9361152a9330939092909101613ba6565b600060405180830381600087803b15801561154457600080fd5b505af1158015611558573d6000803e3d6000fd5b50505050600080600061157d8460000151856020015186604001518760e00151612bb9565b9250925092508360c001516001600160a01b031684604001516001600160a01b0316867f2edb0e99c6ac35be6731dab554c1d1fa1b7beb675090dbb09fb14e615aca1c4a868686604051610ab09392919061423d565b6000806000806115e38787611aeb565b90506115f187878388612db6565b949c919b50939950975050505050505050565b6001600160a01b03166000908152610dad602052604090205490565b6002610b87541415611679576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002610b875560008181526117776020526040902060078101546116af5760405162461bcd60e51b815260040161044690613d9c565b60058101546116e15734816007015411156116dc5760405162461bcd60e51b815260040161044690613df9565b611765565b42816005015410156117055760405162461bcd60e51b815260040161044690613e56565b60068101546001600160a01b03163314156117325760405162461bcd60e51b815260040161044690614084565b6000611741826007015461240d565b9050803410156117635760405162461bcd60e51b815260040161044690613c85565b505b60058101546117a65734600782015560068101805473ffffffffffffffffffffffffffffffffffffffff19163317905560038101544201600582015561180b565b6007810180546006830180543490935573ffffffffffffffffffffffffffffffffffffffff198316331790556004830154600584015491926001600160a01b03169142900310156117fe576004830154420160058401555b6118088183612ec9565b50505b336001600160a01b0316827f26ea3ebbda62eb1baef13e1c237dddd956c87f80b2801f2616d806d52557b12134846005015460405161184b92919061422f565b60405180910390a350506001610b8755565b611865613836565b506000908152611777602090815260409182902082516101008101845281546001600160a01b03908116825260018301549382019390935260028201548316938101939093526003810154606084015260048101546080840152600581015460a0840152600681015490911660c08301526007015460e082015290565b6002610b8754141561193b576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002610b87556001600160a01b0381166000908152610dad6020526040902054806119ad576040805162461bcd60e51b815260206004820152601f60248201527f4e6f2066756e6473206172652070656e64696e67207769746864726177616c00604482015290519081900360640190fd5b6001600160a01b0382166000818152610dad60205260408120556119d19082612ed6565b6040805182815290516001600160a01b038416917f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65919081900360200190a250506001610b8755565b600054610100900460ff1680611a335750611a33612fc0565b80611a41575060005460ff16155b611a7c5760405162461bcd60e51b815260040180806020018281038252602e8152602001806143b9602e913960400191505060405180910390fd5b600054610100900460ff16158015611aa7576000805460ff1961ff0019909116610100171660011790555b611ab082612fd1565b611ab86130f8565b611ac0613100565b8015611ad2576000805461ff00191690555b5050565b6000546201000090046001600160a01b031690565b6000611af7838361310a565b9392505050565b6060806000611b366001600160a01b0387167fec5f752e00000000000000000000000000000000000000000000000000000000613155565b15611c1c57856001600160a01b031663ec5f752e619c40876040518363ffffffff1660e01b81526004018082815260200191505060206040518083038187803b158015611b8257600080fd5b5086fa93505050508015611ba857506040513d6020811015611ba357600080fd5b505160015b611bb157611c1c565b6001600160a01b03811615611c1a5760408051600180825281830190925290602080830190803683370190505093508084600081518110611bee57fe5b6001600160a01b0392831660209182029290920101528181169086161415611c1a575060019050612404565b505b611c4f6001600160a01b0387167f40c1a06400000000000000000000000000000000000000000000000000000000613155565b15611d5757856001600160a01b03166340c1a064619c40876040518363ffffffff1660e01b81526004018082815260200191505060206040518083038187803b158015611c9b57600080fd5b5086fa93505050508015611cc157506040513d6020811015611cbc57600080fd5b505160015b611cca57611d57565b6001600160a01b03811615611d55578351611d4057600160005b50604051908082528060200260200182016040528015611d0e578160200160208202803683370190505b5093508084600081518110611d1f57fe5b60200260200101906001600160a01b031690816001600160a01b0316815250505b6001600160a01b038581169116149050612404565b505b8251158015611d945750611d946001600160a01b0387167fbb3bafd600000000000000000000000000000000000000000000000000000000613155565b15611fda57856001600160a01b031663bb3bafd6619c40876040518363ffffffff1660e01b81526004018082815260200191505060006040518083038187803b158015611de057600080fd5b5086fa93505050508015611f2b57506040513d6000823e601f3d908101601f191682016040908152811015611e1457600080fd5b8101908080516040519392919084640100000000821115611e3457600080fd5b908301906020820185811115611e4957600080fd5b8251866020820283011164010000000082111715611e6657600080fd5b82525081516020918201928201910280838360005b83811015611e93578181015183820152602001611e7b565b5050505090500160405260200180516040519392919084640100000000821115611ebc57600080fd5b908301906020820185811115611ed157600080fd5b8251866020820283011164010000000082111715611eee57600080fd5b82525081516020918201928201910280838360005b83811015611f1b578181015183820152602001611f03565b5050505090500160405250505060015b611f3457611fda565b60008251118015611f46575080518251145b15611fd7576000805b8351811015611fc35760006001600160a01b0316848281518110611f6f57fe5b60200260200101516001600160a01b031614611fbb5760019150876001600160a01b0316848281518110611f9f57fe5b60200260200101516001600160a01b03161415611fbb57600194505b600101611f4f565b508015611fd557509093509150612404565b505b50505b825115801561201757506120176001600160a01b0387167fb779958400000000000000000000000000000000000000000000000000000000613155565b156122e357856001600160a01b031663b9c4d9fb619c40876040518363ffffffff1660e01b81526004018082815260200191505060006040518083038187803b15801561206357600080fd5b5086fa9350505050801561212657506040513d6000823e601f3d908101601f19168201604052602081101561209757600080fd5b81019080805160405193929190846401000000008211156120b757600080fd5b9083019060208201858111156120cc57600080fd5b82518660208202830111640100000000821117156120e957600080fd5b82525081516020918201928201910280838360005b838110156121165781810151838201526020016120fe565b5050505090500160405250505060015b61212f576122e3565b8051156122e157866001600160a01b0316630ebd4c7f619c40886040518363ffffffff1660e01b81526004018082815260200191505060006040518083038187803b15801561217d57600080fd5b5086fa9350505050801561224057506040513d6000823e601f3d908101601f1916820160405260208110156121b157600080fd5b81019080805160405193929190846401000000008211156121d157600080fd5b9083019060208201858111156121e657600080fd5b825186602082028301116401000000008211171561220357600080fd5b82525081516020918201928201910280838360005b83811015612230578181015183820152602001612218565b5050505090500160405250505060015b612249576122e1565b8051825114156122df576000805b83518110156122cb5760006001600160a01b031684828151811061227757fe5b60200260200101516001600160a01b0316146122c35760019150876001600160a01b03168482815181106122a757fe5b60200260200101516001600160a01b031614156122c357600194505b600101612257565b5080156122dd57509093509150612404565b505b505b505b856001600160a01b0316638da5cb5b619c406040518263ffffffff1660e01b815260040160206040518083038187803b15801561231f57600080fd5b5086fa9350505050801561234557506040513d602081101561234057600080fd5b505160015b61234e5761236e565b6001600160a01b0381161561236c578351611d405760016000611ce4565b505b856001600160a01b03166340c1a064619c40876040518363ffffffff1660e01b81526004018082815260200191505060206040518083038187803b1580156123b557600080fd5b5086fa935050505080156123db57506040513d60208110156123d657600080fd5b505160015b6123e457612404565b6001600160a01b03811615612402578351611d405760016000611ce4565b505b93509350939050565b60008061271061242961177854856132cc90919063ffffffff16565b8161243057fe5b0490508061244b57612443836001613325565b915050610806565b6108028184613325565b61138d80546001810190915590565b600061246e611ad6565b6001600160a01b0316636d70f7ae336040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b1580156124ba57600080fd5b505afa1580156124ce573d6000803e3d6000fd5b505050506040513d60208110156124e457600080fd5b5051905090565b60408051602a808252606082810190935260009190602082018180368337019050509050600360fc1b8160008151811061252157fe5b60200101906001600160f81b031916908160001a9053507f78000000000000000000000000000000000000000000000000000000000000008160018151811061256657fe5b60200101906001600160f81b031916908160001a90535060005b601481101561264a5760008160130360080260020a856001600160a01b0316816125a657fe5b0460f81b9050600060108260f81c60ff16816125be57fe5b0460f81b905060008160f81c6010028360f81c0360f81b90506125e08261337f565b8585600202600201815181106125f257fe5b60200101906001600160f81b031916908160001a9053506126128161337f565b85856002026003018151811061262457fe5b60200101906001600160f81b031916908160001a90535050600190920191506125809050565b5092915050565b600061265d82516133b0565b8260405160200180807f19457468657265756d205369676e6564204d6573736167653a0a000000000000815250601a0183805190602001908083835b602083106126b85780518252601f199092019160209182019101612699565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b602083106127005780518252601f1990920191602091820191016126e1565b6001836020036101000a03801982511681845116808217855250505050505090500192505050604051602081830303815290604052805190602001209050919050565b600061274e8461348b565b156128655760408051630b135d3f60e11b815260048101858152602482019283528451604483015284516001600160a01b03881693631626ba7e938893889390929160640190602085019080838360005b838110156127b757818101518382015260200161279f565b50505050905090810190601f1680156127e45780820380516001836020036101000a031916815260200191505b50935050505060206040518083038186803b15801561280257600080fd5b505afa92505050801561282757506040513d602081101561282257600080fd5b505160015b61283357506000611af7565b7fffffffff0000000000000000000000000000000000000000000000000000000016630b135d3f60e11b149050611af7565b836001600160a01b03166128798484613491565b6001600160a01b031614949350505050565b6000612895611ad6565b6001600160a01b03166324d7806c336040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b1580156124ba57600080fd5b611ad2828262033450613507565b604080518082018252600c81527f464e444e46544d61726b6574000000000000000000000000000000000000000060209182015281518083018352600181527f31000000000000000000000000000000000000000000000000000000000000009082015281517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f818301527ffbcf34d9e40a15bdeb367420eb7542a501124a2eeb8d040648f646644b4baf2d818401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a0808301919091528351808303909101815260c09091019092528151910120611b6555565b612710821115612a145760405162461bcd60e51b815260040161044690613f6d565b6305265c00811115612a385760405162461bcd60e51b815260040161044690614027565b610384811015612a5a5760405162461bcd60e51b815260040161044690613fca565b61177882905561177a8190556040517f91b85a126da1d01639347f093e4267f458c9d95265414e2f0bd18e8c5b17d42a90612aa1908490600090859061038490839061420c565b60405180910390a15050565b6127108310612b03576040805162461bcd60e51b815260206004820152601b60248201527f4e46544d61726b6574466565733a2046656573203e3d20313030250000000000604482015290519081900360640190fd5b612710612b108383613325565b10612b62576040805162461bcd60e51b815260206004820152601b60248201527f4e46544d61726b6574466565733a2046656573203e3d20313030250000000000604482015290519081900360640190fd5b610fa1839055610fa2829055610fa3819055604080518481526020810184905280820183905290517f556079cdcafac41390a4af41101fa806590aefd70725513ad900a1df6ef488799181900360600190a1505050565b60008060006060806000612bcf8a8a8a8a612db6565b809950819650829a50839750849850859b505050505050506001610fa460008c6001600160a01b03166001600160a01b0316815260200190815260200160002060008b815260200190815260200160002060006101000a81548160ff021916908315150217905550612c48612c42611ad6565b87612ec9565b8415612d9f57600183511115612d81578251600019016004811115612c6b575060045b6000805b828111612ccc57612710858281518110612c8557fe5b60200260200101511115612c9c5760009250612ccc565b612cc2858281518110612cab57fe5b60200260200101518361332590919063ffffffff16565b9150600101612c6f565b5080612cd757600091505b600060015b838111612d4857600083612d0c888481518110612cf557fe5b60200260200101518c6132cc90919063ffffffff16565b81612d1357fe5b049050612d208382613325565b9250612d3f888381518110612d3157fe5b6020026020010151826128e1565b50600101612cdc565b50612d7986600081518110612d5957fe5b6020026020010151612d74838b6135eb90919063ffffffff16565b6128e1565b505050612d9f565b612d9f83600081518110612d9157fe5b6020026020010151866128e1565b612da981856128e1565b5050509450945094915050565b6000606080600080600080612dcc8b8b8b611afe565b919750955090506000818015612e0757506001600160a01b038c166000908152610fa4602090815260408083208e845290915290205460ff16155b9050612710612e2982612e1d57610fa254612e22565b610fa1545b8b906132cc565b81612e3057fe5b0497508015612e4a57612e4389896135eb565b9450612eba565b865115612eaa578115612e6857612e6189896135eb565b9450612ea5565b612710612e81610fa3548b6132cc90919063ffffffff16565b81612e8857fe5b049450899350612ea285612e9c8b8b6135eb565b906135eb565b92505b612eba565b899350612eb789896135eb565b92505b50509499939850945094509450565b611ad28282614e20613507565b80471015612f2b576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d8060008114612f76576040519150601f19603f3d011682016040523d82523d6000602084013e612f7b565b606091505b5050905080612fbb5760405162461bcd60e51b815260040180806020018281038252603a815260200180614325603a913960400191505060405180910390fd5b505050565b6000612fcb3061348b565b15905090565b600054610100900460ff1680612fea5750612fea612fc0565b80612ff8575060005460ff16155b6130335760405162461bcd60e51b815260040180806020018281038252602e8152602001806143b9602e913960400191505060405180910390fd5b600054610100900460ff1615801561305e576000805460ff1961ff0019909116610100171660011790555b613070826001600160a01b031661348b565b6130ab5760405162461bcd60e51b81526004018080602001828103825260318152602001806142f46031913960400191505060405180910390fd5b600080547fffffffffffffffffffff0000000000000000000000000000000000000000ffff16620100006001600160a01b038516021790558015611ad2576000805461ff00191690555050565b600161138d55565b6201518061177a55565b6001600160a01b03808316600090815261177660209081526040808320858452825280832054835261177790915290206002015416806107b55761314e8383613648565b90506107b5565b604080517fffffffff00000000000000000000000000000000000000000000000000000000831660248083019190915282518083039091018152604490910182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a70000000000000000000000000000000000000000000000000000000017815291518151600093849283926001600160a01b03891692617530928792909182918083835b602083106132215780518252601f199092019160209182019101613202565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303818686fa925050503d8060008114613282576040519150601f19603f3d011682016040523d82523d6000602084013e613287565b606091505b50915091506020815110156132a257600093505050506107b5565b8180156132c257508080602001905160208110156132bf57600080fd5b50515b9695505050505050565b6000826132db575060006107b5565b828202828482816132e857fe5b0414611af75760405162461bcd60e51b81526004018080602001828103825260218152602001806144096021913960400191505060405180910390fd5b600082820183811015611af7576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000600a60f883901c101561339f578160f81c60300160f81b9050610806565b8160f81c60570160f81b9050610806565b6060816133d557506040805180820190915260018152600360fc1b6020820152610806565b8160005b81156133ed57600101600a820491506133d9565b60008167ffffffffffffffff8111801561340657600080fd5b506040519080825280601f01601f191660200182016040528015613431576020820181803683370190505b50859350905060001982015b831561348257600a840660300160f81b8282806001900393508151811061346057fe5b60200101906001600160f81b031916908160001a905350600a8404935061343d565b50949350505050565b3b151590565b600081516041146134e9576040805162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e67746800604482015290519081900360640190fd5b60208201516040830151606084015160001a6132c2868285856136c1565b8161351157612fbb565b6040516000906001600160a01b038516908390859084818181858888f193505050503d806000811461355f576040519150601f19603f3d011682016040523d82523d6000602084013e613564565b606091505b50509050806135e5576001600160a01b0384166000908152610dad60205260409020546135919084613325565b6001600160a01b0385166000818152610dad6020908152604091829020939093558051868152905191927f9a92c3472ba0d2d183e38c3801bae5d41d693c2803377eae8b0f94683862253e92918290030190a25b50505050565b600082821115613642576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6000826001600160a01b0316636352211e836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561368e57600080fd5b505afa1580156136a2573d6000803e3d6000fd5b505050506040513d60208110156136b857600080fd5b50519392505050565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08211156137225760405162461bcd60e51b815260040180806020018281038252602281526020018061435f6022913960400191505060405180910390fd5b8360ff16601b148061373757508360ff16601c145b6137725760405162461bcd60e51b81526004018080602001828103825260228152602001806143e76022913960400191505060405180910390fd5b600060018686868660405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa1580156137ce573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116610546576040805162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015290519081900360640190fd5b60405180610100016040528060006001600160a01b031681526020016000815260200160006001600160a01b0316815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b80356108068161426e565b60008083601f8401126138b2578182fd5b50813567ffffffffffffffff8111156138c9578182fd5b6020830191508360208285010111156138e157600080fd5b9250929050565b6000602082840312156138f9578081fd5b8135611af78161426e565b60008060408385031215613916578081fd5b82356139218161426e565b946020939093013593505050565b600080600060608486031215613943578081fd5b833561394e8161426e565b95602085013595506040909401359392505050565b6000806000806000806080878903121561397b578182fd5b863567ffffffffffffffff80821115613992578384fd5b818901915089601f8301126139a5578384fd5b8135818111156139b3578485fd5b8a602080830285010111156139c6578485fd5b602083019850809750506139dc60208a01613896565b95506139ea60408a01613896565b945060608901359150808211156139ff578384fd5b50613a0c89828a016138a1565b979a9699509497509295939492505050565b60008060008060008060c08789031215613a36578182fd5b8635613a418161426e565b95506020870135945060408701359350606087013560ff81168114613a64578283fd5b9598949750929560808101359460a0909101359350915050565b600060208284031215613a8f578081fd5b5035919050565b60008060408385031215613aa8578182fd5b8235915060208084013567ffffffffffffffff80821115613ac7578384fd5b818601915086601f830112613ada578384fd5b813581811115613ae657fe5b604051601f8201601f1916810185018381118282101715613b0357fe5b6040528181528382018501891015613b19578586fd5b81858501868301378585838301015280955050505050509250929050565b60008060408385031215613b49578182fd5b50508035926020909101359150565b600080600080600060a08688031215613b6f578081fd5b505083359560208501359550604085013594606081013594506080013592509050565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b901515815260200190565b6000602080835283518082850152825b81811015613c0157858101830151858201604001528201613be5565b81811115613c125783604083870101525b50601f01601f1916929092016040019392505050565b6020808252603d908201527f4e46544d61726b65745265736572766541756374696f6e3a205265736572766560408201527f207072696365206d757374206265206174206c65617374203120776569000000606082015260800190565b6020808252602b908201527f4e46544d61726b65745265736572766541756374696f6e3a2042696420616d6f60408201527f756e7420746f6f206c6f77000000000000000000000000000000000000000000606082015260800190565b6020808252603f908201527f4e46544d61726b65745265736572766541756374696f6e3a20496e636c75646560408201527f206120726561736f6e20666f7220746869732063616e63656c6c6174696f6e00606082015260800190565b60208082526029908201527f4e46544d61726b65745265736572766541756374696f6e3a204e6f7420796f7560408201527f722061756374696f6e0000000000000000000000000000000000000000000000606082015260800190565b6020808252602a908201527f4e46544d61726b65745265736572766541756374696f6e3a2041756374696f6e60408201527f206e6f7420666f756e6400000000000000000000000000000000000000000000606082015260800190565b6020808252603f908201527f4e46544d61726b65745265736572766541756374696f6e3a20426964206d757360408201527f74206265206174206c6561737420746865207265736572766520707269636500606082015260800190565b60208082526028908201527f4e46544d61726b65745265736572766541756374696f6e3a2041756374696f6e60408201527f206973206f766572000000000000000000000000000000000000000000000000606082015260800190565b6020808252603c908201527f4e46544d61726b65745265736572766541756374696f6e3a2041756374696f6e60408201527f206e6f7420637265617465642062792074686174206164647265737300000000606082015260800190565b6020808252602c908201527f4e46544d61726b65745265736572766541756374696f6e3a2041756374696f6e60408201527f20696e2070726f67726573730000000000000000000000000000000000000000606082015260800190565b60208082526036908201527f4e46544d61726b65745265736572766541756374696f6e3a204d696e20696e6360408201527f72656d656e74206d757374206265203c3d203130302500000000000000000000606082015260800190565b6020808252603f908201527f4e46544d61726b65745265736572766541756374696f6e3a204475726174696f60408201527f6e206d757374206265203e3d20455854454e53494f4e5f4455524154494f4e00606082015260800190565b60208082526036908201527f4e46544d61726b65745265736572766541756374696f6e3a204475726174696f60408201527f6e206d757374206265203c3d2031303030206461797300000000000000000000606082015260800190565b6020808252603c908201527f4e46544d61726b65745265736572766541756374696f6e3a20596f7520616c7260408201527f65616479206861766520616e206f75747374616e64696e672062696400000000606082015260800190565b60208082526032908201527f4e46544d61726b65745265736572766541756374696f6e3a2041756374696f6e60408201527f207374696c6c20696e2070726f67726573730000000000000000000000000000606082015260800190565b60208082526034908201527f4e46544d61726b65745265736572766541756374696f6e3a2041756374696f6e60408201527f2077617320616c726561647920736574746c6564000000000000000000000000606082015260800190565b6000610100820190506001600160a01b0380845116835260208401516020840152806040850151166040840152606084015160608401526080840151608084015260a084015160a08401528060c08501511660c08401525060e083015160e083015292915050565b90815260200190565b948552602085019390935260408401919091526060830152608082015260a00190565b918252602082015260400190565b9283526020830191909152604082015260600190565b93845260208401929092526040830152606082015260800190565b6001600160a01b038116811461428357600080fd5b5056fe4163636f756e744d6967726174696f6e3a205369676e6174757265206d7573742062652066726f6d20746865206f726967696e616c206163636f756e744920617574686f72697a6520466f756e646174696f6e20746f206d696772617465206d79206163636f756e7420746f20466f756e646174696f6e54726561737572794e6f64653a2041646472657373206973206e6f74206120636f6e7472616374416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d6179206861766520726576657274656445434453413a20696e76616c6964207369676e6174757265202773272076616c7565466f756e646174696f6e41646d696e526f6c653a2063616c6c657220646f6573206e6f742068617665207468652041646d696e20726f6c65496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a656445434453413a20696e76616c6964207369676e6174757265202776272076616c7565536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774163636f756e744d6967726174696f6e3a2043616e6e6f74206d69677261746520746f207468652073616d65206163636f756e744e46544d61726b65745072697661746553616c653a20494e56414c49445f5349474e41545552454163636f756e744d6967726174696f6e3a2043616c6c6572206973206e6f7420616e206f70657261746f72a26469706673582212209bbf621f62df75a7624961530698622fb0a29b912e6d6de52f6d479ae079d96464736f6c63430007060033
Deployed Bytecode
0x60806040526004361061016a5760003560e01c80635ed31d8a116100cb5780637ee8b2f81161007f5780639eca672c116100595780639eca672c146103c3578063c4d66de8146103e3578063f7a2da23146104035761016a565b80637ee8b2f8146103635780639979ef45146103835780639e79b41f146103965761016a565b80636775d96a116100b05780636775d96a146103105780637430e0c61461032357806374a45126146103435761016a565b80635ed31d8a146102cc5780635fbbc0d2146102ec5761016a565b80633ccfd60b116101225780634ce6931a116101075780634ce6931a1461026c5780634d6706631461028c5780635d83d562146102ac5761016a565b80633ccfd60b1461023757806347e357401461024c5761016a565b806321506fff1161015357806321506fff146101c75780632ab2b52b146101e75780633b230bc9146102145761016a565b806303ec16d71461016f5780632047677714610191575b600080fd5b34801561017b57600080fd5b5061018f61018a366004613b37565b610425565b005b34801561019d57600080fd5b506101b16101ac366004613904565b6104f3565b6040516101be9190613bca565b60405180910390f35b3480156101d357600080fd5b5061018f6101e2366004613a7e565b61054f565b3480156101f357600080fd5b50610207610202366004613904565b61078f565b6040516101be9190614203565b34801561022057600080fd5b506102296107bb565b6040516101be92919061422f565b34801561024357600080fd5b5061018f6107c7565b34801561025857600080fd5b50610207610267366004613a7e565b6107d2565b34801561027857600080fd5b5061018f61028736600461392f565b61080b565b34801561029857600080fd5b5061018f6102a7366004613963565b610ac5565b3480156102b857600080fd5b5061018f6102c7366004613a96565b610d4f565b3480156102d857600080fd5b5061018f6102e7366004613b58565b610f9f565b3480156102f857600080fd5b50610301611006565b6040516101be9392919061423d565b61018f61031e366004613a1e565b611017565b34801561032f57600080fd5b5061018f61033e366004613a7e565b61134c565b34801561034f57600080fd5b5061030161035e36600461392f565b6115d3565b34801561036f57600080fd5b5061020761037e3660046138e8565b611604565b61018f610391366004613a7e565b611620565b3480156103a257600080fd5b506103b66103b1366004613a7e565b61185d565b6040516101be919061419b565b3480156103cf57600080fd5b5061018f6103de3660046138e8565b6118e2565b3480156103ef57600080fd5b5061018f6103fe3660046138e8565b611a1a565b34801561040f57600080fd5b50610418611ad6565b6040516101be9190613b92565b806000811161044f5760405162461bcd60e51b815260040161044690613c28565b60405180910390fd5b60008381526117776020526040902060028101546001600160a01b0316331461048a5760405162461bcd60e51b815260040161044690613d3f565b6005810154156104ac5760405162461bcd60e51b815260040161044690613f10565b828160070181905550837f0c0f2662914f0cd1e952db2aa425901cb00e7c1f507687d22cb04e836d55d9c7846040516104e59190614203565b60405180910390a250505050565b6000806105008484611aeb565b9050600061050f858584611afe565b925082915050801561054657506001600160a01b0385166000908152610fa46020908152604080832087845290915290205460ff16155b95945050505050565b6002610b875414156105a8576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002610b878190556000828152611777602090815260409182902082516101008101845281546001600160a01b0390811682526001830154938201939093529381015482169284018390526003810154606085015260048101546080850152600581015460a0850152600681015490911660c08401526007015460e083015233146106455760405162461bcd60e51b815260040161044690613d3f565b60a0810151156106675760405162461bcd60e51b815260040161044690613f10565b80516001600160a01b0390811660009081526117766020908152604080832082860180518552908352818420849055868452611777909252808320805473ffffffffffffffffffffffffffffffffffffffff199081168255600182018590556002820180548216905560038201859055600480830186905560058301869055600683018054909216909155600790910193909355845181860151925191516323b872dd60e01b81529416936323b872dd936107289330939092909101613ba6565b600060405180830381600087803b15801561074257600080fd5b505af1158015610756573d6000803e3d6000fd5b50506040518492507f14b9c40404d5b41deb481f9a40b8aeb2bf4b47679b38cf757075a66ed510f7f19150600090a250506001610b8755565b6001600160a01b0382166000908152611776602090815260408083208484529091529020545b92915050565b6117785461177a549091565b6107d0336118e2565b565b60008181526117776020526040812060058101546107f557600701549050610806565b610802816007015461240d565b9150505b919050565b806000811161082c5760405162461bcd60e51b815260040161044690613c28565b6002610b87541415610885576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002610b87556000610895612455565b9050806117766000876001600160a01b03166001600160a01b03168152602001908152602001600020600086815260200190815260200160002081905550604051806101000160405280866001600160a01b03168152602001858152602001336001600160a01b0316815260200161177a54815260200161038481526020016000815260200160006001600160a01b0316815260200184815250611777600083815260200190815260200160002060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506020820151816001015560408201518160020160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550606082015181600301556080820151816004015560a0820151816005015560c08201518160060160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060e08201518160070155905050846001600160a01b03166323b872dd3330876040518463ffffffff1660e01b8152600401610a2f93929190613ba6565b600060405180830381600087803b158015610a4957600080fd5b505af1158015610a5d573d6000803e3d6000fd5b5050505083856001600160a01b0316336001600160a01b03167f1062dd3b35f12b4064331244d00f40c1d4831965e4285654157a2409c6217cff61177a546103848887604051610ab09493929190614253565b60405180910390a450506001610b8755505050565b838383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610b079250612464915050565b610b425760405162461bcd60e51b815260040180806020018281038252602b815260200180614485602b913960400191505060405180910390fd5b816001600160a01b0316836001600160a01b03161415610b935760405162461bcd60e51b815260040180806020018281038252603481526020018061442a6034913960400191505060405180910390fd5b6000610c16610ba1846124eb565b6040516020018060306142c4823960300182805190602001908083835b60208310610bdd5780518252601f199092019160209182019101610bbe565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051602081830303815290604052612651565b9050610c23848284612743565b610c5e5760405162461bcd60e51b815260040180806020018281038252603d815260200180614287603d913960400191505060405180910390fd5b60005b89811015610d425760008b8b83818110610c7757fe5b60209081029290920135600081815261177790935260409092206002810154929350916001600160a01b0316159050610d385760028101546001600160a01b038c8116911614610cd95760405162461bcd60e51b815260040161044690613eb3565b60028101805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b038c811691821790925560405190918d169084907f099239784bcc562970bdd08339308cf1ff2a1eb4c62e47e52d5b6b064e11a55390600090a45b5050600101610c61565b5050505050505050505050565b610d5761288b565b610d925760405162461bcd60e51b81526004018080602001828103825260388152602001806143816038913960400191505060405180910390fd5b6000815111610db35760405162461bcd60e51b815260040161044690613ce2565b6000828152611777602090815260409182902082516101008101845281546001600160a01b03908116825260018301549382019390935260028201548316938101939093526003810154606084015260048101546080840152600581015460a0840152600681015490911660c08301526007015460e08201819052610e4a5760405162461bcd60e51b815260040161044690613d9c565b80516001600160a01b0390811660009081526117766020908152604080832082860180518552908352818420849055878452611777909252808320805473ffffffffffffffffffffffffffffffffffffffff199081168255600182018590556002820180548216905560038201859055600480830186905560058301869055600683018054909216909155600790910193909355845181860151925191516323b872dd60e01b81529416936323b872dd93610f0b9330939092909101613ba6565b600060405180830381600087803b158015610f2557600080fd5b505af1158015610f39573d6000803e3d6000fd5b5050505060c08101516001600160a01b031615610f6257610f628160c001518260e001516128e1565b827f1d56d378404d81e3fc5f3dfbf88359b8cb2ecafa73b3270c478bf7b2bdd1446983604051610f929190613bd5565b60405180910390a2505050565b610fa761288b565b610fe25760405162461bcd60e51b81526004018080602001828103825260388152602001806143816038913960400191505060405180910390fd5b610fea6128ef565b610ff485856129f2565b610fff838383612aad565b5050505050565b610fa154610fa254610fa354909192565b4284101561106c576040805162461bcd60e51b815260206004820152601d60248201527f4e46544d61726b65745072697661746553616c653a2045585049524544000000604482015290519081900360640190fd5b6000866001600160a01b0316636352211e876040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b1580156110b257600080fd5b505afa1580156110c6573d6000803e3d6000fd5b505050506040513d60208110156110dc57600080fd5b5051611b6554604080517f6f5a5497fcb7364f6bad56db9aad5785b6786717424e748b8bfef6e6554cd5516020828101919091526001600160a01b03808d1683850152606083018c90523360808401523460a084015260c08084018c90528451808503909101815260e0840185528051908301207f1901000000000000000000000000000000000000000000000000000000000000610100850152610102840195909552610122808401959095528351808403909501855261014283018085528551958301959095206000909552610162830180855285905260ff8a166101828401526101a283018990526101c2830188905292519495509293918516926001926101e280840193601f198301929081900390910190855afa158015611206573d6000803e3d6000fd5b505050602060405103516001600160a01b0316146112555760405162461bcd60e51b815260040180806020018281038252602781526020018061445e6027913960400191505060405180910390fd5b50604080516323b872dd60e01b81526001600160a01b038381166004830152336024830152604482018990529151918916916323b872dd9160648082019260009290919082900301818387803b1580156112ae57600080fd5b505af11580156112c2573d6000803e3d6000fd5b5050505060008060006112d78a8a8634612bb9565b604080513381526020810185905280820184905260608101839052608081018d9052905193965091945092506001600160a01b03808716928c92918e16917f6c623fa5e13aaaf28288f807e5b4f9ec6fb7ef812568e00317c552663bea918f919081900360a00190a450505050505050505050565b6002610b875414156113a5576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002610b878190556000828152611777602090815260409182902082516101008101845281546001600160a01b039081168252600183015493820193909352938101548216928401929092526003820154606084015260048201546080840152600582015460a08401819052600683015490911660c084015260079091015460e08301526114455760405162461bcd60e51b81526004016104469061413e565b428160a00151106114685760405162461bcd60e51b8152600401610446906140e1565b80516001600160a01b0390811660009081526117766020908152604080832082860180518552908352818420849055868452611777909252808320805473ffffffffffffffffffffffffffffffffffffffff199081168255600182018590556002820180548216905560038201859055600480830186905560058301869055600683018054909216909155600790910193909355845160c0860151925191516323b872dd60e01b81529416936323b872dd9361152a9330939092909101613ba6565b600060405180830381600087803b15801561154457600080fd5b505af1158015611558573d6000803e3d6000fd5b50505050600080600061157d8460000151856020015186604001518760e00151612bb9565b9250925092508360c001516001600160a01b031684604001516001600160a01b0316867f2edb0e99c6ac35be6731dab554c1d1fa1b7beb675090dbb09fb14e615aca1c4a868686604051610ab09392919061423d565b6000806000806115e38787611aeb565b90506115f187878388612db6565b949c919b50939950975050505050505050565b6001600160a01b03166000908152610dad602052604090205490565b6002610b87541415611679576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002610b875560008181526117776020526040902060078101546116af5760405162461bcd60e51b815260040161044690613d9c565b60058101546116e15734816007015411156116dc5760405162461bcd60e51b815260040161044690613df9565b611765565b42816005015410156117055760405162461bcd60e51b815260040161044690613e56565b60068101546001600160a01b03163314156117325760405162461bcd60e51b815260040161044690614084565b6000611741826007015461240d565b9050803410156117635760405162461bcd60e51b815260040161044690613c85565b505b60058101546117a65734600782015560068101805473ffffffffffffffffffffffffffffffffffffffff19163317905560038101544201600582015561180b565b6007810180546006830180543490935573ffffffffffffffffffffffffffffffffffffffff198316331790556004830154600584015491926001600160a01b03169142900310156117fe576004830154420160058401555b6118088183612ec9565b50505b336001600160a01b0316827f26ea3ebbda62eb1baef13e1c237dddd956c87f80b2801f2616d806d52557b12134846005015460405161184b92919061422f565b60405180910390a350506001610b8755565b611865613836565b506000908152611777602090815260409182902082516101008101845281546001600160a01b03908116825260018301549382019390935260028201548316938101939093526003810154606084015260048101546080840152600581015460a0840152600681015490911660c08301526007015460e082015290565b6002610b8754141561193b576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002610b87556001600160a01b0381166000908152610dad6020526040902054806119ad576040805162461bcd60e51b815260206004820152601f60248201527f4e6f2066756e6473206172652070656e64696e67207769746864726177616c00604482015290519081900360640190fd5b6001600160a01b0382166000818152610dad60205260408120556119d19082612ed6565b6040805182815290516001600160a01b038416917f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65919081900360200190a250506001610b8755565b600054610100900460ff1680611a335750611a33612fc0565b80611a41575060005460ff16155b611a7c5760405162461bcd60e51b815260040180806020018281038252602e8152602001806143b9602e913960400191505060405180910390fd5b600054610100900460ff16158015611aa7576000805460ff1961ff0019909116610100171660011790555b611ab082612fd1565b611ab86130f8565b611ac0613100565b8015611ad2576000805461ff00191690555b5050565b6000546201000090046001600160a01b031690565b6000611af7838361310a565b9392505050565b6060806000611b366001600160a01b0387167fec5f752e00000000000000000000000000000000000000000000000000000000613155565b15611c1c57856001600160a01b031663ec5f752e619c40876040518363ffffffff1660e01b81526004018082815260200191505060206040518083038187803b158015611b8257600080fd5b5086fa93505050508015611ba857506040513d6020811015611ba357600080fd5b505160015b611bb157611c1c565b6001600160a01b03811615611c1a5760408051600180825281830190925290602080830190803683370190505093508084600081518110611bee57fe5b6001600160a01b0392831660209182029290920101528181169086161415611c1a575060019050612404565b505b611c4f6001600160a01b0387167f40c1a06400000000000000000000000000000000000000000000000000000000613155565b15611d5757856001600160a01b03166340c1a064619c40876040518363ffffffff1660e01b81526004018082815260200191505060206040518083038187803b158015611c9b57600080fd5b5086fa93505050508015611cc157506040513d6020811015611cbc57600080fd5b505160015b611cca57611d57565b6001600160a01b03811615611d55578351611d4057600160005b50604051908082528060200260200182016040528015611d0e578160200160208202803683370190505b5093508084600081518110611d1f57fe5b60200260200101906001600160a01b031690816001600160a01b0316815250505b6001600160a01b038581169116149050612404565b505b8251158015611d945750611d946001600160a01b0387167fbb3bafd600000000000000000000000000000000000000000000000000000000613155565b15611fda57856001600160a01b031663bb3bafd6619c40876040518363ffffffff1660e01b81526004018082815260200191505060006040518083038187803b158015611de057600080fd5b5086fa93505050508015611f2b57506040513d6000823e601f3d908101601f191682016040908152811015611e1457600080fd5b8101908080516040519392919084640100000000821115611e3457600080fd5b908301906020820185811115611e4957600080fd5b8251866020820283011164010000000082111715611e6657600080fd5b82525081516020918201928201910280838360005b83811015611e93578181015183820152602001611e7b565b5050505090500160405260200180516040519392919084640100000000821115611ebc57600080fd5b908301906020820185811115611ed157600080fd5b8251866020820283011164010000000082111715611eee57600080fd5b82525081516020918201928201910280838360005b83811015611f1b578181015183820152602001611f03565b5050505090500160405250505060015b611f3457611fda565b60008251118015611f46575080518251145b15611fd7576000805b8351811015611fc35760006001600160a01b0316848281518110611f6f57fe5b60200260200101516001600160a01b031614611fbb5760019150876001600160a01b0316848281518110611f9f57fe5b60200260200101516001600160a01b03161415611fbb57600194505b600101611f4f565b508015611fd557509093509150612404565b505b50505b825115801561201757506120176001600160a01b0387167fb779958400000000000000000000000000000000000000000000000000000000613155565b156122e357856001600160a01b031663b9c4d9fb619c40876040518363ffffffff1660e01b81526004018082815260200191505060006040518083038187803b15801561206357600080fd5b5086fa9350505050801561212657506040513d6000823e601f3d908101601f19168201604052602081101561209757600080fd5b81019080805160405193929190846401000000008211156120b757600080fd5b9083019060208201858111156120cc57600080fd5b82518660208202830111640100000000821117156120e957600080fd5b82525081516020918201928201910280838360005b838110156121165781810151838201526020016120fe565b5050505090500160405250505060015b61212f576122e3565b8051156122e157866001600160a01b0316630ebd4c7f619c40886040518363ffffffff1660e01b81526004018082815260200191505060006040518083038187803b15801561217d57600080fd5b5086fa9350505050801561224057506040513d6000823e601f3d908101601f1916820160405260208110156121b157600080fd5b81019080805160405193929190846401000000008211156121d157600080fd5b9083019060208201858111156121e657600080fd5b825186602082028301116401000000008211171561220357600080fd5b82525081516020918201928201910280838360005b83811015612230578181015183820152602001612218565b5050505090500160405250505060015b612249576122e1565b8051825114156122df576000805b83518110156122cb5760006001600160a01b031684828151811061227757fe5b60200260200101516001600160a01b0316146122c35760019150876001600160a01b03168482815181106122a757fe5b60200260200101516001600160a01b031614156122c357600194505b600101612257565b5080156122dd57509093509150612404565b505b505b505b856001600160a01b0316638da5cb5b619c406040518263ffffffff1660e01b815260040160206040518083038187803b15801561231f57600080fd5b5086fa9350505050801561234557506040513d602081101561234057600080fd5b505160015b61234e5761236e565b6001600160a01b0381161561236c578351611d405760016000611ce4565b505b856001600160a01b03166340c1a064619c40876040518363ffffffff1660e01b81526004018082815260200191505060206040518083038187803b1580156123b557600080fd5b5086fa935050505080156123db57506040513d60208110156123d657600080fd5b505160015b6123e457612404565b6001600160a01b03811615612402578351611d405760016000611ce4565b505b93509350939050565b60008061271061242961177854856132cc90919063ffffffff16565b8161243057fe5b0490508061244b57612443836001613325565b915050610806565b6108028184613325565b61138d80546001810190915590565b600061246e611ad6565b6001600160a01b0316636d70f7ae336040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b1580156124ba57600080fd5b505afa1580156124ce573d6000803e3d6000fd5b505050506040513d60208110156124e457600080fd5b5051905090565b60408051602a808252606082810190935260009190602082018180368337019050509050600360fc1b8160008151811061252157fe5b60200101906001600160f81b031916908160001a9053507f78000000000000000000000000000000000000000000000000000000000000008160018151811061256657fe5b60200101906001600160f81b031916908160001a90535060005b601481101561264a5760008160130360080260020a856001600160a01b0316816125a657fe5b0460f81b9050600060108260f81c60ff16816125be57fe5b0460f81b905060008160f81c6010028360f81c0360f81b90506125e08261337f565b8585600202600201815181106125f257fe5b60200101906001600160f81b031916908160001a9053506126128161337f565b85856002026003018151811061262457fe5b60200101906001600160f81b031916908160001a90535050600190920191506125809050565b5092915050565b600061265d82516133b0565b8260405160200180807f19457468657265756d205369676e6564204d6573736167653a0a000000000000815250601a0183805190602001908083835b602083106126b85780518252601f199092019160209182019101612699565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b602083106127005780518252601f1990920191602091820191016126e1565b6001836020036101000a03801982511681845116808217855250505050505090500192505050604051602081830303815290604052805190602001209050919050565b600061274e8461348b565b156128655760408051630b135d3f60e11b815260048101858152602482019283528451604483015284516001600160a01b03881693631626ba7e938893889390929160640190602085019080838360005b838110156127b757818101518382015260200161279f565b50505050905090810190601f1680156127e45780820380516001836020036101000a031916815260200191505b50935050505060206040518083038186803b15801561280257600080fd5b505afa92505050801561282757506040513d602081101561282257600080fd5b505160015b61283357506000611af7565b7fffffffff0000000000000000000000000000000000000000000000000000000016630b135d3f60e11b149050611af7565b836001600160a01b03166128798484613491565b6001600160a01b031614949350505050565b6000612895611ad6565b6001600160a01b03166324d7806c336040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b1580156124ba57600080fd5b611ad2828262033450613507565b604080518082018252600c81527f464e444e46544d61726b6574000000000000000000000000000000000000000060209182015281518083018352600181527f31000000000000000000000000000000000000000000000000000000000000009082015281517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f818301527ffbcf34d9e40a15bdeb367420eb7542a501124a2eeb8d040648f646644b4baf2d818401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a0808301919091528351808303909101815260c09091019092528151910120611b6555565b612710821115612a145760405162461bcd60e51b815260040161044690613f6d565b6305265c00811115612a385760405162461bcd60e51b815260040161044690614027565b610384811015612a5a5760405162461bcd60e51b815260040161044690613fca565b61177882905561177a8190556040517f91b85a126da1d01639347f093e4267f458c9d95265414e2f0bd18e8c5b17d42a90612aa1908490600090859061038490839061420c565b60405180910390a15050565b6127108310612b03576040805162461bcd60e51b815260206004820152601b60248201527f4e46544d61726b6574466565733a2046656573203e3d20313030250000000000604482015290519081900360640190fd5b612710612b108383613325565b10612b62576040805162461bcd60e51b815260206004820152601b60248201527f4e46544d61726b6574466565733a2046656573203e3d20313030250000000000604482015290519081900360640190fd5b610fa1839055610fa2829055610fa3819055604080518481526020810184905280820183905290517f556079cdcafac41390a4af41101fa806590aefd70725513ad900a1df6ef488799181900360600190a1505050565b60008060006060806000612bcf8a8a8a8a612db6565b809950819650829a50839750849850859b505050505050506001610fa460008c6001600160a01b03166001600160a01b0316815260200190815260200160002060008b815260200190815260200160002060006101000a81548160ff021916908315150217905550612c48612c42611ad6565b87612ec9565b8415612d9f57600183511115612d81578251600019016004811115612c6b575060045b6000805b828111612ccc57612710858281518110612c8557fe5b60200260200101511115612c9c5760009250612ccc565b612cc2858281518110612cab57fe5b60200260200101518361332590919063ffffffff16565b9150600101612c6f565b5080612cd757600091505b600060015b838111612d4857600083612d0c888481518110612cf557fe5b60200260200101518c6132cc90919063ffffffff16565b81612d1357fe5b049050612d208382613325565b9250612d3f888381518110612d3157fe5b6020026020010151826128e1565b50600101612cdc565b50612d7986600081518110612d5957fe5b6020026020010151612d74838b6135eb90919063ffffffff16565b6128e1565b505050612d9f565b612d9f83600081518110612d9157fe5b6020026020010151866128e1565b612da981856128e1565b5050509450945094915050565b6000606080600080600080612dcc8b8b8b611afe565b919750955090506000818015612e0757506001600160a01b038c166000908152610fa4602090815260408083208e845290915290205460ff16155b9050612710612e2982612e1d57610fa254612e22565b610fa1545b8b906132cc565b81612e3057fe5b0497508015612e4a57612e4389896135eb565b9450612eba565b865115612eaa578115612e6857612e6189896135eb565b9450612ea5565b612710612e81610fa3548b6132cc90919063ffffffff16565b81612e8857fe5b049450899350612ea285612e9c8b8b6135eb565b906135eb565b92505b612eba565b899350612eb789896135eb565b92505b50509499939850945094509450565b611ad28282614e20613507565b80471015612f2b576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d8060008114612f76576040519150601f19603f3d011682016040523d82523d6000602084013e612f7b565b606091505b5050905080612fbb5760405162461bcd60e51b815260040180806020018281038252603a815260200180614325603a913960400191505060405180910390fd5b505050565b6000612fcb3061348b565b15905090565b600054610100900460ff1680612fea5750612fea612fc0565b80612ff8575060005460ff16155b6130335760405162461bcd60e51b815260040180806020018281038252602e8152602001806143b9602e913960400191505060405180910390fd5b600054610100900460ff1615801561305e576000805460ff1961ff0019909116610100171660011790555b613070826001600160a01b031661348b565b6130ab5760405162461bcd60e51b81526004018080602001828103825260318152602001806142f46031913960400191505060405180910390fd5b600080547fffffffffffffffffffff0000000000000000000000000000000000000000ffff16620100006001600160a01b038516021790558015611ad2576000805461ff00191690555050565b600161138d55565b6201518061177a55565b6001600160a01b03808316600090815261177660209081526040808320858452825280832054835261177790915290206002015416806107b55761314e8383613648565b90506107b5565b604080517fffffffff00000000000000000000000000000000000000000000000000000000831660248083019190915282518083039091018152604490910182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a70000000000000000000000000000000000000000000000000000000017815291518151600093849283926001600160a01b03891692617530928792909182918083835b602083106132215780518252601f199092019160209182019101613202565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303818686fa925050503d8060008114613282576040519150601f19603f3d011682016040523d82523d6000602084013e613287565b606091505b50915091506020815110156132a257600093505050506107b5565b8180156132c257508080602001905160208110156132bf57600080fd5b50515b9695505050505050565b6000826132db575060006107b5565b828202828482816132e857fe5b0414611af75760405162461bcd60e51b81526004018080602001828103825260218152602001806144096021913960400191505060405180910390fd5b600082820183811015611af7576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000600a60f883901c101561339f578160f81c60300160f81b9050610806565b8160f81c60570160f81b9050610806565b6060816133d557506040805180820190915260018152600360fc1b6020820152610806565b8160005b81156133ed57600101600a820491506133d9565b60008167ffffffffffffffff8111801561340657600080fd5b506040519080825280601f01601f191660200182016040528015613431576020820181803683370190505b50859350905060001982015b831561348257600a840660300160f81b8282806001900393508151811061346057fe5b60200101906001600160f81b031916908160001a905350600a8404935061343d565b50949350505050565b3b151590565b600081516041146134e9576040805162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e67746800604482015290519081900360640190fd5b60208201516040830151606084015160001a6132c2868285856136c1565b8161351157612fbb565b6040516000906001600160a01b038516908390859084818181858888f193505050503d806000811461355f576040519150601f19603f3d011682016040523d82523d6000602084013e613564565b606091505b50509050806135e5576001600160a01b0384166000908152610dad60205260409020546135919084613325565b6001600160a01b0385166000818152610dad6020908152604091829020939093558051868152905191927f9a92c3472ba0d2d183e38c3801bae5d41d693c2803377eae8b0f94683862253e92918290030190a25b50505050565b600082821115613642576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6000826001600160a01b0316636352211e836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561368e57600080fd5b505afa1580156136a2573d6000803e3d6000fd5b505050506040513d60208110156136b857600080fd5b50519392505050565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08211156137225760405162461bcd60e51b815260040180806020018281038252602281526020018061435f6022913960400191505060405180910390fd5b8360ff16601b148061373757508360ff16601c145b6137725760405162461bcd60e51b81526004018080602001828103825260228152602001806143e76022913960400191505060405180910390fd5b600060018686868660405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa1580156137ce573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116610546576040805162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015290519081900360640190fd5b60405180610100016040528060006001600160a01b031681526020016000815260200160006001600160a01b0316815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b80356108068161426e565b60008083601f8401126138b2578182fd5b50813567ffffffffffffffff8111156138c9578182fd5b6020830191508360208285010111156138e157600080fd5b9250929050565b6000602082840312156138f9578081fd5b8135611af78161426e565b60008060408385031215613916578081fd5b82356139218161426e565b946020939093013593505050565b600080600060608486031215613943578081fd5b833561394e8161426e565b95602085013595506040909401359392505050565b6000806000806000806080878903121561397b578182fd5b863567ffffffffffffffff80821115613992578384fd5b818901915089601f8301126139a5578384fd5b8135818111156139b3578485fd5b8a602080830285010111156139c6578485fd5b602083019850809750506139dc60208a01613896565b95506139ea60408a01613896565b945060608901359150808211156139ff578384fd5b50613a0c89828a016138a1565b979a9699509497509295939492505050565b60008060008060008060c08789031215613a36578182fd5b8635613a418161426e565b95506020870135945060408701359350606087013560ff81168114613a64578283fd5b9598949750929560808101359460a0909101359350915050565b600060208284031215613a8f578081fd5b5035919050565b60008060408385031215613aa8578182fd5b8235915060208084013567ffffffffffffffff80821115613ac7578384fd5b818601915086601f830112613ada578384fd5b813581811115613ae657fe5b604051601f8201601f1916810185018381118282101715613b0357fe5b6040528181528382018501891015613b19578586fd5b81858501868301378585838301015280955050505050509250929050565b60008060408385031215613b49578182fd5b50508035926020909101359150565b600080600080600060a08688031215613b6f578081fd5b505083359560208501359550604085013594606081013594506080013592509050565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b901515815260200190565b6000602080835283518082850152825b81811015613c0157858101830151858201604001528201613be5565b81811115613c125783604083870101525b50601f01601f1916929092016040019392505050565b6020808252603d908201527f4e46544d61726b65745265736572766541756374696f6e3a205265736572766560408201527f207072696365206d757374206265206174206c65617374203120776569000000606082015260800190565b6020808252602b908201527f4e46544d61726b65745265736572766541756374696f6e3a2042696420616d6f60408201527f756e7420746f6f206c6f77000000000000000000000000000000000000000000606082015260800190565b6020808252603f908201527f4e46544d61726b65745265736572766541756374696f6e3a20496e636c75646560408201527f206120726561736f6e20666f7220746869732063616e63656c6c6174696f6e00606082015260800190565b60208082526029908201527f4e46544d61726b65745265736572766541756374696f6e3a204e6f7420796f7560408201527f722061756374696f6e0000000000000000000000000000000000000000000000606082015260800190565b6020808252602a908201527f4e46544d61726b65745265736572766541756374696f6e3a2041756374696f6e60408201527f206e6f7420666f756e6400000000000000000000000000000000000000000000606082015260800190565b6020808252603f908201527f4e46544d61726b65745265736572766541756374696f6e3a20426964206d757360408201527f74206265206174206c6561737420746865207265736572766520707269636500606082015260800190565b60208082526028908201527f4e46544d61726b65745265736572766541756374696f6e3a2041756374696f6e60408201527f206973206f766572000000000000000000000000000000000000000000000000606082015260800190565b6020808252603c908201527f4e46544d61726b65745265736572766541756374696f6e3a2041756374696f6e60408201527f206e6f7420637265617465642062792074686174206164647265737300000000606082015260800190565b6020808252602c908201527f4e46544d61726b65745265736572766541756374696f6e3a2041756374696f6e60408201527f20696e2070726f67726573730000000000000000000000000000000000000000606082015260800190565b60208082526036908201527f4e46544d61726b65745265736572766541756374696f6e3a204d696e20696e6360408201527f72656d656e74206d757374206265203c3d203130302500000000000000000000606082015260800190565b6020808252603f908201527f4e46544d61726b65745265736572766541756374696f6e3a204475726174696f60408201527f6e206d757374206265203e3d20455854454e53494f4e5f4455524154494f4e00606082015260800190565b60208082526036908201527f4e46544d61726b65745265736572766541756374696f6e3a204475726174696f60408201527f6e206d757374206265203c3d2031303030206461797300000000000000000000606082015260800190565b6020808252603c908201527f4e46544d61726b65745265736572766541756374696f6e3a20596f7520616c7260408201527f65616479206861766520616e206f75747374616e64696e672062696400000000606082015260800190565b60208082526032908201527f4e46544d61726b65745265736572766541756374696f6e3a2041756374696f6e60408201527f207374696c6c20696e2070726f67726573730000000000000000000000000000606082015260800190565b60208082526034908201527f4e46544d61726b65745265736572766541756374696f6e3a2041756374696f6e60408201527f2077617320616c726561647920736574746c6564000000000000000000000000606082015260800190565b6000610100820190506001600160a01b0380845116835260208401516020840152806040850151166040840152606084015160608401526080840151608084015260a084015160a08401528060c08501511660c08401525060e083015160e083015292915050565b90815260200190565b948552602085019390935260408401919091526060830152608082015260a00190565b918252602082015260400190565b9283526020830191909152604082015260600190565b93845260208401929092526040830152606082015260800190565b6001600160a01b038116811461428357600080fd5b5056fe4163636f756e744d6967726174696f6e3a205369676e6174757265206d7573742062652066726f6d20746865206f726967696e616c206163636f756e744920617574686f72697a6520466f756e646174696f6e20746f206d696772617465206d79206163636f756e7420746f20466f756e646174696f6e54726561737572794e6f64653a2041646472657373206973206e6f74206120636f6e7472616374416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d6179206861766520726576657274656445434453413a20696e76616c6964207369676e6174757265202773272076616c7565466f756e646174696f6e41646d696e526f6c653a2063616c6c657220646f6573206e6f742068617665207468652041646d696e20726f6c65496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a656445434453413a20696e76616c6964207369676e6174757265202776272076616c7565536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774163636f756e744d6967726174696f6e3a2043616e6e6f74206d69677261746520746f207468652073616d65206163636f756e744e46544d61726b65745072697661746553616c653a20494e56414c49445f5349474e41545552454163636f756e744d6967726174696f6e3a2043616c6c6572206973206e6f7420616e206f70657261746f72a26469706673582212209bbf621f62df75a7624961530698622fb0a29b912e6d6de52f6d479ae079d96464736f6c63430007060033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 27 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.