ETH Price: $1,991.29 (-1.40%)

Transaction Decoder

Block:
12971529 at Aug-06-2021 12:54:51 PM +UTC
Transaction Fee:
0.005391321 ETH $10.74
Gas Used:
138,239 Gas / 39 Gwei

Emitted Events:

410 CryptoCorgisBreeder.TransferSingle( operator=[Receiver] CryptoCorgisRescuer, from=0x00000000...000000000, to=[Sender] 0x70e0c842e70e7a1edc48b17ca2fd87f1d15283b9, id=12971353, value=1 )
411 CryptoCorgisBreeder.CorgiSold( corgiNumber=3355, blockNumber=12971353, mutantCorgiId=0, owner=[Sender] 0x70e0c842e70e7a1edc48b17ca2fd87f1d15283b9 )

Account State Difference:

  Address   Before After State Difference Code
(Hiveon Pool)
4,460.104203663945721937 Eth4,460.10468473731864566 Eth0.000481073372923723
0x51e61372...40a7957E4
0x6a86442a...2B1809f2a 5.2896 Eth4.9542 Eth0.3354
0x70E0C842...1d15283b9
1.4939205522820377 Eth
Nonce: 256
1.4785292312820377 Eth
Nonce: 257
0.015391321
0xF2E61080...B3dD98E3c 147.208911451315931884 Eth147.554311451315931884 Eth0.3454

Execution Trace

ETH 0.010000000001 CryptoCorgisRescuer.rescueCorgi( _blockNumber=12971353, _data=0x )
  • CryptoCorgisBreeder.CALL( )
  • CryptoCorgisBreeder.priceForCorgi( _corgiNumber=3355 ) => ( 345400000000000000 )
  • ETH 0.000000000001 0x70e0c842e70e7a1edc48b17ca2fd87f1d15283b9.CALL( )
  • ETH 0.3454 CryptoCorgisBreeder.mint( _blockNumber=12971353, _toAddress=0x70E0C842E70E7a1edC48B17cA2fD87F1d15283b9, _amount=1, _refundAddress=0x70E0C842E70E7a1edC48B17cA2fD87F1d15283b9, _data=0x )
    • ETH 0.3454 0xf2e61080035c5dc890d3602746041f3b3dd98e3c.CALL( )
    • 0x70e0c842e70e7a1edc48b17ca2fd87f1d15283b9.CALL( )
      File 1 of 2: CryptoCorgisRescuer
      //SPDX-License-Identifier: AGPL-3.0
      pragma solidity ^0.7.0;
      import "@openzeppelin/contracts/access/Ownable.sol";
      import "@openzeppelin/contracts/math/SafeMath.sol";
      import "@openzeppelin/contracts/math/Math.sol";
      import "./interfaces/Breeder.sol";
      contract CryptoCorgisRescuer is Ownable {
        using SafeMath for uint256;
        address payable public treasuryAddress;
        address public breederAddress;
        uint256 public discountPerBlockEth;
        uint256 public floorPriceEth;
        constructor(
          address payable _treasuryAddress,
          address _breederAddress,
          uint256 _discountPerBlockEth,
          uint256 _floorPriceEth
        ) {
          treasuryAddress = _treasuryAddress;
          breederAddress = _breederAddress;
          discountPerBlockEth = _discountPerBlockEth;
          floorPriceEth = _floorPriceEth;
        }
        receive() external payable {}
        function setDiscountPerBlock(uint256 _discountPerBlockEth) public onlyOwner {
          discountPerBlockEth = _discountPerBlockEth;
        }
        function setFloorPrice(uint256 _floorPriceEth) public onlyOwner {
          floorPriceEth = _floorPriceEth;
        }
        function returnFunds() public onlyOwner {
          treasuryAddress.transfer(address(this).balance);
        }
        function rescueCorgi(uint256 _blockNumber, bytes calldata _data) public payable {
          uint256 fullPrice = Breeder(breederAddress).priceForCorgi(Breeder(breederAddress).corgisMinted() + 1);
          uint256 discountEth = block.number.sub(_blockNumber).mul(discountPerBlockEth);
          (bool _, uint256 discountedPriceEth) = fullPrice.trySub(discountEth);
          uint finalPrice = Math.max(discountedPriceEth, floorPriceEth);
          require(msg.value >= finalPrice, "CryptoCorgisRescuer: Insufficient funds to rescue a Crypto Corgi.");
          msg.sender.transfer(msg.value.sub(finalPrice));
          Breeder(breederAddress).mint{value: fullPrice}(_blockNumber, msg.sender, 1, msg.sender, _data);
        }
      }// SPDX-License-Identifier: MIT
      pragma solidity >=0.6.0 <0.8.0;
      import "../utils/Context.sol";
      /**
       * @dev Contract module which provides a basic access control mechanism, where
       * there is an account (an owner) that can be granted exclusive access to
       * specific functions.
       *
       * By default, the owner account will be the one that deploys the contract. This
       * can later be changed with {transferOwnership}.
       *
       * This module is used through inheritance. It will make available the modifier
       * `onlyOwner`, which can be applied to your functions to restrict their use to
       * the owner.
       */
      abstract contract Ownable is Context {
          address private _owner;
          event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
          /**
           * @dev Initializes the contract setting the deployer as the initial owner.
           */
          constructor () internal {
              address msgSender = _msgSender();
              _owner = msgSender;
              emit OwnershipTransferred(address(0), msgSender);
          }
          /**
           * @dev Returns the address of the current owner.
           */
          function owner() public view virtual returns (address) {
              return _owner;
          }
          /**
           * @dev Throws if called by any account other than the owner.
           */
          modifier onlyOwner() {
              require(owner() == _msgSender(), "Ownable: caller is not the owner");
              _;
          }
          /**
           * @dev Leaves the contract without owner. It will not be possible to call
           * `onlyOwner` functions anymore. Can only be called by the current owner.
           *
           * NOTE: Renouncing ownership will leave the contract without an owner,
           * thereby removing any functionality that is only available to the owner.
           */
          function renounceOwnership() public virtual onlyOwner {
              emit OwnershipTransferred(_owner, address(0));
              _owner = address(0);
          }
          /**
           * @dev Transfers ownership of the contract to a new account (`newOwner`).
           * Can only be called by the current owner.
           */
          function transferOwnership(address newOwner) public virtual onlyOwner {
              require(newOwner != address(0), "Ownable: new owner is the zero address");
              emit OwnershipTransferred(_owner, newOwner);
              _owner = newOwner;
          }
      }
      // SPDX-License-Identifier: MIT
      pragma solidity >=0.6.0 <0.8.0;
      /**
       * @dev Wrappers over Solidity's arithmetic operations with added overflow
       * checks.
       *
       * Arithmetic operations in Solidity wrap on overflow. This can easily result
       * in bugs, because programmers usually assume that an overflow raises an
       * error, which is the standard behavior in high level programming languages.
       * `SafeMath` restores this intuition by reverting the transaction when an
       * operation overflows.
       *
       * Using this library instead of the unchecked operations eliminates an entire
       * class of bugs, so it's recommended to use it always.
       */
      library SafeMath {
          /**
           * @dev Returns the addition of two unsigned integers, with an overflow flag.
           *
           * _Available since v3.4._
           */
          function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
              uint256 c = a + b;
              if (c < a) return (false, 0);
              return (true, c);
          }
          /**
           * @dev Returns the substraction of two unsigned integers, with an overflow flag.
           *
           * _Available since v3.4._
           */
          function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
              if (b > a) return (false, 0);
              return (true, a - b);
          }
          /**
           * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
           *
           * _Available since v3.4._
           */
          function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
              // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
              // benefit is lost if 'b' is also tested.
              // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
              if (a == 0) return (true, 0);
              uint256 c = a * b;
              if (c / a != b) return (false, 0);
              return (true, c);
          }
          /**
           * @dev Returns the division of two unsigned integers, with a division by zero flag.
           *
           * _Available since v3.4._
           */
          function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
              if (b == 0) return (false, 0);
              return (true, a / b);
          }
          /**
           * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
           *
           * _Available since v3.4._
           */
          function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
              if (b == 0) return (false, 0);
              return (true, a % b);
          }
          /**
           * @dev Returns the addition of two unsigned integers, reverting on
           * overflow.
           *
           * Counterpart to Solidity's `+` operator.
           *
           * Requirements:
           *
           * - Addition cannot overflow.
           */
          function add(uint256 a, uint256 b) internal pure returns (uint256) {
              uint256 c = a + b;
              require(c >= a, "SafeMath: addition overflow");
              return c;
          }
          /**
           * @dev Returns the subtraction of two unsigned integers, reverting on
           * overflow (when the result is negative).
           *
           * Counterpart to Solidity's `-` operator.
           *
           * Requirements:
           *
           * - Subtraction cannot overflow.
           */
          function sub(uint256 a, uint256 b) internal pure returns (uint256) {
              require(b <= a, "SafeMath: subtraction overflow");
              return a - b;
          }
          /**
           * @dev Returns the multiplication of two unsigned integers, reverting on
           * overflow.
           *
           * Counterpart to Solidity's `*` operator.
           *
           * Requirements:
           *
           * - Multiplication cannot overflow.
           */
          function mul(uint256 a, uint256 b) internal pure returns (uint256) {
              if (a == 0) return 0;
              uint256 c = a * b;
              require(c / a == b, "SafeMath: multiplication overflow");
              return c;
          }
          /**
           * @dev Returns the integer division of two unsigned integers, reverting on
           * division by zero. The result is rounded towards zero.
           *
           * Counterpart to Solidity's `/` operator. Note: this function uses a
           * `revert` opcode (which leaves remaining gas untouched) while Solidity
           * uses an invalid opcode to revert (consuming all remaining gas).
           *
           * Requirements:
           *
           * - The divisor cannot be zero.
           */
          function div(uint256 a, uint256 b) internal pure returns (uint256) {
              require(b > 0, "SafeMath: division by zero");
              return a / b;
          }
          /**
           * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
           * reverting when dividing by zero.
           *
           * Counterpart to Solidity's `%` operator. This function uses a `revert`
           * opcode (which leaves remaining gas untouched) while Solidity uses an
           * invalid opcode to revert (consuming all remaining gas).
           *
           * Requirements:
           *
           * - The divisor cannot be zero.
           */
          function mod(uint256 a, uint256 b) internal pure returns (uint256) {
              require(b > 0, "SafeMath: modulo by zero");
              return a % b;
          }
          /**
           * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
           * overflow (when the result is negative).
           *
           * CAUTION: This function is deprecated because it requires allocating memory for the error
           * message unnecessarily. For custom revert reasons use {trySub}.
           *
           * Counterpart to Solidity's `-` operator.
           *
           * Requirements:
           *
           * - Subtraction cannot overflow.
           */
          function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
              require(b <= a, errorMessage);
              return a - b;
          }
          /**
           * @dev Returns the integer division of two unsigned integers, reverting with custom message on
           * division by zero. The result is rounded towards zero.
           *
           * CAUTION: This function is deprecated because it requires allocating memory for the error
           * message unnecessarily. For custom revert reasons use {tryDiv}.
           *
           * Counterpart to Solidity's `/` operator. Note: this function uses a
           * `revert` opcode (which leaves remaining gas untouched) while Solidity
           * uses an invalid opcode to revert (consuming all remaining gas).
           *
           * Requirements:
           *
           * - The divisor cannot be zero.
           */
          function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
              require(b > 0, errorMessage);
              return a / b;
          }
          /**
           * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
           * reverting with custom message when dividing by zero.
           *
           * CAUTION: This function is deprecated because it requires allocating memory for the error
           * message unnecessarily. For custom revert reasons use {tryMod}.
           *
           * Counterpart to Solidity's `%` operator. This function uses a `revert`
           * opcode (which leaves remaining gas untouched) while Solidity uses an
           * invalid opcode to revert (consuming all remaining gas).
           *
           * Requirements:
           *
           * - The divisor cannot be zero.
           */
          function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
              require(b > 0, errorMessage);
              return a % b;
          }
      }
      // SPDX-License-Identifier: MIT
      pragma solidity >=0.6.0 <0.8.0;
      /**
       * @dev Standard math utilities missing in the Solidity language.
       */
      library Math {
          /**
           * @dev Returns the largest of two numbers.
           */
          function max(uint256 a, uint256 b) internal pure returns (uint256) {
              return a >= b ? a : b;
          }
          /**
           * @dev Returns the smallest of two numbers.
           */
          function min(uint256 a, uint256 b) internal pure returns (uint256) {
              return a < b ? a : b;
          }
          /**
           * @dev Returns the average of two numbers. The result is rounded towards
           * zero.
           */
          function average(uint256 a, uint256 b) internal pure returns (uint256) {
              // (a + b) / 2 can overflow, so we distribute
              return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2);
          }
      }
      //SPDX-License-Identifier: AGPL-3.0
      pragma solidity ^0.7.0;
      interface Breeder {
        function corgisMinted() external returns (uint256);
        function priceForCorgi(uint256 _corgiNumber) external pure returns (uint256);
        function mint(
          uint256 _blockNumber,
          address _toAddress,
          uint256 _amount,
          address payable _refundAddress,
          bytes calldata _data
        ) external payable;
      }// SPDX-License-Identifier: MIT
      pragma solidity >=0.6.0 <0.8.0;
      /*
       * @dev Provides information about the current execution context, including the
       * sender of the transaction and its data. While these are generally available
       * via msg.sender and msg.data, they should not be accessed in such a direct
       * manner, since when dealing with GSN meta-transactions the account sending and
       * paying for execution may not be the actual sender (as far as an application
       * is concerned).
       *
       * This contract is only required for intermediate, library-like contracts.
       */
      abstract contract Context {
          function _msgSender() internal view virtual returns (address payable) {
              return msg.sender;
          }
          function _msgData() internal view virtual returns (bytes memory) {
              this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
              return msg.data;
          }
      }
      

      File 2 of 2: CryptoCorgisBreeder
      //SPDX-License-Identifier: AGPL-3.0
      pragma solidity ^0.7.0;
      import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
      import "@openzeppelin/contracts/access/Ownable.sol";
      import "@openzeppelin/contracts/math/SafeMath.sol";
      import "./interfaces/FactoryERC1155.sol";
      contract CryptoCorgisBreeder is Ownable, FactoryERC1155, ERC1155 {
        using SafeMath for uint256;
        event CorgiSold(uint256 corgiNumber, uint256 blockNumber, uint8 mutantCorgiId, address owner);
        uint256 public constant MAX_INT_256 = 2**256 - 1;
        uint256 public constant MAX_CORGIS_MINTED = 10000;
        uint256 public constant CORGI_LIFESPAN_BLOCKS = 256;
        uint256 public constant FIRST_CORGI_PRICE_ETH = 1e16;
        uint256 public constant INCREMENTAL_PRICE_ETH = 1e14;
        uint256 public constant NUMBER_MUTANT_CORGIS = 31;
        // Each mutant corgi has a probability of 6/2^16 of being born.
        uint256 public constant MUTANT_CORGI_PROBABILITY = NUMBER_MUTANT_CORGIS * 6;
        address payable public treasuryAddress;
        uint256 public corgisMinted = 0;
        mapping(uint256 => uint256) public corgiNumberToBlockNumber;
        mapping(uint256 => uint256) public blockNumberToCorgiNumber;
        mapping(uint8 => uint256) public mutantCorgiIdToBlockNumber;
        mapping(uint256 => string) public corgiIdToName;
        string private contractDataURI;
        constructor(
          string memory _metadataURI,
          string memory _contractDataURI,
          address payable _treasuryAddress
        ) ERC1155(_metadataURI) {
          contractDataURI = _contractDataURI;
          treasuryAddress = _treasuryAddress;
        }
        /// @dev https://docs.opensea.io/docs/2-custom-sale-contract-viewing-your-sale-assets-on-opensea
        function name() external pure override returns (string memory) {
          return "Crypto Corgis Breeder";
        }
        function symbol() external pure override returns (string memory) {
          return "CORGI";
        }
        function numOptions() external pure override returns (uint256) {
          return MAX_INT_256;
        }
        /**
         * Indicates that this is a factory contract.
         */
        function supportsFactoryInterface() external pure override returns (bool) {
          return true;
        }
        /**
         * Indicates the Wyvern schema name for assets in this factory, e.g. "ERC1155"
         */
        function factorySchemaName() external pure override returns (string memory) {
          return "ERC1155";
        }
        function getClaimedCorgis() external view returns (uint256[] memory) {
          uint256[] memory blockNumbers = new uint256[](corgisMinted);
          for (uint256 i = 0; i < corgisMinted; i++) {
            blockNumbers[i] = corgiNumberToBlockNumber[i + 1];
          }
          return blockNumbers;
        }
        /// @dev can only can a corgi once and only if you own it.
        function nameCorgi(uint256 id, string memory name) public {
          require(balanceOf(msg.sender, id) == 1, "CryptoCorgisBreeder: Cannot name a corgi you do not own");
          require(bytes(name).length > 0, "CryptoCorgisBreeder: Cannot erase a corgi name");
          require(bytes(corgiIdToName[id]).length == 0, "CryptoCorgisBreeder: Can only name a corgi once");
          corgiIdToName[id] = name;
        }
        /// @dev https://docs.opensea.io/docs/contract-level-metadata
        function contractURI() public view returns (string memory) {
          return contractDataURI;
        }
        /// @dev Allow the deployer to change the smart contract meta-data.
        function setContractDataURI(string memory _contractDataURI) public onlyOwner {
          contractDataURI = _contractDataURI;
        }
        // @dev Allow the deployer to change the ERC-1155 URI
        function setURI(string memory _uri) public onlyOwner {
          _setURI(_uri);
        }
        function dnaForBlockNumber(uint256 _blockNumber) external pure returns (bytes32) {
          return keccak256(abi.encodePacked(_blockNumber));
        }
        /**
         * @dev Returns whether the option ID can be minted. Can return false if the developer wishes to
         * restrict a total supply per option ID (or overall).
         */
        function canMint(uint256 _blockNumber, uint256 _amount) public view override returns (bool) {
          (bool _, uint256 subResult) = block.number.trySub(CORGI_LIFESPAN_BLOCKS);
          if (_blockNumber > block.number || _blockNumber < subResult || _amount > 1) {
            return false;
          }
          return blockNumberToCorgiNumber[_blockNumber] == 0;
        }
        function priceForCorgi(uint256 _corgiNumber) public pure returns (uint256) {
          return FIRST_CORGI_PRICE_ETH.add(INCREMENTAL_PRICE_ETH.mul(_corgiNumber.sub(1)));
        }
        function isMutantCorgi(uint256 _blockNumber) public pure returns (bool, uint8) {
          return isMutantCorgi(keccak256(abi.encodePacked(_blockNumber)));
        }
        /// @dev Return whether a corgi with this DNA is a mutant, and what mutation ID it has.
        function isMutantCorgi(bytes32 _corgiDna) public pure returns (bool, uint8) {
          uint256 corgiDnaNum = uint256(_corgiDna);
          uint16 lastTwoBytesValue = uint16(corgiDnaNum);
          if (lastTwoBytesValue < MUTANT_CORGI_PROBABILITY) {
            return (true, uint8(lastTwoBytesValue / 6) + 1);
          }
          return (false, 0);
        }
        function mint(uint256 _blockNumber, bytes calldata _data) public payable {
          mint(_blockNumber, msg.sender, 1, msg.sender, _data);
        }
        function mint(
          uint256 _blockNumber,
          address _toAddress,
          uint256 _amount,
          bytes calldata _data
        ) public payable override {
          mint(_blockNumber, _toAddress, _amount, msg.sender, _data);
        }
        function mint(
          uint256 _blockNumber,
          address _toAddress,
          uint256 _amount,
          address payable _refundAddress,
          bytes calldata _data
        ) public payable {
          require(corgisMinted < MAX_CORGIS_MINTED, "CryptoCorgisBreeder: Cannot mint any more Crypto Corgis");
          require(canMint(_blockNumber, _amount), "CryptoCorgisBreeder: Not allowed to mint for that block number");
          uint256 nextCorgiId = corgisMinted + 1;
          uint256 price = priceForCorgi(nextCorgiId);
          require(msg.value >= price, "CryptoCorgisBreeder: Insufficient funds to mint a Crypto Corgi");
          treasuryAddress.transfer(price);
          _refundAddress.transfer(msg.value.sub(price));
          bytes32 corgiDna = keccak256(abi.encodePacked(_blockNumber));
          (bool isMutant, uint8 mutantId) = isMutantCorgi(corgiDna);
          if (isMutant) {
            require(mutantCorgiIdToBlockNumber[mutantId] == 0, "CryptoCorgisBreeder: Crypto Corgi mutant already claimed");
            mutantCorgiIdToBlockNumber[mutantId] = _blockNumber;
          }
          corgiNumberToBlockNumber[nextCorgiId] = _blockNumber;
          blockNumberToCorgiNumber[_blockNumber] = nextCorgiId;
          // Use _blockNumber as ID.
          _mint(_toAddress, _blockNumber, 1, _data);
          corgisMinted = nextCorgiId;
          emit CorgiSold(nextCorgiId, _blockNumber, mutantId, _toAddress);
        }
      }
      // SPDX-License-Identifier: MIT
      pragma solidity >=0.6.0 <0.8.0;
      import "./IERC1155.sol";
      import "./IERC1155MetadataURI.sol";
      import "./IERC1155Receiver.sol";
      import "../../utils/Context.sol";
      import "../../introspection/ERC165.sol";
      import "../../math/SafeMath.sol";
      import "../../utils/Address.sol";
      /**
       *
       * @dev Implementation of the basic standard multi-token.
       * See https://eips.ethereum.org/EIPS/eip-1155
       * Originally based on code by Enjin: https://github.com/enjin/erc-1155
       *
       * _Available since v3.1._
       */
      contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {
          using SafeMath for uint256;
          using Address for address;
          // Mapping from token ID to account balances
          mapping (uint256 => mapping(address => uint256)) private _balances;
          // Mapping from account to operator approvals
          mapping (address => mapping(address => bool)) private _operatorApprovals;
          // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json
          string private _uri;
          /*
           *     bytes4(keccak256('balanceOf(address,uint256)')) == 0x00fdd58e
           *     bytes4(keccak256('balanceOfBatch(address[],uint256[])')) == 0x4e1273f4
           *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465
           *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5
           *     bytes4(keccak256('safeTransferFrom(address,address,uint256,uint256,bytes)')) == 0xf242432a
           *     bytes4(keccak256('safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)')) == 0x2eb2c2d6
           *
           *     => 0x00fdd58e ^ 0x4e1273f4 ^ 0xa22cb465 ^
           *        0xe985e9c5 ^ 0xf242432a ^ 0x2eb2c2d6 == 0xd9b67a26
           */
          bytes4 private constant _INTERFACE_ID_ERC1155 = 0xd9b67a26;
          /*
           *     bytes4(keccak256('uri(uint256)')) == 0x0e89341c
           */
          bytes4 private constant _INTERFACE_ID_ERC1155_METADATA_URI = 0x0e89341c;
          /**
           * @dev See {_setURI}.
           */
          constructor (string memory uri_) public {
              _setURI(uri_);
              // register the supported interfaces to conform to ERC1155 via ERC165
              _registerInterface(_INTERFACE_ID_ERC1155);
              // register the supported interfaces to conform to ERC1155MetadataURI via ERC165
              _registerInterface(_INTERFACE_ID_ERC1155_METADATA_URI);
          }
          /**
           * @dev See {IERC1155MetadataURI-uri}.
           *
           * This implementation returns the same URI for *all* token types. It relies
           * on the token type ID substitution mechanism
           * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].
           *
           * Clients calling this function must replace the `\\{id\\}` substring with the
           * actual token type ID.
           */
          function uri(uint256) external view virtual override returns (string memory) {
              return _uri;
          }
          /**
           * @dev See {IERC1155-balanceOf}.
           *
           * Requirements:
           *
           * - `account` cannot be the zero address.
           */
          function balanceOf(address account, uint256 id) public view virtual override returns (uint256) {
              require(account != address(0), "ERC1155: balance query for the zero address");
              return _balances[id][account];
          }
          /**
           * @dev See {IERC1155-balanceOfBatch}.
           *
           * Requirements:
           *
           * - `accounts` and `ids` must have the same length.
           */
          function balanceOfBatch(
              address[] memory accounts,
              uint256[] memory ids
          )
              public
              view
              virtual
              override
              returns (uint256[] memory)
          {
              require(accounts.length == ids.length, "ERC1155: accounts and ids length mismatch");
              uint256[] memory batchBalances = new uint256[](accounts.length);
              for (uint256 i = 0; i < accounts.length; ++i) {
                  batchBalances[i] = balanceOf(accounts[i], ids[i]);
              }
              return batchBalances;
          }
          /**
           * @dev See {IERC1155-setApprovalForAll}.
           */
          function setApprovalForAll(address operator, bool approved) public virtual override {
              require(_msgSender() != operator, "ERC1155: setting approval status for self");
              _operatorApprovals[_msgSender()][operator] = approved;
              emit ApprovalForAll(_msgSender(), operator, approved);
          }
          /**
           * @dev See {IERC1155-isApprovedForAll}.
           */
          function isApprovedForAll(address account, address operator) public view virtual override returns (bool) {
              return _operatorApprovals[account][operator];
          }
          /**
           * @dev See {IERC1155-safeTransferFrom}.
           */
          function safeTransferFrom(
              address from,
              address to,
              uint256 id,
              uint256 amount,
              bytes memory data
          )
              public
              virtual
              override
          {
              require(to != address(0), "ERC1155: transfer to the zero address");
              require(
                  from == _msgSender() || isApprovedForAll(from, _msgSender()),
                  "ERC1155: caller is not owner nor approved"
              );
              address operator = _msgSender();
              _beforeTokenTransfer(operator, from, to, _asSingletonArray(id), _asSingletonArray(amount), data);
              _balances[id][from] = _balances[id][from].sub(amount, "ERC1155: insufficient balance for transfer");
              _balances[id][to] = _balances[id][to].add(amount);
              emit TransferSingle(operator, from, to, id, amount);
              _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);
          }
          /**
           * @dev See {IERC1155-safeBatchTransferFrom}.
           */
          function safeBatchTransferFrom(
              address from,
              address to,
              uint256[] memory ids,
              uint256[] memory amounts,
              bytes memory data
          )
              public
              virtual
              override
          {
              require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");
              require(to != address(0), "ERC1155: transfer to the zero address");
              require(
                  from == _msgSender() || isApprovedForAll(from, _msgSender()),
                  "ERC1155: transfer caller is not owner nor approved"
              );
              address operator = _msgSender();
              _beforeTokenTransfer(operator, from, to, ids, amounts, data);
              for (uint256 i = 0; i < ids.length; ++i) {
                  uint256 id = ids[i];
                  uint256 amount = amounts[i];
                  _balances[id][from] = _balances[id][from].sub(
                      amount,
                      "ERC1155: insufficient balance for transfer"
                  );
                  _balances[id][to] = _balances[id][to].add(amount);
              }
              emit TransferBatch(operator, from, to, ids, amounts);
              _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data);
          }
          /**
           * @dev Sets a new URI for all token types, by relying on the token type ID
           * substitution mechanism
           * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].
           *
           * By this mechanism, any occurrence of the `\\{id\\}` substring in either the
           * URI or any of the amounts in the JSON file at said URI will be replaced by
           * clients with the token type ID.
           *
           * For example, the `https://token-cdn-domain/\\{id\\}.json` URI would be
           * interpreted by clients as
           * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json`
           * for token type ID 0x4cce0.
           *
           * See {uri}.
           *
           * Because these URIs cannot be meaningfully represented by the {URI} event,
           * this function emits no events.
           */
          function _setURI(string memory newuri) internal virtual {
              _uri = newuri;
          }
          /**
           * @dev Creates `amount` tokens of token type `id`, and assigns them to `account`.
           *
           * Emits a {TransferSingle} event.
           *
           * Requirements:
           *
           * - `account` cannot be the zero address.
           * - If `account` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
           * acceptance magic value.
           */
          function _mint(address account, uint256 id, uint256 amount, bytes memory data) internal virtual {
              require(account != address(0), "ERC1155: mint to the zero address");
              address operator = _msgSender();
              _beforeTokenTransfer(operator, address(0), account, _asSingletonArray(id), _asSingletonArray(amount), data);
              _balances[id][account] = _balances[id][account].add(amount);
              emit TransferSingle(operator, address(0), account, id, amount);
              _doSafeTransferAcceptanceCheck(operator, address(0), account, id, amount, data);
          }
          /**
           * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}.
           *
           * 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 _mintBatch(address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data) internal virtual {
              require(to != address(0), "ERC1155: mint to the zero address");
              require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");
              address operator = _msgSender();
              _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);
              for (uint i = 0; i < ids.length; i++) {
                  _balances[ids[i]][to] = amounts[i].add(_balances[ids[i]][to]);
              }
              emit TransferBatch(operator, address(0), to, ids, amounts);
              _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);
          }
          /**
           * @dev Destroys `amount` tokens of token type `id` from `account`
           *
           * Requirements:
           *
           * - `account` cannot be the zero address.
           * - `account` must have at least `amount` tokens of token type `id`.
           */
          function _burn(address account, uint256 id, uint256 amount) internal virtual {
              require(account != address(0), "ERC1155: burn from the zero address");
              address operator = _msgSender();
              _beforeTokenTransfer(operator, account, address(0), _asSingletonArray(id), _asSingletonArray(amount), "");
              _balances[id][account] = _balances[id][account].sub(
                  amount,
                  "ERC1155: burn amount exceeds balance"
              );
              emit TransferSingle(operator, account, address(0), id, amount);
          }
          /**
           * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}.
           *
           * Requirements:
           *
           * - `ids` and `amounts` must have the same length.
           */
          function _burnBatch(address account, uint256[] memory ids, uint256[] memory amounts) internal virtual {
              require(account != address(0), "ERC1155: burn from the zero address");
              require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");
              address operator = _msgSender();
              _beforeTokenTransfer(operator, account, address(0), ids, amounts, "");
              for (uint i = 0; i < ids.length; i++) {
                  _balances[ids[i]][account] = _balances[ids[i]][account].sub(
                      amounts[i],
                      "ERC1155: burn amount exceeds balance"
                  );
              }
              emit TransferBatch(operator, account, address(0), ids, amounts);
          }
          /**
           * @dev Hook that is called before any token transfer. This includes minting
           * and burning, as well as batched variants.
           *
           * The same hook is called on both single and batched variants. For single
           * transfers, the length of the `id` and `amount` arrays will be 1.
           *
           * Calling conditions (for each `id` and `amount` pair):
           *
           * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens
           * of token type `id` will be  transferred to `to`.
           * - When `from` is zero, `amount` tokens of token type `id` will be minted
           * for `to`.
           * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`
           * will be burned.
           * - `from` and `to` are never both zero.
           * - `ids` and `amounts` have the same, non-zero length.
           *
           * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
           */
          function _beforeTokenTransfer(
              address operator,
              address from,
              address to,
              uint256[] memory ids,
              uint256[] memory amounts,
              bytes memory data
          )
              internal
              virtual
          { }
          function _doSafeTransferAcceptanceCheck(
              address operator,
              address from,
              address to,
              uint256 id,
              uint256 amount,
              bytes memory data
          )
              private
          {
              if (to.isContract()) {
                  try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) {
                      if (response != IERC1155Receiver(to).onERC1155Received.selector) {
                          revert("ERC1155: ERC1155Receiver rejected tokens");
                      }
                  } catch Error(string memory reason) {
                      revert(reason);
                  } catch {
                      revert("ERC1155: transfer to non ERC1155Receiver implementer");
                  }
              }
          }
          function _doSafeBatchTransferAcceptanceCheck(
              address operator,
              address from,
              address to,
              uint256[] memory ids,
              uint256[] memory amounts,
              bytes memory data
          )
              private
          {
              if (to.isContract()) {
                  try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (bytes4 response) {
                      if (response != IERC1155Receiver(to).onERC1155BatchReceived.selector) {
                          revert("ERC1155: ERC1155Receiver rejected tokens");
                      }
                  } catch Error(string memory reason) {
                      revert(reason);
                  } catch {
                      revert("ERC1155: transfer to non ERC1155Receiver implementer");
                  }
              }
          }
          function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) {
              uint256[] memory array = new uint256[](1);
              array[0] = element;
              return array;
          }
      }
      // SPDX-License-Identifier: MIT
      pragma solidity >=0.6.0 <0.8.0;
      import "../utils/Context.sol";
      /**
       * @dev Contract module which provides a basic access control mechanism, where
       * there is an account (an owner) that can be granted exclusive access to
       * specific functions.
       *
       * By default, the owner account will be the one that deploys the contract. This
       * can later be changed with {transferOwnership}.
       *
       * This module is used through inheritance. It will make available the modifier
       * `onlyOwner`, which can be applied to your functions to restrict their use to
       * the owner.
       */
      abstract contract Ownable is Context {
          address private _owner;
          event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
          /**
           * @dev Initializes the contract setting the deployer as the initial owner.
           */
          constructor () internal {
              address msgSender = _msgSender();
              _owner = msgSender;
              emit OwnershipTransferred(address(0), msgSender);
          }
          /**
           * @dev Returns the address of the current owner.
           */
          function owner() public view virtual returns (address) {
              return _owner;
          }
          /**
           * @dev Throws if called by any account other than the owner.
           */
          modifier onlyOwner() {
              require(owner() == _msgSender(), "Ownable: caller is not the owner");
              _;
          }
          /**
           * @dev Leaves the contract without owner. It will not be possible to call
           * `onlyOwner` functions anymore. Can only be called by the current owner.
           *
           * NOTE: Renouncing ownership will leave the contract without an owner,
           * thereby removing any functionality that is only available to the owner.
           */
          function renounceOwnership() public virtual onlyOwner {
              emit OwnershipTransferred(_owner, address(0));
              _owner = address(0);
          }
          /**
           * @dev Transfers ownership of the contract to a new account (`newOwner`).
           * Can only be called by the current owner.
           */
          function transferOwnership(address newOwner) public virtual onlyOwner {
              require(newOwner != address(0), "Ownable: new owner is the zero address");
              emit OwnershipTransferred(_owner, newOwner);
              _owner = newOwner;
          }
      }
      // SPDX-License-Identifier: MIT
      pragma solidity >=0.6.0 <0.8.0;
      /**
       * @dev Wrappers over Solidity's arithmetic operations with added overflow
       * checks.
       *
       * Arithmetic operations in Solidity wrap on overflow. This can easily result
       * in bugs, because programmers usually assume that an overflow raises an
       * error, which is the standard behavior in high level programming languages.
       * `SafeMath` restores this intuition by reverting the transaction when an
       * operation overflows.
       *
       * Using this library instead of the unchecked operations eliminates an entire
       * class of bugs, so it's recommended to use it always.
       */
      library SafeMath {
          /**
           * @dev Returns the addition of two unsigned integers, with an overflow flag.
           *
           * _Available since v3.4._
           */
          function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
              uint256 c = a + b;
              if (c < a) return (false, 0);
              return (true, c);
          }
          /**
           * @dev Returns the substraction of two unsigned integers, with an overflow flag.
           *
           * _Available since v3.4._
           */
          function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
              if (b > a) return (false, 0);
              return (true, a - b);
          }
          /**
           * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
           *
           * _Available since v3.4._
           */
          function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
              // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
              // benefit is lost if 'b' is also tested.
              // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
              if (a == 0) return (true, 0);
              uint256 c = a * b;
              if (c / a != b) return (false, 0);
              return (true, c);
          }
          /**
           * @dev Returns the division of two unsigned integers, with a division by zero flag.
           *
           * _Available since v3.4._
           */
          function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
              if (b == 0) return (false, 0);
              return (true, a / b);
          }
          /**
           * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
           *
           * _Available since v3.4._
           */
          function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
              if (b == 0) return (false, 0);
              return (true, a % b);
          }
          /**
           * @dev Returns the addition of two unsigned integers, reverting on
           * overflow.
           *
           * Counterpart to Solidity's `+` operator.
           *
           * Requirements:
           *
           * - Addition cannot overflow.
           */
          function add(uint256 a, uint256 b) internal pure returns (uint256) {
              uint256 c = a + b;
              require(c >= a, "SafeMath: addition overflow");
              return c;
          }
          /**
           * @dev Returns the subtraction of two unsigned integers, reverting on
           * overflow (when the result is negative).
           *
           * Counterpart to Solidity's `-` operator.
           *
           * Requirements:
           *
           * - Subtraction cannot overflow.
           */
          function sub(uint256 a, uint256 b) internal pure returns (uint256) {
              require(b <= a, "SafeMath: subtraction overflow");
              return a - b;
          }
          /**
           * @dev Returns the multiplication of two unsigned integers, reverting on
           * overflow.
           *
           * Counterpart to Solidity's `*` operator.
           *
           * Requirements:
           *
           * - Multiplication cannot overflow.
           */
          function mul(uint256 a, uint256 b) internal pure returns (uint256) {
              if (a == 0) return 0;
              uint256 c = a * b;
              require(c / a == b, "SafeMath: multiplication overflow");
              return c;
          }
          /**
           * @dev Returns the integer division of two unsigned integers, reverting on
           * division by zero. The result is rounded towards zero.
           *
           * Counterpart to Solidity's `/` operator. Note: this function uses a
           * `revert` opcode (which leaves remaining gas untouched) while Solidity
           * uses an invalid opcode to revert (consuming all remaining gas).
           *
           * Requirements:
           *
           * - The divisor cannot be zero.
           */
          function div(uint256 a, uint256 b) internal pure returns (uint256) {
              require(b > 0, "SafeMath: division by zero");
              return a / b;
          }
          /**
           * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
           * reverting when dividing by zero.
           *
           * Counterpart to Solidity's `%` operator. This function uses a `revert`
           * opcode (which leaves remaining gas untouched) while Solidity uses an
           * invalid opcode to revert (consuming all remaining gas).
           *
           * Requirements:
           *
           * - The divisor cannot be zero.
           */
          function mod(uint256 a, uint256 b) internal pure returns (uint256) {
              require(b > 0, "SafeMath: modulo by zero");
              return a % b;
          }
          /**
           * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
           * overflow (when the result is negative).
           *
           * CAUTION: This function is deprecated because it requires allocating memory for the error
           * message unnecessarily. For custom revert reasons use {trySub}.
           *
           * Counterpart to Solidity's `-` operator.
           *
           * Requirements:
           *
           * - Subtraction cannot overflow.
           */
          function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
              require(b <= a, errorMessage);
              return a - b;
          }
          /**
           * @dev Returns the integer division of two unsigned integers, reverting with custom message on
           * division by zero. The result is rounded towards zero.
           *
           * CAUTION: This function is deprecated because it requires allocating memory for the error
           * message unnecessarily. For custom revert reasons use {tryDiv}.
           *
           * Counterpart to Solidity's `/` operator. Note: this function uses a
           * `revert` opcode (which leaves remaining gas untouched) while Solidity
           * uses an invalid opcode to revert (consuming all remaining gas).
           *
           * Requirements:
           *
           * - The divisor cannot be zero.
           */
          function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
              require(b > 0, errorMessage);
              return a / b;
          }
          /**
           * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
           * reverting with custom message when dividing by zero.
           *
           * CAUTION: This function is deprecated because it requires allocating memory for the error
           * message unnecessarily. For custom revert reasons use {tryMod}.
           *
           * Counterpart to Solidity's `%` operator. This function uses a `revert`
           * opcode (which leaves remaining gas untouched) while Solidity uses an
           * invalid opcode to revert (consuming all remaining gas).
           *
           * Requirements:
           *
           * - The divisor cannot be zero.
           */
          function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
              require(b > 0, errorMessage);
              return a % b;
          }
      }
      //SPDX-License-Identifier: AGPL-3.0
      pragma solidity ^0.7.0;
      /**
       * This is a generic factory contract that can be used to mint tokens. The configuration
       * for minting is specified by an _optionId, which can be used to delineate various
       * ways of minting.
       *
       * https://docs.opensea.io/docs/2-custom-item-sale-contract
       */
      interface FactoryERC1155 {
        /**
         * Returns the name of this factory.
         */
        function name() external view returns (string memory);
        /**
         * Returns the symbol for this factory.
         */
        function symbol() external view returns (string memory);
        /**
         * Number of options the factory supports.
         */
        function numOptions() external view returns (uint256);
        /**
         * @dev Returns whether the option ID can be minted. Can return false if the developer wishes to
         * restrict a total supply per option ID (or overall).
         */
        function canMint(uint256 _optionId, uint256 _amount) external view returns (bool);
        /**
         * Indicates that this is a factory contract. Ideally would use EIP 165 supportsInterface()
         */
        function supportsFactoryInterface() external view returns (bool);
        /**
         * Indicates the Wyvern schema name for assets in this lootbox, e.g. "ERC1155"
         */
        function factorySchemaName() external view returns (string memory);
        /**
         * @dev Mints asset(s) in accordance to a specific address with a particular "option". This should be
         * callable only by the contract owner or the owner's Wyvern Proxy (later universal login will solve this).
         * Options should also be delineated 0 - (numOptions() - 1) for convenient indexing.
         * @param _optionId the option id
         * @param _toAddress address of the future owner of the asset(s)
         * @param _amount amount of the option to mint
         * @param _data Extra data to pass during safeTransferFrom
         */
        function mint(
          uint256 _optionId,
          address _toAddress,
          uint256 _amount,
          bytes calldata _data
        ) external payable;
      }
      // SPDX-License-Identifier: MIT
      pragma solidity >=0.6.2 <0.8.0;
      import "../../introspection/IERC165.sol";
      /**
       * @dev Required interface of an ERC1155 compliant contract, as defined in the
       * https://eips.ethereum.org/EIPS/eip-1155[EIP].
       *
       * _Available since v3.1._
       */
      interface IERC1155 is IERC165 {
          /**
           * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.
           */
          event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);
          /**
           * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all
           * transfers.
           */
          event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values);
          /**
           * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to
           * `approved`.
           */
          event ApprovalForAll(address indexed account, address indexed operator, bool approved);
          /**
           * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.
           *
           * If an {URI} event was emitted for `id`, the standard
           * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value
           * returned by {IERC1155MetadataURI-uri}.
           */
          event URI(string value, uint256 indexed id);
          /**
           * @dev Returns the amount of tokens of token type `id` owned by `account`.
           *
           * Requirements:
           *
           * - `account` cannot be the zero address.
           */
          function balanceOf(address account, uint256 id) external view returns (uint256);
          /**
           * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.
           *
           * Requirements:
           *
           * - `accounts` and `ids` must have the same length.
           */
          function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory);
          /**
           * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,
           *
           * Emits an {ApprovalForAll} event.
           *
           * Requirements:
           *
           * - `operator` cannot be the caller.
           */
          function setApprovalForAll(address operator, bool approved) external;
          /**
           * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.
           *
           * See {setApprovalForAll}.
           */
          function isApprovedForAll(address account, address operator) external view returns (bool);
          /**
           * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.
           *
           * Emits a {TransferSingle} event.
           *
           * Requirements:
           *
           * - `to` cannot be the zero address.
           * - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}.
           * - `from` must have a balance of tokens of type `id` of at least `amount`.
           * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
           * acceptance magic value.
           */
          function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;
          /**
           * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
           *
           * Emits a {TransferBatch} event.
           *
           * Requirements:
           *
           * - `ids` and `amounts` must have the same length.
           * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
           * acceptance magic value.
           */
          function safeBatchTransferFrom(address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data) external;
      }
      // SPDX-License-Identifier: MIT
      pragma solidity >=0.6.2 <0.8.0;
      import "./IERC1155.sol";
      /**
       * @dev Interface of the optional ERC1155MetadataExtension interface, as defined
       * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP].
       *
       * _Available since v3.1._
       */
      interface IERC1155MetadataURI is IERC1155 {
          /**
           * @dev Returns the URI for token type `id`.
           *
           * If the `\\{id\\}` substring is present in the URI, it must be replaced by
           * clients with the actual token type ID.
           */
          function uri(uint256 id) external view returns (string memory);
      }
      // SPDX-License-Identifier: MIT
      pragma solidity >=0.6.0 <0.8.0;
      import "../../introspection/IERC165.sol";
      /**
       * _Available since v3.1._
       */
      interface IERC1155Receiver is IERC165 {
          /**
              @dev Handles the receipt of a single ERC1155 token type. This function is
              called at the end of a `safeTransferFrom` after the balance has been updated.
              To accept the transfer, this must return
              `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
              (i.e. 0xf23a6e61, or its own function selector).
              @param operator The address which initiated the transfer (i.e. msg.sender)
              @param from The address which previously owned the token
              @param id The ID of the token being transferred
              @param value The amount of tokens being transferred
              @param data Additional data with no specified format
              @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed
          */
          function onERC1155Received(
              address operator,
              address from,
              uint256 id,
              uint256 value,
              bytes calldata data
          )
              external
              returns(bytes4);
          /**
              @dev Handles the receipt of a multiple ERC1155 token types. This function
              is called at the end of a `safeBatchTransferFrom` after the balances have
              been updated. To accept the transfer(s), this must return
              `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
              (i.e. 0xbc197c81, or its own function selector).
              @param operator The address which initiated the batch transfer (i.e. msg.sender)
              @param from The address which previously owned the token
              @param ids An array containing ids of each token being transferred (order and length must match values array)
              @param values An array containing amounts of each token being transferred (order and length must match ids array)
              @param data Additional data with no specified format
              @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed
          */
          function onERC1155BatchReceived(
              address operator,
              address from,
              uint256[] calldata ids,
              uint256[] calldata values,
              bytes calldata data
          )
              external
              returns(bytes4);
      }
      // SPDX-License-Identifier: MIT
      pragma solidity >=0.6.0 <0.8.0;
      /*
       * @dev Provides information about the current execution context, including the
       * sender of the transaction and its data. While these are generally available
       * via msg.sender and msg.data, they should not be accessed in such a direct
       * manner, since when dealing with GSN meta-transactions the account sending and
       * paying for execution may not be the actual sender (as far as an application
       * is concerned).
       *
       * This contract is only required for intermediate, library-like contracts.
       */
      abstract contract Context {
          function _msgSender() internal view virtual returns (address payable) {
              return msg.sender;
          }
          function _msgData() internal view virtual returns (bytes memory) {
              this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
              return msg.data;
          }
      }
      // SPDX-License-Identifier: MIT
      pragma solidity >=0.6.0 <0.8.0;
      import "./IERC165.sol";
      /**
       * @dev Implementation of the {IERC165} interface.
       *
       * Contracts may inherit from this and call {_registerInterface} to declare
       * their support of an interface.
       */
      abstract contract ERC165 is IERC165 {
          /*
           * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7
           */
          bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;
          /**
           * @dev Mapping of interface ids to whether or not it's supported.
           */
          mapping(bytes4 => bool) private _supportedInterfaces;
          constructor () internal {
              // Derived contracts need only register support for their own interfaces,
              // we register support for ERC165 itself here
              _registerInterface(_INTERFACE_ID_ERC165);
          }
          /**
           * @dev See {IERC165-supportsInterface}.
           *
           * Time complexity O(1), guaranteed to always use less than 30 000 gas.
           */
          function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
              return _supportedInterfaces[interfaceId];
          }
          /**
           * @dev Registers the contract as an implementer of the interface defined by
           * `interfaceId`. Support of the actual ERC165 interface is automatic and
           * registering its interface id is not required.
           *
           * See {IERC165-supportsInterface}.
           *
           * Requirements:
           *
           * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).
           */
          function _registerInterface(bytes4 interfaceId) internal virtual {
              require(interfaceId != 0xffffffff, "ERC165: invalid interface id");
              _supportedInterfaces[interfaceId] = true;
          }
      }
      // SPDX-License-Identifier: MIT
      pragma solidity >=0.6.2 <0.8.0;
      /**
       * @dev Collection of functions related to the address type
       */
      library Address {
          /**
           * @dev Returns true if `account` is a contract.
           *
           * [IMPORTANT]
           * ====
           * It is unsafe to assume that an address for which this function returns
           * false is an externally-owned account (EOA) and not a contract.
           *
           * Among others, `isContract` will return false for the following
           * types of addresses:
           *
           *  - an externally-owned account
           *  - a contract in construction
           *  - an address where a contract will be created
           *  - an address where a contract lived, but was destroyed
           * ====
           */
          function isContract(address account) internal view returns (bool) {
              // This method relies on extcodesize, which returns 0 for contracts in
              // construction, since the code is only stored at the end of the
              // constructor execution.
              uint256 size;
              // solhint-disable-next-line no-inline-assembly
              assembly { size := extcodesize(account) }
              return size > 0;
          }
          /**
           * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
           * `recipient`, forwarding all available gas and reverting on errors.
           *
           * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
           * of certain opcodes, possibly making contracts go over the 2300 gas limit
           * imposed by `transfer`, making them unable to receive funds via
           * `transfer`. {sendValue} removes this limitation.
           *
           * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
           *
           * IMPORTANT: because control is transferred to `recipient`, care must be
           * taken to not create reentrancy vulnerabilities. Consider using
           * {ReentrancyGuard} or the
           * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
           */
          function sendValue(address payable recipient, uint256 amount) internal {
              require(address(this).balance >= amount, "Address: insufficient balance");
              // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
              (bool success, ) = recipient.call{ value: amount }("");
              require(success, "Address: unable to send value, recipient may have reverted");
          }
          /**
           * @dev Performs a Solidity function call using a low level `call`. A
           * plain`call` is an unsafe replacement for a function call: use this
           * function instead.
           *
           * If `target` reverts with a revert reason, it is bubbled up by this
           * function (like regular Solidity function calls).
           *
           * Returns the raw returned data. To convert to the expected return value,
           * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
           *
           * Requirements:
           *
           * - `target` must be a contract.
           * - calling `target` with `data` must not revert.
           *
           * _Available since v3.1._
           */
          function functionCall(address target, bytes memory data) internal returns (bytes memory) {
            return functionCall(target, data, "Address: low-level call failed");
          }
          /**
           * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
           * `errorMessage` as a fallback revert reason when `target` reverts.
           *
           * _Available since v3.1._
           */
          function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
              return functionCallWithValue(target, data, 0, errorMessage);
          }
          /**
           * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
           * but also transferring `value` wei to `target`.
           *
           * Requirements:
           *
           * - the calling contract must have an ETH balance of at least `value`.
           * - the called Solidity function must be `payable`.
           *
           * _Available since v3.1._
           */
          function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
              return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
          }
          /**
           * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
           * with `errorMessage` as a fallback revert reason when `target` reverts.
           *
           * _Available since v3.1._
           */
          function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
              require(address(this).balance >= value, "Address: insufficient balance for call");
              require(isContract(target), "Address: call to non-contract");
              // solhint-disable-next-line avoid-low-level-calls
              (bool success, bytes memory returndata) = target.call{ value: value }(data);
              return _verifyCallResult(success, returndata, errorMessage);
          }
          /**
           * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
           * but performing a static call.
           *
           * _Available since v3.3._
           */
          function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
              return functionStaticCall(target, data, "Address: low-level static call failed");
          }
          /**
           * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
           * but performing a static call.
           *
           * _Available since v3.3._
           */
          function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
              require(isContract(target), "Address: static call to non-contract");
              // solhint-disable-next-line avoid-low-level-calls
              (bool success, bytes memory returndata) = target.staticcall(data);
              return _verifyCallResult(success, returndata, errorMessage);
          }
          /**
           * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
           * but performing a delegate call.
           *
           * _Available since v3.4._
           */
          function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
              return functionDelegateCall(target, data, "Address: low-level delegate call failed");
          }
          /**
           * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
           * but performing a delegate call.
           *
           * _Available since v3.4._
           */
          function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
              require(isContract(target), "Address: delegate call to non-contract");
              // solhint-disable-next-line avoid-low-level-calls
              (bool success, bytes memory returndata) = target.delegatecall(data);
              return _verifyCallResult(success, returndata, errorMessage);
          }
          function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
              if (success) {
                  return returndata;
              } else {
                  // Look for revert reason and bubble it up if present
                  if (returndata.length > 0) {
                      // The easiest way to bubble the revert reason is using memory via assembly
                      // solhint-disable-next-line no-inline-assembly
                      assembly {
                          let returndata_size := mload(returndata)
                          revert(add(32, returndata), returndata_size)
                      }
                  } else {
                      revert(errorMessage);
                  }
              }
          }
      }
      // SPDX-License-Identifier: MIT
      pragma solidity >=0.6.0 <0.8.0;
      /**
       * @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);
      }