ETH Price: $2,683.09 (-0.69%)

Contract

0x58bB2431D80E571A50356d5f2e4EBe5c97C22A41
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Withdraw144767782022-03-28 20:23:121058 days ago1648498992IN
0x58bB2431...c97C22A41
0 ETH0.0024299667.11490121
Withdraw144767052022-03-28 20:06:531058 days ago1648498013IN
0x58bB2431...c97C22A41
0 ETH0.0028164477.81521132
Withdraw144766502022-03-28 19:55:141058 days ago1648497314IN
0x58bB2431...c97C22A41
0 ETH0.0028663479.22006465
Purchase144509882022-03-24 19:56:181062 days ago1648151778IN
0x58bB2431...c97C22A41
0.24 ETH0.0263336360.41347716
Purchase144508802022-03-24 19:30:401062 days ago1648150240IN
0x58bB2431...c97C22A41
0.08 ETH0.0152659243.47470389
Purchase144505502022-03-24 18:18:581062 days ago1648145938IN
0x58bB2431...c97C22A41
0.12 ETH0.0151739855.97375399
Purchase144467812022-03-24 4:13:221063 days ago1648095202IN
0x58bB2431...c97C22A41
0.12 ETH0.0101942740.13638239
Purchase144462752022-03-24 2:20:281063 days ago1648088428IN
0x58bB2431...c97C22A41
0.12 ETH0.0091132135.88005674
Purchase144444642022-03-23 19:32:481063 days ago1648063968IN
0x58bB2431...c97C22A41
0.12 ETH0.0105917237.42247347
Purchase144438002022-03-23 17:03:051063 days ago1648054985IN
0x58bB2431...c97C22A41
0.12 ETH0.007296626.91570549
Purchase144396792022-03-23 1:39:061064 days ago1647999546IN
0x58bB2431...c97C22A41
0.12 ETH0.0099088235.00969336
Purchase144308302022-03-21 16:39:121065 days ago1647880752IN
0x58bB2431...c97C22A41
0.12 ETH0.0101906836.00556101
Purchase144298192022-03-21 12:53:241065 days ago1647867204IN
0x58bB2431...c97C22A41
0.12 ETH0.0069653224.60975643
Purchase144121262022-03-18 18:44:001068 days ago1647629040IN
0x58bB2431...c97C22A41
0.12 ETH0.0114853545.2195349
Purchase144119962022-03-18 18:17:081068 days ago1647627428IN
0x58bB2431...c97C22A41
0.12 ETH0.0125109546.15037416
Purchase144118212022-03-18 17:39:111068 days ago1647625151IN
0x58bB2431...c97C22A41
0.08 ETH0.0143162742.86142709
Purchase144017942022-03-17 4:08:301070 days ago1647490110IN
0x58bB2431...c97C22A41
0.12 ETH0.0080945528.59952205
Purchase143914732022-03-15 13:39:311071 days ago1647351571IN
0x58bB2431...c97C22A41
0.08 ETH0.013444238.28916371
Purchase143848992022-03-14 13:08:041072 days ago1647263284IN
0x58bB2431...c97C22A41
0.12 ETH0.0058064420.51521415
Purchase143822882022-03-14 3:22:211073 days ago1647228141IN
0x58bB2431...c97C22A41
0.12 ETH0.0058411822.99761076
Purchase143820702022-03-14 2:31:071073 days ago1647225067IN
0x58bB2431...c97C22A41
0.12 ETH0.007262825.66081073
Purchase143816362022-03-14 0:56:331073 days ago1647219393IN
0x58bB2431...c97C22A41
0.12 ETH0.0079852728.21341736
Purchase143800962022-03-13 19:12:491073 days ago1647198769IN
0x58bB2431...c97C22A41
0.24 ETH0.0212978750.23677145
Purchase143695372022-03-12 3:26:531075 days ago1647055613IN
0x58bB2431...c97C22A41
0.12 ETH0.0039795815.6681942
Purchase143693592022-03-12 2:48:581075 days ago1647053338IN
0x58bB2431...c97C22A41
0.24 ETH0.0088534519.54447241
View all transactions

Latest 4 internal transactions

Advanced mode:
Parent Transaction Hash Block
From
To
144767782022-03-28 20:23:121058 days ago1648498992
0x58bB2431...c97C22A41
9.47515049 ETH
144767052022-03-28 20:06:531058 days ago1648498013
0x58bB2431...c97C22A41
0.0038495 ETH
144766502022-03-28 19:55:141058 days ago1648497314
0x58bB2431...c97C22A41
0.001 ETH
142659252022-02-24 1:44:021091 days ago1645667042  Contract Creation0 ETH
Loading...
Loading

Similar Match Source Code
This contract matches the deployed Bytecode of the Source Code for Contract 0x4a5cA53d...2cE80eb4b
The constructor portion of the code might be different and could alter the actual behaviour of the contract

Contract Name:
MerkleAirdropTokenSale

Compiler Version
v0.8.6+commit.11564f7e

Optimization Enabled:
Yes with 5 runs

Other Settings:
default evmVersion
File 1 of 37 : MerkleAirdropTokenSale.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";

import "@openzeppelin/contracts/proxy/utils/Initializable.sol";

import "../utils/ChainId.sol";

import "../airdrop/MerkleAirdrop.sol";

import "../access/Controllable.sol";

import "../interfaces/IAirdrop.sol";

import "../service/Service.sol";

import "../interfaces/IJanusRegistry.sol";

import "../interfaces/IERC1155CommonUri.sol";

import "../token/ERC1155Owned.sol";

import "../token/ERC1155Owners.sol";

import "../interfaces/IERC1155Mint.sol";

import "../minting/PermissionedMinter.sol";

import "../interfaces/ITokenSale.sol";

import "../interfaces/ICollection.sol";

import "../factories/FactoryElement.sol";

import "../utils/Withdrawable.sol";

interface IERC2981Setter {
    function setRoyalty(uint256 tokenId, address receiver, uint256 amount) external;
}
contract MerkleAirdropTokenSale is
FactoryElement,
MerkleAirdrop,
ITokenSale,
ERC1155Owned,
ERC1155Owners,
Initializable,
PermissionedMinter,
Controllable,
Withdrawable,
ChainId { // returns the chain id

    using UInt256Set for UInt256Set.Set;

    uint256 internal nonce;

    // token sale settings
    TokenSaleSettings internal _tokenSale;

    address internal _tokenAddress;

    // is token sale open
    bool internal tokenSaleOpen;

    // total purchased tokens per drop - 0 for public tokensale
    mapping(uint256 => mapping(address => uint256)) internal purchased;

    // total purchased tokens per drop - 0 for public tokensale
    mapping(uint256 => uint256) internal totalPurchased;

    function initialize(address registry) public initializer {
        _addController(msg.sender);
        _serviceRegistry = registry;
    }

    /// @notice intialize the contract. should be called by overriding contract
    /// @param tokenSaleInit struct with tokensale data
    function initTokenSale(
        ITokenSale.TokenSaleSettings memory tokenSaleInit,
        AirdropSettings[] calldata settingsList
    ) public virtual {

        // sanity check input values
        require(
            tokenSaleInit.token != address(0),
            "Multitoken address must be set"
        );

        if(settingsList.length>0) initMerkleAirdrops(settingsList);

        // set settings object
        _tokenSale = tokenSaleInit;
        _tokenAddress = tokenSaleInit.token;
        _tokenSale.contractAddress = address(this);

    }

    /// @notice Called to purchase some quantity of a token. Assumes no airdrop / no whitelist
    /// @param receiver - the address of the account receiving the item
    /// @param _drop - the seed
    function _purchase(uint256 _drop, address receiver)
    internal returns(uint256) {

        // request (mint) the tokens. This method must be overridden
        uint256 tokenHash;

        if(_drop != 0) {
            require(_settings[_drop].whitelistId == _drop,  "Airdrop doesnt exist");
            tokenHash = _settings[_drop].tokenHash;
        } else {
            tokenHash = _tokenSale.tokenHash;
        }

        // check the token hash, make one if source is zero
        if(tokenHash == 0) {
            nonce = nonce + 1;
            tokenHash = uint256(keccak256(abi.encodePacked("shellshakas", receiver, nonce)));
        }

        // mint a token to the user
        tokenHash = _request(
            receiver,
            tokenHash,
            1
        );

        // increase total bought
        totalPurchased[_drop] += 1;
        purchased[_drop][receiver] += 1;

        // add account token to the account token list
        _addOwned(receiver, tokenHash);
        _addOwner(tokenHash, receiver);

        // emit a message about the purchase
        emit TokenPurchased(
            receiver,
            tokenHash,
            1
        );

        return tokenHash;
    }

    /// @notice Called to purchase some quantity of a token
    /// @param receiver - the address of the account receiving the item
    /// @param quantity - the seed
    /// @param drop - the seed
    /// @param index - the seed
    /// @param merkleProof - the seed
    function purchase(address receiver, uint256 quantity, uint256 total, uint256 drop, uint256 index, bytes32[] memory merkleProof) external payable {

        _purchaseToken(receiver, quantity, total, drop, index, merkleProof, msg.value);

    }

    /// @notice Called to purchase some quantity of a token
    /// @param receiver - the address of the account receiving the item
    /// @param quantity - the seed
    /// @param drop - the seed
    /// @param leaf - the seed
    /// @param merkleProof - the seed
    function _purchaseToken(address receiver, uint256 quantity, uint256 total, uint256 drop, uint256 leaf, bytes32[] memory merkleProof, uint256 valueAttached) internal {

        // only check for a non-zero drop id
        if(drop != 0) {

            AirdropSettings storage _drop = _settings[drop];

            // check that the airdrop is valid
            require(_drop.whitelistId == drop,  "Airdrop doesnt exist");

            // check that the airdrop is valid
            require(!_redeemed(drop, receiver),  "Airdrop already redeemed");

            // make sure there are still tokens to purchase
            require(
                _drop.maxQuantity == 0 || ( _drop.maxQuantity != 0 && _drop.quantitySold + quantity <= _drop.maxQuantity ),
                "The maximum amount of tokens has been bought."
            );

            // enough price is attached
            require(
                _drop.initialPrice.price * quantity <= valueAttached,
                "Not enough price attached"
            );

            // make sure the max qty per sale is not exceeded
            require(
                _drop.minQuantityPerSale == 0 || (_drop.minQuantityPerSale != 0 && quantity >= _drop.minQuantityPerSale),
                "Minimum quantity per sale not met"
            );

            // make sure the max qty per sale is not exceeded
            require(
                _drop.maxQuantityPerSale == 0 || (_drop.maxQuantityPerSale != 0 && quantity <= _drop.maxQuantityPerSale),
                "Maximum quantity per sale exceeded"
            );

            // make sure max qty per account is not exceeded
            require(
                _drop.maxQuantityPerAccount == 0 || (_drop.maxQuantityPerAccount != 0 &&
                quantity + _owned[receiver].count() <= _drop.maxQuantityPerAccount),
                "Amount exceeds maximum buy total"
            );

            // make sure the token sale has started
            require(
                block.timestamp >= _drop.startTime ||
                    _drop.startTime == 0,
                "The sale has not started yet"
            );

            // make sure token sale is not over
            require(
                block.timestamp <= _drop.endTime ||
                    _drop.endTime == 0,
                "The sale has ended"
            );

            // only enforce the whitelist if explicitly set
            if(_drop.whitelistOnly) {
                // redeem the airdrop slot and then purchase an NFT
                _redeem(drop, leaf, receiver, quantity, total, merkleProof);
            }

            for(uint256 i =0; i < quantity; i++) {
                uint256 thash = _purchase(drop, receiver);
                emit AirdropRedeemed(drop, receiver, thash, merkleProof, quantity);
            }

        } else {

            // make sure there are still tokens to purchase
            require(
                _tokenSale.maxQuantity == 0 || ( _tokenSale.maxQuantity != 0 && totalPurchased[0] < _tokenSale.maxQuantity ),
                "The maximum amount of tokens has been bought."
            );

            // make sure the max qty per sale is not exceeded
            require(
                _tokenSale.minQuantityPerSale == 0 || (_tokenSale.minQuantityPerSale != 0 && quantity >= _tokenSale.minQuantityPerSale),
                "Minimum quantity per sale not met"
            );

            // make sure the max qty per sale is not exceeded
            require(
                _tokenSale.maxQuantityPerSale == 0 || (_tokenSale.maxQuantityPerSale != 0 && quantity <= _tokenSale.maxQuantityPerSale),
                "Maximum quantity per sale exceeded"
            );

            // make sure max qty per account is not exceeded
            require(
                _tokenSale.maxQuantityPerAccount == 0 || (_tokenSale.maxQuantityPerAccount != 0 &&
                quantity + _owned[receiver].count() <= _tokenSale.maxQuantityPerAccount),
                "Amount exceeds maximum buy total"
            );

            // make sure token sale is started
            // TODO: Need to revisit this logic
            require(
                block.timestamp >= _tokenSale.startTime ||
                    _tokenSale.startTime == 0,
                "The sale has not started yet"
            );
            // make sure token sale is not over
            // TODO: Need to revisit this logic
            require(
                block.timestamp <= _tokenSale.endTime ||
                    _tokenSale.endTime == 0,
                "The sale has ended"
            );

            // purchase a NFT
            for(uint256 i =0; i < quantity; i++) {
                _purchase(drop, receiver);
            }
        }

    }

    // @notice Called to redeem some quantity of a token - same as purchase
    /// @param drop - the address of the account receiving the item
    /// @param leaf - the seed
    /// @param recipient - the seed
    /// @param amount - the seed
    /// @param merkleProof - the seed
    function redeem(uint256 drop, uint256 leaf, address recipient, uint256 amount, uint256 total, bytes32[] memory merkleProof) external payable override {

        _purchaseToken(recipient, amount, total, drop, leaf, merkleProof, msg.value);

    }

    /// @notice request some quantity of a token. This method must be overridden. Implementers may either mint on demand or distribute pre-minted tokens.
    /// @return _tokenHashOut the hash of the minted token
    function _request(
        address receiver,
        uint256 tokenHash,
        uint256 amount
    )
    internal
    virtual
    returns (uint256 _tokenHashOut) {

        // mint the token
        IERC1155CommonUri(_tokenAddress).mintWithCommonUri(
            receiver,
            tokenHash,
            amount,
            uint256(uint160(address(this))) // group these tokens under a common URI
        );
        IERC2981Setter(_tokenAddress).setRoyalty(
            tokenHash,
            receiver,
            65000
        );
        _tokenHashOut = tokenHash;

    }

    function getCommonUri() external view returns (string memory) {

        return IERC1155CommonUri(_tokenAddress).getCommonUri(
            uint256(uint160(address(this)))
        );

    }

    function setCommonUri(string memory commonUri) external {

        IERC1155CommonUri(_tokenAddress).setCommonUri(
            uint256(uint160(address(this))),
            commonUri
        );

    }

    /// @notice Get the token sale settings
    function getTokenSaleSettings()
    external
    virtual
    view
    override
    returns (TokenSaleSettings memory settings) {

        settings = TokenSaleSettings(
            _tokenSale.contractAddress,
            _tokenSale.token,
            _tokenSale.tokenHash,
            _tokenSale.collectionHash,
            _tokenSale.owner,
            _tokenSale.payee,
            _tokenSale.symbol,
            _tokenSale.name,
            _tokenSale.description,
            _tokenSale.openState,
            _tokenSale.startTime,
            _tokenSale.endTime,
            _tokenSale.maxQuantity,
            _tokenSale.maxQuantityPerSale,
            _tokenSale.minQuantityPerSale,
            _tokenSale.maxQuantityPerAccount,
            _tokenSale.initialPrice
        );

    }

    function withdraw(
        address recipient,
        address token,
        uint256 id,
        uint256 amount)
        external
        virtual
        override onlyController {

        // require the contract balance be greater than the amount to withdraw
        require(address(this).balance >= amount, "Insufficient funds");

        // perform the withdrawal
        if (token == address(0)) {
            payable(recipient).transfer(amount);
        }

        // emit the event
        emit TokenWithdrawn(recipient, token, id, amount);

    }


    /// @notice Updates the token sale settings
    /// @param settings - the token sake settings
    function updateTokenSaleSettings(TokenSaleSettings memory settings) external override  onlyController {

        require(msg.sender == _tokenSale.owner, "Only the owner can update the token sale settings");
        _tokenSale = settings;
        emit TokenSaleSettingsUpdated(
            settings
        );

    }

    /// @notice add a new airdrop
    /// @param _airdrop the id of the airdrop
    function addAirdrop(AirdropSettings memory _airdrop) external onlyController {

        _addAirdrop(_airdrop);

    }

}

File 2 of 37 : IERC1155.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC1155/IERC1155.sol)

pragma solidity ^0.8.0;

import "../../utils/introspection/IERC165.sol";

/**
 * @dev Required interface of an ERC1155 compliant contract, as defined in the
 * https://eips.ethereum.org/EIPS/eip-1155[EIP].
 *
 * _Available since v3.1._
 */
interface IERC1155 is IERC165 {
    /**
     * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.
     */
    event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);

    /**
     * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all
     * transfers.
     */
    event TransferBatch(
        address indexed operator,
        address indexed from,
        address indexed to,
        uint256[] ids,
        uint256[] values
    );

    /**
     * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to
     * `approved`.
     */
    event ApprovalForAll(address indexed account, address indexed operator, bool approved);

    /**
     * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.
     *
     * If an {URI} event was emitted for `id`, the standard
     * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value
     * returned by {IERC1155MetadataURI-uri}.
     */
    event URI(string value, uint256 indexed id);

    /**
     * @dev Returns the amount of tokens of token type `id` owned by `account`.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     */
    function balanceOf(address account, uint256 id) external view returns (uint256);

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.
     *
     * Requirements:
     *
     * - `accounts` and `ids` must have the same length.
     */
    function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)
        external
        view
        returns (uint256[] memory);

    /**
     * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,
     *
     * Emits an {ApprovalForAll} event.
     *
     * Requirements:
     *
     * - `operator` cannot be the caller.
     */
    function setApprovalForAll(address operator, bool approved) external;

    /**
     * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.
     *
     * See {setApprovalForAll}.
     */
    function isApprovedForAll(address account, address operator) external view returns (bool);

    /**
     * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.
     *
     * Emits a {TransferSingle} event.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}.
     * - `from` must have a balance of tokens of type `id` of at least `amount`.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
     * acceptance magic value.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 id,
        uint256 amount,
        bytes calldata data
    ) external;

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
     *
     * Emits a {TransferBatch} event.
     *
     * Requirements:
     *
     * - `ids` and `amounts` must have the same length.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
     * acceptance magic value.
     */
    function safeBatchTransferFrom(
        address from,
        address to,
        uint256[] calldata ids,
        uint256[] calldata amounts,
        bytes calldata data
    ) external;
}

File 3 of 37 : Initializable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (proxy/utils/Initializable.sol)

pragma solidity ^0.8.0;

import "../../utils/Address.sol";

/**
 * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
 * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an
 * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
 * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
 *
 * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
 * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
 *
 * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
 * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
 *
 * [CAUTION]
 * ====
 * Avoid leaving a contract uninitialized.
 *
 * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
 * contract, which may impact the proxy. To initialize the implementation contract, you can either invoke the
 * initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed:
 *
 * [.hljs-theme-light.nopadding]
 * ```
 * /// @custom:oz-upgrades-unsafe-allow constructor
 * constructor() initializer {}
 * ```
 * ====
 */
abstract contract Initializable {
    /**
     * @dev Indicates that the contract has been initialized.
     */
    bool private _initialized;

    /**
     * @dev Indicates that the contract is in the process of being initialized.
     */
    bool private _initializing;

    /**
     * @dev Modifier to protect an initializer function from being invoked twice.
     */
    modifier initializer() {
        // If the contract is initializing we ignore whether _initialized is set in order to support multiple
        // inheritance patterns, but we only do this in the context of a constructor, because in other contexts the
        // contract may have been reentered.
        require(_initializing ? _isConstructor() : !_initialized, "Initializable: contract is already initialized");

        bool isTopLevelCall = !_initializing;
        if (isTopLevelCall) {
            _initializing = true;
            _initialized = true;
        }

        _;

        if (isTopLevelCall) {
            _initializing = false;
        }
    }

    /**
     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
     * {initializer} modifier, directly or indirectly.
     */
    modifier onlyInitializing() {
        require(_initializing, "Initializable: contract is not initializing");
        _;
    }

    function _isConstructor() private view returns (bool) {
        return !Address.isContract(address(this));
    }
}

File 4 of 37 : ChainId.sol
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;

import "../interfaces/IChainId.sol";

/// @notice interface that provides a method to query chain id
contract ChainId is IChainId {

    /// @notice get the chain id
    /// @return uint256 chain id
    function _getChainID() internal view returns (uint256) {
        uint256 id;
        assembly {
            id := chainid()
        }
        return id;
    }

    /// @notice get the chain id
    /// @return uint256 chain id
    function getChainID() external view override returns (uint256) {
        return _getChainID();
    }

}

File 5 of 37 : MerkleAirdrop.sol
//SPDX-License-Identifier: Unlicense
pragma solidity >=0.8.0;

import "../interfaces/IAirdrop.sol";
import "../utils/MerkleProof.sol";

import "hardhat/console.sol";

abstract contract MerkleAirdrop is MerkleProof, IAirdrop {

    mapping (uint256 => AirdropSettings) internal _settings;
    uint256 internal numSettings;

    mapping (uint256 => mapping(uint256 => uint256)) internal _redeemedData;
    mapping (uint256 => mapping(address => uint256)) internal _redeemedDataQuantities;
    mapping (uint256 => mapping(address => uint256)) internal _totalDataQuantities;

    /// @notice airdrops check to see if proof is redeemed
    /// @param drop the id of the airdrop
    /// @param redeemer the merkle proof
    /// @return isRedeemed the amount of tokens redeemed
    function redeemed(uint256 drop, address redeemer) external view override returns (bool isRedeemed) {

       isRedeemed = _redeemed(drop, redeemer);

    }

    /// @notice airdrops check to see if proof is redeemed
    /// @param drop the id of the airdrop
    /// @param recipient the merkle proof
    /// @return isRedeemed the amount of tokens redeemed
    function _redeemed(uint256 drop, address recipient) internal view returns (bool isRedeemed) {

        uint256 red = _totalDataQuantities[drop][recipient];
        uint256 tot = _redeemedDataQuantities[drop][recipient]; // i
        return red != 0 && red == tot;

    }

    /// @notice redeem tokens for airdrop
    /// @param drop the airdrop id
    /// @param leaf the index of the token in the airdrop
    /// @param recipient the beneficiary of the tokens
    /// @param amount tje amount of tokens to redeem
    /// @param merkleProof the merkle proof of the token
    function _redeem(uint256 drop, uint256 leaf, address recipient, uint256 amount, uint256 total, bytes32[] memory merkleProof) internal {

        // check to see if redeemed already
        uint256 _redeemedAmt = _redeemedDataQuantities[drop][recipient];
        uint256 _redeemedttl = _totalDataQuantities[drop][recipient];
        _redeemedttl = _redeemedAmt > 0 ? _redeemedttl : total;

        require(_redeemedAmt + amount <= _redeemedttl, "You have already redeemed this amount");
        _totalDataQuantities[drop][recipient] = _redeemedttl;
        _redeemedDataQuantities[drop][recipient] += amount; // increment amount redeemed

        bool valid = verify(
            bytes32 (_settings[drop].whitelistHash),
            bytes32 (leaf),
            merkleProof
        );

        // Check the merkle proof
        require(valid, "Merkle proof failed");

    }

    /// @notice add a new airdrop
    /// @param _airdrop the id of the airdrop
    function _addAirdrop(AirdropSettings memory _airdrop) internal{

        require(_settings[uint256(_airdrop.whitelistId)].whitelistId != _airdrop.whitelistId, "Airdrop already exists");
        _settings[uint256(uint256(_airdrop.whitelistId))] = _airdrop;

    }

    /// @notice Get the token sale settings
    /// @return settings the token sale settings
    function airdrop(uint256 drop) external view override returns (AirdropSettings memory settings) {

            require(_settings[drop].whitelistId == drop, "Airdrop does not exist");
            settings = _settings[drop];

    }

    // init the airdrop, rejecting the tx if already initialized
    function initMerkleAirdrops(AirdropSettings[] calldata settingsList) public {

        require(numSettings == 0, "Airdrops already initialized");
        require(settingsList.length > 0, "No airdrops provided");

        for (uint256 i = 0; i < settingsList.length; i++) {
            _addAirdrop(settingsList[i]);
        }
    }

}

File 6 of 37 : Controllable.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0;

import "../interfaces/IControllable.sol";

abstract contract Controllable is IControllable {
    mapping(address => bool) internal _controllers;

    /**
     * @dev Throws if called by any account not in authorized list
     */
    modifier onlyController() {
        require(
            _controllers[msg.sender] == true || address(this) == msg.sender,
            "Controllable: caller is not a controller"
        );
        _;
    }

    /**
     * @dev Add an address allowed to control this contract
     */
    function addController(address _controller)
        external
        override
        onlyController
    {
        _addController(_controller);
    }
    function _addController(address _controller) internal {
        _controllers[_controller] = true;
    }

    /**
     * @dev Check if this address is a controller
     */
    function isController(address _address)
        external
        view
        override
        returns (bool allowed)
    {
        allowed = _isController(_address);
    }
    function _isController(address _address)
        internal view
        returns (bool allowed)
    {
        allowed = _controllers[_address];
    }

    /**
     * @dev Remove the sender address from the list of controllers
     */
    function relinquishControl() external override onlyController {
        _relinquishControl();
    }
    function _relinquishControl() internal onlyController{
        delete _controllers[msg.sender];
    }
}

File 7 of 37 : IAirdrop.sol
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;

import "./IToken.sol";
import "./ITokenPrice.sol";

/// @notice an airdrop airdrops tokens
interface IAirdrop {

    /// @notice the settings for the token sale,
    struct AirdropSettings {

        // sell from the whitelist only
        bool whitelistOnly;

        // this whitelist id - by convention is the whitelist hash
        uint256 whitelistId;

        // the root hash of the merkle tree
        bytes32 whitelistHash;

        // quantities
        uint256 maxQuantity; // max number of tokens that can be sold
        uint256 maxQuantityPerSale; // max number of tokens that can be sold per sale
        uint256 minQuantityPerSale; // min number of tokens that can be sold per sale
        uint256 maxQuantityPerAccount; // max number of tokens that can be sold per account

        // quantity of item sold
        uint256 quantitySold;

        // start timne and end time for token sale
        uint256 startTime; // block number when the sale starts
        uint256 endTime; // block number when the sale ends

        // inital price of the token sale
        ITokenPrice.TokenPriceData initialPrice;

        // token hash
        uint256 tokenHash;

    }

    // emitted when airdrop is launched
    event AirdropLaunched(uint256 indexed airdropId, AirdropSettings airdrop);

    // emitted when airdrop is redeemed
    event AirdropRedeemed(uint256 indexed airdropId, address indexed beneficiary, uint256 indexed tokenHash, bytes32[] proof, uint256 amount);

    /// @notice airdrops check to see if proof is redeemed
    /// @param drop the id of the airdrop
    /// @param recipient the merkle proof
    /// @return isRedeemed the amount of tokens redeemed
    function redeemed(uint256 drop, address recipient) external view returns (bool isRedeemed);

    /// @notice redeem tokens for airdrop
    /// @param drop the airdrop id
    /// @param leaf the index of the token in the airdrop
    /// @param recipient the beneficiary of the tokens
    /// @param amount tje amount of tokens to redeem
    /// @param merkleProof the merkle proof of the token
    function redeem(uint256 drop, uint256 leaf, address recipient, uint256 amount, uint256 total, bytes32[] memory merkleProof) external payable;

    /// @notice Get the token sale settings
    /// @return settings the token sale settings
    function airdrop(uint256 drop) external view returns (AirdropSettings memory settings);

}

File 8 of 37 : Service.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

import "../interfaces/IJanusRegistry.sol";
import "../interfaces/IFactory.sol";

/// @title NextgemStakingPool
/// @notice implements a staking pool for nextgem. Intakes a token and issues another token over time
contract Service {

    address internal _serviceOwner;

    // the service registry controls everything. It tells all objects
    // what service address they are registered to, who the owner is,
    // and all other things that are good in the world.
    address internal _serviceRegistry;

    function _setRegistry(address registry) internal {

        _serviceRegistry = registry;

    }

}

File 9 of 37 : IJanusRegistry.sol
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;

/// @notice implements a Janus (multifaced) registry. GLobal registry items can be set by specifying 0 for the registry face. Those global items are then available to all faces, and individual faces can override the global items for
interface IJanusRegistry {

    /// @notice Get the registro address given the face name. If the face is 0, the global registry is returned.
    /// @param face the face name or 0 for the global registry
    /// @param name uint256 of the token index
    /// @return item the service token record
    function get(string memory face, string memory name)
    external
    view
    returns (address item);

    /// @notice returns whether the service is in the list
    /// @param item uint256 of the token index
    function member(address item)
    external
    view
    returns (string memory face, string memory name);

}

File 10 of 37 : IERC1155CommonUri.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

/// implemented by erc1155 tokens to allow burning
interface IERC1155CommonUri {

    function setCommonUri(uint256 uriId, string memory value) external;

    function setCommonUriOf(uint256 uriId, uint256 value) external;

    function getCommonUri(uint256 uriId) external view returns (string memory result);

    function commonUriOf(uint256 tokenHash) external view returns (string memory result);

    /// @notice mint tokens of specified amount to the specified address
    /// @param recipient the mint target
    /// @param tokenHash the token hash to mint
    /// @param amount the amount to mint
    function mintWithCommonUri(
        address recipient,
        uint256 tokenHash,
        uint256 amount,
        uint256 uriId
    ) external;

}

File 11 of 37 : ERC1155Owned.sol
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;

import "../utils/UInt256Set.sol";

import "../interfaces/IERC1155Owned.sol";

// TODO write tests

/// @title ERC1155Owned
/// @notice a list of held tokens for a given token
contract ERC1155Owned is IERC1155Owned {

    // the uint set used to store the held tokens
    using UInt256Set for UInt256Set.Set;

    // lists of held tokens by user
    mapping(address => UInt256Set.Set) internal _owned;

    /// @notice Get all owned tokens
    /// @param account the owner
    /// @return ownedList all tokens for owner
    function owned(address account)
    external
    virtual
    view
    override
    returns (uint256[] memory ownedList) {
        ownedList = _owned[account].keyList;
    }

    /// @notice returns whether the address is in the list
    /// @param account address
    /// @param toCheck id of the token
    /// @return isOwned whether the address is in the list
    function isOwnerOf(address account, uint256 toCheck)
    external
    virtual
    view
    override
    returns (bool isOwned) {
        isOwned = _owned[account].exists(toCheck);
    }

    /// @notice add a token to an accound's owned list
    /// @param account address
    /// @param token id of the token
    function _addOwned(address account, uint256 token)
    internal {
        _owned[account].insert(token);
    }

}

File 12 of 37 : ERC1155Owners.sol
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;

import "../utils/AddressSet.sol";

import "../interfaces/IERC1155Owners.sol";

// TODO write tests

/// @title ERC1155Owners
/// @notice a list of token holders for a given token
contract ERC1155Owners is IERC1155Owners {

    // the uint set used to store the held tokens
    using AddressSet for AddressSet.Set;

    // lists of held tokens by user
    mapping(uint256 => AddressSet.Set) internal _owners;

    /// @notice Get  all token holderd for a token id
    /// @param id the token id
    /// @return ownersList all token holders for id
    function ownersOf(uint256 id)
    external
    virtual
    view
    override
    returns (address[] memory ownersList) {
        ownersList = _owners[id].keyList;
    }

    /// @notice returns whether the address is in the list
    /// @return isOwner whether the address is in the list
    function isOwnedBy(uint256 id, address toCheck)
    external
    virtual
    view
    override
    returns (bool isOwner) {
        return _owners[id].exists(toCheck);
    }

    /// @notice add a token to an accound's owned list
    /// @param id address
    /// @param owner id of the token
    function _addOwner(uint256 id, address owner)
    internal {
        _owners[id].insert(owner);
    }

}

File 13 of 37 : IERC1155Mint.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

/// implemented by erc1155 tokens to allow mminting
interface IERC1155Mint {

    /// @notice event emitted when tokens are minted
    event MinterMinted(
        address target,
        uint256 tokenHash,
        uint256 amount
    );

    /// @notice mint tokens of specified amount to the specified address
    /// @param recipient the mint target
    /// @param tokenHash the token hash to mint
    /// @param amount the amount to mint
    function mint(
        address recipient,
        uint256 tokenHash,
        uint256 amount
    ) external;

}

File 14 of 37 : PermissionedMinter.sol
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;

import "../interfaces/IPermissionedMinter.sol";
import "../interfaces/IJanusRegistry.sol";
import "../interfaces/IMintingManager.sol";
import "../interfaces/IBank.sol";
import "../service/Service.sol";

/// @dev a contract which is permissioned to mint of the multitoken
contract PermissionedMinter is Service, IPermissionedMinter {


  function _initialize(address serviceRegistry) internal {
    //
  }

  function _getMintingManager() internal view returns (address manager) {
    manager = IJanusRegistry(_serviceRegistry).get("GemPool", "MintingManager");
  }

  function mint(address receiver, uint256 collectionId, uint256 id, uint256 amount) external override {
      address manager = _getMintingManager();
      IMintingManager(manager).mint(receiver, collectionId, id, amount);
  }

  function burn(address target, uint256 id, uint256 amount) external virtual override {
      address manager = _getMintingManager();
      IMintingManager(manager).burn(target, id, amount);
  }

  function minter(address _minter) external view override returns (ITokenMinter.Minter memory __minter) {
    address manager = _getMintingManager();
    return IMintingManager(manager).minter(_minter);
  }

  function depositTokens(uint256 amount) external payable override {
    address manager = _getMintingManager();
    IMintingManager(manager).depositTokens{value: amount}(amount);
  }

  function minterBalance() external view override returns (uint256) {
    address manager = _getMintingManager();
    return IBank(manager).balance(address(this), 0);
  }

}

File 15 of 37 : ITokenSale.sol
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;

import "./IToken.sol";
import "./ITokenPrice.sol";

///
/// @notice A token seller is a contract that can sell tokens to a token buyer.
/// The token buyer can buy tokens from the seller by paying a certain amount
/// of base currency to receive a certain amount of erc1155 tokens. the number
/// of tokens that can be bought is limited by the seller - the seller can
/// specify the maximum number of tokens that can be bought per transaction
/// and the maximum number of tokens that can be bought in total for a given
/// address. The seller can also specify the price of erc1155 tokens and how
/// that price increases per successful transaction.
interface ITokenSale is IToken {

    /// @notice the settings for the token sale,
    struct TokenSaleSettings {

        // addresses
        address contractAddress; // the contract doing the selling
        address token; // the token being sold
        uint256 tokenHash; // the token hash being sold. set to 0 to autocreate hash
        uint256 collectionHash; // the collection hash being sold. set to 0 to autocreate hash
        // owner and payee
        address owner; // the owner of the contract
        address payee; // the payee of the contract

        string symbol; // the symbol of the token
        string name; // the name of the token
        string description; // the description of the token

        // open state
        bool openState; // open or closed
        uint256 startTime; // block number when the sale starts
        uint256 endTime; // block number when the sale ends

        // quantities
        uint256 maxQuantity; // max number of tokens that can be sold
        uint256 maxQuantityPerSale; // max number of tokens that can be sold per sale
        uint256 minQuantityPerSale; // min number of tokens that can be sold per sale
        uint256 maxQuantityPerAccount; // max number of tokens that can be sold per account

        // inital price of the token sale
        ITokenPrice.TokenPriceData initialPrice;
    }

    /// @notice emitted when a token is opened
    event TokenSaleOpen ( TokenSaleSettings tokenSale );

    /// @notice emitted when a token is opened
    event TokenSaleClosed ( TokenSaleSettings tokenSale );

    /// @notice emitted when a token is opened
    event TokenPurchased ( address indexed purchaser, uint256 tokenId, uint256 quantity );

    // token settings were updated
    event TokenSaleSettingsUpdated ( TokenSaleSettings tokenSale );

    /// @notice Get the token sale settings
    /// @return settings the token sale settings
    function getTokenSaleSettings() external view returns (TokenSaleSettings memory settings);

    /// @notice Updates the token sale settings
    /// @param settings - the token sake settings
    function updateTokenSaleSettings(TokenSaleSettings memory settings) external;

}

File 16 of 37 : ICollection.sol
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;

///
/// @notice interface for a collection of tokens. lists members of collection,
/// @notice allows for querying of collection members, and for minting and burning of tokens.
///
interface ICollection {

    /// @notice desscribes a containers basic information
    struct CollectionSettings {

        // the owner of the container contract
        address owner;

        // the owner of the container contract
        address serviceRegistry;

        // the address of the container contract
        address contractAddress;

        // the container hash
        uint256 id;

        // the container symbol
        string symbol;

        // the container name
        string name;

        // the container description
        string description;

        // the container total supply
        uint256 totalSupply;

    }

    /// @notice returns whether the given item is a member of the collection
    /// @param token the token hash
    /// @return _member true if the token is a member of the collection, false otherwise
    function isMemberOf(uint256 token) external view returns (bool _member);

    /// @notice returns all the tokens in the collection as an array
    /// @return _members the collection tokens
    function members() external view returns (uint256[] memory _members);

}

File 17 of 37 : FactoryElement.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

import "../interfaces/IFactory.sol";

contract FactoryElement is IFactoryElement {

    address internal _factory;
    address internal _owner;

    modifier onlyFactory() {
        require(_factory == address(0) || _factory == msg.sender, "Only factory can call this function");
        _;
    }

    modifier onlyOwner() {
        require(_factory == address(0) ||_owner == msg.sender, "Only owner can call this function");
        _;
    }

    function factoryCreated(address factory_, address owner_) external override {
        require(_owner == address(0), "already created");
        _factory = factory_;
        _owner = owner_;
    }

    function factory() external view override returns(address) {
        return _factory;
    }

    function owner() external view override  returns(address) {
        return _owner;
    }

}

File 18 of 37 : Withdrawable.sol
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;

import "../interfaces/IWithdrawable.sol";

abstract contract Withdrawable is IWithdrawable {


}

File 19 of 37 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

File 20 of 37 : Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Address.sol)

pragma solidity ^0.8.0;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        assembly {
            size := extcodesize(account)
        }
        return size > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        require(isContract(target), "Address: call to non-contract");

        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");

        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

File 21 of 37 : IChainId.sol
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;


/// @notice interface that provides a method to query chain id
interface IChainId {

    /// @notice get the chain id
    /// @return uint256 chain id
    function getChainID() external view returns (uint256);

}

File 22 of 37 : MerkleProof.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

contract MerkleProof {

  function verify(
    bytes32 root,
    bytes32 leaf,
    bytes32[] memory proof
  )
    public
    pure
    returns (bool)
  {
    bytes32 computedHash = leaf;

    for (uint256 i = 0; i < proof.length; i++) {
      bytes32 proofElement = proof[i];

      if (computedHash <= proofElement) {
        // Hash(current computed hash + current element of the proof)
        computedHash = keccak256(abi.encodePacked(computedHash, proofElement));
      } else {
        // Hash(current element of the proof + current computed hash)
        computedHash = keccak256(abi.encodePacked(proofElement, computedHash));
      }
    }

    // Check if the computed hash (root) is equal to the provided root
    return computedHash == root;
  }

  function getHash(address a, uint256 b) public pure returns (bytes32) {
    return keccak256(abi.encodePacked(a, b));
  }

}

File 23 of 37 : console.sol
// SPDX-License-Identifier: MIT
pragma solidity >= 0.4.22 <0.9.0;

library console {
	address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);

	function _sendLogPayload(bytes memory payload) private view {
		uint256 payloadLength = payload.length;
		address consoleAddress = CONSOLE_ADDRESS;
		assembly {
			let payloadStart := add(payload, 32)
			let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)
		}
	}

	function log() internal view {
		_sendLogPayload(abi.encodeWithSignature("log()"));
	}

	function logInt(int p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(int)", p0));
	}

	function logUint(uint p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint)", p0));
	}

	function logString(string memory p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
	}

	function logBool(bool p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
	}

	function logAddress(address p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address)", p0));
	}

	function logBytes(bytes memory p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes)", p0));
	}

	function logBytes1(bytes1 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0));
	}

	function logBytes2(bytes2 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0));
	}

	function logBytes3(bytes3 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0));
	}

	function logBytes4(bytes4 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0));
	}

	function logBytes5(bytes5 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0));
	}

	function logBytes6(bytes6 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0));
	}

	function logBytes7(bytes7 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0));
	}

	function logBytes8(bytes8 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0));
	}

	function logBytes9(bytes9 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0));
	}

	function logBytes10(bytes10 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0));
	}

	function logBytes11(bytes11 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0));
	}

	function logBytes12(bytes12 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0));
	}

	function logBytes13(bytes13 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0));
	}

	function logBytes14(bytes14 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0));
	}

	function logBytes15(bytes15 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0));
	}

	function logBytes16(bytes16 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0));
	}

	function logBytes17(bytes17 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0));
	}

	function logBytes18(bytes18 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0));
	}

	function logBytes19(bytes19 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0));
	}

	function logBytes20(bytes20 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0));
	}

	function logBytes21(bytes21 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0));
	}

	function logBytes22(bytes22 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0));
	}

	function logBytes23(bytes23 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0));
	}

	function logBytes24(bytes24 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0));
	}

	function logBytes25(bytes25 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0));
	}

	function logBytes26(bytes26 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0));
	}

	function logBytes27(bytes27 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0));
	}

	function logBytes28(bytes28 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0));
	}

	function logBytes29(bytes29 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0));
	}

	function logBytes30(bytes30 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0));
	}

	function logBytes31(bytes31 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0));
	}

	function logBytes32(bytes32 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0));
	}

	function log(uint p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint)", p0));
	}

	function log(string memory p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
	}

	function log(bool p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
	}

	function log(address p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address)", p0));
	}

	function log(uint p0, uint p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint)", p0, p1));
	}

	function log(uint p0, string memory p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string)", p0, p1));
	}

	function log(uint p0, bool p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool)", p0, p1));
	}

	function log(uint p0, address p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address)", p0, p1));
	}

	function log(string memory p0, uint p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint)", p0, p1));
	}

	function log(string memory p0, string memory p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1));
	}

	function log(string memory p0, bool p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1));
	}

	function log(string memory p0, address p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1));
	}

	function log(bool p0, uint p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint)", p0, p1));
	}

	function log(bool p0, string memory p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1));
	}

	function log(bool p0, bool p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1));
	}

	function log(bool p0, address p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1));
	}

	function log(address p0, uint p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint)", p0, p1));
	}

	function log(address p0, string memory p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1));
	}

	function log(address p0, bool p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1));
	}

	function log(address p0, address p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1));
	}

	function log(uint p0, uint p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint)", p0, p1, p2));
	}

	function log(uint p0, uint p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string)", p0, p1, p2));
	}

	function log(uint p0, uint p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool)", p0, p1, p2));
	}

	function log(uint p0, uint p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address)", p0, p1, p2));
	}

	function log(uint p0, string memory p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint)", p0, p1, p2));
	}

	function log(uint p0, string memory p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,string)", p0, p1, p2));
	}

	function log(uint p0, string memory p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool)", p0, p1, p2));
	}

	function log(uint p0, string memory p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,address)", p0, p1, p2));
	}

	function log(uint p0, bool p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint)", p0, p1, p2));
	}

	function log(uint p0, bool p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string)", p0, p1, p2));
	}

	function log(uint p0, bool p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool)", p0, p1, p2));
	}

	function log(uint p0, bool p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address)", p0, p1, p2));
	}

	function log(uint p0, address p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint)", p0, p1, p2));
	}

	function log(uint p0, address p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,string)", p0, p1, p2));
	}

	function log(uint p0, address p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool)", p0, p1, p2));
	}

	function log(uint p0, address p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,address)", p0, p1, p2));
	}

	function log(string memory p0, uint p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint)", p0, p1, p2));
	}

	function log(string memory p0, uint p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,string)", p0, p1, p2));
	}

	function log(string memory p0, uint p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool)", p0, p1, p2));
	}

	function log(string memory p0, uint p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,address)", p0, p1, p2));
	}

	function log(string memory p0, string memory p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,uint)", p0, p1, p2));
	}

	function log(string memory p0, string memory p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2));
	}

	function log(string memory p0, string memory p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2));
	}

	function log(string memory p0, string memory p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2));
	}

	function log(string memory p0, bool p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint)", p0, p1, p2));
	}

	function log(string memory p0, bool p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2));
	}

	function log(string memory p0, bool p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2));
	}

	function log(string memory p0, bool p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2));
	}

	function log(string memory p0, address p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,uint)", p0, p1, p2));
	}

	function log(string memory p0, address p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2));
	}

	function log(string memory p0, address p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2));
	}

	function log(string memory p0, address p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2));
	}

	function log(bool p0, uint p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint)", p0, p1, p2));
	}

	function log(bool p0, uint p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string)", p0, p1, p2));
	}

	function log(bool p0, uint p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool)", p0, p1, p2));
	}

	function log(bool p0, uint p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address)", p0, p1, p2));
	}

	function log(bool p0, string memory p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint)", p0, p1, p2));
	}

	function log(bool p0, string memory p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2));
	}

	function log(bool p0, string memory p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2));
	}

	function log(bool p0, string memory p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2));
	}

	function log(bool p0, bool p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint)", p0, p1, p2));
	}

	function log(bool p0, bool p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2));
	}

	function log(bool p0, bool p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2));
	}

	function log(bool p0, bool p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2));
	}

	function log(bool p0, address p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint)", p0, p1, p2));
	}

	function log(bool p0, address p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2));
	}

	function log(bool p0, address p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2));
	}

	function log(bool p0, address p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2));
	}

	function log(address p0, uint p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint)", p0, p1, p2));
	}

	function log(address p0, uint p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,string)", p0, p1, p2));
	}

	function log(address p0, uint p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool)", p0, p1, p2));
	}

	function log(address p0, uint p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,address)", p0, p1, p2));
	}

	function log(address p0, string memory p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,uint)", p0, p1, p2));
	}

	function log(address p0, string memory p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2));
	}

	function log(address p0, string memory p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2));
	}

	function log(address p0, string memory p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2));
	}

	function log(address p0, bool p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint)", p0, p1, p2));
	}

	function log(address p0, bool p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2));
	}

	function log(address p0, bool p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2));
	}

	function log(address p0, bool p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2));
	}

	function log(address p0, address p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,uint)", p0, p1, p2));
	}

	function log(address p0, address p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2));
	}

	function log(address p0, address p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2));
	}

	function log(address p0, address p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2));
	}

	function log(uint p0, uint p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,string)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,address)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,string)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,address)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,string)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,address)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,string)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,address)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,string)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,address)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,string)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,address)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,string)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,address)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,string)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,address)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,string)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,address)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,string)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,address)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,string)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,address)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,string)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,address)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,string)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,address)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,string)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,address)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,string)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,address)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,string)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,string)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,address)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,string)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,address)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,string)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,address)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,string)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,address)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,string)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,address)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,string)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,address)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,address)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,string)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,address)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,string)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,address)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,string)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,address)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,string)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,address)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,string)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,address)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,string)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,address)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,uint)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,string)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,bool)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,address)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,uint)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,string)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,bool)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,address)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,uint)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,string)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,bool)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,address)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,uint)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,string)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,bool)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,address)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,uint)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,string)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,bool)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,address)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,string,string)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,string,bool)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,string,address)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,string)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,bool)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,address)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,address,string)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,address,bool)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,address,address)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,uint)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,string)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,bool)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,address)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,string)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,bool)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,address)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,string)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,bool)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,address)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,string)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,bool)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,address)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,uint)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,string)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,bool)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,address)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,string,string)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,string,bool)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,string,address)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,string)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,bool)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,address)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,address,string)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,address,bool)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3));
	}

}

File 24 of 37 : IToken.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;


/// @notice common struct definitions for tokens
interface IToken {

    struct Token {

        uint256 id;
        uint256 balance;
        bool burn;

    }

    /// @notice a set of tokens.
    struct TokenSet {

        mapping(uint256 => uint256) keyPointers;
        uint256[] keyList;
        Token[] valueList;

    }

    /// @notice the definition for a token.
    struct TokenDefinition {

        // the host multitoken
        address token;

        // the id of the token definition. if static mint then also token hash
        uint256 id;

        // the category name
        uint256 collectionId;

        // the name of the token
        string name;

        // the symbol of the token
        string symbol;

        // the description of the token
        string description;

        // the decimals of the token. 0 for NFT
        uint8 decimals;

        // the total supply of the token
        uint256 totalSupply;

        // whether to generate the id or not for new tokens. if false then we use id field of the definition to mint tokens
        bool generateId;

        // probability of the item being awarded
        uint256 probability;

         // the index of the probability in its array
        uint256 probabilityIndex;

         // the index of the probability in its array
        uint256 probabilityRoll;

    }

    struct TokenRecord {

        uint256 id;
        address owner;
        address minter;
        uint256 _type;
        uint256 balance;

    }

    /// @notice the token source type. Either a static source or a collection.
    enum TokenSourceType {

        Static,
        Collection

    }

    /// @notice the token source. Specifies the source of the token - either a static source or a collection.
    struct TokenSource {

        // the token source type
        TokenSourceType _type;
        // the source id if a static collection
        uint256 staticSourceId;
        // the collection source address if collection
        address collectionSourceAddress;

    }
}

File 25 of 37 : ITokenPrice.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;


/// @notice common struct definitions for tokens
interface ITokenPrice {

    /// @notice DIctates how the price of the token is increased post every sale
    enum PriceModifier {

        None,
        Fixed,
        Exponential,
        InverseLog

    }

    /// @notice a token price and how it changes
    struct TokenPriceData {

        // the price of the token
        uint256 price;
         // how the price is modified
        PriceModifier priceModifier;
        // only used if priceModifier is EXPONENTIAL or INVERSELOG or FIXED
        uint256 priceModifierFactor;
        // max price for the token
        uint256 maxPrice;

    }

    /// @notice get the increased price of the token
    function getIncreasedPrice() external view returns (uint256);

    /// @notice get the increased price of the token
    function getTokenPrice() external view returns (TokenPriceData memory);


}

File 26 of 37 : IControllable.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

/// @notice a controllable contract interface. allows for controllers to perform privileged actions. controllera can other controllers and remove themselves.
interface IControllable {

    /// @notice emitted when a controller is added.
    event ControllerAdded(
        address indexed contractAddress,
        address indexed controllerAddress
    );

    /// @notice emitted when a controller is removed.
    event ControllerRemoved(
        address indexed contractAddress,
        address indexed controllerAddress
    );

    /// @notice adds a controller.
    /// @param controller the controller to add.
    function addController(address controller) external;

    /// @notice removes a controller.
    /// @param controller the address to check
    /// @return true if the address is a controller
    function isController(address controller) external view returns (bool);

    /// @notice remove ourselves from the list of controllers.
    function relinquishControl() external;
}

File 27 of 37 : IFactory.sol
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;

interface IFactoryElement {
    function factoryCreated(address _factory, address _owner) external;
    function factory() external returns(address);
    function owner() external returns(address);
}

/// @title A title that should describe the contract/interface
/// @author The name of the author
/// @notice Explain to an end user what this does
/// @dev Explain to a developer any extra details
/// @notice a contract factory. Can create an instance of a new contract and return elements from that list to callers
interface IFactory {

    /// @notice a contract instance.
    struct Instance {
        address factory;
        address contractAddress;
    }

    /// @dev emitted when a new contract instance has been craeted
    event InstanceCreated(
        address factory,
        address contractAddress,
        Instance data
    );

    /// @notice a set of requirements. used for random access
    struct FactoryInstanceSet {
        mapping(uint256 => uint256) keyPointers;
        uint256[] keyList;
        Instance[] valueList;
    }

    struct FactoryData {
        FactoryInstanceSet instances;
    }

    struct FactorySettings {
        FactoryData data;
    }

    /// @notice returns the contract bytecode
    /// @return _instances the contract bytecode
    function contractBytes() external view returns (bytes memory _instances);

    /// @notice returns the contract instances as a list of instances
    /// @return _instances the contract instances
    function instances() external view returns (Instance[] memory _instances);

    /// @notice returns the contract instance at the given index
    /// @param idx the index of the instance to return
    /// @return instance the instance at the given index
    function at(uint256 idx) external view returns (Instance memory instance);

    /// @notice returns the length of the already-created contracts list
    /// @return _length the length of the list
    function count() external view returns (uint256 _length);

    /// @notice creates a new contract instance
    /// @param owner the owner of the new contract
    /// @param salt the salt to use for the new contract
    /// @return instanceOut the address of the new contract
    function create(address owner, uint256 salt)
        external
        returns (Instance memory instanceOut);

}

File 28 of 37 : UInt256Set.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0;

/**
 * @notice Key sets with enumeration and delete. Uses mappings for random
 * and existence checks and dynamic arrays for enumeration. Key uniqueness is enforced.
 * @dev Sets are unordered. Delete operations reorder keys. All operations have a
 * fixed gas cost at any scale, O(1).
 * author: Rob Hitchens
 */

library UInt256Set {
    struct Set {
        mapping(uint256 => uint256) keyPointers;
        uint256[] keyList;
    }

    /**
     * @notice insert a key.
     * @dev duplicate keys are not permitted.
     * @param self storage pointer to a Set.
     * @param key value to insert.
     */
    function insert(Set storage self, uint256 key) public {
        require(
            !exists(self, key),
            "UInt256Set: key already exists in the set."
        );
        self.keyList.push(key);
        self.keyPointers[key] = self.keyList.length - 1;
    }

    /**
     * @notice remove a key.
     * @dev key to remove must exist.
     * @param self storage pointer to a Set.
     * @param key value to remove.
     */
    function remove(Set storage self, uint256 key) public {
        // TODO: I commented this out do get a test to pass - need to figure out what is up here
        // require(
        //     exists(self, key),
        //     "UInt256Set: key does not exist in the set."
        // );
        if (!exists(self, key)) return;
        uint256 last = count(self) - 1;
        uint256 rowToReplace = self.keyPointers[key];
        if (rowToReplace != last) {
            uint256 keyToMove = self.keyList[last];
            self.keyPointers[keyToMove] = rowToReplace;
            self.keyList[rowToReplace] = keyToMove;
        }
        delete self.keyPointers[key];
        delete self.keyList[self.keyList.length - 1];
    }

    /**
     * @notice count the keys.
     * @param self storage pointer to a Set.
     */
    function count(Set storage self) public view returns (uint256) {
        return (self.keyList.length);
    }

    /**
     * @notice check if a key is in the Set.
     * @param self storage pointer to a Set.
     * @param key value to check.
     * @return bool true: Set member, false: not a Set member.
     */
    function exists(Set storage self, uint256 key)
        public
        view
        returns (bool)
    {
        if (self.keyList.length == 0) return false;
        return self.keyList[self.keyPointers[key]] == key;
    }

    /**
     * @notice fetch a key by row (enumerate).
     * @param self storage pointer to a Set.
     * @param index row to enumerate. Must be < count() - 1.
     */
    function keyAtIndex(Set storage self, uint256 index)
        public
        view
        returns (uint256)
    {
        return self.keyList[index];
    }
}

File 29 of 37 : IERC1155Owned.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

/// implemented by erc1155 tokens to allow mminting
interface IERC1155Owned {

    /// @notice returns the owned tokens of the account
    /// @param owner the owner address
    /// @param ids owned token ids
    function owned(address owner) external view returns (uint256[] memory ids);

    /// @notice returns whether given id is owned by the account
    /// @param account tthe account
    /// @param toCheck the token id to check
    /// @param isOwner whether the given address is owner of the token id
    function isOwnerOf(address account, uint256 toCheck) external view returns (bool isOwner);

}

File 30 of 37 : AddressSet.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0;

/**
 * @notice Key sets with enumeration and delete. Uses mappings for random
 * and existence checks and dynamic arrays for enumeration. Key uniqueness is enforced.
 * @dev Sets are unordered. Delete operations reorder keys. All operations have a
 * fixed gas cost at any scale, O(1).
 * author: Rob Hitchens
 */

library AddressSet {
    struct Set {
        mapping(address => uint256) keyPointers;
        address[] keyList;
    }

    /**
     * @notice insert a key.
     * @dev duplicate keys are not permitted.
     * @param self storage pointer to a Set.
     * @param key value to insert.
     */
    function insert(Set storage self, address key) public {
        require(
            !exists(self, key),
            "AddressSet: key already exists in the set."
        );
        self.keyList.push(key);
        self.keyPointers[key] = self.keyList.length - 1;
    }

    /**
     * @notice remove a key.
     * @dev key to remove must exist.
     * @param self storage pointer to a Set.
     * @param key value to remove.
     */
    function remove(Set storage self, address key) public {
        // TODO: I commented this out do get a test to pass - need to figure out what is up here
        require(
            exists(self, key),
            "AddressSet: key does not exist in the set."
        );
        if (!exists(self, key)) return;
        uint256 last = count(self) - 1;
        uint256 rowToReplace = self.keyPointers[key];
        if (rowToReplace != last) {
            address keyToMove = self.keyList[last];
            self.keyPointers[keyToMove] = rowToReplace;
            self.keyList[rowToReplace] = keyToMove;
        }
        delete self.keyPointers[key];
        self.keyList.pop();
    }

    /**
     * @notice count the keys.
     * @param self storage pointer to a Set.
     */
    function count(Set storage self) public view returns (uint256) {
        return (self.keyList.length);
    }

    /**
     * @notice check if a key is in the Set.
     * @param self storage pointer to a Set.
     * @param key value to check.
     * @return bool true: Set member, false: not a Set member.
     */
    function exists(Set storage self, address key)
        public
        view
        returns (bool)
    {
        if (self.keyList.length == 0) return false;
        return self.keyList[self.keyPointers[key]] == key;
    }

    /**
     * @notice fetch a key by row (enumerate).
     * @param self storage pointer to a Set.
     * @param index row to enumerate. Must be < count() - 1.
     */
    function keyAtIndex(Set storage self, uint256 index)
        public
        view
        returns (address)
    {
        return self.keyList[index];
    }
}

File 31 of 37 : IERC1155Owners.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

/// implemented by erc1155 tokens to allow mminting
interface IERC1155Owners {

    /// @notice returns the owners of the token
    /// @param tokenId the token id
    /// @param owners the owner addresses of the token id
    function ownersOf(uint256 tokenId) external view returns (address[] memory owners);

    /// @notice returns whether given address owns given id
    /// @param tokenId the token id
    /// @param toCheck the address to check
    /// @param isOwner whether the given address is owner of the token id
    function isOwnedBy(uint256 tokenId, address toCheck) external view returns (bool isOwner);

}

File 32 of 37 : IPermissionedMinter.sol
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;

import "../interfaces/ITokenMinter.sol";

/// @dev a contract which is permissioned to mint of the multitoken
interface IPermissionedMinter {

 function mint(address receiver, uint256 collectionId, uint256 id, uint256 amount) external;
 function burn(address target, uint256 id, uint256 amount) external;
 function depositTokens(uint256 amount) external payable;
 function minterBalance() external view returns (uint256);
 function minter(address _minter) external view returns (ITokenMinter.Minter memory __minter);

}

File 33 of 37 : IMintingManager.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

import "../interfaces/ITokenMinter.sol";

/**
 * @notice This intreface provides a way for users to register addresses as permissioned minters, mint * burn, unregister, and reload the permissioned minter account.
 */
interface IMintingManager {

 function mint(address receiver, uint256 collectionId, uint256 id, uint256 amount) external;
 function burn(address target, uint256 id, uint256 amount) external;
 function minter(address _minter) external view returns (ITokenMinter.Minter memory __minter);
 function depositTokens(uint256 amount) external payable ;
 function makeHash(uint256 tokenId) external view returns (uint256);

}

File 34 of 37 : IBank.sol
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;

/// @notice a pool of tokens that users can deposit into and withdraw from
interface IBank {

    /// @notice emitted when a token is added to the collection
    event Deposited (
        address indexed bank,
        address indexed account,
        uint256 indexed id,
        uint256 amount
    );

    /// @notice emitted when a token is added to the collection
    event Withdrew (
        address indexed bank,
        address indexed account,
        uint256 indexed id,
        uint256 amount
    );

    /// @notice deposit tokens into the pool
    /// @param id the token id to deposit
    /// @param amount the amount of tokens to deposit
    function deposit(uint256 id, uint256 amount) external payable;

    /// @notice deposit tokens into the pool
    /// @param id the token id to deposit
    /// @param amount the amount of tokens to deposit
    function depositFrom(address account, uint256 id, uint256 amount) external payable;

    /// @notice withdraw all tokens with id from the pool
    /// @param id the token id to withdraw
    function withdraw(uint256 id, uint256 amount) external returns (uint256);

    /// @notice withdraw all tokens with id from the pool
    /// @param to to address of the account
    /// @param id he token id to withdraw
    /// @param amount the amount of tokens to deposit
    function withdrawTo(address to, uint256 id, uint256 amount) external returns (uint256);

    /// @notice get the deposited amount of tokens with id
    /// @param id the token id to get the amount of
    /// @return the amount of tokens with id
    function balance(address _account, uint256 id) external view returns (uint256);

}

File 35 of 37 : ITokenMinter.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

import "./IERC1155Burn.sol";

/**
 * @notice This intreface provides a way for users to register addresses as permissioned minters, mint * burn, unregister, and reload the permissioned minter account.
 */
interface ITokenMinter {

    /// @notice a registration record for a permissioned minter.
    struct Minter {

        // the account address of the permissioned minter.
        address account;
        // the amount of tokens minted by the permissioned minter.
        uint256 minted;
        // the amount of tokens minted by the permissioned minter.
        uint256 burned;
        // the amount of payment spent by the permissioned minter.
        uint256 spent;
        // an approval map for this minter. sets a count of tokens the approved can mint.
        // mapping(address => uint256) approved; // TODO implement this.

    }

    /// @notice event emitted when minter is registered
    event MinterRegistered(
        address indexed registrant,
        uint256 depositPaid
    );

    /// @notice emoitted when minter is unregistered
    event MinterUnregistered(
        address indexed registrant,
        uint256 depositReturned
    );

    /// @notice emitted when minter address is reloaded
    event MinterReloaded(
        address indexed registrant,
        uint256 amountDeposited
    );

    // TODO handle fees

    /// @notice get the registration record for a permissioned minter.
    /// @param _minter the address
    /// @return _minterObj the address
    function minter(address _minter) external returns (Minter memory _minterObj);

    /// @notice mint a token associated with a collection with an amount
    /// @param receiver the mint receiver
    /// @param collectionId the collection id
    /// @param amount the amount to mint
    function mint(address receiver, uint256 collectionId, uint256 id, uint256 amount) external;

    /// @notice mint a token associated with a collection with an amount
    /// @param target the mint receiver
    /// @param id the collection id
    /// @param amount the amount to mint
    function burn(address target, uint256 id, uint256 amount) external;

}

File 36 of 37 : IERC1155Burn.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

/// implemented by erc1155 tokens to allow burning
interface IERC1155Burn {

    /// @notice event emitted when tokens are burned
    event MinterBurned(
        address target,
        uint256 tokenHash,
        uint256 amount
    );

    /// @notice burn tokens of specified amount from the specified address
    /// @param target the burn target
    /// @param tokenHash the token hash to burn
    /// @param amount the amount to burn
    function burn(
        address target,
        uint256 tokenHash,
        uint256 amount
    ) external;


}

File 37 of 37 : IWithdrawable.sol
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;

/// @notice a contract that can be withdrawn from by some user
interface IWithdrawable {

    /// @notice withdraw some amount of either a token or ether
    /// @param token the erc20 token to withdraw or 0 for the base token (ether)
    /// @param id the token id to withdraw or 0 for the base token (ether)
    /// @param amount the amount to withdraw
    function withdraw(address recipient, address token, uint256 id, uint256 amount) external;

    /// @notice emitted when a withdrawal is made
    event TokenWithdrawn(address recipient, address token, uint256 id, uint256 amount);

}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 5
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "metadata": {
    "useLiteralContent": true
  },
  "libraries": {
    "contracts/utils/AddressSet.sol": {
      "AddressSet": "0xae09d7b704281cf10e7bb1776b68fca3d8c94e7c"
    },
    "contracts/utils/UInt256Set.sol": {
      "UInt256Set": "0x3a5107297dc01bab0d18a987a47de8befbcf6eed"
    }
  }
}

Contract Security Audit

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"airdropId","type":"uint256"},{"components":[{"internalType":"bool","name":"whitelistOnly","type":"bool"},{"internalType":"uint256","name":"whitelistId","type":"uint256"},{"internalType":"bytes32","name":"whitelistHash","type":"bytes32"},{"internalType":"uint256","name":"maxQuantity","type":"uint256"},{"internalType":"uint256","name":"maxQuantityPerSale","type":"uint256"},{"internalType":"uint256","name":"minQuantityPerSale","type":"uint256"},{"internalType":"uint256","name":"maxQuantityPerAccount","type":"uint256"},{"internalType":"uint256","name":"quantitySold","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"components":[{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"enum ITokenPrice.PriceModifier","name":"priceModifier","type":"uint8"},{"internalType":"uint256","name":"priceModifierFactor","type":"uint256"},{"internalType":"uint256","name":"maxPrice","type":"uint256"}],"internalType":"struct ITokenPrice.TokenPriceData","name":"initialPrice","type":"tuple"},{"internalType":"uint256","name":"tokenHash","type":"uint256"}],"indexed":false,"internalType":"struct IAirdrop.AirdropSettings","name":"airdrop","type":"tuple"}],"name":"AirdropLaunched","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"airdropId","type":"uint256"},{"indexed":true,"internalType":"address","name":"beneficiary","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenHash","type":"uint256"},{"indexed":false,"internalType":"bytes32[]","name":"proof","type":"bytes32[]"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"AirdropRedeemed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"},{"indexed":true,"internalType":"address","name":"controllerAddress","type":"address"}],"name":"ControllerAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"},{"indexed":true,"internalType":"address","name":"controllerAddress","type":"address"}],"name":"ControllerRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"purchaser","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"TokenPurchased","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"tokenHash","type":"uint256"},{"internalType":"uint256","name":"collectionHash","type":"uint256"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"payee","type":"address"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"description","type":"string"},{"internalType":"bool","name":"openState","type":"bool"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"uint256","name":"maxQuantity","type":"uint256"},{"internalType":"uint256","name":"maxQuantityPerSale","type":"uint256"},{"internalType":"uint256","name":"minQuantityPerSale","type":"uint256"},{"internalType":"uint256","name":"maxQuantityPerAccount","type":"uint256"},{"components":[{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"enum ITokenPrice.PriceModifier","name":"priceModifier","type":"uint8"},{"internalType":"uint256","name":"priceModifierFactor","type":"uint256"},{"internalType":"uint256","name":"maxPrice","type":"uint256"}],"internalType":"struct ITokenPrice.TokenPriceData","name":"initialPrice","type":"tuple"}],"indexed":false,"internalType":"struct ITokenSale.TokenSaleSettings","name":"tokenSale","type":"tuple"}],"name":"TokenSaleClosed","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"tokenHash","type":"uint256"},{"internalType":"uint256","name":"collectionHash","type":"uint256"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"payee","type":"address"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"description","type":"string"},{"internalType":"bool","name":"openState","type":"bool"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"uint256","name":"maxQuantity","type":"uint256"},{"internalType":"uint256","name":"maxQuantityPerSale","type":"uint256"},{"internalType":"uint256","name":"minQuantityPerSale","type":"uint256"},{"internalType":"uint256","name":"maxQuantityPerAccount","type":"uint256"},{"components":[{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"enum ITokenPrice.PriceModifier","name":"priceModifier","type":"uint8"},{"internalType":"uint256","name":"priceModifierFactor","type":"uint256"},{"internalType":"uint256","name":"maxPrice","type":"uint256"}],"internalType":"struct ITokenPrice.TokenPriceData","name":"initialPrice","type":"tuple"}],"indexed":false,"internalType":"struct ITokenSale.TokenSaleSettings","name":"tokenSale","type":"tuple"}],"name":"TokenSaleOpen","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"tokenHash","type":"uint256"},{"internalType":"uint256","name":"collectionHash","type":"uint256"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"payee","type":"address"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"description","type":"string"},{"internalType":"bool","name":"openState","type":"bool"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"uint256","name":"maxQuantity","type":"uint256"},{"internalType":"uint256","name":"maxQuantityPerSale","type":"uint256"},{"internalType":"uint256","name":"minQuantityPerSale","type":"uint256"},{"internalType":"uint256","name":"maxQuantityPerAccount","type":"uint256"},{"components":[{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"enum ITokenPrice.PriceModifier","name":"priceModifier","type":"uint8"},{"internalType":"uint256","name":"priceModifierFactor","type":"uint256"},{"internalType":"uint256","name":"maxPrice","type":"uint256"}],"internalType":"struct ITokenPrice.TokenPriceData","name":"initialPrice","type":"tuple"}],"indexed":false,"internalType":"struct ITokenSale.TokenSaleSettings","name":"tokenSale","type":"tuple"}],"name":"TokenSaleSettingsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TokenWithdrawn","type":"event"},{"inputs":[{"components":[{"internalType":"bool","name":"whitelistOnly","type":"bool"},{"internalType":"uint256","name":"whitelistId","type":"uint256"},{"internalType":"bytes32","name":"whitelistHash","type":"bytes32"},{"internalType":"uint256","name":"maxQuantity","type":"uint256"},{"internalType":"uint256","name":"maxQuantityPerSale","type":"uint256"},{"internalType":"uint256","name":"minQuantityPerSale","type":"uint256"},{"internalType":"uint256","name":"maxQuantityPerAccount","type":"uint256"},{"internalType":"uint256","name":"quantitySold","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"components":[{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"enum ITokenPrice.PriceModifier","name":"priceModifier","type":"uint8"},{"internalType":"uint256","name":"priceModifierFactor","type":"uint256"},{"internalType":"uint256","name":"maxPrice","type":"uint256"}],"internalType":"struct ITokenPrice.TokenPriceData","name":"initialPrice","type":"tuple"},{"internalType":"uint256","name":"tokenHash","type":"uint256"}],"internalType":"struct IAirdrop.AirdropSettings","name":"_airdrop","type":"tuple"}],"name":"addAirdrop","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_controller","type":"address"}],"name":"addController","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"drop","type":"uint256"}],"name":"airdrop","outputs":[{"components":[{"internalType":"bool","name":"whitelistOnly","type":"bool"},{"internalType":"uint256","name":"whitelistId","type":"uint256"},{"internalType":"bytes32","name":"whitelistHash","type":"bytes32"},{"internalType":"uint256","name":"maxQuantity","type":"uint256"},{"internalType":"uint256","name":"maxQuantityPerSale","type":"uint256"},{"internalType":"uint256","name":"minQuantityPerSale","type":"uint256"},{"internalType":"uint256","name":"maxQuantityPerAccount","type":"uint256"},{"internalType":"uint256","name":"quantitySold","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"components":[{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"enum ITokenPrice.PriceModifier","name":"priceModifier","type":"uint8"},{"internalType":"uint256","name":"priceModifierFactor","type":"uint256"},{"internalType":"uint256","name":"maxPrice","type":"uint256"}],"internalType":"struct ITokenPrice.TokenPriceData","name":"initialPrice","type":"tuple"},{"internalType":"uint256","name":"tokenHash","type":"uint256"}],"internalType":"struct IAirdrop.AirdropSettings","name":"settings","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"depositTokens","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"factory_","type":"address"},{"internalType":"address","name":"owner_","type":"address"}],"name":"factoryCreated","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getChainID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCommonUri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"a","type":"address"},{"internalType":"uint256","name":"b","type":"uint256"}],"name":"getHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getTokenSaleSettings","outputs":[{"components":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"tokenHash","type":"uint256"},{"internalType":"uint256","name":"collectionHash","type":"uint256"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"payee","type":"address"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"description","type":"string"},{"internalType":"bool","name":"openState","type":"bool"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"uint256","name":"maxQuantity","type":"uint256"},{"internalType":"uint256","name":"maxQuantityPerSale","type":"uint256"},{"internalType":"uint256","name":"minQuantityPerSale","type":"uint256"},{"internalType":"uint256","name":"maxQuantityPerAccount","type":"uint256"},{"components":[{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"enum ITokenPrice.PriceModifier","name":"priceModifier","type":"uint8"},{"internalType":"uint256","name":"priceModifierFactor","type":"uint256"},{"internalType":"uint256","name":"maxPrice","type":"uint256"}],"internalType":"struct ITokenPrice.TokenPriceData","name":"initialPrice","type":"tuple"}],"internalType":"struct ITokenSale.TokenSaleSettings","name":"settings","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bool","name":"whitelistOnly","type":"bool"},{"internalType":"uint256","name":"whitelistId","type":"uint256"},{"internalType":"bytes32","name":"whitelistHash","type":"bytes32"},{"internalType":"uint256","name":"maxQuantity","type":"uint256"},{"internalType":"uint256","name":"maxQuantityPerSale","type":"uint256"},{"internalType":"uint256","name":"minQuantityPerSale","type":"uint256"},{"internalType":"uint256","name":"maxQuantityPerAccount","type":"uint256"},{"internalType":"uint256","name":"quantitySold","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"components":[{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"enum ITokenPrice.PriceModifier","name":"priceModifier","type":"uint8"},{"internalType":"uint256","name":"priceModifierFactor","type":"uint256"},{"internalType":"uint256","name":"maxPrice","type":"uint256"}],"internalType":"struct ITokenPrice.TokenPriceData","name":"initialPrice","type":"tuple"},{"internalType":"uint256","name":"tokenHash","type":"uint256"}],"internalType":"struct IAirdrop.AirdropSettings[]","name":"settingsList","type":"tuple[]"}],"name":"initMerkleAirdrops","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"tokenHash","type":"uint256"},{"internalType":"uint256","name":"collectionHash","type":"uint256"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"payee","type":"address"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"description","type":"string"},{"internalType":"bool","name":"openState","type":"bool"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"uint256","name":"maxQuantity","type":"uint256"},{"internalType":"uint256","name":"maxQuantityPerSale","type":"uint256"},{"internalType":"uint256","name":"minQuantityPerSale","type":"uint256"},{"internalType":"uint256","name":"maxQuantityPerAccount","type":"uint256"},{"components":[{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"enum ITokenPrice.PriceModifier","name":"priceModifier","type":"uint8"},{"internalType":"uint256","name":"priceModifierFactor","type":"uint256"},{"internalType":"uint256","name":"maxPrice","type":"uint256"}],"internalType":"struct ITokenPrice.TokenPriceData","name":"initialPrice","type":"tuple"}],"internalType":"struct ITokenSale.TokenSaleSettings","name":"tokenSaleInit","type":"tuple"},{"components":[{"internalType":"bool","name":"whitelistOnly","type":"bool"},{"internalType":"uint256","name":"whitelistId","type":"uint256"},{"internalType":"bytes32","name":"whitelistHash","type":"bytes32"},{"internalType":"uint256","name":"maxQuantity","type":"uint256"},{"internalType":"uint256","name":"maxQuantityPerSale","type":"uint256"},{"internalType":"uint256","name":"minQuantityPerSale","type":"uint256"},{"internalType":"uint256","name":"maxQuantityPerAccount","type":"uint256"},{"internalType":"uint256","name":"quantitySold","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"components":[{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"enum ITokenPrice.PriceModifier","name":"priceModifier","type":"uint8"},{"internalType":"uint256","name":"priceModifierFactor","type":"uint256"},{"internalType":"uint256","name":"maxPrice","type":"uint256"}],"internalType":"struct ITokenPrice.TokenPriceData","name":"initialPrice","type":"tuple"},{"internalType":"uint256","name":"tokenHash","type":"uint256"}],"internalType":"struct IAirdrop.AirdropSettings[]","name":"settingsList","type":"tuple[]"}],"name":"initTokenSale","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"registry","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"isController","outputs":[{"internalType":"bool","name":"allowed","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"toCheck","type":"address"}],"name":"isOwnedBy","outputs":[{"internalType":"bool","name":"isOwner","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"toCheck","type":"uint256"}],"name":"isOwnerOf","outputs":[{"internalType":"bool","name":"isOwned","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"collectionId","type":"uint256"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_minter","type":"address"}],"name":"minter","outputs":[{"components":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"minted","type":"uint256"},{"internalType":"uint256","name":"burned","type":"uint256"},{"internalType":"uint256","name":"spent","type":"uint256"}],"internalType":"struct ITokenMinter.Minter","name":"__minter","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minterBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"owned","outputs":[{"internalType":"uint256[]","name":"ownedList","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"ownersOf","outputs":[{"internalType":"address[]","name":"ownersList","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"quantity","type":"uint256"},{"internalType":"uint256","name":"total","type":"uint256"},{"internalType":"uint256","name":"drop","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"}],"name":"purchase","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"drop","type":"uint256"},{"internalType":"uint256","name":"leaf","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"total","type":"uint256"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"}],"name":"redeem","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"drop","type":"uint256"},{"internalType":"address","name":"redeemer","type":"address"}],"name":"redeemed","outputs":[{"internalType":"bool","name":"isRedeemed","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"relinquishControl","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"commonUri","type":"string"}],"name":"setCommonUri","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"tokenHash","type":"uint256"},{"internalType":"uint256","name":"collectionHash","type":"uint256"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"payee","type":"address"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"description","type":"string"},{"internalType":"bool","name":"openState","type":"bool"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"uint256","name":"maxQuantity","type":"uint256"},{"internalType":"uint256","name":"maxQuantityPerSale","type":"uint256"},{"internalType":"uint256","name":"minQuantityPerSale","type":"uint256"},{"internalType":"uint256","name":"maxQuantityPerAccount","type":"uint256"},{"components":[{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"enum ITokenPrice.PriceModifier","name":"priceModifier","type":"uint8"},{"internalType":"uint256","name":"priceModifierFactor","type":"uint256"},{"internalType":"uint256","name":"maxPrice","type":"uint256"}],"internalType":"struct ITokenPrice.TokenPriceData","name":"initialPrice","type":"tuple"}],"internalType":"struct ITokenSale.TokenSaleSettings","name":"settings","type":"tuple"}],"name":"updateTokenSaleSettings","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"root","type":"bytes32"},{"internalType":"bytes32","name":"leaf","type":"bytes32"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"verify","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]

Deployed Bytecode

0x6080604052600436106101675760003560e01c80628114971461016c5780630a2b1a4a1461018e5780631e7a1d76146101b95780632ed418b5146101db5780633423e548146101fb5780633dd08c381461022b5780634f7f887014610287578063564b81ef1461029a578063570ad0b4146102b75780635ddb0845146102ca578063671b250f146102ea5780636c7818181461030a5780637bfe950c1461031f57806386ca9e7a1461033f5780638da5cb5b1461035f57806397dc4a1314610386578063a584ab29146103b3578063a647e8ec146103e0578063a7fc7a0714610400578063ae1e4df114610420578063b1ab931714610440578063b429afeb1461046d578063c45a0155146104a6578063c4d66de8146104c4578063c5b8f772146104e4578063d9d182a614610504578063dd49756e14610524578063e1c28bef14610537578063ed05582b1461054c578063ed901985146105a9578063f5298aca146105c9575b600080fd5b34801561017857600080fd5b5061018c610187366004612f30565b6105e9565b005b34801561019a57600080fd5b506101a361084c565b6040516101b091906131ff565b60405180910390f35b3480156101c557600080fd5b506101ce6108d1565b6040516101b09190613496565b3480156101e757600080fd5b5061018c6101f6366004612f64565b610b8b565b34801561020757600080fd5b5061021b610216366004612d1f565b610d95565b60405190151581526020016101b0565b34801561023757600080fd5b5061024b610246366004612af8565b610e44565b6040516101b0919081516001600160a01b0316815260208083015190820152604080830151908201526060918201519181019190915260800190565b61018c610295366004613023565b610f08565b3480156102a657600080fd5b50465b6040519081526020016101b0565b61018c6102c5366004612c4d565b610f1f565b3480156102d657600080fd5b5061021b6102e5366004612ffe565b610f2e565b3480156102f657600080fd5b5061018c610305366004612cc1565b610f3a565b34801561031657600080fd5b506102a9611020565b34801561032b57600080fd5b5061018c61033a366004612b6b565b6110b2565b34801561034b57600080fd5b5061018c61035a366004612e17565b6111d3565b34801561036b57600080fd5b506001546001600160a01b03165b6040516101b091906130f8565b34801561039257600080fd5b506103a66103a1366004612fcc565b61121d565b6040516101b091906133ef565b3480156103bf57600080fd5b506103d36103ce366004612fcc565b611377565b6040516101b09190613132565b3480156103ec57600080fd5b5061018c6103fb366004612c12565b6113e6565b34801561040c57600080fd5b5061018c61041b366004612af8565b61145e565b34801561042c57600080fd5b5061021b61043b366004612ffe565b6114a5565b34801561044c57600080fd5b5061046061045b366004612af8565b61153b565b6040516101b091906131c7565b34801561047957600080fd5b5061021b610488366004612af8565b6001600160a01b03166000908152600b602052604090205460ff1690565b3480156104b257600080fd5b506000546001600160a01b0316610379565b3480156104d057600080fd5b5061018c6104df366004612af8565b6115a9565b3480156104f057600080fd5b5061021b6104ff366004612bb1565b611687565b34801561051057600080fd5b5061018c61051f366004612b32565b6116df565b61018c610532366004612fcc565b611758565b34801561054357600080fd5b5061018c6117c5565b34801561055857600080fd5b506102a9610567366004612bb1565b6040516001600160601b0319606084901b1660208201526034810182905260009060540160405160208183030381529060405280519060200120905092915050565b3480156105b557600080fd5b5061018c6105c4366004612d6e565b61180d565b3480156105d557600080fd5b5061018c6105e4366004612bdd565b611874565b336000908152600b602052604090205460ff1615156001148061060b57503033145b6106305760405162461bcd60e51b815260040161062790613310565b60405180910390fd5b6011546001600160a01b031633146106a45760405162461bcd60e51b815260206004820152603160248201527f4f6e6c7920746865206f776e65722063616e207570646174652074686520746f6044820152706b656e2073616c652073657474696e677360781b6064820152608401610627565b8051600d80546001600160a01b03199081166001600160a01b03938416178255602080850151600e805484169186169190911790556040850151600f556060850151601055608085015160118054841691861691909117905560a085015160128054909316941693909317905560c08301518051849361072992601392910190612612565b5060e08201518051610745916007840191602090910190612612565b506101008201518051610762916008840191602090910190612612565b5061012082015160098201805491151560ff19928316179055610140830151600a830155610160830151600b830155610180830151600c8301556101a0830151600d8301556101c0830151600e8301556101e0830151600f830155610200830151805160108401908155602082015160118501805493949293919290911660018360038111156107f4576107f4613763565b0217905550604082015181600201556060820151816003015550509050507fea22972dcdc3aa4be8582e63c7cde870fc266986eee7a46bd751330f0895e5be816040516108419190613496565b60405180910390a150565b602154604051630d47824f60e21b81523060048201526060916001600160a01b03169063351e093c9060240160006040518083038186803b15801561089057600080fd5b505afa1580156108a4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108cc9190810190612daa565b905090565b6108d9612696565b6040805161022081018252600d546001600160a01b039081168252600e5481166020830152600f549282019290925260105460608201526011548216608082015260125490911660a08201526013805460c083019190610938906136f7565b80601f0160208091040260200160405190810160405280929190818152602001828054610964906136f7565b80156109b15780601f10610986576101008083540402835291602001916109b1565b820191906000526020600020905b81548152906001019060200180831161099457829003601f168201915b50505050508152602001600d60070180546109cb906136f7565b80601f01602080910402602001604051908101604052809291908181526020018280546109f7906136f7565b8015610a445780601f10610a1957610100808354040283529160200191610a44565b820191906000526020600020905b815481529060010190602001808311610a2757829003601f168201915b50505050508152602001600d6008018054610a5e906136f7565b80601f0160208091040260200160405190810160405280929190818152602001828054610a8a906136f7565b8015610ad75780601f10610aac57610100808354040283529160200191610ad7565b820191906000526020600020905b815481529060010190602001808311610aba57829003601f168201915b505050918352505060165460ff90811615156020808401919091526017546040808501919091526018546060850152601954608080860191909152601a5460a0860152601b5460c0860152601c5460e08601528151908101909152601d80548252601e546101009095019491939092840191166003811115610b5b57610b5b613763565b6003811115610b6c57610b6c613763565b8152600282015460208201526003909101546040909101529052919050565b60208301516001600160a01b0316610be55760405162461bcd60e51b815260206004820152601e60248201527f4d756c7469746f6b656e2061646472657373206d7573742062652073657400006044820152606401610627565b8015610bf557610bf58282610f3a565b8251600d80546001600160a01b03199081166001600160a01b03938416178255602080870151600e805484169186169190911790556040870151600f556060870151601055608087015160118054841691861691909117905560a087015160128054909316941693909317905560c085015180518693610c7a92601392910190612612565b5060e08201518051610c96916007840191602090910190612612565b506101008201518051610cb3916008840191602090910190612612565b5061012082015160098201805491151560ff19928316179055610140830151600a830155610160830151600b830155610180830151600c8301556101a0830151600d8301556101c0830151600e8301556101e0830151600f83015561020083015180516010840190815560208201516011850180549394929391929091166001836003811115610d4557610d45613763565b021790555060408201516002820155606090910151600390910155505050602090910151602180546001600160a01b039092166001600160a01b0319928316179055600d80549091163017905550565b600082815b8351811015610e39576000848281518110610db757610db7613779565b60200260200101519050808311610df9576040805160208101859052908101829052606001604051602081830303815290604052805190602001209250610e26565b60408051602081018390529081018490526060016040516020818303038152906040528051906020012092505b5080610e3181613732565b915050610d9a565b509093149392505050565b610e78604051806080016040528060006001600160a01b031681526020016000815260200160008152602001600081525090565b6000610e826118f1565b6040516307ba118760e31b81529091506001600160a01b03821690633dd08c3890610eb19086906004016130f8565b60806040518083038186803b158015610ec957600080fd5b505afa158015610edd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f019190612ec2565b9392505050565b610f17848484898986346119ac565b505050505050565b610f17868686868686346119ac565b6000610f018383611f69565b60035415610f895760405162461bcd60e51b815260206004820152601c60248201527b105a5c991c9bdc1cc8185b1c9958591e481a5b9a5d1a585b1a5e995960221b6044820152606401610627565b80610fcd5760405162461bcd60e51b8152602060048201526014602482015273139bc8185a5c991c9bdc1cc81c1c9bdd9a59195960621b6044820152606401610627565b60005b8181101561101b57611009838383818110610fed57610fed613779565b90506101e002018036038101906110049190612e17565b611fb7565b8061101381613732565b915050610fd0565b505050565b60008061102b6118f1565b6040516336c642cd60e11b8152306004820152600060248201529091506001600160a01b03821690636d8c859a9060440160206040518083038186803b15801561107457600080fd5b505afa158015611088573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110ac9190612fe5565b91505090565b336000908152600b602052604090205460ff161515600114806110d457503033145b6110f05760405162461bcd60e51b815260040161062790613310565b804710156111355760405162461bcd60e51b8152602060048201526012602482015271496e73756666696369656e742066756e647360701b6044820152606401610627565b6001600160a01b03831661117b576040516001600160a01b0385169082156108fc029083906000818181858888f19350505050158015611179573d6000803e3d6000fd5b505b604080516001600160a01b03808716825285166020820152908101839052606081018290527f7a163cc3488948c84f02deddd608c9465235f04837413e5f1051007d0da746d29060800160405180910390a150505050565b336000908152600b602052604090205460ff161515600114806111f557503033145b6112115760405162461bcd60e51b815260040161062790613310565b61121a81611fb7565b50565b611225612745565b600082815260026020526040902060010154821461127e5760405162461bcd60e51b8152602060048201526016602482015275105a5c991c9bdc08191bd95cc81b9bdd08195e1a5cdd60521b6044820152606401610627565b600082815260026020818152604092839020835161018081018552815460ff90811615158252600183015482850152938201548186015260038083015460608301526004830154608080840191909152600584015460a0840152600684015460c0840152600784015460e0840152600884015461010084015260098401546101208401528651908101909652600a830180548752600b8401549296939561014088019591939185019291169081111561133957611339613763565b600381111561134a5761134a613763565b8152602001600282015481526020016003820154815250508152602001600e820154815250509050919050565b6000818152600860209081526040918290206001018054835181840281018401909452808452606093928301828280156113da57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116113bc575b50505050509050919050565b60006113f06118f1565b604051632991fa3b60e21b81529091506001600160a01b0382169063a647e8ec9061142590889088908890889060040161310c565b600060405180830381600087803b15801561143f57600080fd5b505af1158015611453573d6000803e3d6000fd5b505050505050505050565b336000908152600b602052604090205460ff1615156001148061148057503033145b61149c5760405162461bcd60e51b815260040161062790613310565b61121a81612103565b600082815260086020526040808220905163a8a37bd360e01b815273ae09d7b704281cf10e7bb1776b68fca3d8c94e7c9163a8a37bd3916114eb9190869060040161347f565b60206040518083038186803b15801561150357600080fd5b505af4158015611517573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f019190612d02565b6001600160a01b0381166000908152600760209081526040918290206001018054835181840281018401909452808452606093928301828280156113da57602002820191906000526020600020905b81548152602001906001019080831161158a5750505050509050919050565b600954610100900460ff166115c45760095460ff16156115c8565b303b155b61162b5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610627565b600954610100900460ff1615801561164d576009805461ffff19166101011790555b61165633612103565b600a80546001600160a01b0319166001600160a01b0384161790558015611683576009805461ff00191690555b5050565b6001600160a01b0382166000908152600760205260408082209051631bf945d160e21b8152600481019190915260248101839052733a5107297dc01bab0d18a987a47de8befbcf6eed90636fe51744906044016114eb565b6001546001600160a01b03161561172a5760405162461bcd60e51b815260206004820152600f60248201526e185b1c9958591e4818dc99585d1959608a1b6044820152606401610627565b600080546001600160a01b039384166001600160a01b03199182161790915560018054929093169116179055565b60006117626118f1565b604051636ea4bab760e11b8152600481018490529091506001600160a01b0382169063dd49756e9084906024016000604051808303818588803b1580156117a857600080fd5b505af11580156117bc573d6000803e3d6000fd5b50505050505050565b336000908152600b602052604090205460ff161515600114806117e757503033145b6118035760405162461bcd60e51b815260040161062790613310565b61180b612127565b565b60215460405163a92f2bdb60e01b81526001600160a01b039091169063a92f2bdb9061183f90309085906004016135d4565b600060405180830381600087803b15801561185957600080fd5b505af115801561186d573d6000803e3d6000fd5b5050505050565b600061187e6118f1565b604051637a94c56560e11b81526001600160a01b03868116600483015260248201869052604482018590529192509082169063f5298aca90606401600060405180830381600087803b1580156118d357600080fd5b505af11580156118e7573d6000803e3d6000fd5b5050505050505050565b600a5460408051633e10510b60e01b81526004810191909152600760448201526611d95b541bdbdb60ca1b606482015260806024820152600e60848201526d26b4b73a34b733a6b0b730b3b2b960911b60a48201526000916001600160a01b031690633e10510b9060c40160206040518083038186803b15801561197457600080fd5b505afa158015611988573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108cc9190612b15565b8315611d34576000848152600260205260409020600181015485146119e35760405162461bcd60e51b815260040161062790613212565b6119ed8589611f69565b15611a355760405162461bcd60e51b8152602060048201526018602482015277105a5c991c9bdc08185b1c9958591e481c995919595b595960421b6044820152606401610627565b60038101541580611a675750600381015415801590611a6757508060030154878260070154611a649190613690565b11155b611a835760405162461bcd60e51b815260040161062790613240565b600a8101548290611a959089906136a8565b1115611adf5760405162461bcd60e51b8152602060048201526019602482015278139bdd08195b9bdd59da081c1c9a58d948185d1d1858da1959603a1b6044820152606401610627565b60058101541580611b025750600581015415801590611b02575080600501548710155b611b1e5760405162461bcd60e51b8152600401610627906132cf565b60048101541580611b415750600481015415801590611b41575080600401548711155b611b5d5760405162461bcd60e51b81526004016106279061328d565b60068101541580611c265750600681015415801590611c26575060068101546001600160a01b0389166000908152600760205260409081902090516334a122fb60e01b81526004810191909152733a5107297dc01bab0d18a987a47de8befbcf6eed906334a122fb9060240160206040518083038186803b158015611be157600080fd5b505af4158015611bf5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c199190612fe5565b611c239089613690565b11155b611c425760405162461bcd60e51b8152600401610627906133ba565b806008015442101580611c5757506008810154155b611c735760405162461bcd60e51b815260040161062790613358565b806009015442111580611c8857506009810154155b611ca45760405162461bcd60e51b81526004016106279061338e565b805460ff1615611cbc57611cbc85858a8a8a8861217e565b60005b87811015611d2d576000611cd3878b6122dc565b9050808a6001600160a01b0316887feb9003c9338711a06346a071b24d5af50fadfd3cad38bfe99b34f0ec9af2e24a888d604051611d1292919061317f565b60405180910390a45080611d2581613732565b915050611cbf565b50506117bc565b6019541580611d7a575060195415801590611d7a57506019546000805260236020527fec8fa5b038da1e720ea021ba5ca9b6d584cce4d81a9a9ab37c8a07ee3bc6511054105b611d965760405162461bcd60e51b815260040161062790613240565b601b541580611db35750601b5415801590611db35750601b548610155b611dcf5760405162461bcd60e51b8152600401610627906132cf565b601a541580611dec5750601a5415801590611dec5750601a548611155b611e085760405162461bcd60e51b81526004016106279061328d565b601c541580611ecb5750601c5415801590611ecb5750601c546001600160a01b0388166000908152600760205260409081902090516334a122fb60e01b81526004810191909152733a5107297dc01bab0d18a987a47de8befbcf6eed906334a122fb9060240160206040518083038186803b158015611e8657600080fd5b505af4158015611e9a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ebe9190612fe5565b611ec89088613690565b11155b611ee75760405162461bcd60e51b8152600401610627906133ba565b60175442101580611ef85750601754155b611f145760405162461bcd60e51b815260040161062790613358565b60185442111580611f255750601854155b611f415760405162461bcd60e51b81526004016106279061338e565b60005b868110156118e757611f5685896122dc565b5080611f6181613732565b915050611f44565b60008281526006602090815260408083206001600160a01b038516808552908352818420548685526005845282852091855292528220548115801590611fae57508082145b95945050505050565b6020808201516000818152600290925260409091206001015414156120175760405162461bcd60e51b815260206004820152601660248201527541697264726f7020616c72656164792065786973747360501b6044820152606401610627565b60208082018051600090815260028084526040918290208551815490151560ff199182161782559351600180830191909155928601519181019190915560608501516003808301919091556080860151600483015560a0860151600583015560c0860151600683015560e08601516007830155610100860151600883015561012086015160098301556101408601518051600a840190815595810151600b840180548998959793969294919316919084908111156120d7576120d7613763565b02179055506040820151816002015560608201518160030155505061016082015181600e015590505050565b6001600160a01b03166000908152600b60205260409020805460ff19166001179055565b336000908152600b602052604090205460ff1615156001148061214957503033145b6121655760405162461bcd60e51b815260040161062790613310565b336000908152600b60205260409020805460ff19169055565b60008681526005602090815260408083206001600160a01b038816808552908352818420548a855260068452828520918552925290912054816121c157836121c3565b805b9050806121d08684613690565b111561222c5760405162461bcd60e51b815260206004820152602560248201527f596f75206861766520616c72656164792072656465656d6564207468697320616044820152641b5bdd5b9d60da1b6064820152608401610627565b60008881526006602090815260408083206001600160a01b038a168085529083528184208590558b84526005835281842090845290915281208054879290612275908490613690565b9091555050600088815260026020819052604082200154612297908986610d95565b9050806114535760405162461bcd60e51b815260206004820152601360248201527213595c9adb19481c1c9bdbd98819985a5b1959606a1b6044820152606401610627565b600080831561232d5760008481526002602052604090206001015484146123155760405162461bcd60e51b815260040161062790613212565b506000838152600260205260409020600e0154612332565b50600f545b8061239c57600c54612345906001613690565b600c8190556040516a7368656c6c7368616b617360a81b60208201526001600160601b0319606086901b16602b820152603f810191909152605f016040516020818303038152906040528051906020012060001c90505b6123a88382600161246b565b905060016023600086815260200190815260200160002060008282546123ce9190613690565b909155505060008481526022602090815260408083206001600160a01b03871684529091528120805460019290612406908490613690565b909155506124169050838261254a565b61242081846125cb565b60408051828152600160208201526001600160a01b038516917f3ceffd410054fdaed44f598ff5c1fb450658778e2241892da4aa646979dee617910160405180910390a29392505050565b60215460405163148d6d8560e01b81526000916001600160a01b03169063148d6d85906124a290879087908790309060040161310c565b600060405180830381600087803b1580156124bc57600080fd5b505af11580156124d0573d6000803e3d6000fd5b5050602154604051630fb6790560e31b8152600481018790526001600160a01b03888116602483015261fde860448301529091169250637db3c8289150606401600060405180830381600087803b15801561252a57600080fd5b505af115801561253e573d6000803e3d6000fd5b50949695505050505050565b6001600160a01b0382166000908152600760205260409081902090516309a18d5f60e11b8152600481019190915260248101829052733a5107297dc01bab0d18a987a47de8befbcf6eed906313431abe906044015b60006040518083038186803b1580156125b757600080fd5b505af4158015610f17573d6000803e3d6000fd5b60008281526008602052604090819020905163989779e960e01b815273ae09d7b704281cf10e7bb1776b68fca3d8c94e7c9163989779e99161259f9190859060040161347f565b82805461261e906136f7565b90600052602060002090601f0160209004810192826126405760008555612686565b82601f1061265957805160ff1916838001178555612686565b82800160010185558215612686579182015b8281111561268657825182559160200191906001019061266b565b506126929291506127b1565b5090565b60405180610220016040528060006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160006001600160a01b0316815260200160006001600160a01b031681526020016060815260200160608152602001606081526020016000151581526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016127406127c6565b905290565b6040518061018001604052806000151581526020016000815260200160008019168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016127a46127c6565b8152602001600081525090565b5b8082111561269257600081556001016127b2565b604080516080810190915260008082526020820190815260200160008152602001600081525090565b80356127fa816137a5565b919050565b600082601f83011261281057600080fd5b813560206001600160401b0382111561282b5761282b61378f565b8160051b61283a828201613639565b83815282810190868401838801850189101561285557600080fd5b600093505b8584101561287857803583526001939093019291840191840161285a565b50979650505050505050565b60008083601f84011261289657600080fd5b5081356001600160401b038111156128ad57600080fd5b6020830191508360206101e0830285010111156128c957600080fd5b9250929050565b80356127fa816137ba565b600082601f8301126128ec57600080fd5b81356128ff6128fa82613669565b613639565b81815284602083860101111561291457600080fd5b816020850160208301376000918101602001919091529392505050565b60006080828403121561294357600080fd5b604051608081016001600160401b03811182821017156129655761296561378f565b6040528235815290508060208301356004811061298157600080fd5b8060208301525060408301356040820152606083013560608201525092915050565b600061028082840312156129b657600080fd5b6129be6135ed565b90506129c9826127ef565b81526129d7602083016127ef565b602082015260408201356040820152606082013560608201526129fc608083016127ef565b6080820152612a0d60a083016127ef565b60a082015260c08201356001600160401b0380821115612a2c57600080fd5b612a38858386016128db565b60c084015260e0840135915080821115612a5157600080fd5b612a5d858386016128db565b60e084015261010091508184013581811115612a7857600080fd5b612a84868287016128db565b83850152505050610120612a998184016128d0565b908201526101408281013590820152610160808301359082015261018080830135908201526101a080830135908201526101c080830135908201526101e08083013590820152610200612aee84828501612931565b9082015292915050565b600060208284031215612b0a57600080fd5b8135610f01816137a5565b600060208284031215612b2757600080fd5b8151610f01816137a5565b60008060408385031215612b4557600080fd5b8235612b50816137a5565b91506020830135612b60816137a5565b809150509250929050565b60008060008060808587031215612b8157600080fd5b8435612b8c816137a5565b93506020850135612b9c816137a5565b93969395505050506040820135916060013590565b60008060408385031215612bc457600080fd5b8235612bcf816137a5565b946020939093013593505050565b600080600060608486031215612bf257600080fd5b8335612bfd816137a5565b95602085013595506040909401359392505050565b60008060008060808587031215612c2857600080fd5b8435612c33816137a5565b966020860135965060408601359560600135945092505050565b60008060008060008060c08789031215612c6657600080fd5b8635612c71816137a5565b95506020870135945060408701359350606087013592506080870135915060a08701356001600160401b03811115612ca857600080fd5b612cb489828a016127ff565b9150509295509295509295565b60008060208385031215612cd457600080fd5b82356001600160401b03811115612cea57600080fd5b612cf685828601612884565b90969095509350505050565b600060208284031215612d1457600080fd5b8151610f01816137ba565b600080600060608486031215612d3457600080fd5b833592506020840135915060408401356001600160401b03811115612d5857600080fd5b612d64868287016127ff565b9150509250925092565b600060208284031215612d8057600080fd5b81356001600160401b03811115612d9657600080fd5b612da2848285016128db565b949350505050565b600060208284031215612dbc57600080fd5b81516001600160401b03811115612dd257600080fd5b8201601f81018413612de357600080fd5b8051612df16128fa82613669565b818152856020838501011115612e0657600080fd5b611fae8260208301602086016136c7565b60006101e08284031215612e2a57600080fd5b612e32613616565b612e3b836128d0565b81526020830135602082015260408301356040820152606083013560608201526080830135608082015260a083013560a082015260c083013560c082015260e083013560e0820152610100808401358183015250610120808401358183015250610140612eaa85828601612931565b908201526101c0929092013561016083015250919050565b600060808284031215612ed457600080fd5b604051608081016001600160401b0381118282101715612ef657612ef661378f565b6040528251612f04816137a5565b808252506020830151602082015260408301516040820152606083015160608201528091505092915050565b600060208284031215612f4257600080fd5b81356001600160401b03811115612f5857600080fd5b612da2848285016129a3565b600080600060408486031215612f7957600080fd5b83356001600160401b0380821115612f9057600080fd5b612f9c878388016129a3565b94506020860135915080821115612fb257600080fd5b50612fbf86828701612884565b9497909650939450505050565b600060208284031215612fde57600080fd5b5035919050565b600060208284031215612ff757600080fd5b5051919050565b6000806040838503121561301157600080fd5b823591506020830135612b60816137a5565b60008060008060008060c0878903121561303c57600080fd5b86359550602087013594506040870135613055816137a5565b9350606087013592506080870135915060a08701356001600160401b03811115612ca857600080fd5b6001600160a01b03169052565b600081518084526130a38160208601602086016136c7565b601f01601f19169290920160200192915050565b805182526020810151600481106130de57634e487b7160e01b600052602160045260246000fd5b602083015260408181015190830152606090810151910152565b6001600160a01b0391909116815260200190565b6001600160a01b0394909416845260208401929092526040830152606082015260800190565b6020808252825182820181905260009190848201906040850190845b818110156131735783516001600160a01b03168352928401929184019160010161314e565b50909695505050505050565b604080825283519082018190526000906020906060840190828701845b828110156131b85781518452928401929084019060010161319c565b50505092019290925292915050565b6020808252825182820181905260009190848201906040850190845b81811015613173578351835292840192918401916001016131e3565b602081526000610f01602083018461308b565b602080825260149082015273105a5c991c9bdc08191bd95cdb9d08195e1a5cdd60621b604082015260600190565b6020808252602d908201527f546865206d6178696d756d20616d6f756e74206f6620746f6b656e732068617360408201526c103132b2b7103137bab3b43a1760991b606082015260800190565b60208082526022908201527f4d6178696d756d207175616e74697479207065722073616c6520657863656564604082015261195960f21b606082015260800190565b60208082526021908201527f4d696e696d756d207175616e74697479207065722073616c65206e6f74206d656040820152601d60fa1b606082015260800190565b60208082526028908201527f436f6e74726f6c6c61626c653a2063616c6c6572206973206e6f74206120636f604082015267373a3937b63632b960c11b606082015260800190565b6020808252601c908201527b151a19481cd85b19481a185cc81b9bdd081cdd185c9d1959081e595d60221b604082015260600190565b602080825260129082015271151a19481cd85b19481a185cc8195b99195960721b604082015260600190565b6020808252818101527f416d6f756e742065786365656473206d6178696d756d2062757920746f74616c604082015260600190565b8151151581526101e081016020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015260c083015160c083015260e083015160e08301526101008084015181840152506101208084015181840152506101408084015161346b828501826130b7565b50506101608301516101c083015292915050565b9182526001600160a01b0316602082015260400190565b602081526134a860208201835161307e565b600060208301516134bc604084018261307e565b50604083015160608301526060830151608083015260808301516134e360a084018261307e565b5060a08301516134f660c084018261307e565b5060c083015161028060e08401526135126102a084018261308b565b905060e0840151601f19610100818685030181870152613532848461308b565b935080870151925050610120818685030181870152613551848461308b565b9350808701519250505061014061356b8186018315159052565b85015161016085810191909152850151610180808601919091528501516101a0808601919091528501516101c0808601919091528501516101e0808601919091528501516102008086019190915285015190506135cc6102208501826130b7565b509392505050565b828152604060208201526000612da2604083018461308b565b60405161022081016001600160401b03811182821017156136105761361061378f565b60405290565b60405161018081016001600160401b03811182821017156136105761361061378f565b604051601f8201601f191681016001600160401b03811182821017156136615761366161378f565b604052919050565b60006001600160401b038211156136825761368261378f565b50601f01601f191660200190565b600082198211156136a3576136a361374d565b500190565b60008160001904831182151516156136c2576136c261374d565b500290565b60005b838110156136e25781810151838201526020016136ca565b838111156136f1576000848401525b50505050565b600181811c9082168061370b57607f821691505b6020821081141561372c57634e487b7160e01b600052602260045260246000fd5b50919050565b60006000198214156137465761374661374d565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461121a57600080fd5b801515811461121a57600080fdfea26469706673582212205370bf261eb315aedcf27f65510ae8bd94d20d7b9e68dc97e506fab3adccb50464736f6c63430008060033

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
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.