Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 135 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Team Mint | 19142073 | 362 days ago | IN | 0 ETH | 0.01988729 | ||||
Purchase MMM | 19101716 | 368 days ago | IN | 0.4 ETH | 0.00633027 | ||||
Purchase MMM | 19099945 | 368 days ago | IN | 0.04 ETH | 0.00249806 | ||||
Purchase MMM | 19091977 | 369 days ago | IN | 0.04 ETH | 0.00484137 | ||||
Purchase MMM | 19036097 | 377 days ago | IN | 0.12 ETH | 0.01105634 | ||||
Purchase MMM | 19006849 | 381 days ago | IN | 0.4 ETH | 0.01239049 | ||||
Purchase MMM | 18998407 | 382 days ago | IN | 0.4 ETH | 0.01016769 | ||||
Purchase MMM | 18997779 | 382 days ago | IN | 0.36 ETH | 0.00744585 | ||||
Purchase MMM | 18996395 | 383 days ago | IN | 0.08 ETH | 0.00440856 | ||||
Purchase MMM | 18994594 | 383 days ago | IN | 0.04 ETH | 0.00381997 | ||||
Purchase MMM | 18993148 | 383 days ago | IN | 0.04 ETH | 0.00461118 | ||||
Purchase MMM | 18991481 | 383 days ago | IN | 0.2 ETH | 0.0098425 | ||||
Purchase MMM | 18991194 | 383 days ago | IN | 0.04 ETH | 0.00670814 | ||||
Purchase MMM | 18991030 | 383 days ago | IN | 0.04 ETH | 0.005989 | ||||
Purchase MMM | 18990697 | 383 days ago | IN | 0.04 ETH | 0.00546837 | ||||
Purchase MMM | 18987926 | 384 days ago | IN | 0.16 ETH | 0.00627135 | ||||
Purchase MMM | 18987914 | 384 days ago | IN | 0.04 ETH | 0.00368301 | ||||
Purchase MMM | 18987898 | 384 days ago | IN | 0.04 ETH | 0.00422726 | ||||
Purchase MMM | 18969070 | 386 days ago | IN | 0.04 ETH | 0.00337134 | ||||
Purchase MMM | 18966382 | 387 days ago | IN | 0.04 ETH | 0.00382135 | ||||
Purchase MMM | 18965382 | 387 days ago | IN | 0.04 ETH | 0.00493648 | ||||
Purchase MMM | 18965356 | 387 days ago | IN | 0.04 ETH | 0.00585395 | ||||
Purchase MMM | 18964940 | 387 days ago | IN | 0.04 ETH | 0.00780366 | ||||
Purchase MMM | 18963154 | 387 days ago | IN | 0.08 ETH | 0.00637041 | ||||
Purchase MMM | 18963118 | 387 days ago | IN | 0.08 ETH | 0.00572111 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
19101716 | 368 days ago | 0.108 ETH | ||||
19101716 | 368 days ago | 0.252 ETH | ||||
19101716 | 368 days ago | 0.04 ETH | ||||
19099945 | 368 days ago | 0.0108 ETH | ||||
19099945 | 368 days ago | 0.0252 ETH | ||||
19099945 | 368 days ago | 0.004 ETH | ||||
19091977 | 369 days ago | 0.0108 ETH | ||||
19091977 | 369 days ago | 0.0252 ETH | ||||
19091977 | 369 days ago | 0.004 ETH | ||||
19036097 | 377 days ago | 0.0324 ETH | ||||
19036097 | 377 days ago | 0.0756 ETH | ||||
19036097 | 377 days ago | 0.012 ETH | ||||
19006849 | 381 days ago | 0.108 ETH | ||||
19006849 | 381 days ago | 0.252 ETH | ||||
19006849 | 381 days ago | 0.04 ETH | ||||
18998407 | 382 days ago | 0.108 ETH | ||||
18998407 | 382 days ago | 0.252 ETH | ||||
18998407 | 382 days ago | 0.04 ETH | ||||
18997779 | 382 days ago | 0.0972 ETH | ||||
18997779 | 382 days ago | 0.2268 ETH | ||||
18997779 | 382 days ago | 0.036 ETH | ||||
18996395 | 383 days ago | 0.0216 ETH | ||||
18996395 | 383 days ago | 0.0504 ETH | ||||
18996395 | 383 days ago | 0.008 ETH | ||||
18994594 | 383 days ago | 0.0108 ETH |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
MultiMerkleMinterV1
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
No with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity 0.8.17; // Created By: @backseats_eth // Forked from and inspired by ArtBlocks' MerkleMinterV1 contract // https://github.com/ArtBlocks/artblocks-contracts/blob/32738da594e7b9d18e25011b1c7fefa4abb1bda9/contracts/archive/minter-suite/Minters/MinterMerkle/MinterMerkleV1.sol import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import { MerkleProof } from "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol"; import { ReentrancyGuard } from "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import "./interfaces/IGenArt721CoreContractV3_Base.sol"; import "./interfaces/IFilteredMinterMerkleV2.sol"; import "./interfaces/IMinterFilterV0.sol"; import "./MinterBase_v0_1_1.sol"; /** * @title Filtered Minter contract that allows tokens to be minted with ETH * for addresses in a Merkle allowlist. * This is designed to be used with GenArt721CoreContractV3 flagship or * engine contracts. * @notice Privileged Roles and Ownership: * This contract is designed to be managed, with limited powers. * Privileged roles and abilities are controlled by the project's artist, which * can be modified by the core contract's Admin ACL contract. Both of these * roles hold extensive power and can modify minter details. * Care must be taken to ensure that the admin ACL contract and artist * addresses are secure behind a multi-sig or other access control mechanism. * ---------------------------------------------------------------------------- * The following functions are restricted to a project's artist: * - createNewStage * - manuallyLimitProjectMaxInvocations * - setProjectMaxInvocations * - teamMint * - updateMerkleRoot * - updatePricePerTokenInWei * - updateSystemAddress * ---------------------------------------------------------------------------- * Additional admin and artist privileged roles may be described on other * contracts that this minter integrates with. * ---------------------------------------------------------------------------- */ contract MultiMerkleMinterV1 is ReentrancyGuard, MinterBase, IFilteredMinterMerkleV2 { using MerkleProof for bytes32[]; using ECDSA for bytes32; // Used for unneeded protocol-conformance functions error ActionNotSupported(); /*////////////////////////////////////////////////////////////// STORAGE //////////////////////////////////////////////////////////////*/ /// Core contract address this minter interacts with address public immutable genArt721CoreAddress; /// The core contract integrates with V3 contracts IGenArt721CoreContractV3_Base private immutable genArtCoreContract_Base; /// Minter filter address this minter interacts with address public immutable minterFilterAddress; /// Minter filter this minter may interact with. IMinterFilterV0 private immutable minterFilter; /// minterType for this minter string public constant minterType = "MultiMerkleMinterV1"; /// The theoretical total number of tokens that can be minted for a project on GenArt721Core uint256 constant ONE_MILLION = 1_000_000; // A mapping of project ids to their Project Config mapping(uint256 => ProjectConfig) public projectConfig; /*////////////////////////////////////////////////////////////// STRUCTS //////////////////////////////////////////////////////////////*/ // A ProjectConfig is specific to the MultiMerkleMinter so that it can be re-used to mint // multiple GenArtCoreV3-conforming projects struct ProjectConfig { // If the project has minted out bool maxHasBeenInvoked; // If the creator or artist has configured the price bool priceIsConfigured; // The id of the current stage of the mint. If 0, the project is minted out or not started uint8 currentStageId; // The count of the stages for the project. Starts at 0 for no Stages created uint8 stagesCount; // The maximum amount of tokens that can be minted for the project uint24 maxInvocations; // Which system address is the signer for the project id address systemAddress; // If a nonce has been used or not to mint the project mapping(string => bool) usedNonces; // How many times an address has minted for the project at this Stage mapping(uint8 => mapping(address => uint)) addressMintedCount; // A mapping of the id of the Stage to the Stage, sequentially from 1. mapping(uint8 => Stage) stages; } struct Stage { // The id of the Stage. Starts at 1. 0 is the null state uint8 id; // The maximum amount of tokens a wallet can mint in that stage uint8 transactionMaxInvocations; // The Unix timestamp of when the stage starts. Suffers from the 2038 problem but we'll be fine uint32 stageStartTime; // Optional Merkle Root. Use 0x if not used bytes32 merkleRoot; // The price of the token for that stage uint256 pricePerTokenInWei; } /*////////////////////////////////////////////////////////////// MODIFIER //////////////////////////////////////////////////////////////*/ modifier onlyArtist(uint256 _projectId) { require(msg.sender == genArtCoreContract_Base.projectIdToArtistAddress(_projectId), "Only Artist"); _; } /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ /** * @notice Initializes contract to be a Filtered Minter for * `_minterFilter`, integrated with Art Blocks core contract * at address `_genArt721Address`. * @param _genArt721Address Art Blocks core contract address for * which this contract will be a minter. * @param _minterFilter Minter filter for which this will be a * filtered minter. */ constructor( address _genArt721Address, address _minterFilter ) ReentrancyGuard() MinterBase(_genArt721Address) { genArt721CoreAddress = _genArt721Address; // always populate immutable engine contracts, but only use appropriate // interface based on isEngine in the rest of the contract genArtCoreContract_Base = IGenArt721CoreContractV3_Base( _genArt721Address ); minterFilterAddress = _minterFilter; minterFilter = IMinterFilterV0(_minterFilter); require(minterFilter.genArt721CoreAddress() == _genArt721Address, "Illegal Contract Pairing"); } /** * @notice Update the Merkle root for project `_projectId`. * @param _projectId Project ID to be updated. * @param _stageId Stage ID to be updated. * @param _root root of Merkle tree defining addresses allowed to mint * on project `_projectId`. */ function updateMerkleRoot( uint256 _projectId, uint8 _stageId, bytes32 _root ) external onlyArtist(_projectId) { ProjectConfig storage _projectConfig = projectConfig[_projectId]; _projectConfig.stages[_stageId].merkleRoot = _root; } function updateStartingTimeForStage( uint256 _projectId, uint8 _stageId, uint32 _newStartingTime ) external onlyArtist(_projectId) { require(_stageId > 0, "Can't be 0"); ProjectConfig storage _projectConfig = projectConfig[_projectId]; require(_projectConfig.stagesCount > 0, "No Stages exist for project"); require(_newStartingTime > 0, "Can't be 0"); require(_newStartingTime > block.timestamp, "Must be in the future"); require(_stageId <= _projectConfig.stagesCount, "Stage doesn't exist"); if (_stageId == _projectConfig.stagesCount) { _projectConfig.stages[_stageId].stageStartTime = _newStartingTime; } else if (_stageId + 1 <= _projectConfig.stagesCount) { // Ensure future stage exists and it doesn't collide Stage memory futureStage = _projectConfig.stages[_stageId + 1]; require(_newStartingTime < futureStage.stageStartTime, "Stage can't start after next one"); _projectConfig.stages[_stageId].stageStartTime = _newStartingTime; } } /** * @notice Returns hashed address (to be used as merkle tree leaf). * Included as a public function to enable users to calculate their hashed * address in Solidity when generating proofs off-chain. * @param _address address to be hashed * @return bytes32 hashed address, via keccak256 (using encodePacked) */ function hashAddress(address _address) public pure returns (bytes32) { return keccak256(abi.encodePacked(_address)); } /** * @notice Verify if address is allowed to mint on project `_projectId`. * @param _merkleRoot The Merkle root for the project. * @param _proof Merkle proof for address. * @param _address Addrexss to check. * @return inAllowlist true only if address is allowed to mint and valid * Merkle proof was provided */ function verifyAddress( bytes32 _merkleRoot, bytes32[] calldata _proof, address _address ) public pure returns (bool) { return _proof.verifyCalldata(_merkleRoot, hashAddress(_address)); } /** * @notice Syncs local maximum invocations of project `_projectId` based on * the value currently defined in the core contract. * @param _projectId Project ID to set the maximum invocations for. * @dev this enables gas reduction after maxInvocations have been reached - * core contracts shall still enforce a maxInvocation check during mint. */ function setProjectMaxInvocations(uint256 _projectId) external onlyArtist(_projectId) { uint256 maxInvocations; uint256 invocations; (invocations, maxInvocations, , , , ) = genArtCoreContract_Base .projectStateData(_projectId); // update storage with results projectConfig[_projectId].maxInvocations = uint24(maxInvocations); // We need to ensure maxHasBeenInvoked is correctly set after manually syncing the // local maxInvocations value with the core contract's maxInvocations value. // This synced value of maxInvocations from the core contract will always be greater // than or equal to the previous value of maxInvocations stored locally. projectConfig[_projectId].maxHasBeenInvoked = invocations == maxInvocations; emit ProjectMaxInvocationsLimitUpdated(_projectId, maxInvocations); } /** * @notice Manually sets the local maximum invocations of project `_projectId` * with the provided `_maxInvocations`, checking that `_maxInvocations` is less * than or equal to the value of project `_project_id`'s maximum invocations that is * set on the core contract. * @dev Note that a `_maxInvocations` of 0 can only be set if the current `invocations` * value is also 0 and this would also set `maxHasBeenInvoked` to true, correctly short-circuiting * this minter's purchase function, avoiding extra gas costs from the core contract's maxInvocations check. * @param _projectId Project ID to set the maximum invocations for. * @param _maxInvocations Maximum invocations to set for the project. */ function manuallyLimitProjectMaxInvocations( uint256 _projectId, uint256 _maxInvocations ) external onlyArtist(_projectId) { // CHECKS // ensure that the manually set maxInvocations is not greater than what is set on the core contract uint256 maxInvocations; uint256 invocations; (invocations, maxInvocations, , , , ) = genArtCoreContract_Base.projectStateData(_projectId); require( _maxInvocations <= maxInvocations, "Cannot increase project max invocations above core contract set project max invocations" ); require( _maxInvocations >= invocations, "Cannot set project max invocations to less than current invocations" ); // EFFECTS // update storage with results projectConfig[_projectId].maxInvocations = uint24(_maxInvocations); // We need to ensure maxHasBeenInvoked is correctly set after manually setting the // local maxInvocations value. projectConfig[_projectId].maxHasBeenInvoked = invocations == _maxInvocations; emit ProjectMaxInvocationsLimitUpdated(_projectId, _maxInvocations); } /** * @notice projectId => has project reached its maximum number of * invocations? Note that this returns a local cache of the core contract's * state, and may be out of sync with the core contract. This is * intentional, as it only enables gas optimization of mints after a * project's maximum invocations has been reached. A false negative will * only result in a gas cost increase, since the core contract will still * enforce a maxInvocation check during minting. A false positive is not * possible because the V3 core contract only allows maximum invocations * to be reduced, not increased. Based on this rationale, we intentionally * do not do input validation in this method as to whether or not the input * `_projectId` is an existing project ID. */ function projectMaxHasBeenInvoked( uint256 _projectId ) external view returns (bool) { return projectConfig[_projectId].maxHasBeenInvoked; } // Returns the number of tokens minted for an address for a project id function getAddressMintedCount(uint256 _projectId, uint8 _stageId, address _address) external view returns (uint) { return projectConfig[_projectId].addressMintedCount[_stageId][_address]; } /** * @notice projectId => project's maximum number of invocations. * Optionally synced with core contract value, for gas optimization. * Note that this returns a local cache of the core contract's * state, and may be out of sync with the core contract. This is * intentional, as it only enables gas optimization of mints after a * project's maximum invocations has been reached. * @dev A number greater than the core contract's project max invocations * will only result in a gas cost increase, since the core contract will * still enforce a maxInvocation check during minting. A number less than * the core contract's project max invocations is only possible when the * project's max invocations have not been synced on this minter, since the * V3 core contract only allows maximum invocations to be reduced, not * increased. When this happens, the minter will enable minting, allowing * the core contract to enforce the max invocations check. Based on this * rationale, we intentionally do not do input validation in this method as * to whether or not the input `_projectId` is an existing project ID. */ function projectMaxInvocations( uint256 _projectId ) external view returns (uint256) { return uint256(projectConfig[_projectId].maxInvocations); } /** * @notice Updates this minter's price per token of project `_projectId` * to be '_pricePerTokenInWei`, in Wei. * This price supersedes any legacy core contract price per token value. * @dev Note that it is intentionally supported here that the configured * price may be explicitly set to `0`. */ function updatePricePerTokenInWei( uint256 _projectId, uint8 _stageId, uint256 _pricePerTokenInWei ) external onlyArtist(_projectId) { ProjectConfig storage _projectConfig = projectConfig[_projectId]; _projectConfig.priceIsConfigured = true; _projectConfig.stages[_stageId].pricePerTokenInWei = _pricePerTokenInWei; } /** * @notice Purchases 1 or more tokens from a project * @param _projectId The project id * @param _amount The number of tokens to purchase * @param _signature A signature, generated from the minting site * @param _data abi-encoded data, generated from the minting site * @param _nonce A nonce, to accompany the signature */ function purchaseMMM( uint256 _projectId, uint256 _amount, bytes calldata _signature, bytes calldata _data, bytes32[] calldata _merkleProof, string calldata _nonce ) public payable nonReentrant() { uint256 pid = _projectId; uint256 amount = _amount; bytes memory sig = _signature; // CHECKS ProjectConfig storage _projectConfig = projectConfig[pid]; // Note that `maxHasBeenInvoked` is only checked here to reduce gas // consumption after a project has been fully minted. // `_projectConfig.maxHasBeenInvoked` is locally cached to reduce // gas consumption, but if not in sync with the core contract's value, // the core contract also enforces its own max invocation check during // minting. require(!_projectConfig.maxHasBeenInvoked, "Max Invocations Reached"); // Gets the current Stage by timestamp Stage memory _currentStage = currentStage(pid); // If what we have set in storage is not the current Stage, update it if (_projectConfig.currentStageId != _currentStage.id) { _projectConfig.currentStageId = _currentStage.id; } // See function `createNewStage` require(_currentStage.stageStartTime != 0, "Create A Stage To Begin"); // require artist to have configured price of token on this minter require(_projectConfig.priceIsConfigured, "Price Not Configured"); // Check the price is correct uint256 expectedPrice = currentStagePrice(pid) * amount; require(msg.value == expectedPrice, "Wrong Price"); // Ensure the nonce coming from the server hasn't already been used require(!_projectConfig.usedNonces[_nonce], "Nonce Used"); // Ensure the data signed from the server is valid require(isValidSignature( _projectConfig.systemAddress, keccak256(abi.encodePacked(msg.sender, amount, _nonce)), sig), "Invalid Signature" ); // Decode a tuple of the address and the max they can mint and ensure the data coming from the server is correct (address _address, uint256 maxMintCount) = abi.decode(_data, (address, uint256)); require(_address == msg.sender, "Bad Data"); // If server sends through a maxMintCount > 0, check how many they've minted this stage bool doMaxCheckForStage = maxMintCount > 0; // Check to see if the msg.sender is on the allowlist if the Stage has an allowlist. First checks to see if the merkle root is the 0 address if (address(uint160(uint256(currentStage(pid).merkleRoot))) != address(0)) { bytes32 leaf = keccak256(abi.encodePacked(msg.sender)); require(MerkleProof.verify(_merkleProof, _currentStage.merkleRoot, leaf), "Not On Allowlist"); } // Ensure the amount they're minting doesn't exceed their max for the stage if (doMaxCheckForStage) { require(_projectConfig.addressMintedCount[_currentStage.id][msg.sender] + amount <= maxMintCount, "Can't Mint That Many"); } // Update the record of the nonce and the overall msg.sender mint count _projectConfig.usedNonces[_nonce] = true; // Increment user's minted count for this project unchecked { _projectConfig.addressMintedCount[_currentStage.id][msg.sender] += amount; } // Mint tokens uint i; do { uint256 tokenId = minterFilter.mint(msg.sender, pid, msg.sender); // If the max has been reached, set the flag to true unchecked { if (tokenId % ONE_MILLION == _projectConfig.maxInvocations - 1) { _projectConfig.maxHasBeenInvoked = true; // If minted out, set this to 0. _projectConfig.currentStageId = 0; } } unchecked { ++i; } } while (i < amount); // INTERACTIONS splitFundsETH(pid, msg.value, genArt721CoreAddress); } function teamMint( uint256 _projectId, address[] calldata _addresses, uint256[] calldata _counts ) external onlyArtist(_projectId) { require(_addresses.length == _counts.length, "Unequal arrays"); uint256 length = _addresses.length; // Outer loop iterator uint256 i; // Inner loop iterator uint256 n; // Loops through the addresses do { // Loops through the tokens to mint the address do { // This will fail in the underlying contract if exceeds project invocations minterFilter.mint(_addresses[i], _projectId, msg.sender); unchecked { ++n; } } while (n < _counts[i]); unchecked { ++i; } } while (i < length); } function createNewStage( uint256 _projectId, uint32 _stageStartTime, bytes32 _merkleRoot, uint256 _pricePerTokenInWei, uint8 _transactionMaxInvocations ) onlyArtist(_projectId) external { // Ensure the Stage start time is in the future require(_stageStartTime > block.timestamp, "No Start Block In Past"); // Get ProjectConfig from mapping ProjectConfig storage config = projectConfig[_projectId]; // Don't create a new Stage if minted out require(!config.maxHasBeenInvoked, "Minted Out Cant Create New Stage"); // Start the `stages` mapping IDs at 1 so that 0 can be a null state // Set the ProjectConfig's `priceIsConfigured` if this is the first Stage uint8 nextStageId; if (config.stagesCount == 0) { nextStageId = 1; config.priceIsConfigured = true; } else { nextStageId = config.stagesCount + 1; } // Increment the ProjectConfig's Stages count (i.e. 2 stages, stagesCount = 2) unchecked { ++config.stagesCount; } // Store the new Stage config.stages[nextStageId] = Stage({ id: nextStageId, transactionMaxInvocations: _transactionMaxInvocations, stageStartTime: _stageStartTime, merkleRoot: _merkleRoot, pricePerTokenInWei: _pricePerTokenInWei }); } // Returns an array of all of the Stages for a given Project id function allStages(uint256 _projectId) public view returns (Stage[] memory) { ProjectConfig storage config = projectConfig[_projectId]; // i.e. 2 stages, length = 2 uint8 length = config.stagesCount; Stage[] memory stages = new Stage[](length); for(uint8 i; i < length;) { // Add 1 to `i` here because Stages start at 1; 0 is the null state stages[i] = getStage(_projectId, i + 1); unchecked { ++i; } } return stages; } function getStage(uint256 _productId, uint8 _stageId) public view returns (Stage memory) { return projectConfig[_productId].stages[_stageId]; } // Returns the current Stage in progress for a mint. If a Project is finished, it will return an empty Stage function currentStage(uint256 _projectId) public view returns (Stage memory) { Stage[] memory _stages = allStages(_projectId); // 0 indexed uint length = _stages.length; for(uint i; i < length;) { if (block.timestamp >= _stages[i].stageStartTime) { // If there is no subsequent stage, return the current one if (i + 1 >= length) { return _stages[i]; } // If the next stage's start time is in the future, return the current one if (block.timestamp < _stages[i + 1].stageStartTime) { return _stages[i]; } } unchecked { ++i; } } Stage memory empty; return empty; } // Returns the current Stage's id function currentStageId(uint256 _projectId) public view returns (uint8) { return currentStage(_projectId).id; } // Returns the current Stage price in wei function currentStagePrice(uint256 _projectId) public view returns (uint256) { return currentStage(_projectId).pricePerTokenInWei; } // Returns the next Stage as a struct function nextStage(uint256 _projectId) public view returns (Stage memory) { ProjectConfig storage config = projectConfig[_projectId]; Stage memory _currentStage = currentStage(_projectId); if (_currentStage.id == 0) { return _currentStage; } else if (config.stages[config.currentStageId + 1].id != 0) { return config.stages[config.currentStageId + 1]; } else { Stage memory empty; return empty; } } // Returns the next Stage's price in wei function nextStagePrice(uint256 _projectId) external view returns (uint256) { return nextStage(_projectId).pricePerTokenInWei; } // Returns the next stage start time as a Unix timestamp in seconds function startingTimeOfNextStage(uint256 _projectId) external view returns (uint256) { return nextStage(_projectId).stageStartTime; } /** * @notice Process proof for an address. Returns Merkle root. Included to * enable users to easily verify a proof's validity. * @param _proof Merkle proof for address. * @param _address Address to process. * @return merkleRoot Merkle root for `_address` and `_proof` */ function processProofForAddress( bytes32[] calldata _proof, address _address ) external pure returns (bytes32) { return _proof.processProofCalldata(hashAddress(_address)); } /** * @notice Gets if price of token is configured, price of minting a * token on project `_projectId`, and currency symbol and address to be * used as payment. Supersedes any core contract price information. * @param _projectId Project ID to get price information for. * @return isConfigured true only if token price has been configured on * this minter * @return tokenPriceInWei current price of token on this minter - invalid * if price has not yet been configured * @return currencySymbol currency symbol for purchases of project on this * minter. This minter always returns "ETH" * @return currencyAddress currency address for purchases of project on * this minter. This minter always returns null address, reserved for ether */ function getPriceInfo(uint256 _projectId) external view returns ( bool isConfigured, uint256 tokenPriceInWei, string memory currencySymbol, address currencyAddress ) { ProjectConfig storage _projectConfig = projectConfig[_projectId]; isConfigured = _projectConfig.priceIsConfigured; tokenPriceInWei = currentStagePrice(_projectId); currencySymbol = "ETH"; currencyAddress = address(0); } function updateSystemAddress(uint256 _projectId, address _address) external onlyArtist(_projectId) { ProjectConfig storage _projectConfig = projectConfig[_projectId]; _projectConfig.systemAddress = _address; } /// @notice Checks if the private key that singed the nonce matches the system address of the contract function isValidSignature( address _systemAddress, bytes32 hash, bytes memory signature ) internal pure returns (bool) { // Artist Owner should call `updateSystemAddress` with // the address corresponding to the private key that // signs the data payload from the backend being fed into the mint function. require(_systemAddress != address(0), "Missing System Address"); bytes32 signedHash = hash.toEthSignedMessageHash(); return signedHash.recover(signature) == _systemAddress; } /*////////////////////////////////////////////////////////////// UNSUPPORTED //////////////////////////////////////////////////////////////*/ /** * @notice Inactive function - requires Merkle proof to purchase. */ function purchase(uint256) external payable returns (uint256) { revert ActionNotSupported(); } /** * @notice Inactive function - requires Merkle proof to purchase. */ function purchaseTo(address, uint256) public payable returns (uint256) { revert ActionNotSupported(); } /** * @notice Inactive function */ function purchase(uint256, bytes32[] calldata) external payable returns (uint256) { revert ActionNotSupported(); } /** * @notice Inactive function */ function purchaseTo(address, uint256, bytes32[] calldata) external payable returns (uint256) { revert ActionNotSupported(); } /** * @notice Inactive function */ function togglePurchaseToDisabled(uint256) external pure { revert ActionNotSupported(); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be _NOT_ENTERED require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.0; import "../Strings.sol"; /** * @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 { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS, InvalidSignatureV // Deprecated in v4.8 } function _throwError(RecoverError error) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert("ECDSA: invalid signature"); } else if (error == RecoverError.InvalidSignatureLength) { revert("ECDSA: invalid signature length"); } else if (error == RecoverError.InvalidSignatureS) { revert("ECDSA: invalid signature 's' value"); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature` or error string. 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. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength); } } /** * @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) { (address recovered, RecoverError error) = tryRecover(hash, signature); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] * * _Available since v4.3._ */ function tryRecover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address, RecoverError) { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. * * _Available since v4.2._ */ function recover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, r, vs); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. * * _Available since v4.3._ */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError) { // 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 (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature); } return (signer, RecoverError.NoError); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, v, r, s); _throwError(error); return recovered; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * 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)); } /** * @dev Returns an Ethereum Signed Message, created from `s`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol) pragma solidity ^0.8.0; /** * @dev These functions deal with verification of Merkle Tree proofs. * * The tree and the proofs can be generated using our * https://github.com/OpenZeppelin/merkle-tree[JavaScript library]. * You will find a quickstart guide in the readme. * * WARNING: You should avoid using leaf values that are 64 bytes long prior to * hashing, or use a hash function other than keccak256 for hashing leaves. * This is because the concatenation of a sorted pair of internal nodes in * the merkle tree could be reinterpreted as a leaf value. * OpenZeppelin's JavaScript library generates merkle trees that are safe * against this attack out of the box. */ library MerkleProof { /** * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree * defined by `root`. For this, a `proof` must be provided, containing * sibling hashes on the branch from the leaf to the root of the tree. Each * pair of leaves and each pair of pre-images are assumed to be sorted. */ function verify( bytes32[] memory proof, bytes32 root, bytes32 leaf ) internal pure returns (bool) { return processProof(proof, leaf) == root; } /** * @dev Calldata version of {verify} * * _Available since v4.7._ */ function verifyCalldata( bytes32[] calldata proof, bytes32 root, bytes32 leaf ) internal pure returns (bool) { return processProofCalldata(proof, leaf) == root; } /** * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt * hash matches the root of the tree. When processing the proof, the pairs * of leafs & pre-images are assumed to be sorted. * * _Available since v4.4._ */ function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { computedHash = _hashPair(computedHash, proof[i]); } return computedHash; } /** * @dev Calldata version of {processProof} * * _Available since v4.7._ */ function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { computedHash = _hashPair(computedHash, proof[i]); } return computedHash; } /** * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}. * * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details. * * _Available since v4.7._ */ function multiProofVerify( bytes32[] memory proof, bool[] memory proofFlags, bytes32 root, bytes32[] memory leaves ) internal pure returns (bool) { return processMultiProof(proof, proofFlags, leaves) == root; } /** * @dev Calldata version of {multiProofVerify} * * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details. * * _Available since v4.7._ */ function multiProofVerifyCalldata( bytes32[] calldata proof, bool[] calldata proofFlags, bytes32 root, bytes32[] memory leaves ) internal pure returns (bool) { return processMultiProofCalldata(proof, proofFlags, leaves) == root; } /** * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false * respectively. * * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer). * * _Available since v4.7._ */ function processMultiProof( bytes32[] memory proof, bool[] memory proofFlags, bytes32[] memory leaves ) internal pure returns (bytes32 merkleRoot) { // This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of // the merkle tree. uint256 leavesLen = leaves.length; uint256 totalHashes = proofFlags.length; // Check proof validity. require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof"); // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". bytes32[] memory hashes = new bytes32[](totalHashes); uint256 leafPos = 0; uint256 hashPos = 0; uint256 proofPos = 0; // At each step, we compute the next hash using two values: // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we // get the next hash. // - depending on the flag, either another value for the "main queue" (merging branches) or an element from the // `proof` array. for (uint256 i = 0; i < totalHashes; i++) { bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++]; hashes[i] = _hashPair(a, b); } if (totalHashes > 0) { return hashes[totalHashes - 1]; } else if (leavesLen > 0) { return leaves[0]; } else { return proof[0]; } } /** * @dev Calldata version of {processMultiProof}. * * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details. * * _Available since v4.7._ */ function processMultiProofCalldata( bytes32[] calldata proof, bool[] calldata proofFlags, bytes32[] memory leaves ) internal pure returns (bytes32 merkleRoot) { // This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of // the merkle tree. uint256 leavesLen = leaves.length; uint256 totalHashes = proofFlags.length; // Check proof validity. require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof"); // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". bytes32[] memory hashes = new bytes32[](totalHashes); uint256 leafPos = 0; uint256 hashPos = 0; uint256 proofPos = 0; // At each step, we compute the next hash using two values: // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we // get the next hash. // - depending on the flag, either another value for the "main queue" (merging branches) or an element from the // `proof` array. for (uint256 i = 0; i < totalHashes; i++) { bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++]; hashes[i] = _hashPair(a, b); } if (totalHashes > 0) { return hashes[totalHashes - 1]; } else if (leavesLen > 0) { return leaves[0]; } else { return proof[0]; } } function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) { return a < b ? _efficientHash(a, b) : _efficientHash(b, a); } function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) { /// @solidity memory-safe-assembly assembly { mstore(0x00, a) mstore(0x20, b) value := keccak256(0x00, 0x40) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv( uint256 x, uint256 y, uint256 denominator, Rounding rounding ) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10**64) { value /= 10**64; result += 64; } if (value >= 10**32) { value /= 10**32; result += 32; } if (value >= 10**16) { value /= 10**16; result += 16; } if (value >= 10**8) { value /= 10**8; result += 8; } if (value >= 10**4) { value /= 10**4; result += 4; } if (value >= 10**2) { value /= 10**2; result += 2; } if (value >= 10**1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/Math.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } }
// SPDX-License-Identifier: LGPL-3.0-only // Created By: Art Blocks Inc. pragma solidity ^0.8.0; interface IAdminACLV0 { /** * @notice Token ID `_tokenId` minted to `_to`. * @param previousSuperAdmin The previous superAdmin address. * @param newSuperAdmin The new superAdmin address. * @param genArt721CoreAddressesToUpdate Array of genArt721Core * addresses to update to the new superAdmin, for indexing purposes only. */ event SuperAdminTransferred( address indexed previousSuperAdmin, address indexed newSuperAdmin, address[] genArt721CoreAddressesToUpdate ); /// Type of the Admin ACL contract, e.g. "AdminACLV0" function AdminACLType() external view returns (string memory); /// super admin address function superAdmin() external view returns (address); /** * @notice Calls transferOwnership on other contract from this contract. * This is useful for updating to a new AdminACL contract. * @dev this function should be gated to only superAdmin-like addresses. */ function transferOwnershipOn( address _contract, address _newAdminACL ) external; /** * @notice Calls renounceOwnership on other contract from this contract. * @dev this function should be gated to only superAdmin-like addresses. */ function renounceOwnershipOn(address _contract) external; /** * @notice Checks if sender `_sender` is allowed to call function with selector * `_selector` on contract `_contract`. */ function allowed( address _sender, address _contract, bytes4 _selector ) external returns (bool); }
// SPDX-License-Identifier: LGPL-3.0-only // Created By: Art Blocks Inc. import "./IFilteredMinterV1.sol"; pragma solidity ^0.8.0; /** * @title This interface extends the IFilteredMinterV1 interface in order to * add support for including Merkle proofs when purchasing. * @author Art Blocks Inc. */ interface IFilteredMinterMerkleV0 is IFilteredMinterV1 { /** * @notice Notifies of the contract's default maximum mints allowed per * user for a given project, on this minter. This value can be overridden * by the artist of any project at any time. */ event DefaultMaxInvocationsPerAddress( uint256 defaultMaxInvocationsPerAddress ); // Triggers a purchase of a token from the desired project, to the // TX-sending address. Requires Merkle proof. function purchase( uint256 _projectId, bytes32[] memory _proof ) external payable returns (uint256 tokenId); // Triggers a purchase of a token from the desired project, to the specified // receiving address. Requires Merkle proof. function purchaseTo( address _to, uint256 _projectId, bytes32[] memory _proof ) external payable returns (uint256 tokenId); }
// SPDX-License-Identifier: LGPL-3.0-only // Created By: Art Blocks Inc. import "./IFilteredMinterMerkleV0.sol"; pragma solidity ^0.8.0; /** * @title This interface extends the IFilteredMinterMerkleV0 interface in order * to add support for configuring and indexing the delegation registry address. * @author Art Blocks Inc. */ interface IFilteredMinterMerkleV1 is IFilteredMinterMerkleV0 { /** * @notice Notifies of the contract's configured delegation registry * address. */ event DelegationRegistryUpdated(address delegationRegistryAddress); }
// SPDX-License-Identifier: LGPL-3.0-only // Created By: Art Blocks Inc. import "./IFilteredMinterMerkleV1.sol"; import "./IFilteredMinterV2.sol"; pragma solidity ^0.8.0; /** * @title This interface extends the IFilteredMinterMerkleV0 interface in order to * add support for manually setting project max invocations. * @author Art Blocks Inc. */ interface IFilteredMinterMerkleV2 is IFilteredMinterMerkleV1, IFilteredMinterV2 {}
// SPDX-License-Identifier: LGPL-3.0-only // Created By: Art Blocks Inc. pragma solidity ^0.8.0; interface IFilteredMinterV0 { /** * @notice Price per token in wei updated for project `_projectId` to * `_pricePerTokenInWei`. */ event PricePerTokenInWeiUpdated( uint256 indexed _projectId, uint256 indexed _pricePerTokenInWei ); /** * @notice Currency updated for project `_projectId` to symbol * `_currencySymbol` and address `_currencyAddress`. */ event ProjectCurrencyInfoUpdated( uint256 indexed _projectId, address indexed _currencyAddress, string _currencySymbol ); /// togglePurchaseToDisabled updated event PurchaseToDisabledUpdated( uint256 indexed _projectId, bool _purchaseToDisabled ); // getter function of public variable function minterType() external view returns (string memory); function genArt721CoreAddress() external returns (address); function minterFilterAddress() external returns (address); // Triggers a purchase of a token from the desired project, to the // TX-sending address. function purchase( uint256 _projectId ) external payable returns (uint256 tokenId); // Triggers a purchase of a token from the desired project, to the specified // receiving address. function purchaseTo( address _to, uint256 _projectId ) external payable returns (uint256 tokenId); // Toggles the ability for `purchaseTo` to be called directly with a // specified receiving address that differs from the TX-sending address. function togglePurchaseToDisabled(uint256 _projectId) external; // Called to make the minter contract aware of the max invocations for a // given project. function setProjectMaxInvocations(uint256 _projectId) external; // Gets if token price is configured, token price in wei, currency symbol, // and currency address, assuming this is project's minter. // Supersedes any defined core price. function getPriceInfo( uint256 _projectId ) external view returns ( bool isConfigured, uint256 tokenPriceInWei, string memory currencySymbol, address currencyAddress ); }
// SPDX-License-Identifier: LGPL-3.0-only // Created By: Art Blocks Inc. import "./IFilteredMinterV0.sol"; pragma solidity ^0.8.0; /** * @title This interface extends the IFilteredMinterV0 interface in order to * add support for generic project minter configuration updates. * @dev keys represent strings of finite length encoded in bytes32 to minimize * gas. * @author Art Blocks Inc. */ interface IFilteredMinterV1 is IFilteredMinterV0 { /// ANY /** * @notice Generic project minter configuration event. Removes key `_key` * for project `_projectId`. */ event ConfigKeyRemoved(uint256 indexed _projectId, bytes32 _key); /// BOOL /** * @notice Generic project minter configuration event. Sets value of key * `_key` to `_value` for project `_projectId`. */ event ConfigValueSet(uint256 indexed _projectId, bytes32 _key, bool _value); /// UINT256 /** * @notice Generic project minter configuration event. Sets value of key * `_key` to `_value` for project `_projectId`. */ event ConfigValueSet( uint256 indexed _projectId, bytes32 _key, uint256 _value ); /** * @notice Generic project minter configuration event. Adds value `_value` * to the set of uint256 at key `_key` for project `_projectId`. */ event ConfigValueAddedToSet( uint256 indexed _projectId, bytes32 _key, uint256 _value ); /** * @notice Generic project minter configuration event. Removes value * `_value` to the set of uint256 at key `_key` for project `_projectId`. */ event ConfigValueRemovedFromSet( uint256 indexed _projectId, bytes32 _key, uint256 _value ); /// ADDRESS /** * @notice Generic project minter configuration event. Sets value of key * `_key` to `_value` for project `_projectId`. */ event ConfigValueSet( uint256 indexed _projectId, bytes32 _key, address _value ); /** * @notice Generic project minter configuration event. Adds value `_value` * to the set of addresses at key `_key` for project `_projectId`. */ event ConfigValueAddedToSet( uint256 indexed _projectId, bytes32 _key, address _value ); /** * @notice Generic project minter configuration event. Removes value * `_value` to the set of addresses at key `_key` for project `_projectId`. */ event ConfigValueRemovedFromSet( uint256 indexed _projectId, bytes32 _key, address _value ); /// BYTES32 /** * @notice Generic project minter configuration event. Sets value of key * `_key` to `_value` for project `_projectId`. */ event ConfigValueSet( uint256 indexed _projectId, bytes32 _key, bytes32 _value ); /** * @notice Generic project minter configuration event. Adds value `_value` * to the set of bytes32 at key `_key` for project `_projectId`. */ event ConfigValueAddedToSet( uint256 indexed _projectId, bytes32 _key, bytes32 _value ); /** * @notice Generic project minter configuration event. Removes value * `_value` to the set of bytes32 at key `_key` for project `_projectId`. */ event ConfigValueRemovedFromSet( uint256 indexed _projectId, bytes32 _key, bytes32 _value ); /** * @dev Strings not supported. Recommend conversion of (short) strings to * bytes32 to remain gas-efficient. */ }
// SPDX-License-Identifier: LGPL-3.0-only // Created By: Art Blocks Inc. import "./IFilteredMinterV1.sol"; pragma solidity ^0.8.0; /** * @title This interface extends the IFilteredMinterV1 interface in order to * add support for manually setting project max invocations. * @author Art Blocks Inc. */ interface IFilteredMinterV2 is IFilteredMinterV1 { /** * @notice Local max invocations for project `_projectId`, tied to core contract `_coreContractAddress`, * updated to `_maxInvocations`. */ event ProjectMaxInvocationsLimitUpdated( uint256 indexed _projectId, uint256 _maxInvocations ); // Sets the local max invocations for a given project, checking that the provided max invocations is // less than or equal to the global max invocations for the project set on the core contract. // This does not impact the max invocations value defined on the core contract. function manuallyLimitProjectMaxInvocations( uint256 _projectId, uint256 _maxInvocations ) external; }
// SPDX-License-Identifier: LGPL-3.0-only // Created By: Art Blocks Inc. pragma solidity ^0.8.0; import "./IAdminACLV0.sol"; /// use the Royalty Registry's IManifold interface for token royalties import "./IManifold.sol"; /** * @title This interface is intended to house interface items that are common * across all GenArt721CoreContractV3 flagship and derivative implementations. * This interface extends the IManifold royalty interface in order to * add support the Royalty Registry by default. * @author Art Blocks Inc. */ interface IGenArt721CoreContractV3_Base is IManifold { /** * @notice Token ID `_tokenId` minted to `_to`. */ event Mint(address indexed _to, uint256 indexed _tokenId); /** * @notice currentMinter updated to `_currentMinter`. * @dev Implemented starting with V3 core */ event MinterUpdated(address indexed _currentMinter); /** * @notice Platform updated on bytes32-encoded field `_field`. */ event PlatformUpdated(bytes32 indexed _field); /** * @notice Project ID `_projectId` updated on bytes32-encoded field * `_update`. */ event ProjectUpdated(uint256 indexed _projectId, bytes32 indexed _update); event ProposedArtistAddressesAndSplits( uint256 indexed _projectId, address _artistAddress, address _additionalPayeePrimarySales, uint256 _additionalPayeePrimarySalesPercentage, address _additionalPayeeSecondarySales, uint256 _additionalPayeeSecondarySalesPercentage ); event AcceptedArtistAddressesAndSplits(uint256 indexed _projectId); // version and type of the core contract // coreVersion is a string of the form "0.x.y" function coreVersion() external view returns (string memory); // coreType is a string of the form "GenArt721CoreV3" function coreType() external view returns (string memory); // owner (pre-V3 was named admin) of contract // this is expected to be an Admin ACL contract for V3 function owner() external view returns (address); // Admin ACL contract for V3, will be at the address owner() function adminACLContract() external returns (IAdminACLV0); // backwards-compatible (pre-V3) admin - equal to owner() function admin() external view returns (address); /** * Function determining if _sender is allowed to call function with * selector _selector on contract `_contract`. Intended to be used with * peripheral contracts such as minters, as well as internally by the * core contract itself. */ function adminACLAllowed( address _sender, address _contract, bytes4 _selector ) external returns (bool); // getter function of public variable function nextProjectId() external view returns (uint256); // getter function of public mapping function tokenIdToProjectId( uint256 tokenId ) external view returns (uint256 projectId); // @dev this is not available in V0 function isMintWhitelisted(address minter) external view returns (bool); function projectIdToArtistAddress( uint256 _projectId ) external view returns (address payable); function projectIdToAdditionalPayeePrimarySales( uint256 _projectId ) external view returns (address payable); function projectIdToAdditionalPayeePrimarySalesPercentage( uint256 _projectId ) external view returns (uint256); // @dev new function in V3 function projectStateData( uint256 _projectId ) external view returns ( uint256 invocations, uint256 maxInvocations, bool active, bool paused, uint256 completedTimestamp, bool locked ); // function to set a token's hash (must be guarded) function setTokenHash_8PT(uint256 _tokenId, bytes32 _hash) external; // @dev gas-optimized signature in V3 for `mint` function mint_Ecf( address _to, uint256 _projectId, address _by ) external returns (uint256 tokenId); }
// SPDX-License-Identifier: LGPL-3.0-only // Created By: Art Blocks Inc. pragma solidity ^0.8.0; import "./IAdminACLV0.sol"; import "./IGenArt721CoreContractV3_Base.sol"; interface IGenArt721CoreContractV3_Engine is IGenArt721CoreContractV3_Base { // @dev new function in V3 function getPrimaryRevenueSplits( uint256 _projectId, uint256 _price ) external view returns ( uint256 renderProviderRevenue_, address payable renderProviderAddress_, uint256 platformProviderRevenue_, address payable platformProviderAddress_, uint256 artistRevenue_, address payable artistAddress_, uint256 additionalPayeePrimaryRevenue_, address payable additionalPayeePrimaryAddress_ ); // @dev The render provider primary sales payment address function renderProviderPrimarySalesAddress() external view returns (address payable); // @dev The platform provider primary sales payment address function platformProviderPrimarySalesAddress() external view returns (address payable); // @dev Percentage of primary sales allocated to the render provider function renderProviderPrimarySalesPercentage() external view returns (uint256); // @dev Percentage of primary sales allocated to the platform provider function platformProviderPrimarySalesPercentage() external view returns (uint256); // @dev The render provider secondary sales royalties payment address function renderProviderSecondarySalesAddress() external view returns (address payable); // @dev The platform provider secondary sales royalties payment address function platformProviderSecondarySalesAddress() external view returns (address payable); // @dev Basis points of secondary sales allocated to the render provider function renderProviderSecondarySalesBPS() external view returns (uint256); // @dev Basis points of secondary sales allocated to the platform provider function platformProviderSecondarySalesBPS() external view returns (uint256); // function to read the hash for a given tokenId function tokenIdToHash(uint256 _tokenId) external view returns (bytes32); // function to read the hash-seed for a given tokenId function tokenIdToHashSeed( uint256 _tokenId ) external view returns (bytes12); }
// SPDX-License-Identifier: LGPL-3.0-only // Created By: Art Blocks Inc. pragma solidity ^0.8.0; import "./IAdminACLV0.sol"; import "./IGenArt721CoreContractV3_Base.sol"; /** * @title This interface extends IGenArt721CoreContractV3_Base with functions * that are part of the Art Blocks Flagship core contract. * @author Art Blocks Inc. */ // This interface extends IGenArt721CoreContractV3_Base with functions that are // in part of the Art Blocks Flagship core contract. interface IGenArt721CoreContractV3 is IGenArt721CoreContractV3_Base { // @dev new function in V3 function getPrimaryRevenueSplits( uint256 _projectId, uint256 _price ) external view returns ( uint256 artblocksRevenue_, address payable artblocksAddress_, uint256 artistRevenue_, address payable artistAddress_, uint256 additionalPayeePrimaryRevenue_, address payable additionalPayeePrimaryAddress_ ); // @dev Art Blocks primary sales payment address function artblocksPrimarySalesAddress() external view returns (address payable); /** * @notice Backwards-compatible (pre-V3) function returning Art Blocks * primary sales payment address (now called artblocksPrimarySalesAddress). */ function artblocksAddress() external view returns (address payable); // @dev Percentage of primary sales allocated to Art Blocks function artblocksPrimarySalesPercentage() external view returns (uint256); /** * @notice Backwards-compatible (pre-V3) function returning Art Blocks * primary sales percentage (now called artblocksPrimarySalesPercentage). */ function artblocksPercentage() external view returns (uint256); // @dev Art Blocks secondary sales royalties payment address function artblocksSecondarySalesAddress() external view returns (address payable); // @dev Basis points of secondary sales allocated to Art Blocks function artblocksSecondarySalesBPS() external view returns (uint256); /** * @notice Backwards-compatible (pre-V3) function that gets artist + * artist's additional payee royalty data for token ID `_tokenId`. * WARNING: Does not include Art Blocks portion of royalties. */ function getRoyaltyData( uint256 _tokenId ) external view returns ( address artistAddress, address additionalPayee, uint256 additionalPayeePercentage, uint256 royaltyFeeByID ); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @dev Royalty Registry interface, used to support the Royalty Registry. /// @dev Source: https://github.com/manifoldxyz/royalty-registry-solidity/blob/main/contracts/specs/IManifold.sol /// @author: manifold.xyz /** * @dev Royalty interface for creator core classes */ interface IManifold { /** * @dev Get royalites of a token. Returns list of receivers and basisPoints * * bytes4(keccak256('getRoyalties(uint256)')) == 0xbb3bafd6 * * => 0xbb3bafd6 = 0xbb3bafd6 */ function getRoyalties( uint256 tokenId ) external view returns (address payable[] memory, uint256[] memory); }
// SPDX-License-Identifier: LGPL-3.0-only // Created By: Art Blocks Inc. import "./IFilteredMinterV2.sol"; pragma solidity ^0.8.0; /** * @title This interface defines any events or functions required for a minter * to conform to the MinterBase contract. * @dev The MinterBase contract was not implemented from the beginning of the * MinterSuite contract suite, therefore early versions of some minters may not * conform to this interface. * @author Art Blocks Inc. */ interface IMinterBaseV0 { // Function that returns if a minter is configured to integrate with a V3 flagship or V3 engine contract. // Returns true only if the minter is configured to integrate with an engine contract. function isEngine() external returns (bool isEngine); }
// SPDX-License-Identifier: LGPL-3.0-only // Created By: Art Blocks Inc. pragma solidity ^0.8.0; interface IMinterFilterV0 { /** * @notice Approved minter `_minterAddress`. */ event MinterApproved(address indexed _minterAddress, string _minterType); /** * @notice Revoked approval for minter `_minterAddress` */ event MinterRevoked(address indexed _minterAddress); /** * @notice Minter `_minterAddress` of type `_minterType` * registered for project `_projectId`. */ event ProjectMinterRegistered( uint256 indexed _projectId, address indexed _minterAddress, string _minterType ); /** * @notice Any active minter removed for project `_projectId`. */ event ProjectMinterRemoved(uint256 indexed _projectId); function genArt721CoreAddress() external returns (address); function setMinterForProject(uint256, address) external; function removeMinterForProject(uint256) external; function mint( address _to, uint256 _projectId, address sender ) external returns (uint256); function getMinterForProject(uint256) external view returns (address); function projectHasMinter(uint256) external view returns (bool); }
// SPDX-License-Identifier: LGPL-3.0-only // Created By: Art Blocks Inc. import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "./interfaces/IMinterBaseV0.sol"; import "./interfaces/IGenArt721CoreContractV3_Base.sol"; import "./interfaces/IGenArt721CoreContractV3.sol"; import "./interfaces/IGenArt721CoreContractV3_Engine.sol"; pragma solidity ^0.8.0; /** * @title Art Blocks Minter Base Class * @notice A base class for Art Blocks minter contracts that provides common * functionality used across minter contracts. * This contract is not intended to be deployed directly, but rather to be * inherited by other minter contracts. * From a design perspective, this contract is intended to remain simple and * easy to understand. It is not intended to cause a complex inheritance tree, * and instead should keep minter contracts as readable as possible for * collectors and developers. * @dev Semantic versioning is used in the solidity file name, and is therefore * controlled by contracts importing the appropriate filename version. * @author Art Blocks Inc. */ abstract contract MinterBase is IMinterBaseV0 { /// state variable that tracks whether this contract's associated core /// contract is an Engine contract, where Engine contracts have an /// additional revenue split for the platform provider bool public immutable isEngine; // @dev we do not track an initialization state, as the only state variable // is immutable, which the compiler enforces to be assigned during // construction. /** * @notice Initializes contract to ensure state variable `isEngine` is set * appropriately based on the minter's associated core contract address. * @param genArt721Address Art Blocks core contract address for * which this contract will be a minter. */ constructor(address genArt721Address) { // set state variable isEngine isEngine = _getV3CoreIsEngine(genArt721Address); } /** * @notice splits ETH funds between sender (if refund), providers, * artist, and artist's additional payee for a token purchased on * project `_projectId`. * WARNING: This function uses msg.value and msg.sender to determine * refund amounts, and therefore may not be applicable to all use cases * (e.g. do not use with Dutch Auctions with on-chain settlement). * @dev possible DoS during splits is acknowledged, and mitigated by * business practices, including end-to-end testing on mainnet, and * admin-accepted artist payment addresses. * @param projectId Project ID for which funds shall be split. * @param pricePerTokenInWei Current price of token, in Wei. */ function splitFundsETH( uint256 projectId, uint256 pricePerTokenInWei, address genArt721CoreAddress ) internal { if (msg.value > 0) { bool success_; // send refund to sender uint256 refund = msg.value - pricePerTokenInWei; if (refund > 0) { (success_, ) = msg.sender.call{value: refund}(""); require(success_, "Refund failed"); } // split revenues splitRevenuesETH( projectId, pricePerTokenInWei, genArt721CoreAddress ); } } /** * @notice splits ETH revenues between providers, artist, and artist's * additional payee for revenue generated by project `_projectId`. * @dev possible DoS during splits is acknowledged, and mitigated by * business practices, including end-to-end testing on mainnet, and * admin-accepted artist payment addresses. * @param projectId Project ID for which funds shall be split. * @param valueInWei Value to be split, in Wei. */ function splitRevenuesETH( uint256 projectId, uint256 valueInWei, address genArtCoreContract ) internal { if (valueInWei <= 0) { return; // return early } bool success; // split funds between platforms, artist, and artist's // additional payee uint256 renderProviderRevenue_; address payable renderProviderAddress_; uint256 artistRevenue_; address payable artistAddress_; uint256 additionalPayeePrimaryRevenue_; address payable additionalPayeePrimaryAddress_; if (isEngine) { // get engine splits uint256 platformProviderRevenue_; address payable platformProviderAddress_; ( renderProviderRevenue_, renderProviderAddress_, platformProviderRevenue_, platformProviderAddress_, artistRevenue_, artistAddress_, additionalPayeePrimaryRevenue_, additionalPayeePrimaryAddress_ ) = IGenArt721CoreContractV3_Engine(genArtCoreContract) .getPrimaryRevenueSplits(projectId, valueInWei); // Platform Provider payment (only possible if engine) if (platformProviderRevenue_ > 0) { (success, ) = platformProviderAddress_.call{ value: platformProviderRevenue_ }(""); require(success, "Platform Provider payment failed"); } } else { // get flagship splits ( renderProviderRevenue_, // artblocks revenue renderProviderAddress_, // artblocks address artistRevenue_, artistAddress_, additionalPayeePrimaryRevenue_, additionalPayeePrimaryAddress_ ) = IGenArt721CoreContractV3(genArtCoreContract) .getPrimaryRevenueSplits(projectId, valueInWei); } // Render Provider / Art Blocks payment if (renderProviderRevenue_ > 0) { (success, ) = renderProviderAddress_.call{ value: renderProviderRevenue_ }(""); require(success, "Render Provider payment failed"); } // artist payment if (artistRevenue_ > 0) { (success, ) = artistAddress_.call{value: artistRevenue_}(""); require(success, "Artist payment failed"); } // additional payee payment if (additionalPayeePrimaryRevenue_ > 0) { (success, ) = additionalPayeePrimaryAddress_.call{ value: additionalPayeePrimaryRevenue_ }(""); require(success, "Additional Payee payment failed"); } } /** * @notice splits ERC-20 funds between providers, artist, and artist's * additional payee, for a token purchased on project `_projectId`. * @dev possible DoS during splits is acknowledged, and mitigated by * business practices, including end-to-end testing on mainnet, and * admin-accepted artist payment addresses. */ function splitFundsERC20( uint256 projectId, uint256 pricePerTokenInWei, address currencyAddress, address genArtCoreContract ) internal { IERC20 _projectCurrency = IERC20(currencyAddress); // split remaining funds between foundation, artist, and artist's // additional payee uint256 renderProviderRevenue_; address payable renderProviderAddress_; uint256 artistRevenue_; address payable artistAddress_; uint256 additionalPayeePrimaryRevenue_; address payable additionalPayeePrimaryAddress_; if (isEngine) { // get engine splits uint256 platformProviderRevenue_; address payable platformProviderAddress_; ( renderProviderRevenue_, renderProviderAddress_, platformProviderRevenue_, platformProviderAddress_, artistRevenue_, artistAddress_, additionalPayeePrimaryRevenue_, additionalPayeePrimaryAddress_ ) = IGenArt721CoreContractV3_Engine(genArtCoreContract) .getPrimaryRevenueSplits(projectId, pricePerTokenInWei); // Platform Provider payment (only possible if engine) if (platformProviderRevenue_ > 0) { _projectCurrency.transferFrom( msg.sender, platformProviderAddress_, platformProviderRevenue_ ); } } else { // get flagship splits ( renderProviderRevenue_, // artblocks revenue renderProviderAddress_, // artblocks address artistRevenue_, artistAddress_, additionalPayeePrimaryRevenue_, additionalPayeePrimaryAddress_ ) = IGenArt721CoreContractV3(genArtCoreContract) .getPrimaryRevenueSplits(projectId, pricePerTokenInWei); } // Art Blocks payment if (renderProviderRevenue_ > 0) { _projectCurrency.transferFrom( msg.sender, renderProviderAddress_, renderProviderRevenue_ ); } // artist payment if (artistRevenue_ > 0) { _projectCurrency.transferFrom( msg.sender, artistAddress_, artistRevenue_ ); } // additional payee payment if (additionalPayeePrimaryRevenue_ > 0) { _projectCurrency.transferFrom( msg.sender, additionalPayeePrimaryAddress_, additionalPayeePrimaryRevenue_ ); } } /** * @notice Returns whether a V3 core contract is an Art Blocks Engine * contract or not. Return value of false indicates that the core is a * flagship contract. * @dev this function reverts if a core contract does not return the * expected number of return values from getPrimaryRevenueSplits() for * either a flagship or engine core contract. * @dev this function uses the length of the return data (in bytes) to * determine whether the core is an engine or not. * @param genArt721CoreV3 The address of the deployed core contract. */ function _getV3CoreIsEngine( address genArt721CoreV3 ) private returns (bool) { // call getPrimaryRevenueSplits() on core contract bytes memory payload = abi.encodeWithSignature( "getPrimaryRevenueSplits(uint256,uint256)", 0, 0 ); (bool success, bytes memory returnData) = genArt721CoreV3.call(payload); require(success, "getPrimaryRevenueSplits() call failed"); // determine whether core is engine or not, based on return data length uint256 returnDataLength = returnData.length; if (returnDataLength == 6 * 32) { // 6 32-byte words returned if flagship (not engine) // @dev 6 32-byte words are expected because the non-engine core // contracts return a payout address and uint256 payment value for // the artist, and artist's additional payee, and Art Blocks. // also note that per Solidity ABI encoding, the address return // values are padded to 32 bytes. return false; } else if (returnDataLength == 8 * 32) { // 8 32-byte words returned if engine // @dev 8 32-byte words are expected because the engine core // contracts return a payout address and uint256 payment value for // the artist, artist's additional payee, render provider // typically Art Blocks, and platform provider (partner). // also note that per Solidity ABI encoding, the address return // values are padded to 32 bytes. return true; } else { // unexpected return value length revert("Unexpected revenue split bytes"); } } }
{ "optimizer": { "enabled": false, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_genArt721Address","type":"address"},{"internalType":"address","name":"_minterFilter","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ActionNotSupported","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_projectId","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"_key","type":"bytes32"}],"name":"ConfigKeyRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_projectId","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"_key","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"ConfigValueAddedToSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_projectId","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"_key","type":"bytes32"},{"indexed":false,"internalType":"address","name":"_value","type":"address"}],"name":"ConfigValueAddedToSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_projectId","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"_key","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"_value","type":"bytes32"}],"name":"ConfigValueAddedToSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_projectId","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"_key","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"ConfigValueRemovedFromSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_projectId","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"_key","type":"bytes32"},{"indexed":false,"internalType":"address","name":"_value","type":"address"}],"name":"ConfigValueRemovedFromSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_projectId","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"_key","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"_value","type":"bytes32"}],"name":"ConfigValueRemovedFromSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_projectId","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"_key","type":"bytes32"},{"indexed":false,"internalType":"bool","name":"_value","type":"bool"}],"name":"ConfigValueSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_projectId","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"_key","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"ConfigValueSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_projectId","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"_key","type":"bytes32"},{"indexed":false,"internalType":"address","name":"_value","type":"address"}],"name":"ConfigValueSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_projectId","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"_key","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"_value","type":"bytes32"}],"name":"ConfigValueSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"defaultMaxInvocationsPerAddress","type":"uint256"}],"name":"DefaultMaxInvocationsPerAddress","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"delegationRegistryAddress","type":"address"}],"name":"DelegationRegistryUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_projectId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"_pricePerTokenInWei","type":"uint256"}],"name":"PricePerTokenInWeiUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_projectId","type":"uint256"},{"indexed":true,"internalType":"address","name":"_currencyAddress","type":"address"},{"indexed":false,"internalType":"string","name":"_currencySymbol","type":"string"}],"name":"ProjectCurrencyInfoUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_projectId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_maxInvocations","type":"uint256"}],"name":"ProjectMaxInvocationsLimitUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_projectId","type":"uint256"},{"indexed":false,"internalType":"bool","name":"_purchaseToDisabled","type":"bool"}],"name":"PurchaseToDisabledUpdated","type":"event"},{"inputs":[{"internalType":"uint256","name":"_projectId","type":"uint256"}],"name":"allStages","outputs":[{"components":[{"internalType":"uint8","name":"id","type":"uint8"},{"internalType":"uint8","name":"transactionMaxInvocations","type":"uint8"},{"internalType":"uint32","name":"stageStartTime","type":"uint32"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"},{"internalType":"uint256","name":"pricePerTokenInWei","type":"uint256"}],"internalType":"struct MultiMerkleMinterV1.Stage[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_projectId","type":"uint256"},{"internalType":"uint32","name":"_stageStartTime","type":"uint32"},{"internalType":"bytes32","name":"_merkleRoot","type":"bytes32"},{"internalType":"uint256","name":"_pricePerTokenInWei","type":"uint256"},{"internalType":"uint8","name":"_transactionMaxInvocations","type":"uint8"}],"name":"createNewStage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_projectId","type":"uint256"}],"name":"currentStage","outputs":[{"components":[{"internalType":"uint8","name":"id","type":"uint8"},{"internalType":"uint8","name":"transactionMaxInvocations","type":"uint8"},{"internalType":"uint32","name":"stageStartTime","type":"uint32"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"},{"internalType":"uint256","name":"pricePerTokenInWei","type":"uint256"}],"internalType":"struct MultiMerkleMinterV1.Stage","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_projectId","type":"uint256"}],"name":"currentStageId","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_projectId","type":"uint256"}],"name":"currentStagePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"genArt721CoreAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_projectId","type":"uint256"},{"internalType":"uint8","name":"_stageId","type":"uint8"},{"internalType":"address","name":"_address","type":"address"}],"name":"getAddressMintedCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_projectId","type":"uint256"}],"name":"getPriceInfo","outputs":[{"internalType":"bool","name":"isConfigured","type":"bool"},{"internalType":"uint256","name":"tokenPriceInWei","type":"uint256"},{"internalType":"string","name":"currencySymbol","type":"string"},{"internalType":"address","name":"currencyAddress","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_productId","type":"uint256"},{"internalType":"uint8","name":"_stageId","type":"uint8"}],"name":"getStage","outputs":[{"components":[{"internalType":"uint8","name":"id","type":"uint8"},{"internalType":"uint8","name":"transactionMaxInvocations","type":"uint8"},{"internalType":"uint32","name":"stageStartTime","type":"uint32"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"},{"internalType":"uint256","name":"pricePerTokenInWei","type":"uint256"}],"internalType":"struct MultiMerkleMinterV1.Stage","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"hashAddress","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"isEngine","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_projectId","type":"uint256"},{"internalType":"uint256","name":"_maxInvocations","type":"uint256"}],"name":"manuallyLimitProjectMaxInvocations","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"minterFilterAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minterType","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_projectId","type":"uint256"}],"name":"nextStage","outputs":[{"components":[{"internalType":"uint8","name":"id","type":"uint8"},{"internalType":"uint8","name":"transactionMaxInvocations","type":"uint8"},{"internalType":"uint32","name":"stageStartTime","type":"uint32"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"},{"internalType":"uint256","name":"pricePerTokenInWei","type":"uint256"}],"internalType":"struct MultiMerkleMinterV1.Stage","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_projectId","type":"uint256"}],"name":"nextStagePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"_proof","type":"bytes32[]"},{"internalType":"address","name":"_address","type":"address"}],"name":"processProofForAddress","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"projectConfig","outputs":[{"internalType":"bool","name":"maxHasBeenInvoked","type":"bool"},{"internalType":"bool","name":"priceIsConfigured","type":"bool"},{"internalType":"uint8","name":"currentStageId","type":"uint8"},{"internalType":"uint8","name":"stagesCount","type":"uint8"},{"internalType":"uint24","name":"maxInvocations","type":"uint24"},{"internalType":"address","name":"systemAddress","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_projectId","type":"uint256"}],"name":"projectMaxHasBeenInvoked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_projectId","type":"uint256"}],"name":"projectMaxInvocations","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes32[]","name":"","type":"bytes32[]"}],"name":"purchase","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"purchase","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_projectId","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes","name":"_signature","type":"bytes"},{"internalType":"bytes","name":"_data","type":"bytes"},{"internalType":"bytes32[]","name":"_merkleProof","type":"bytes32[]"},{"internalType":"string","name":"_nonce","type":"string"}],"name":"purchaseMMM","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes32[]","name":"","type":"bytes32[]"}],"name":"purchaseTo","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"purchaseTo","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_projectId","type":"uint256"}],"name":"setProjectMaxInvocations","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_projectId","type":"uint256"}],"name":"startingTimeOfNextStage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_projectId","type":"uint256"},{"internalType":"address[]","name":"_addresses","type":"address[]"},{"internalType":"uint256[]","name":"_counts","type":"uint256[]"}],"name":"teamMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"togglePurchaseToDisabled","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"_projectId","type":"uint256"},{"internalType":"uint8","name":"_stageId","type":"uint8"},{"internalType":"bytes32","name":"_root","type":"bytes32"}],"name":"updateMerkleRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_projectId","type":"uint256"},{"internalType":"uint8","name":"_stageId","type":"uint8"},{"internalType":"uint256","name":"_pricePerTokenInWei","type":"uint256"}],"name":"updatePricePerTokenInWei","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_projectId","type":"uint256"},{"internalType":"uint8","name":"_stageId","type":"uint8"},{"internalType":"uint32","name":"_newStartingTime","type":"uint32"}],"name":"updateStartingTimeForStage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_projectId","type":"uint256"},{"internalType":"address","name":"_address","type":"address"}],"name":"updateSystemAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_merkleRoot","type":"bytes32"},{"internalType":"bytes32[]","name":"_proof","type":"bytes32[]"},{"internalType":"address","name":"_address","type":"address"}],"name":"verifyAddress","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"}]
Contract Creation Code
6101206040523480156200001257600080fd5b50604051620061d3380380620061d383398181016040528101906200003891906200044d565b81600160008190555062000052816200021e60201b60201c565b1515608081151581525050508173ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff16815250508173ffffffffffffffffffffffffffffffffffffffff1660c08173ffffffffffffffffffffffffffffffffffffffff16815250508073ffffffffffffffffffffffffffffffffffffffff1660e08173ffffffffffffffffffffffffffffffffffffffff16815250508073ffffffffffffffffffffffffffffffffffffffff166101008173ffffffffffffffffffffffffffffffffffffffff16815250508173ffffffffffffffffffffffffffffffffffffffff166101005173ffffffffffffffffffffffffffffffffffffffff166392a10f836040518163ffffffff1660e01b81526004016020604051808303816000875af115801562000197573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001bd919062000494565b73ffffffffffffffffffffffffffffffffffffffff161462000216576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200020d9062000527565b60405180910390fd5b50506200076c565b60008060008060405160240162000237929190620005a3565b6040516020818303038152906040527f8639415b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090506000808473ffffffffffffffffffffffffffffffffffffffff1683604051620002e0919062000649565b6000604051808303816000865af19150503d80600081146200031f576040519150601f19603f3d011682016040523d82523d6000602084013e62000324565b606091505b5091509150816200036c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200036390620006d8565b60405180910390fd5b60008151905060c0810362000389576000945050505050620003de565b6101008103620003a1576001945050505050620003de565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620003d5906200074a565b60405180910390fd5b919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006200041582620003e8565b9050919050565b620004278162000408565b81146200043357600080fd5b50565b60008151905062000447816200041c565b92915050565b60008060408385031215620004675762000466620003e3565b5b6000620004778582860162000436565b92505060206200048a8582860162000436565b9150509250929050565b600060208284031215620004ad57620004ac620003e3565b5b6000620004bd8482850162000436565b91505092915050565b600082825260208201905092915050565b7f496c6c6567616c20436f6e74726163742050616972696e670000000000000000600082015250565b60006200050f601883620004c6565b91506200051c82620004d7565b602082019050919050565b60006020820190508181036000830152620005428162000500565b9050919050565b6000819050919050565b600060ff82169050919050565b6000819050919050565b60006200058b620005856200057f8462000549565b62000560565b62000553565b9050919050565b6200059d816200056a565b82525050565b6000604082019050620005ba600083018562000592565b620005c9602083018462000592565b9392505050565b600081519050919050565b600081905092915050565b60005b8381101562000606578082015181840152602081019050620005e9565b60008484015250505050565b60006200061f82620005d0565b6200062b8185620005db565b93506200063d818560208601620005e6565b80840191505092915050565b600062000657828462000612565b915081905092915050565b7f6765745072696d617279526576656e756553706c69747328292063616c6c206660008201527f61696c6564000000000000000000000000000000000000000000000000000000602082015250565b6000620006c0602583620004c6565b9150620006cd8262000662565b604082019050919050565b60006020820190508181036000830152620006f381620006b1565b9050919050565b7f556e657870656374656420726576656e75652073706c69742062797465730000600082015250565b600062000732601e83620004c6565b91506200073f82620006fa565b602082019050919050565b60006020820190508181036000830152620007658162000723565b9050919050565b60805160a05160c05160e051610100516159ce6200080560003960008181611bc901526128010152600061261301526000818161090201528181610a6a01528181610bd001528181610cda01528181610f0b015281816110e301528181611fa4015281816126a5015281816129080152612a12015260008181611cef0152611f690152600081816125ef0152612f9301526159ce6000f3fe6080604052600436106101f95760003560e01c8063891407c01161010d578063c8a1f9b1116100a0578063e9d1e8ac1161006f578063e9d1e8ac146107e5578063efef39a114610810578063f002d9f314610840578063f7bd4b8814610869578063f849584d14610892576101f9565b8063c8a1f9b114610722578063da7e7c501461075f578063db6921b21461078f578063dd85582f146107ba576101f9565b8063a0b4cd18116100dc578063a0b4cd181461063d578063b836fefe1461067a578063c21ab44e146106a3578063c71b1b71146106e0576101f9565b8063891407c014610568578063894edcd414610598578063903488df146105d557806392a10f8314610612576101f9565b806340d1397e1161019057806356690aaf1161015f57806356690aaf1461045557806358f2a2b3146104925780635a23ac25146104cf578063676d9fcd1461050c578063774159c614610528576101f9565b806340d1397e14610389578063462add46146103b25780634fbd7fa1146103ef57806352b9c2d614610418576101f9565b80631ec2e523116101cc5780631ec2e523146102b6578063202c5805146102f357806325075249146103235780633aa5fe591461034c576101f9565b8063087b0581146101fe5780630f113ede1461023b5780631593e74c146102645780631607c9951461028d575b600080fd5b34801561020a57600080fd5b50610225600480360381019061022091906137c9565b6108cf565b6040516102329190613858565b60405180910390f35b34801561024757600080fd5b50610262600480360381019061025d91906138a9565b6108ff565b005b34801561027057600080fd5b5061028b60048036038101906102869190613922565b610a67565b005b34801561029957600080fd5b506102b460048036038101906102af9190613975565b610bcd565b005b3480156102c257600080fd5b506102dd60048036038101906102d891906139b5565b610eac565b6040516102ea9190613a24565b60405180910390f35b61030d60048036038101906103089190613a3f565b610ed4565b60405161031a9190613ac2565b60405180910390f35b34801561032f57600080fd5b5061034a60048036038101906103459190613add565b610f08565b005b34801561035857600080fd5b50610373600480360381019061036e9190613b30565b611051565b6040516103809190613a24565b60405180910390f35b34801561039557600080fd5b506103b060048036038101906103ab9190613b5d565b611081565b005b3480156103be57600080fd5b506103d960048036038101906103d49190613b5d565b6110b3565b6040516103e69190613858565b60405180910390f35b3480156103fb57600080fd5b5061041660048036038101906104119190613bc6565b6110e0565b005b34801561042457600080fd5b5061043f600480360381019061043a9190613c41565b611404565b60405161044c9190613ac2565b60405180910390f35b34801561046157600080fd5b5061047c60048036038101906104779190613b5d565b61147a565b6040516104899190613ac2565b60405180910390f35b34801561049e57600080fd5b506104b960048036038101906104b49190613b5d565b6114ae565b6040516104c69190613ac2565b60405180910390f35b3480156104db57600080fd5b506104f660048036038101906104f19190613b5d565b6114c4565b6040516105039190613d38565b60405180910390f35b61052660048036038101906105219190613dff565b6115cb565b005b34801561053457600080fd5b5061054f600480360381019061054a9190613b5d565b611d31565b60405161055f9493929190613fae565b60405180910390f35b610582600480360381019061057d9190613ffa565b611db1565b60405161058f9190613ac2565b60405180910390f35b3480156105a457600080fd5b506105bf60048036038101906105ba9190613b5d565b611de5565b6040516105cc9190613d38565b60405180910390f35b3480156105e157600080fd5b506105fc60048036038101906105f79190613b5d565b611f51565b6040516106099190613ac2565b60405180910390f35b34801561061e57600080fd5b50610627611f67565b604051610634919061403a565b60405180910390f35b34801561064957600080fd5b50610664600480360381019061065f9190613b5d565b611f8b565b6040516106719190614064565b60405180910390f35b34801561068657600080fd5b506106a1600480360381019061069c919061407f565b611fa1565b005b3480156106af57600080fd5b506106ca60048036038101906106c59190613b5d565b612415565b6040516106d79190613ac2565b60405180910390f35b3480156106ec57600080fd5b5061070760048036038101906107029190613b5d565b612431565b604051610719969594939291906140f0565b60405180910390f35b34801561072e57600080fd5b5061074960048036038101906107449190613b5d565b6124d0565b6040516107569190614268565b60405180910390f35b6107796004803603810190610774919061428a565b6125b9565b6040516107869190613ac2565b60405180910390f35b34801561079b57600080fd5b506107a46125ed565b6040516107b19190613858565b60405180910390f35b3480156107c657600080fd5b506107cf612611565b6040516107dc919061403a565b60405180910390f35b3480156107f157600080fd5b506107fa612635565b60405161080791906142ea565b60405180910390f35b61082a60048036038101906108259190613b5d565b61266e565b6040516108379190613ac2565b60405180910390f35b34801561084c57600080fd5b50610867600480360381019061086291906143b8565b6126a2565b005b34801561087557600080fd5b50610890600480360381019061088b9190613b5d565b612905565b005b34801561089e57600080fd5b506108b960048036038101906108b4919061444d565b612b5d565b6040516108c69190613d38565b60405180910390f35b60006108f5856108de84611051565b8686612c199190939291909392919063ffffffff16565b9050949350505050565b817f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a47d29cb826040518263ffffffff1660e01b81526004016109599190613ac2565b602060405180830381865afa158015610976573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099a91906144cb565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610a07576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109fe90614544565b60405180910390fd5b6000600160008581526020019081526020016000209050828160000160076101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505050565b827f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a47d29cb826040518263ffffffff1660e01b8152600401610ac19190613ac2565b602060405180830381865afa158015610ade573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b0291906144cb565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610b6f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b6690614544565b60405180910390fd5b600060016000868152602001908152602001600020905060018160000160016101000a81548160ff021916908315150217905550828160030160008660ff1660ff168152602001908152602001600020600201819055505050505050565b817f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a47d29cb826040518263ffffffff1660e01b8152600401610c279190613ac2565b602060405180830381865afa158015610c44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c6891906144cb565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610cd5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ccc90614544565b60405180910390fd5b6000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16630ea5613f866040518263ffffffff1660e01b8152600401610d319190613ac2565b60c060405180830381865afa158015610d4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d7291906145a5565b90919250909150905050809350819250505081841115610dc7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dbe906146ca565b60405180910390fd5b80841015610e0a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e0190614782565b60405180910390fd5b836001600087815260200190815260200160002060000160046101000a81548162ffffff021916908362ffffff1602179055508381146001600087815260200190815260200160002060000160006101000a81548160ff021916908315150217905550847f8445d32a2ee05956c6c842357ca16ee41e92657b1cbcbf1c94f500672e48c3b185604051610e9d9190613ac2565b60405180910390a25050505050565b6000610ecb610eba83611051565b8585612c329290919263ffffffff16565b90509392505050565b60006040517fd0df97cc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b827f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a47d29cb826040518263ffffffff1660e01b8152600401610f629190613ac2565b602060405180830381865afa158015610f7f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fa391906144cb565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611010576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161100790614544565b60405180910390fd5b6000600160008681526020019081526020016000209050828160030160008660ff1660ff168152602001908152602001600020600101819055505050505050565b60008160405160200161106491906147ea565b604051602081830303815290604052805190602001209050919050565b6040517fd0df97cc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006001600083815260200190815260200160002060000160009054906101000a900460ff169050919050565b847f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a47d29cb826040518263ffffffff1660e01b815260040161113a9190613ac2565b602060405180830381865afa158015611157573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117b91906144cb565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146111e8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111df90614544565b60405180910390fd5b428563ffffffff1611611230576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161122790614851565b60405180910390fd5b60006001600088815260200190815260200160002090508060000160009054906101000a900460ff1615611299576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611290906148bd565b60405180910390fd5b6000808260000160039054906101000a900460ff1660ff16036112dc576001905060018260000160016101000a81548160ff0219169083151502179055506112fd565b60018260000160039054906101000a900460ff166112fa919061490c565b90505b81600001600381819054906101000a900460ff1660010191906101000a81548160ff021916908360ff1602179055506040518060a001604052808260ff1681526020018560ff1681526020018863ffffffff168152602001878152602001868152508260030160008360ff1660ff16815260200190815260200160002060008201518160000160006101000a81548160ff021916908360ff16021790555060208201518160000160016101000a81548160ff021916908360ff16021790555060408201518160000160026101000a81548163ffffffff021916908363ffffffff16021790555060608201518160010155608082015181600201559050505050505050505050565b60006001600085815260200190815260200160002060020160008460ff1660ff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490509392505050565b60006001600083815260200190815260200160002060000160049054906101000a900462ffffff1662ffffff169050919050565b60006114b982611de5565b608001519050919050565b6114cc613688565b60006114d7836124d0565b905060008151905060005b818110156115b6578281815181106114fd576114fc614941565b5b60200260200101516040015163ffffffff1642106115ab57816001826115239190614970565b1061154d5782818151811061153b5761153a614941565b5b602002602001015193505050506115c6565b8260018261155b9190614970565b8151811061156c5761156b614941565b5b60200260200101516040015163ffffffff164210156115aa5782818151811061159857611597614941565b5b602002602001015193505050506115c6565b5b8060010190506114e2565b506115bf613688565b8093505050505b919050565b6115d3612c8a565b60008a905060008a905060008a8a8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050905060006001600085815260200190815260200160002090508060000160009054906101000a900460ff161561168f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611686906149f0565b60405180910390fd5b600061169a856114c4565b9050806000015160ff168260000160029054906101000a900460ff1660ff16146116e05780600001518260000160026101000a81548160ff021916908360ff1602179055505b6000816040015163ffffffff160361172d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161172490614a5c565b60405180910390fd5b8160000160019054906101000a900460ff1661177e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161177590614ac8565b60405180910390fd5b60008461178a87611f51565b6117949190614ae8565b90508034146117d8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117cf90614b76565b60405180910390fd5b8260010188886040516117ec929190614bd5565b908152602001604051809103902060009054906101000a900460ff1615611848576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161183f90614c3a565b60405180910390fd5b6118a38360000160079054906101000a900473ffffffffffffffffffffffffffffffffffffffff1633878b8b6040516020016118879493929190614c7b565b6040516020818303038152906040528051906020012086612cd9565b6118e2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118d990614d02565b60405180910390fd5b6000808d8d8101906118f49190614d37565b915091503373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614611966576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161195d90614dc3565b60405180910390fd5b60008082119050600073ffffffffffffffffffffffffffffffffffffffff1661198e8a6114c4565b6060015160001c73ffffffffffffffffffffffffffffffffffffffff1614611a6c576000336040516020016119c391906147ea565b604051602081830303815290604052805190602001209050611a2b8e8e80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f82011690508083019250505050505050876060015183612da1565b611a6a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a6190614e2f565b60405180910390fd5b505b8015611b1d578188876002016000886000015160ff1660ff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054611adb9190614970565b1115611b1c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b1390614e9b565b60405180910390fd5b5b6001866001018c8c604051611b33929190614bd5565b908152602001604051809103902060006101000a81548160ff02191690831515021790555087866002016000876000015160ff1660ff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555060005b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16630d4d1513338d336040518463ffffffff1660e01b8152600401611c2493929190614ebb565b6020604051808303816000875af1158015611c43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c679190614ef2565b905060018860000160049054906101000a900462ffffff160362ffffff16620f42408281611c9857611c97614f1f565b5b0603611cda5760018860000160006101000a81548160ff02191690831515021790555060008860000160026101000a81548160ff021916908360ff1602179055505b81600101915050888110611bc557611d138a347f0000000000000000000000000000000000000000000000000000000000000000612db8565b50505050505050505050611d25612e9b565b50505050505050505050565b60008060606000806001600087815260200190815260200160002090508060000160019054906101000a900460ff169450611d6b86611f51565b93506040518060400160405280600381526020017f4554480000000000000000000000000000000000000000000000000000000000815250925060009150509193509193565b60006040517fd0df97cc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611ded613688565b60006001600084815260200190815260200160002090506000611e0f846114c4565b90506000816000015160ff1603611e2a578092505050611f4c565b600082600301600060018560000160029054906101000a900460ff16611e50919061490c565b60ff1660ff16815260200190815260200160002060000160009054906101000a900460ff1660ff1614611f3d5781600301600060018460000160029054906101000a900460ff16611ea1919061490c565b60ff1660ff1681526020019081526020016000206040518060a00160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900460ff1660ff1660ff1681526020016000820160029054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016001820154815260200160028201548152505092505050611f4c565b611f45613688565b8093505050505b919050565b6000611f5c826114c4565b608001519050919050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000611f96826114c4565b600001519050919050565b827f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a47d29cb826040518263ffffffff1660e01b8152600401611ffb9190613ac2565b602060405180830381865afa158015612018573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061203c91906144cb565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146120a9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120a090614544565b60405180910390fd5b60008360ff16116120ef576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120e690614f9a565b60405180910390fd5b600060016000868152602001908152602001600020905060008160000160039054906101000a900460ff1660ff161161215d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161215490615006565b60405180910390fd5b60008363ffffffff16116121a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161219d90614f9a565b60405180910390fd5b428363ffffffff16116121ee576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121e590615072565b60405180910390fd5b8060000160039054906101000a900460ff1660ff168460ff161115612248576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161223f906150de565b60405180910390fd5b8060000160039054906101000a900460ff1660ff168460ff16036122a857828160030160008660ff1660ff16815260200190815260200160002060000160026101000a81548163ffffffff021916908363ffffffff16021790555061240e565b8060000160039054906101000a900460ff1660ff166001856122ca919061490c565b60ff161161240d5760008160030160006001876122e7919061490c565b60ff1660ff1681526020019081526020016000206040518060a00160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900460ff1660ff1660ff1681526020016000820160029054906101000a900463ffffffff1663ffffffff1663ffffffff168152602001600182015481526020016002820154815250509050806040015163ffffffff168463ffffffff16106123ce576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123c59061514a565b60405180910390fd5b838260030160008760ff1660ff16815260200190815260200160002060000160026101000a81548163ffffffff021916908363ffffffff160217905550505b5b5050505050565b600061242082611de5565b6040015163ffffffff169050919050565b60016020528060005260406000206000915090508060000160009054906101000a900460ff16908060000160019054906101000a900460ff16908060000160029054906101000a900460ff16908060000160039054906101000a900460ff16908060000160049054906101000a900462ffffff16908060000160079054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905086565b6060600060016000848152602001908152602001600020905060008160000160039054906101000a900460ff16905060008160ff1667ffffffffffffffff81111561251e5761251d61516a565b5b60405190808252806020026020018201604052801561255757816020015b612544613688565b81526020019060019003908161253c5790505b50905060005b8260ff168160ff1610156125ad576125818660018361257c919061490c565b612b5d565b828260ff168151811061259757612596614941565b5b602002602001018190525080600101905061255d565b50809350505050919050565b60006040517fd0df97cc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6040518060400160405280601381526020017f4d756c74694d65726b6c654d696e74657256310000000000000000000000000081525081565b60006040517fd0df97cc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b847f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a47d29cb826040518263ffffffff1660e01b81526004016126fc9190613ac2565b602060405180830381865afa158015612719573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061273d91906144cb565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146127aa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127a190614544565b60405180910390fd5b8282905085859050146127f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127e9906151e5565b60405180910390fd5b60008585905090506000805b5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16630d4d151389898581811061284e5761284d614941565b5b90506020020160208101906128639190613b30565b8b336040518463ffffffff1660e01b815260040161288393929190614ebb565b6020604051808303816000875af11580156128a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128c69190614ef2565b508060010190508585838181106128e0576128df614941565b5b9050602002013581106127ff578160010191508282106127fe57505050505050505050565b807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a47d29cb826040518263ffffffff1660e01b815260040161295f9190613ac2565b602060405180830381865afa15801561297c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129a091906144cb565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612a0d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a0490614544565b60405180910390fd5b6000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16630ea5613f856040518263ffffffff1660e01b8152600401612a699190613ac2565b60c060405180830381865afa158015612a86573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612aaa91906145a5565b909192509091509050508093508192505050816001600086815260200190815260200160002060000160046101000a81548162ffffff021916908362ffffff1602179055508181146001600086815260200190815260200160002060000160006101000a81548160ff021916908315150217905550837f8445d32a2ee05956c6c842357ca16ee41e92657b1cbcbf1c94f500672e48c3b183604051612b4f9190613ac2565b60405180910390a250505050565b612b65613688565b6001600084815260200190815260200160002060030160008360ff1660ff1681526020019081526020016000206040518060a00160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900460ff1660ff1660ff1681526020016000820160029054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160018201548152602001600282015481525050905092915050565b600082612c27868685612c32565b149050949350505050565b60008082905060005b85859050811015612c7e57612c6982878784818110612c5d57612c5c614941565b5b90506020020135612ea5565b91508080612c7690615205565b915050612c3b565b50809150509392505050565b600260005403612ccf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612cc690615299565b60405180910390fd5b6002600081905550565b60008073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603612d49576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d4090615305565b60405180910390fd5b6000612d5484612ed0565b90508473ffffffffffffffffffffffffffffffffffffffff16612d808483612f0090919063ffffffff16565b73ffffffffffffffffffffffffffffffffffffffff16149150509392505050565b600082612dae8584612f27565b1490509392505050565b6000341115612e96576000808334612dd09190615325565b90506000811115612e88573373ffffffffffffffffffffffffffffffffffffffff1681604051612dff9061538a565b60006040518083038185875af1925050503d8060008114612e3c576040519150601f19603f3d011682016040523d82523d6000602084013e612e41565b606091505b50508092505081612e87576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e7e906153eb565b60405180910390fd5b5b612e93858585612f7d565b50505b505050565b6001600081905550565b6000818310612ebd57612eb882846133d8565b612ec8565b612ec783836133d8565b5b905092915050565b600081604051602001612ee39190615478565b604051602081830303815290604052805190602001209050919050565b6000806000612f0f85856133ef565b91509150612f1c81613440565b819250505092915050565b60008082905060005b8451811015612f7257612f5d82868381518110612f5057612f4f614941565b5b6020026020010151612ea5565b91508080612f6a90615205565b915050612f30565b508091505092915050565b60008211156133d35760008060008060008060007f000000000000000000000000000000000000000000000000000000000000000015613114576000808973ffffffffffffffffffffffffffffffffffffffff16638639415b8d8d6040518363ffffffff1660e01b8152600401612ff592919061549e565b61010060405180830381865afa158015613013573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061303791906154c7565b809a50819b50829c50839d50849850859950869e50879f505050505050505050600082111561310d578073ffffffffffffffffffffffffffffffffffffffff16826040516130849061538a565b60006040518083038185875af1925050503d80600081146130c1576040519150601f19603f3d011682016040523d82523d6000602084013e6130c6565b606091505b5050809950508861310c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613103906155c9565b60405180910390fd5b5b50506131a9565b8773ffffffffffffffffffffffffffffffffffffffff16638639415b8b8b6040518363ffffffff1660e01b815260040161314f92919061549e565b60c060405180830381865afa15801561316c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061319091906155e9565b809650819750829850839950849a50859b505050505050505b600086111561325f578473ffffffffffffffffffffffffffffffffffffffff16866040516131d69061538a565b60006040518083038185875af1925050503d8060008114613213576040519150601f19603f3d011682016040523d82523d6000602084013e613218565b606091505b5050809750508661325e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613255906156c2565b60405180910390fd5b5b6000841115613315578273ffffffffffffffffffffffffffffffffffffffff168460405161328c9061538a565b60006040518083038185875af1925050503d80600081146132c9576040519150601f19603f3d011682016040523d82523d6000602084013e6132ce565b606091505b50508097505086613314576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161330b9061572e565b60405180910390fd5b5b60008211156133cb578073ffffffffffffffffffffffffffffffffffffffff16826040516133429061538a565b60006040518083038185875af1925050503d806000811461337f576040519150601f19603f3d011682016040523d82523d6000602084013e613384565b606091505b505080975050866133ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016133c19061579a565b60405180910390fd5b5b505050505050505b505050565b600082600052816020526040600020905092915050565b60008060418351036134305760008060006020860151925060408601519150606086015160001a9050613424878285856135a6565b94509450505050613439565b60006002915091505b9250929050565b60006004811115613454576134536157ba565b5b816004811115613467576134666157ba565b5b03156135a35760016004811115613481576134806157ba565b5b816004811115613494576134936157ba565b5b036134d4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016134cb90615835565b60405180910390fd5b600260048111156134e8576134e76157ba565b5b8160048111156134fb576134fa6157ba565b5b0361353b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613532906158a1565b60405180910390fd5b6003600481111561354f5761354e6157ba565b5b816004811115613562576135616157ba565b5b036135a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161359990615933565b60405180910390fd5b5b50565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08360001c11156135e157600060039150915061367f565b6000600187878787604051600081526020016040526040516136069493929190615953565b6020604051602081039080840390855afa158015613628573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036136765760006001925092505061367f565b80600092509250505b94509492505050565b6040518060a00160405280600060ff168152602001600060ff168152602001600063ffffffff16815260200160008019168152602001600081525090565b600080fd5b600080fd5b6000819050919050565b6136e3816136d0565b81146136ee57600080fd5b50565b600081359050613700816136da565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f84011261372b5761372a613706565b5b8235905067ffffffffffffffff8111156137485761374761370b565b5b60208301915083602082028301111561376457613763613710565b5b9250929050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006137968261376b565b9050919050565b6137a68161378b565b81146137b157600080fd5b50565b6000813590506137c38161379d565b92915050565b600080600080606085870312156137e3576137e26136c6565b5b60006137f1878288016136f1565b945050602085013567ffffffffffffffff811115613812576138116136cb565b5b61381e87828801613715565b93509350506040613831878288016137b4565b91505092959194509250565b60008115159050919050565b6138528161383d565b82525050565b600060208201905061386d6000830184613849565b92915050565b6000819050919050565b61388681613873565b811461389157600080fd5b50565b6000813590506138a38161387d565b92915050565b600080604083850312156138c0576138bf6136c6565b5b60006138ce85828601613894565b92505060206138df858286016137b4565b9150509250929050565b600060ff82169050919050565b6138ff816138e9565b811461390a57600080fd5b50565b60008135905061391c816138f6565b92915050565b60008060006060848603121561393b5761393a6136c6565b5b600061394986828701613894565b935050602061395a8682870161390d565b925050604061396b86828701613894565b9150509250925092565b6000806040838503121561398c5761398b6136c6565b5b600061399a85828601613894565b92505060206139ab85828601613894565b9150509250929050565b6000806000604084860312156139ce576139cd6136c6565b5b600084013567ffffffffffffffff8111156139ec576139eb6136cb565b5b6139f886828701613715565b93509350506020613a0b868287016137b4565b9150509250925092565b613a1e816136d0565b82525050565b6000602082019050613a396000830184613a15565b92915050565b60008060008060608587031215613a5957613a586136c6565b5b6000613a67878288016137b4565b9450506020613a7887828801613894565b935050604085013567ffffffffffffffff811115613a9957613a986136cb565b5b613aa587828801613715565b925092505092959194509250565b613abc81613873565b82525050565b6000602082019050613ad76000830184613ab3565b92915050565b600080600060608486031215613af657613af56136c6565b5b6000613b0486828701613894565b9350506020613b158682870161390d565b9250506040613b26868287016136f1565b9150509250925092565b600060208284031215613b4657613b456136c6565b5b6000613b54848285016137b4565b91505092915050565b600060208284031215613b7357613b726136c6565b5b6000613b8184828501613894565b91505092915050565b600063ffffffff82169050919050565b613ba381613b8a565b8114613bae57600080fd5b50565b600081359050613bc081613b9a565b92915050565b600080600080600060a08688031215613be257613be16136c6565b5b6000613bf088828901613894565b9550506020613c0188828901613bb1565b9450506040613c12888289016136f1565b9350506060613c2388828901613894565b9250506080613c348882890161390d565b9150509295509295909350565b600080600060608486031215613c5a57613c596136c6565b5b6000613c6886828701613894565b9350506020613c798682870161390d565b9250506040613c8a868287016137b4565b9150509250925092565b613c9d816138e9565b82525050565b613cac81613b8a565b82525050565b613cbb816136d0565b82525050565b613cca81613873565b82525050565b60a082016000820151613ce66000850182613c94565b506020820151613cf96020850182613c94565b506040820151613d0c6040850182613ca3565b506060820151613d1f6060850182613cb2565b506080820151613d326080850182613cc1565b50505050565b600060a082019050613d4d6000830184613cd0565b92915050565b60008083601f840112613d6957613d68613706565b5b8235905067ffffffffffffffff811115613d8657613d8561370b565b5b602083019150836001820283011115613da257613da1613710565b5b9250929050565b60008083601f840112613dbf57613dbe613706565b5b8235905067ffffffffffffffff811115613ddc57613ddb61370b565b5b602083019150836001820283011115613df857613df7613710565b5b9250929050565b60008060008060008060008060008060c08b8d031215613e2257613e216136c6565b5b6000613e308d828e01613894565b9a50506020613e418d828e01613894565b99505060408b013567ffffffffffffffff811115613e6257613e616136cb565b5b613e6e8d828e01613d53565b985098505060608b013567ffffffffffffffff811115613e9157613e906136cb565b5b613e9d8d828e01613d53565b965096505060808b013567ffffffffffffffff811115613ec057613ebf6136cb565b5b613ecc8d828e01613715565b945094505060a08b013567ffffffffffffffff811115613eef57613eee6136cb565b5b613efb8d828e01613da9565b92509250509295989b9194979a5092959850565b600081519050919050565b600082825260208201905092915050565b60005b83811015613f49578082015181840152602081019050613f2e565b60008484015250505050565b6000601f19601f8301169050919050565b6000613f7182613f0f565b613f7b8185613f1a565b9350613f8b818560208601613f2b565b613f9481613f55565b840191505092915050565b613fa88161378b565b82525050565b6000608082019050613fc36000830187613849565b613fd06020830186613ab3565b8181036040830152613fe28185613f66565b9050613ff16060830184613f9f565b95945050505050565b60008060408385031215614011576140106136c6565b5b600061401f858286016137b4565b925050602061403085828601613894565b9150509250929050565b600060208201905061404f6000830184613f9f565b92915050565b61405e816138e9565b82525050565b60006020820190506140796000830184614055565b92915050565b600080600060608486031215614098576140976136c6565b5b60006140a686828701613894565b93505060206140b78682870161390d565b92505060406140c886828701613bb1565b9150509250925092565b600062ffffff82169050919050565b6140ea816140d2565b82525050565b600060c0820190506141056000830189613849565b6141126020830188613849565b61411f6040830187614055565b61412c6060830186614055565b61413960808301856140e1565b61414660a0830184613f9f565b979650505050505050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60a0820160008201516141936000850182613c94565b5060208201516141a66020850182613c94565b5060408201516141b96040850182613ca3565b5060608201516141cc6060850182613cb2565b5060808201516141df6080850182613cc1565b50505050565b60006141f1838361417d565b60a08301905092915050565b6000602082019050919050565b600061421582614151565b61421f818561415c565b935061422a8361416d565b8060005b8381101561425b57815161424288826141e5565b975061424d836141fd565b92505060018101905061422e565b5085935050505092915050565b60006020820190508181036000830152614282818461420a565b905092915050565b6000806000604084860312156142a3576142a26136c6565b5b60006142b186828701613894565b935050602084013567ffffffffffffffff8111156142d2576142d16136cb565b5b6142de86828701613715565b92509250509250925092565b600060208201905081810360008301526143048184613f66565b905092915050565b60008083601f84011261432257614321613706565b5b8235905067ffffffffffffffff81111561433f5761433e61370b565b5b60208301915083602082028301111561435b5761435a613710565b5b9250929050565b60008083601f84011261437857614377613706565b5b8235905067ffffffffffffffff8111156143955761439461370b565b5b6020830191508360208202830111156143b1576143b0613710565b5b9250929050565b6000806000806000606086880312156143d4576143d36136c6565b5b60006143e288828901613894565b955050602086013567ffffffffffffffff811115614403576144026136cb565b5b61440f8882890161430c565b9450945050604086013567ffffffffffffffff811115614432576144316136cb565b5b61443e88828901614362565b92509250509295509295909350565b60008060408385031215614464576144636136c6565b5b600061447285828601613894565b92505060206144838582860161390d565b9150509250929050565b60006144988261376b565b9050919050565b6144a88161448d565b81146144b357600080fd5b50565b6000815190506144c58161449f565b92915050565b6000602082840312156144e1576144e06136c6565b5b60006144ef848285016144b6565b91505092915050565b7f4f6e6c7920417274697374000000000000000000000000000000000000000000600082015250565b600061452e600b83613f1a565b9150614539826144f8565b602082019050919050565b6000602082019050818103600083015261455d81614521565b9050919050565b6000815190506145738161387d565b92915050565b6145828161383d565b811461458d57600080fd5b50565b60008151905061459f81614579565b92915050565b60008060008060008060c087890312156145c2576145c16136c6565b5b60006145d089828a01614564565b96505060206145e189828a01614564565b95505060406145f289828a01614590565b945050606061460389828a01614590565b935050608061461489828a01614564565b92505060a061462589828a01614590565b9150509295509295509295565b7f43616e6e6f7420696e6372656173652070726f6a656374206d617820696e766f60008201527f636174696f6e732061626f766520636f726520636f6e7472616374207365742060208201527f70726f6a656374206d617820696e766f636174696f6e73000000000000000000604082015250565b60006146b4605783613f1a565b91506146bf82614632565b606082019050919050565b600060208201905081810360008301526146e3816146a7565b9050919050565b7f43616e6e6f74207365742070726f6a656374206d617820696e766f636174696f60008201527f6e7320746f206c657373207468616e2063757272656e7420696e766f6361746960208201527f6f6e730000000000000000000000000000000000000000000000000000000000604082015250565b600061476c604383613f1a565b9150614777826146ea565b606082019050919050565b6000602082019050818103600083015261479b8161475f565b9050919050565b60008160601b9050919050565b60006147ba826147a2565b9050919050565b60006147cc826147af565b9050919050565b6147e46147df8261378b565b6147c1565b82525050565b60006147f682846147d3565b60148201915081905092915050565b7f4e6f20537461727420426c6f636b20496e205061737400000000000000000000600082015250565b600061483b601683613f1a565b915061484682614805565b602082019050919050565b6000602082019050818103600083015261486a8161482e565b9050919050565b7f4d696e746564204f75742043616e7420437265617465204e6577205374616765600082015250565b60006148a7602083613f1a565b91506148b282614871565b602082019050919050565b600060208201905081810360008301526148d68161489a565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000614917826138e9565b9150614922836138e9565b9250828201905060ff81111561493b5761493a6148dd565b5b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600061497b82613873565b915061498683613873565b925082820190508082111561499e5761499d6148dd565b5b92915050565b7f4d617820496e766f636174696f6e732052656163686564000000000000000000600082015250565b60006149da601783613f1a565b91506149e5826149a4565b602082019050919050565b60006020820190508181036000830152614a09816149cd565b9050919050565b7f437265617465204120537461676520546f20426567696e000000000000000000600082015250565b6000614a46601783613f1a565b9150614a5182614a10565b602082019050919050565b60006020820190508181036000830152614a7581614a39565b9050919050565b7f5072696365204e6f7420436f6e66696775726564000000000000000000000000600082015250565b6000614ab2601483613f1a565b9150614abd82614a7c565b602082019050919050565b60006020820190508181036000830152614ae181614aa5565b9050919050565b6000614af382613873565b9150614afe83613873565b9250828202614b0c81613873565b91508282048414831517614b2357614b226148dd565b5b5092915050565b7f57726f6e67205072696365000000000000000000000000000000000000000000600082015250565b6000614b60600b83613f1a565b9150614b6b82614b2a565b602082019050919050565b60006020820190508181036000830152614b8f81614b53565b9050919050565b600081905092915050565b82818337600083830152505050565b6000614bbc8385614b96565b9350614bc9838584614ba1565b82840190509392505050565b6000614be2828486614bb0565b91508190509392505050565b7f4e6f6e6365205573656400000000000000000000000000000000000000000000600082015250565b6000614c24600a83613f1a565b9150614c2f82614bee565b602082019050919050565b60006020820190508181036000830152614c5381614c17565b9050919050565b6000819050919050565b614c75614c7082613873565b614c5a565b82525050565b6000614c8782876147d3565b601482019150614c978286614c64565b602082019150614ca8828486614bb0565b915081905095945050505050565b7f496e76616c6964205369676e6174757265000000000000000000000000000000600082015250565b6000614cec601183613f1a565b9150614cf782614cb6565b602082019050919050565b60006020820190508181036000830152614d1b81614cdf565b9050919050565b600081359050614d318161449f565b92915050565b60008060408385031215614d4e57614d4d6136c6565b5b6000614d5c85828601614d22565b9250506020614d6d85828601613894565b9150509250929050565b7f4261642044617461000000000000000000000000000000000000000000000000600082015250565b6000614dad600883613f1a565b9150614db882614d77565b602082019050919050565b60006020820190508181036000830152614ddc81614da0565b9050919050565b7f4e6f74204f6e20416c6c6f776c69737400000000000000000000000000000000600082015250565b6000614e19601083613f1a565b9150614e2482614de3565b602082019050919050565b60006020820190508181036000830152614e4881614e0c565b9050919050565b7f43616e2774204d696e742054686174204d616e79000000000000000000000000600082015250565b6000614e85601483613f1a565b9150614e9082614e4f565b602082019050919050565b60006020820190508181036000830152614eb481614e78565b9050919050565b6000606082019050614ed06000830186613f9f565b614edd6020830185613ab3565b614eea6040830184613f9f565b949350505050565b600060208284031215614f0857614f076136c6565b5b6000614f1684828501614564565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f43616e2774206265203000000000000000000000000000000000000000000000600082015250565b6000614f84600a83613f1a565b9150614f8f82614f4e565b602082019050919050565b60006020820190508181036000830152614fb381614f77565b9050919050565b7f4e6f2053746167657320657869737420666f722070726f6a6563740000000000600082015250565b6000614ff0601b83613f1a565b9150614ffb82614fba565b602082019050919050565b6000602082019050818103600083015261501f81614fe3565b9050919050565b7f4d75737420626520696e20746865206675747572650000000000000000000000600082015250565b600061505c601583613f1a565b915061506782615026565b602082019050919050565b6000602082019050818103600083015261508b8161504f565b9050919050565b7f537461676520646f65736e277420657869737400000000000000000000000000600082015250565b60006150c8601383613f1a565b91506150d382615092565b602082019050919050565b600060208201905081810360008301526150f7816150bb565b9050919050565b7f53746167652063616e2774207374617274206166746572206e657874206f6e65600082015250565b6000615134602083613f1a565b915061513f826150fe565b602082019050919050565b6000602082019050818103600083015261516381615127565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f556e657175616c20617272617973000000000000000000000000000000000000600082015250565b60006151cf600e83613f1a565b91506151da82615199565b602082019050919050565b600060208201905081810360008301526151fe816151c2565b9050919050565b600061521082613873565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615242576152416148dd565b5b600182019050919050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b6000615283601f83613f1a565b915061528e8261524d565b602082019050919050565b600060208201905081810360008301526152b281615276565b9050919050565b7f4d697373696e672053797374656d204164647265737300000000000000000000600082015250565b60006152ef601683613f1a565b91506152fa826152b9565b602082019050919050565b6000602082019050818103600083015261531e816152e2565b9050919050565b600061533082613873565b915061533b83613873565b9250828203905081811115615353576153526148dd565b5b92915050565b600081905092915050565b50565b6000615374600083615359565b915061537f82615364565b600082019050919050565b600061539582615367565b9150819050919050565b7f526566756e64206661696c656400000000000000000000000000000000000000600082015250565b60006153d5600d83613f1a565b91506153e08261539f565b602082019050919050565b60006020820190508181036000830152615404816153c8565b9050919050565b7f19457468657265756d205369676e6564204d6573736167653a0a333200000000600082015250565b6000615441601c83614b96565b915061544c8261540b565b601c82019050919050565b6000819050919050565b61547261546d826136d0565b615457565b82525050565b600061548382615434565b915061548f8284615461565b60208201915081905092915050565b60006040820190506154b36000830185613ab3565b6154c06020830184613ab3565b9392505050565b600080600080600080600080610100898b0312156154e8576154e76136c6565b5b60006154f68b828c01614564565b98505060206155078b828c016144b6565b97505060406155188b828c01614564565b96505060606155298b828c016144b6565b955050608061553a8b828c01614564565b94505060a061554b8b828c016144b6565b93505060c061555c8b828c01614564565b92505060e061556d8b828c016144b6565b9150509295985092959890939650565b7f506c6174666f726d2050726f7669646572207061796d656e74206661696c6564600082015250565b60006155b3602083613f1a565b91506155be8261557d565b602082019050919050565b600060208201905081810360008301526155e2816155a6565b9050919050565b60008060008060008060c08789031215615606576156056136c6565b5b600061561489828a01614564565b965050602061562589828a016144b6565b955050604061563689828a01614564565b945050606061564789828a016144b6565b935050608061565889828a01614564565b92505060a061566989828a016144b6565b9150509295509295509295565b7f52656e6465722050726f7669646572207061796d656e74206661696c65640000600082015250565b60006156ac601e83613f1a565b91506156b782615676565b602082019050919050565b600060208201905081810360008301526156db8161569f565b9050919050565b7f417274697374207061796d656e74206661696c65640000000000000000000000600082015250565b6000615718601583613f1a565b9150615723826156e2565b602082019050919050565b600060208201905081810360008301526157478161570b565b9050919050565b7f4164646974696f6e616c205061796565207061796d656e74206661696c656400600082015250565b6000615784601f83613f1a565b915061578f8261574e565b602082019050919050565b600060208201905081810360008301526157b381615777565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f45434453413a20696e76616c6964207369676e61747572650000000000000000600082015250565b600061581f601883613f1a565b915061582a826157e9565b602082019050919050565b6000602082019050818103600083015261584e81615812565b9050919050565b7f45434453413a20696e76616c6964207369676e6174757265206c656e67746800600082015250565b600061588b601f83613f1a565b915061589682615855565b602082019050919050565b600060208201905081810360008301526158ba8161587e565b9050919050565b7f45434453413a20696e76616c6964207369676e6174757265202773272076616c60008201527f7565000000000000000000000000000000000000000000000000000000000000602082015250565b600061591d602283613f1a565b9150615928826158c1565b604082019050919050565b6000602082019050818103600083015261594c81615910565b9050919050565b60006080820190506159686000830187613a15565b6159756020830186614055565b6159826040830185613a15565b61598f6060830184613a15565b9594505050505056fea2646970667358221220c51bb48a70916c9af3acc634454b189186eb302e1c2185c6726f2df957adb4e664736f6c63430008110033000000000000000000000000959d2f3caf19d20bdbb4e0a4f21ca8a815eddf650000000000000000000000003b90746ac1ccbfc5d6ac3a09d9930dc3b224a0f9
Deployed Bytecode
0x6080604052600436106101f95760003560e01c8063891407c01161010d578063c8a1f9b1116100a0578063e9d1e8ac1161006f578063e9d1e8ac146107e5578063efef39a114610810578063f002d9f314610840578063f7bd4b8814610869578063f849584d14610892576101f9565b8063c8a1f9b114610722578063da7e7c501461075f578063db6921b21461078f578063dd85582f146107ba576101f9565b8063a0b4cd18116100dc578063a0b4cd181461063d578063b836fefe1461067a578063c21ab44e146106a3578063c71b1b71146106e0576101f9565b8063891407c014610568578063894edcd414610598578063903488df146105d557806392a10f8314610612576101f9565b806340d1397e1161019057806356690aaf1161015f57806356690aaf1461045557806358f2a2b3146104925780635a23ac25146104cf578063676d9fcd1461050c578063774159c614610528576101f9565b806340d1397e14610389578063462add46146103b25780634fbd7fa1146103ef57806352b9c2d614610418576101f9565b80631ec2e523116101cc5780631ec2e523146102b6578063202c5805146102f357806325075249146103235780633aa5fe591461034c576101f9565b8063087b0581146101fe5780630f113ede1461023b5780631593e74c146102645780631607c9951461028d575b600080fd5b34801561020a57600080fd5b50610225600480360381019061022091906137c9565b6108cf565b6040516102329190613858565b60405180910390f35b34801561024757600080fd5b50610262600480360381019061025d91906138a9565b6108ff565b005b34801561027057600080fd5b5061028b60048036038101906102869190613922565b610a67565b005b34801561029957600080fd5b506102b460048036038101906102af9190613975565b610bcd565b005b3480156102c257600080fd5b506102dd60048036038101906102d891906139b5565b610eac565b6040516102ea9190613a24565b60405180910390f35b61030d60048036038101906103089190613a3f565b610ed4565b60405161031a9190613ac2565b60405180910390f35b34801561032f57600080fd5b5061034a60048036038101906103459190613add565b610f08565b005b34801561035857600080fd5b50610373600480360381019061036e9190613b30565b611051565b6040516103809190613a24565b60405180910390f35b34801561039557600080fd5b506103b060048036038101906103ab9190613b5d565b611081565b005b3480156103be57600080fd5b506103d960048036038101906103d49190613b5d565b6110b3565b6040516103e69190613858565b60405180910390f35b3480156103fb57600080fd5b5061041660048036038101906104119190613bc6565b6110e0565b005b34801561042457600080fd5b5061043f600480360381019061043a9190613c41565b611404565b60405161044c9190613ac2565b60405180910390f35b34801561046157600080fd5b5061047c60048036038101906104779190613b5d565b61147a565b6040516104899190613ac2565b60405180910390f35b34801561049e57600080fd5b506104b960048036038101906104b49190613b5d565b6114ae565b6040516104c69190613ac2565b60405180910390f35b3480156104db57600080fd5b506104f660048036038101906104f19190613b5d565b6114c4565b6040516105039190613d38565b60405180910390f35b61052660048036038101906105219190613dff565b6115cb565b005b34801561053457600080fd5b5061054f600480360381019061054a9190613b5d565b611d31565b60405161055f9493929190613fae565b60405180910390f35b610582600480360381019061057d9190613ffa565b611db1565b60405161058f9190613ac2565b60405180910390f35b3480156105a457600080fd5b506105bf60048036038101906105ba9190613b5d565b611de5565b6040516105cc9190613d38565b60405180910390f35b3480156105e157600080fd5b506105fc60048036038101906105f79190613b5d565b611f51565b6040516106099190613ac2565b60405180910390f35b34801561061e57600080fd5b50610627611f67565b604051610634919061403a565b60405180910390f35b34801561064957600080fd5b50610664600480360381019061065f9190613b5d565b611f8b565b6040516106719190614064565b60405180910390f35b34801561068657600080fd5b506106a1600480360381019061069c919061407f565b611fa1565b005b3480156106af57600080fd5b506106ca60048036038101906106c59190613b5d565b612415565b6040516106d79190613ac2565b60405180910390f35b3480156106ec57600080fd5b5061070760048036038101906107029190613b5d565b612431565b604051610719969594939291906140f0565b60405180910390f35b34801561072e57600080fd5b5061074960048036038101906107449190613b5d565b6124d0565b6040516107569190614268565b60405180910390f35b6107796004803603810190610774919061428a565b6125b9565b6040516107869190613ac2565b60405180910390f35b34801561079b57600080fd5b506107a46125ed565b6040516107b19190613858565b60405180910390f35b3480156107c657600080fd5b506107cf612611565b6040516107dc919061403a565b60405180910390f35b3480156107f157600080fd5b506107fa612635565b60405161080791906142ea565b60405180910390f35b61082a60048036038101906108259190613b5d565b61266e565b6040516108379190613ac2565b60405180910390f35b34801561084c57600080fd5b50610867600480360381019061086291906143b8565b6126a2565b005b34801561087557600080fd5b50610890600480360381019061088b9190613b5d565b612905565b005b34801561089e57600080fd5b506108b960048036038101906108b4919061444d565b612b5d565b6040516108c69190613d38565b60405180910390f35b60006108f5856108de84611051565b8686612c199190939291909392919063ffffffff16565b9050949350505050565b817f000000000000000000000000959d2f3caf19d20bdbb4e0a4f21ca8a815eddf6573ffffffffffffffffffffffffffffffffffffffff1663a47d29cb826040518263ffffffff1660e01b81526004016109599190613ac2565b602060405180830381865afa158015610976573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099a91906144cb565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610a07576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109fe90614544565b60405180910390fd5b6000600160008581526020019081526020016000209050828160000160076101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505050565b827f000000000000000000000000959d2f3caf19d20bdbb4e0a4f21ca8a815eddf6573ffffffffffffffffffffffffffffffffffffffff1663a47d29cb826040518263ffffffff1660e01b8152600401610ac19190613ac2565b602060405180830381865afa158015610ade573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b0291906144cb565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610b6f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b6690614544565b60405180910390fd5b600060016000868152602001908152602001600020905060018160000160016101000a81548160ff021916908315150217905550828160030160008660ff1660ff168152602001908152602001600020600201819055505050505050565b817f000000000000000000000000959d2f3caf19d20bdbb4e0a4f21ca8a815eddf6573ffffffffffffffffffffffffffffffffffffffff1663a47d29cb826040518263ffffffff1660e01b8152600401610c279190613ac2565b602060405180830381865afa158015610c44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c6891906144cb565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610cd5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ccc90614544565b60405180910390fd5b6000807f000000000000000000000000959d2f3caf19d20bdbb4e0a4f21ca8a815eddf6573ffffffffffffffffffffffffffffffffffffffff16630ea5613f866040518263ffffffff1660e01b8152600401610d319190613ac2565b60c060405180830381865afa158015610d4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d7291906145a5565b90919250909150905050809350819250505081841115610dc7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dbe906146ca565b60405180910390fd5b80841015610e0a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e0190614782565b60405180910390fd5b836001600087815260200190815260200160002060000160046101000a81548162ffffff021916908362ffffff1602179055508381146001600087815260200190815260200160002060000160006101000a81548160ff021916908315150217905550847f8445d32a2ee05956c6c842357ca16ee41e92657b1cbcbf1c94f500672e48c3b185604051610e9d9190613ac2565b60405180910390a25050505050565b6000610ecb610eba83611051565b8585612c329290919263ffffffff16565b90509392505050565b60006040517fd0df97cc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b827f000000000000000000000000959d2f3caf19d20bdbb4e0a4f21ca8a815eddf6573ffffffffffffffffffffffffffffffffffffffff1663a47d29cb826040518263ffffffff1660e01b8152600401610f629190613ac2565b602060405180830381865afa158015610f7f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fa391906144cb565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611010576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161100790614544565b60405180910390fd5b6000600160008681526020019081526020016000209050828160030160008660ff1660ff168152602001908152602001600020600101819055505050505050565b60008160405160200161106491906147ea565b604051602081830303815290604052805190602001209050919050565b6040517fd0df97cc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006001600083815260200190815260200160002060000160009054906101000a900460ff169050919050565b847f000000000000000000000000959d2f3caf19d20bdbb4e0a4f21ca8a815eddf6573ffffffffffffffffffffffffffffffffffffffff1663a47d29cb826040518263ffffffff1660e01b815260040161113a9190613ac2565b602060405180830381865afa158015611157573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117b91906144cb565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146111e8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111df90614544565b60405180910390fd5b428563ffffffff1611611230576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161122790614851565b60405180910390fd5b60006001600088815260200190815260200160002090508060000160009054906101000a900460ff1615611299576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611290906148bd565b60405180910390fd5b6000808260000160039054906101000a900460ff1660ff16036112dc576001905060018260000160016101000a81548160ff0219169083151502179055506112fd565b60018260000160039054906101000a900460ff166112fa919061490c565b90505b81600001600381819054906101000a900460ff1660010191906101000a81548160ff021916908360ff1602179055506040518060a001604052808260ff1681526020018560ff1681526020018863ffffffff168152602001878152602001868152508260030160008360ff1660ff16815260200190815260200160002060008201518160000160006101000a81548160ff021916908360ff16021790555060208201518160000160016101000a81548160ff021916908360ff16021790555060408201518160000160026101000a81548163ffffffff021916908363ffffffff16021790555060608201518160010155608082015181600201559050505050505050505050565b60006001600085815260200190815260200160002060020160008460ff1660ff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490509392505050565b60006001600083815260200190815260200160002060000160049054906101000a900462ffffff1662ffffff169050919050565b60006114b982611de5565b608001519050919050565b6114cc613688565b60006114d7836124d0565b905060008151905060005b818110156115b6578281815181106114fd576114fc614941565b5b60200260200101516040015163ffffffff1642106115ab57816001826115239190614970565b1061154d5782818151811061153b5761153a614941565b5b602002602001015193505050506115c6565b8260018261155b9190614970565b8151811061156c5761156b614941565b5b60200260200101516040015163ffffffff164210156115aa5782818151811061159857611597614941565b5b602002602001015193505050506115c6565b5b8060010190506114e2565b506115bf613688565b8093505050505b919050565b6115d3612c8a565b60008a905060008a905060008a8a8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050905060006001600085815260200190815260200160002090508060000160009054906101000a900460ff161561168f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611686906149f0565b60405180910390fd5b600061169a856114c4565b9050806000015160ff168260000160029054906101000a900460ff1660ff16146116e05780600001518260000160026101000a81548160ff021916908360ff1602179055505b6000816040015163ffffffff160361172d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161172490614a5c565b60405180910390fd5b8160000160019054906101000a900460ff1661177e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161177590614ac8565b60405180910390fd5b60008461178a87611f51565b6117949190614ae8565b90508034146117d8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117cf90614b76565b60405180910390fd5b8260010188886040516117ec929190614bd5565b908152602001604051809103902060009054906101000a900460ff1615611848576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161183f90614c3a565b60405180910390fd5b6118a38360000160079054906101000a900473ffffffffffffffffffffffffffffffffffffffff1633878b8b6040516020016118879493929190614c7b565b6040516020818303038152906040528051906020012086612cd9565b6118e2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118d990614d02565b60405180910390fd5b6000808d8d8101906118f49190614d37565b915091503373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614611966576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161195d90614dc3565b60405180910390fd5b60008082119050600073ffffffffffffffffffffffffffffffffffffffff1661198e8a6114c4565b6060015160001c73ffffffffffffffffffffffffffffffffffffffff1614611a6c576000336040516020016119c391906147ea565b604051602081830303815290604052805190602001209050611a2b8e8e80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f82011690508083019250505050505050876060015183612da1565b611a6a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a6190614e2f565b60405180910390fd5b505b8015611b1d578188876002016000886000015160ff1660ff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054611adb9190614970565b1115611b1c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b1390614e9b565b60405180910390fd5b5b6001866001018c8c604051611b33929190614bd5565b908152602001604051809103902060006101000a81548160ff02191690831515021790555087866002016000876000015160ff1660ff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555060005b60007f0000000000000000000000003b90746ac1ccbfc5d6ac3a09d9930dc3b224a0f973ffffffffffffffffffffffffffffffffffffffff16630d4d1513338d336040518463ffffffff1660e01b8152600401611c2493929190614ebb565b6020604051808303816000875af1158015611c43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c679190614ef2565b905060018860000160049054906101000a900462ffffff160362ffffff16620f42408281611c9857611c97614f1f565b5b0603611cda5760018860000160006101000a81548160ff02191690831515021790555060008860000160026101000a81548160ff021916908360ff1602179055505b81600101915050888110611bc557611d138a347f000000000000000000000000959d2f3caf19d20bdbb4e0a4f21ca8a815eddf65612db8565b50505050505050505050611d25612e9b565b50505050505050505050565b60008060606000806001600087815260200190815260200160002090508060000160019054906101000a900460ff169450611d6b86611f51565b93506040518060400160405280600381526020017f4554480000000000000000000000000000000000000000000000000000000000815250925060009150509193509193565b60006040517fd0df97cc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611ded613688565b60006001600084815260200190815260200160002090506000611e0f846114c4565b90506000816000015160ff1603611e2a578092505050611f4c565b600082600301600060018560000160029054906101000a900460ff16611e50919061490c565b60ff1660ff16815260200190815260200160002060000160009054906101000a900460ff1660ff1614611f3d5781600301600060018460000160029054906101000a900460ff16611ea1919061490c565b60ff1660ff1681526020019081526020016000206040518060a00160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900460ff1660ff1660ff1681526020016000820160029054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016001820154815260200160028201548152505092505050611f4c565b611f45613688565b8093505050505b919050565b6000611f5c826114c4565b608001519050919050565b7f000000000000000000000000959d2f3caf19d20bdbb4e0a4f21ca8a815eddf6581565b6000611f96826114c4565b600001519050919050565b827f000000000000000000000000959d2f3caf19d20bdbb4e0a4f21ca8a815eddf6573ffffffffffffffffffffffffffffffffffffffff1663a47d29cb826040518263ffffffff1660e01b8152600401611ffb9190613ac2565b602060405180830381865afa158015612018573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061203c91906144cb565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146120a9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120a090614544565b60405180910390fd5b60008360ff16116120ef576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120e690614f9a565b60405180910390fd5b600060016000868152602001908152602001600020905060008160000160039054906101000a900460ff1660ff161161215d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161215490615006565b60405180910390fd5b60008363ffffffff16116121a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161219d90614f9a565b60405180910390fd5b428363ffffffff16116121ee576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121e590615072565b60405180910390fd5b8060000160039054906101000a900460ff1660ff168460ff161115612248576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161223f906150de565b60405180910390fd5b8060000160039054906101000a900460ff1660ff168460ff16036122a857828160030160008660ff1660ff16815260200190815260200160002060000160026101000a81548163ffffffff021916908363ffffffff16021790555061240e565b8060000160039054906101000a900460ff1660ff166001856122ca919061490c565b60ff161161240d5760008160030160006001876122e7919061490c565b60ff1660ff1681526020019081526020016000206040518060a00160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900460ff1660ff1660ff1681526020016000820160029054906101000a900463ffffffff1663ffffffff1663ffffffff168152602001600182015481526020016002820154815250509050806040015163ffffffff168463ffffffff16106123ce576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123c59061514a565b60405180910390fd5b838260030160008760ff1660ff16815260200190815260200160002060000160026101000a81548163ffffffff021916908363ffffffff160217905550505b5b5050505050565b600061242082611de5565b6040015163ffffffff169050919050565b60016020528060005260406000206000915090508060000160009054906101000a900460ff16908060000160019054906101000a900460ff16908060000160029054906101000a900460ff16908060000160039054906101000a900460ff16908060000160049054906101000a900462ffffff16908060000160079054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905086565b6060600060016000848152602001908152602001600020905060008160000160039054906101000a900460ff16905060008160ff1667ffffffffffffffff81111561251e5761251d61516a565b5b60405190808252806020026020018201604052801561255757816020015b612544613688565b81526020019060019003908161253c5790505b50905060005b8260ff168160ff1610156125ad576125818660018361257c919061490c565b612b5d565b828260ff168151811061259757612596614941565b5b602002602001018190525080600101905061255d565b50809350505050919050565b60006040517fd0df97cc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000181565b7f0000000000000000000000003b90746ac1ccbfc5d6ac3a09d9930dc3b224a0f981565b6040518060400160405280601381526020017f4d756c74694d65726b6c654d696e74657256310000000000000000000000000081525081565b60006040517fd0df97cc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b847f000000000000000000000000959d2f3caf19d20bdbb4e0a4f21ca8a815eddf6573ffffffffffffffffffffffffffffffffffffffff1663a47d29cb826040518263ffffffff1660e01b81526004016126fc9190613ac2565b602060405180830381865afa158015612719573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061273d91906144cb565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146127aa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127a190614544565b60405180910390fd5b8282905085859050146127f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127e9906151e5565b60405180910390fd5b60008585905090506000805b5b7f0000000000000000000000003b90746ac1ccbfc5d6ac3a09d9930dc3b224a0f973ffffffffffffffffffffffffffffffffffffffff16630d4d151389898581811061284e5761284d614941565b5b90506020020160208101906128639190613b30565b8b336040518463ffffffff1660e01b815260040161288393929190614ebb565b6020604051808303816000875af11580156128a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128c69190614ef2565b508060010190508585838181106128e0576128df614941565b5b9050602002013581106127ff578160010191508282106127fe57505050505050505050565b807f000000000000000000000000959d2f3caf19d20bdbb4e0a4f21ca8a815eddf6573ffffffffffffffffffffffffffffffffffffffff1663a47d29cb826040518263ffffffff1660e01b815260040161295f9190613ac2565b602060405180830381865afa15801561297c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129a091906144cb565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612a0d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a0490614544565b60405180910390fd5b6000807f000000000000000000000000959d2f3caf19d20bdbb4e0a4f21ca8a815eddf6573ffffffffffffffffffffffffffffffffffffffff16630ea5613f856040518263ffffffff1660e01b8152600401612a699190613ac2565b60c060405180830381865afa158015612a86573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612aaa91906145a5565b909192509091509050508093508192505050816001600086815260200190815260200160002060000160046101000a81548162ffffff021916908362ffffff1602179055508181146001600086815260200190815260200160002060000160006101000a81548160ff021916908315150217905550837f8445d32a2ee05956c6c842357ca16ee41e92657b1cbcbf1c94f500672e48c3b183604051612b4f9190613ac2565b60405180910390a250505050565b612b65613688565b6001600084815260200190815260200160002060030160008360ff1660ff1681526020019081526020016000206040518060a00160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900460ff1660ff1660ff1681526020016000820160029054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160018201548152602001600282015481525050905092915050565b600082612c27868685612c32565b149050949350505050565b60008082905060005b85859050811015612c7e57612c6982878784818110612c5d57612c5c614941565b5b90506020020135612ea5565b91508080612c7690615205565b915050612c3b565b50809150509392505050565b600260005403612ccf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612cc690615299565b60405180910390fd5b6002600081905550565b60008073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603612d49576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d4090615305565b60405180910390fd5b6000612d5484612ed0565b90508473ffffffffffffffffffffffffffffffffffffffff16612d808483612f0090919063ffffffff16565b73ffffffffffffffffffffffffffffffffffffffff16149150509392505050565b600082612dae8584612f27565b1490509392505050565b6000341115612e96576000808334612dd09190615325565b90506000811115612e88573373ffffffffffffffffffffffffffffffffffffffff1681604051612dff9061538a565b60006040518083038185875af1925050503d8060008114612e3c576040519150601f19603f3d011682016040523d82523d6000602084013e612e41565b606091505b50508092505081612e87576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e7e906153eb565b60405180910390fd5b5b612e93858585612f7d565b50505b505050565b6001600081905550565b6000818310612ebd57612eb882846133d8565b612ec8565b612ec783836133d8565b5b905092915050565b600081604051602001612ee39190615478565b604051602081830303815290604052805190602001209050919050565b6000806000612f0f85856133ef565b91509150612f1c81613440565b819250505092915050565b60008082905060005b8451811015612f7257612f5d82868381518110612f5057612f4f614941565b5b6020026020010151612ea5565b91508080612f6a90615205565b915050612f30565b508091505092915050565b60008211156133d35760008060008060008060007f000000000000000000000000000000000000000000000000000000000000000115613114576000808973ffffffffffffffffffffffffffffffffffffffff16638639415b8d8d6040518363ffffffff1660e01b8152600401612ff592919061549e565b61010060405180830381865afa158015613013573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061303791906154c7565b809a50819b50829c50839d50849850859950869e50879f505050505050505050600082111561310d578073ffffffffffffffffffffffffffffffffffffffff16826040516130849061538a565b60006040518083038185875af1925050503d80600081146130c1576040519150601f19603f3d011682016040523d82523d6000602084013e6130c6565b606091505b5050809950508861310c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613103906155c9565b60405180910390fd5b5b50506131a9565b8773ffffffffffffffffffffffffffffffffffffffff16638639415b8b8b6040518363ffffffff1660e01b815260040161314f92919061549e565b60c060405180830381865afa15801561316c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061319091906155e9565b809650819750829850839950849a50859b505050505050505b600086111561325f578473ffffffffffffffffffffffffffffffffffffffff16866040516131d69061538a565b60006040518083038185875af1925050503d8060008114613213576040519150601f19603f3d011682016040523d82523d6000602084013e613218565b606091505b5050809750508661325e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613255906156c2565b60405180910390fd5b5b6000841115613315578273ffffffffffffffffffffffffffffffffffffffff168460405161328c9061538a565b60006040518083038185875af1925050503d80600081146132c9576040519150601f19603f3d011682016040523d82523d6000602084013e6132ce565b606091505b50508097505086613314576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161330b9061572e565b60405180910390fd5b5b60008211156133cb578073ffffffffffffffffffffffffffffffffffffffff16826040516133429061538a565b60006040518083038185875af1925050503d806000811461337f576040519150601f19603f3d011682016040523d82523d6000602084013e613384565b606091505b505080975050866133ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016133c19061579a565b60405180910390fd5b5b505050505050505b505050565b600082600052816020526040600020905092915050565b60008060418351036134305760008060006020860151925060408601519150606086015160001a9050613424878285856135a6565b94509450505050613439565b60006002915091505b9250929050565b60006004811115613454576134536157ba565b5b816004811115613467576134666157ba565b5b03156135a35760016004811115613481576134806157ba565b5b816004811115613494576134936157ba565b5b036134d4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016134cb90615835565b60405180910390fd5b600260048111156134e8576134e76157ba565b5b8160048111156134fb576134fa6157ba565b5b0361353b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613532906158a1565b60405180910390fd5b6003600481111561354f5761354e6157ba565b5b816004811115613562576135616157ba565b5b036135a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161359990615933565b60405180910390fd5b5b50565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08360001c11156135e157600060039150915061367f565b6000600187878787604051600081526020016040526040516136069493929190615953565b6020604051602081039080840390855afa158015613628573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036136765760006001925092505061367f565b80600092509250505b94509492505050565b6040518060a00160405280600060ff168152602001600060ff168152602001600063ffffffff16815260200160008019168152602001600081525090565b600080fd5b600080fd5b6000819050919050565b6136e3816136d0565b81146136ee57600080fd5b50565b600081359050613700816136da565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f84011261372b5761372a613706565b5b8235905067ffffffffffffffff8111156137485761374761370b565b5b60208301915083602082028301111561376457613763613710565b5b9250929050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006137968261376b565b9050919050565b6137a68161378b565b81146137b157600080fd5b50565b6000813590506137c38161379d565b92915050565b600080600080606085870312156137e3576137e26136c6565b5b60006137f1878288016136f1565b945050602085013567ffffffffffffffff811115613812576138116136cb565b5b61381e87828801613715565b93509350506040613831878288016137b4565b91505092959194509250565b60008115159050919050565b6138528161383d565b82525050565b600060208201905061386d6000830184613849565b92915050565b6000819050919050565b61388681613873565b811461389157600080fd5b50565b6000813590506138a38161387d565b92915050565b600080604083850312156138c0576138bf6136c6565b5b60006138ce85828601613894565b92505060206138df858286016137b4565b9150509250929050565b600060ff82169050919050565b6138ff816138e9565b811461390a57600080fd5b50565b60008135905061391c816138f6565b92915050565b60008060006060848603121561393b5761393a6136c6565b5b600061394986828701613894565b935050602061395a8682870161390d565b925050604061396b86828701613894565b9150509250925092565b6000806040838503121561398c5761398b6136c6565b5b600061399a85828601613894565b92505060206139ab85828601613894565b9150509250929050565b6000806000604084860312156139ce576139cd6136c6565b5b600084013567ffffffffffffffff8111156139ec576139eb6136cb565b5b6139f886828701613715565b93509350506020613a0b868287016137b4565b9150509250925092565b613a1e816136d0565b82525050565b6000602082019050613a396000830184613a15565b92915050565b60008060008060608587031215613a5957613a586136c6565b5b6000613a67878288016137b4565b9450506020613a7887828801613894565b935050604085013567ffffffffffffffff811115613a9957613a986136cb565b5b613aa587828801613715565b925092505092959194509250565b613abc81613873565b82525050565b6000602082019050613ad76000830184613ab3565b92915050565b600080600060608486031215613af657613af56136c6565b5b6000613b0486828701613894565b9350506020613b158682870161390d565b9250506040613b26868287016136f1565b9150509250925092565b600060208284031215613b4657613b456136c6565b5b6000613b54848285016137b4565b91505092915050565b600060208284031215613b7357613b726136c6565b5b6000613b8184828501613894565b91505092915050565b600063ffffffff82169050919050565b613ba381613b8a565b8114613bae57600080fd5b50565b600081359050613bc081613b9a565b92915050565b600080600080600060a08688031215613be257613be16136c6565b5b6000613bf088828901613894565b9550506020613c0188828901613bb1565b9450506040613c12888289016136f1565b9350506060613c2388828901613894565b9250506080613c348882890161390d565b9150509295509295909350565b600080600060608486031215613c5a57613c596136c6565b5b6000613c6886828701613894565b9350506020613c798682870161390d565b9250506040613c8a868287016137b4565b9150509250925092565b613c9d816138e9565b82525050565b613cac81613b8a565b82525050565b613cbb816136d0565b82525050565b613cca81613873565b82525050565b60a082016000820151613ce66000850182613c94565b506020820151613cf96020850182613c94565b506040820151613d0c6040850182613ca3565b506060820151613d1f6060850182613cb2565b506080820151613d326080850182613cc1565b50505050565b600060a082019050613d4d6000830184613cd0565b92915050565b60008083601f840112613d6957613d68613706565b5b8235905067ffffffffffffffff811115613d8657613d8561370b565b5b602083019150836001820283011115613da257613da1613710565b5b9250929050565b60008083601f840112613dbf57613dbe613706565b5b8235905067ffffffffffffffff811115613ddc57613ddb61370b565b5b602083019150836001820283011115613df857613df7613710565b5b9250929050565b60008060008060008060008060008060c08b8d031215613e2257613e216136c6565b5b6000613e308d828e01613894565b9a50506020613e418d828e01613894565b99505060408b013567ffffffffffffffff811115613e6257613e616136cb565b5b613e6e8d828e01613d53565b985098505060608b013567ffffffffffffffff811115613e9157613e906136cb565b5b613e9d8d828e01613d53565b965096505060808b013567ffffffffffffffff811115613ec057613ebf6136cb565b5b613ecc8d828e01613715565b945094505060a08b013567ffffffffffffffff811115613eef57613eee6136cb565b5b613efb8d828e01613da9565b92509250509295989b9194979a5092959850565b600081519050919050565b600082825260208201905092915050565b60005b83811015613f49578082015181840152602081019050613f2e565b60008484015250505050565b6000601f19601f8301169050919050565b6000613f7182613f0f565b613f7b8185613f1a565b9350613f8b818560208601613f2b565b613f9481613f55565b840191505092915050565b613fa88161378b565b82525050565b6000608082019050613fc36000830187613849565b613fd06020830186613ab3565b8181036040830152613fe28185613f66565b9050613ff16060830184613f9f565b95945050505050565b60008060408385031215614011576140106136c6565b5b600061401f858286016137b4565b925050602061403085828601613894565b9150509250929050565b600060208201905061404f6000830184613f9f565b92915050565b61405e816138e9565b82525050565b60006020820190506140796000830184614055565b92915050565b600080600060608486031215614098576140976136c6565b5b60006140a686828701613894565b93505060206140b78682870161390d565b92505060406140c886828701613bb1565b9150509250925092565b600062ffffff82169050919050565b6140ea816140d2565b82525050565b600060c0820190506141056000830189613849565b6141126020830188613849565b61411f6040830187614055565b61412c6060830186614055565b61413960808301856140e1565b61414660a0830184613f9f565b979650505050505050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60a0820160008201516141936000850182613c94565b5060208201516141a66020850182613c94565b5060408201516141b96040850182613ca3565b5060608201516141cc6060850182613cb2565b5060808201516141df6080850182613cc1565b50505050565b60006141f1838361417d565b60a08301905092915050565b6000602082019050919050565b600061421582614151565b61421f818561415c565b935061422a8361416d565b8060005b8381101561425b57815161424288826141e5565b975061424d836141fd565b92505060018101905061422e565b5085935050505092915050565b60006020820190508181036000830152614282818461420a565b905092915050565b6000806000604084860312156142a3576142a26136c6565b5b60006142b186828701613894565b935050602084013567ffffffffffffffff8111156142d2576142d16136cb565b5b6142de86828701613715565b92509250509250925092565b600060208201905081810360008301526143048184613f66565b905092915050565b60008083601f84011261432257614321613706565b5b8235905067ffffffffffffffff81111561433f5761433e61370b565b5b60208301915083602082028301111561435b5761435a613710565b5b9250929050565b60008083601f84011261437857614377613706565b5b8235905067ffffffffffffffff8111156143955761439461370b565b5b6020830191508360208202830111156143b1576143b0613710565b5b9250929050565b6000806000806000606086880312156143d4576143d36136c6565b5b60006143e288828901613894565b955050602086013567ffffffffffffffff811115614403576144026136cb565b5b61440f8882890161430c565b9450945050604086013567ffffffffffffffff811115614432576144316136cb565b5b61443e88828901614362565b92509250509295509295909350565b60008060408385031215614464576144636136c6565b5b600061447285828601613894565b92505060206144838582860161390d565b9150509250929050565b60006144988261376b565b9050919050565b6144a88161448d565b81146144b357600080fd5b50565b6000815190506144c58161449f565b92915050565b6000602082840312156144e1576144e06136c6565b5b60006144ef848285016144b6565b91505092915050565b7f4f6e6c7920417274697374000000000000000000000000000000000000000000600082015250565b600061452e600b83613f1a565b9150614539826144f8565b602082019050919050565b6000602082019050818103600083015261455d81614521565b9050919050565b6000815190506145738161387d565b92915050565b6145828161383d565b811461458d57600080fd5b50565b60008151905061459f81614579565b92915050565b60008060008060008060c087890312156145c2576145c16136c6565b5b60006145d089828a01614564565b96505060206145e189828a01614564565b95505060406145f289828a01614590565b945050606061460389828a01614590565b935050608061461489828a01614564565b92505060a061462589828a01614590565b9150509295509295509295565b7f43616e6e6f7420696e6372656173652070726f6a656374206d617820696e766f60008201527f636174696f6e732061626f766520636f726520636f6e7472616374207365742060208201527f70726f6a656374206d617820696e766f636174696f6e73000000000000000000604082015250565b60006146b4605783613f1a565b91506146bf82614632565b606082019050919050565b600060208201905081810360008301526146e3816146a7565b9050919050565b7f43616e6e6f74207365742070726f6a656374206d617820696e766f636174696f60008201527f6e7320746f206c657373207468616e2063757272656e7420696e766f6361746960208201527f6f6e730000000000000000000000000000000000000000000000000000000000604082015250565b600061476c604383613f1a565b9150614777826146ea565b606082019050919050565b6000602082019050818103600083015261479b8161475f565b9050919050565b60008160601b9050919050565b60006147ba826147a2565b9050919050565b60006147cc826147af565b9050919050565b6147e46147df8261378b565b6147c1565b82525050565b60006147f682846147d3565b60148201915081905092915050565b7f4e6f20537461727420426c6f636b20496e205061737400000000000000000000600082015250565b600061483b601683613f1a565b915061484682614805565b602082019050919050565b6000602082019050818103600083015261486a8161482e565b9050919050565b7f4d696e746564204f75742043616e7420437265617465204e6577205374616765600082015250565b60006148a7602083613f1a565b91506148b282614871565b602082019050919050565b600060208201905081810360008301526148d68161489a565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000614917826138e9565b9150614922836138e9565b9250828201905060ff81111561493b5761493a6148dd565b5b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600061497b82613873565b915061498683613873565b925082820190508082111561499e5761499d6148dd565b5b92915050565b7f4d617820496e766f636174696f6e732052656163686564000000000000000000600082015250565b60006149da601783613f1a565b91506149e5826149a4565b602082019050919050565b60006020820190508181036000830152614a09816149cd565b9050919050565b7f437265617465204120537461676520546f20426567696e000000000000000000600082015250565b6000614a46601783613f1a565b9150614a5182614a10565b602082019050919050565b60006020820190508181036000830152614a7581614a39565b9050919050565b7f5072696365204e6f7420436f6e66696775726564000000000000000000000000600082015250565b6000614ab2601483613f1a565b9150614abd82614a7c565b602082019050919050565b60006020820190508181036000830152614ae181614aa5565b9050919050565b6000614af382613873565b9150614afe83613873565b9250828202614b0c81613873565b91508282048414831517614b2357614b226148dd565b5b5092915050565b7f57726f6e67205072696365000000000000000000000000000000000000000000600082015250565b6000614b60600b83613f1a565b9150614b6b82614b2a565b602082019050919050565b60006020820190508181036000830152614b8f81614b53565b9050919050565b600081905092915050565b82818337600083830152505050565b6000614bbc8385614b96565b9350614bc9838584614ba1565b82840190509392505050565b6000614be2828486614bb0565b91508190509392505050565b7f4e6f6e6365205573656400000000000000000000000000000000000000000000600082015250565b6000614c24600a83613f1a565b9150614c2f82614bee565b602082019050919050565b60006020820190508181036000830152614c5381614c17565b9050919050565b6000819050919050565b614c75614c7082613873565b614c5a565b82525050565b6000614c8782876147d3565b601482019150614c978286614c64565b602082019150614ca8828486614bb0565b915081905095945050505050565b7f496e76616c6964205369676e6174757265000000000000000000000000000000600082015250565b6000614cec601183613f1a565b9150614cf782614cb6565b602082019050919050565b60006020820190508181036000830152614d1b81614cdf565b9050919050565b600081359050614d318161449f565b92915050565b60008060408385031215614d4e57614d4d6136c6565b5b6000614d5c85828601614d22565b9250506020614d6d85828601613894565b9150509250929050565b7f4261642044617461000000000000000000000000000000000000000000000000600082015250565b6000614dad600883613f1a565b9150614db882614d77565b602082019050919050565b60006020820190508181036000830152614ddc81614da0565b9050919050565b7f4e6f74204f6e20416c6c6f776c69737400000000000000000000000000000000600082015250565b6000614e19601083613f1a565b9150614e2482614de3565b602082019050919050565b60006020820190508181036000830152614e4881614e0c565b9050919050565b7f43616e2774204d696e742054686174204d616e79000000000000000000000000600082015250565b6000614e85601483613f1a565b9150614e9082614e4f565b602082019050919050565b60006020820190508181036000830152614eb481614e78565b9050919050565b6000606082019050614ed06000830186613f9f565b614edd6020830185613ab3565b614eea6040830184613f9f565b949350505050565b600060208284031215614f0857614f076136c6565b5b6000614f1684828501614564565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f43616e2774206265203000000000000000000000000000000000000000000000600082015250565b6000614f84600a83613f1a565b9150614f8f82614f4e565b602082019050919050565b60006020820190508181036000830152614fb381614f77565b9050919050565b7f4e6f2053746167657320657869737420666f722070726f6a6563740000000000600082015250565b6000614ff0601b83613f1a565b9150614ffb82614fba565b602082019050919050565b6000602082019050818103600083015261501f81614fe3565b9050919050565b7f4d75737420626520696e20746865206675747572650000000000000000000000600082015250565b600061505c601583613f1a565b915061506782615026565b602082019050919050565b6000602082019050818103600083015261508b8161504f565b9050919050565b7f537461676520646f65736e277420657869737400000000000000000000000000600082015250565b60006150c8601383613f1a565b91506150d382615092565b602082019050919050565b600060208201905081810360008301526150f7816150bb565b9050919050565b7f53746167652063616e2774207374617274206166746572206e657874206f6e65600082015250565b6000615134602083613f1a565b915061513f826150fe565b602082019050919050565b6000602082019050818103600083015261516381615127565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f556e657175616c20617272617973000000000000000000000000000000000000600082015250565b60006151cf600e83613f1a565b91506151da82615199565b602082019050919050565b600060208201905081810360008301526151fe816151c2565b9050919050565b600061521082613873565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615242576152416148dd565b5b600182019050919050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b6000615283601f83613f1a565b915061528e8261524d565b602082019050919050565b600060208201905081810360008301526152b281615276565b9050919050565b7f4d697373696e672053797374656d204164647265737300000000000000000000600082015250565b60006152ef601683613f1a565b91506152fa826152b9565b602082019050919050565b6000602082019050818103600083015261531e816152e2565b9050919050565b600061533082613873565b915061533b83613873565b9250828203905081811115615353576153526148dd565b5b92915050565b600081905092915050565b50565b6000615374600083615359565b915061537f82615364565b600082019050919050565b600061539582615367565b9150819050919050565b7f526566756e64206661696c656400000000000000000000000000000000000000600082015250565b60006153d5600d83613f1a565b91506153e08261539f565b602082019050919050565b60006020820190508181036000830152615404816153c8565b9050919050565b7f19457468657265756d205369676e6564204d6573736167653a0a333200000000600082015250565b6000615441601c83614b96565b915061544c8261540b565b601c82019050919050565b6000819050919050565b61547261546d826136d0565b615457565b82525050565b600061548382615434565b915061548f8284615461565b60208201915081905092915050565b60006040820190506154b36000830185613ab3565b6154c06020830184613ab3565b9392505050565b600080600080600080600080610100898b0312156154e8576154e76136c6565b5b60006154f68b828c01614564565b98505060206155078b828c016144b6565b97505060406155188b828c01614564565b96505060606155298b828c016144b6565b955050608061553a8b828c01614564565b94505060a061554b8b828c016144b6565b93505060c061555c8b828c01614564565b92505060e061556d8b828c016144b6565b9150509295985092959890939650565b7f506c6174666f726d2050726f7669646572207061796d656e74206661696c6564600082015250565b60006155b3602083613f1a565b91506155be8261557d565b602082019050919050565b600060208201905081810360008301526155e2816155a6565b9050919050565b60008060008060008060c08789031215615606576156056136c6565b5b600061561489828a01614564565b965050602061562589828a016144b6565b955050604061563689828a01614564565b945050606061564789828a016144b6565b935050608061565889828a01614564565b92505060a061566989828a016144b6565b9150509295509295509295565b7f52656e6465722050726f7669646572207061796d656e74206661696c65640000600082015250565b60006156ac601e83613f1a565b91506156b782615676565b602082019050919050565b600060208201905081810360008301526156db8161569f565b9050919050565b7f417274697374207061796d656e74206661696c65640000000000000000000000600082015250565b6000615718601583613f1a565b9150615723826156e2565b602082019050919050565b600060208201905081810360008301526157478161570b565b9050919050565b7f4164646974696f6e616c205061796565207061796d656e74206661696c656400600082015250565b6000615784601f83613f1a565b915061578f8261574e565b602082019050919050565b600060208201905081810360008301526157b381615777565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f45434453413a20696e76616c6964207369676e61747572650000000000000000600082015250565b600061581f601883613f1a565b915061582a826157e9565b602082019050919050565b6000602082019050818103600083015261584e81615812565b9050919050565b7f45434453413a20696e76616c6964207369676e6174757265206c656e67746800600082015250565b600061588b601f83613f1a565b915061589682615855565b602082019050919050565b600060208201905081810360008301526158ba8161587e565b9050919050565b7f45434453413a20696e76616c6964207369676e6174757265202773272076616c60008201527f7565000000000000000000000000000000000000000000000000000000000000602082015250565b600061591d602283613f1a565b9150615928826158c1565b604082019050919050565b6000602082019050818103600083015261594c81615910565b9050919050565b60006080820190506159686000830187613a15565b6159756020830186614055565b6159826040830185613a15565b61598f6060830184613a15565b9594505050505056fea2646970667358221220c51bb48a70916c9af3acc634454b189186eb302e1c2185c6726f2df957adb4e664736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000959d2f3caf19d20bdbb4e0a4f21ca8a815eddf650000000000000000000000003b90746ac1ccbfc5d6ac3a09d9930dc3b224a0f9
-----Decoded View---------------
Arg [0] : _genArt721Address (address): 0x959d2F3cAF19d20BDBb4e0A4f21cA8A815EDDF65
Arg [1] : _minterFilter (address): 0x3b90746ac1ccBFC5D6aC3a09d9930Dc3B224a0F9
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000959d2f3caf19d20bdbb4e0a4f21ca8a815eddf65
Arg [1] : 0000000000000000000000003b90746ac1ccbfc5d6ac3a09d9930dc3b224a0f9
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.