ETH Price: $3,814.02 (+5.43%)

Contract

0xEdAC00935844245e40218F418cC6527C41513B25
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Set Custom146158332022-04-19 13:44:23960 days ago1650375863IN
0xEdAC0093...C41513B25
0 ETH0.0025489260
Set Traits144706272022-03-27 21:19:04983 days ago1648415944IN
0xEdAC0093...C41513B25
0 ETH0.0067768168.65276492
Set Trait Rearra...144464462022-03-24 2:57:44986 days ago1648090664IN
0xEdAC0093...C41513B25
0 ETH0.0134044943.69387113
Set Trait Rearra...144464462022-03-24 2:57:44986 days ago1648090664IN
0xEdAC0093...C41513B25
0 ETH0.0134044943.69387113
Set Trait Rearra...144464462022-03-24 2:57:44986 days ago1648090664IN
0xEdAC0093...C41513B25
0 ETH0.0123819243.69387113
Set Trait Rearra...144464462022-03-24 2:57:44986 days ago1648090664IN
0xEdAC0093...C41513B25
0 ETH0.0134044943.69387113
Set Trait Rearra...144464462022-03-24 2:57:44986 days ago1648090664IN
0xEdAC0093...C41513B25
0 ETH0.0123819243.69387113
Set Trait Rearra...144464462022-03-24 2:57:44986 days ago1648090664IN
0xEdAC0093...C41513B25
0 ETH0.0123819243.69387113
Set Trait Exclus...144464462022-03-24 2:57:44986 days ago1648090664IN
0xEdAC0093...C41513B25
0 ETH0.0042006443.69387113
Set Trait Exclus...144464462022-03-24 2:57:44986 days ago1648090664IN
0xEdAC0093...C41513B25
0 ETH0.0042006443.69387113
Set Trait Exclus...144464462022-03-24 2:57:44986 days ago1648090664IN
0xEdAC0093...C41513B25
0 ETH0.0042006443.69387113
Set Trait Exclus...144464452022-03-24 2:57:14986 days ago1648090634IN
0xEdAC0093...C41513B25
0 ETH0.0028333738.95417862
Set Trait Exclus...144464452022-03-24 2:57:14986 days ago1648090634IN
0xEdAC0093...C41513B25
0 ETH0.0046565838.95417862
Set Trait Exclus...144464452022-03-24 2:57:14986 days ago1648090634IN
0xEdAC0093...C41513B25
0 ETH0.011037938.95417862
Set Trait Exclus...144464452022-03-24 2:57:14986 days ago1648090634IN
0xEdAC0093...C41513B25
0 ETH0.0174192938.95417862
Set Trait Exclus...144464452022-03-24 2:57:14986 days ago1648090634IN
0xEdAC0093...C41513B25
0 ETH0.0046565838.95417862
Set Trait Exclus...144464452022-03-24 2:57:14986 days ago1648090634IN
0xEdAC0093...C41513B25
0 ETH0.0046565838.95417862
Set Trait Exclus...144464452022-03-24 2:57:14986 days ago1648090634IN
0xEdAC0093...C41513B25
0 ETH0.0192425838.95417862
Set Trait Exclus...144464452022-03-24 2:57:14986 days ago1648090634IN
0xEdAC0093...C41513B25
0 ETH0.0046565838.95417862
Set Trait Exclus...144464452022-03-24 2:57:14986 days ago1648090634IN
0xEdAC0093...C41513B25
0 ETH0.0028333738.95417862
Set Trait Exclus...144464422022-03-24 2:56:43986 days ago1648090603IN
0xEdAC0093...C41513B25
0 ETH0.0037578339.08796509
Set Trait Exclus...144464422022-03-24 2:56:43986 days ago1648090603IN
0xEdAC0093...C41513B25
0 ETH0.002843139.08796509
Set Trait Exclus...144464422022-03-24 2:56:43986 days ago1648090603IN
0xEdAC0093...C41513B25
0 ETH0.0037578339.08796509
Set Trait Exclus...144464412022-03-24 2:56:41986 days ago1648090601IN
0xEdAC0093...C41513B25
0 ETH0.0029442640.4788283
Set Trait Exclus...144464412022-03-24 2:56:41986 days ago1648090601IN
0xEdAC0093...C41513B25
0 ETH0.0038915540.4788283
View all transactions

Advanced mode:
Parent Transaction Hash Block From To
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
EthTerrestrialsV2Descriptor

Compiler Version
v0.8.7+commit.e28d00a7

Optimization Enabled:
Yes with 2000 runs

Other Settings:
default evmVersion
File 1 of 6 : V2_descriptor.sol
//	SPDX-License-Identifier: MIT

/// @title  ETHTerrestrials by Kye descriptor (v2)
/// @notice Image and traits stored on-chain and assembled by this contract

pragma solidity ^0.8.0;

import "./InflateLib.sol";
import "./Strings.sol";
import "./Base64.sol";
import "@0xsequence/sstore2/contracts/SSTORE2.sol";

interface Terraforms {
   function tokenSVG(uint256 tokenId) external view returns (string memory);
}

contract EthTerrestrialsV2Descriptor {
   using Strings for uint256;
   using InflateLib for bytes;

   /// @notice Storage entry for a trait type (category)
   struct TraitType {
      string name; //the name of the category (i.e., 'Clothes')
      uint16[] rarity; //the rarity table is mapped to each Trait in a TraitType and should be provided as an array of desired occurrences out of 1000 samples. E.g.: [500,200,200,100,100]. 0 rarity indicates that the trait will not occur naturally.
   }
   mapping(uint8 => TraitType) public traitTypes;
   /*   Note: Certain layers have only one trait - left in code for consistency/future projects
    *    0 position will be null for certain traits
    *   Trait Types:
    *   0: Background
    *   1: Hoodie Back
    *   2: Head Color
    *   3: Head Outline
    *   4: Ears
    *   5: Mouths
    *   6: Eyes
    *   7: Head Accessories
    *   8: Apparel
    *   9: Front
    */

   mapping(uint8 => bool) hiddentrait; //No need to display metadta for certain layers.

   /// @notice Storage entry for a single trait/custom token
   struct Trait {
      address imageStore; //SSTORE2 storage location for SVG image data, compressed using DEFLATE (python zlib). Header (first 2 bytes) and checksum (last 4 bytes) truncated.
      uint96 imagelen; //The length of the uncomressed image date (required for decompression).
      string name; //the name of the trait (i.e. "grey hoodie") or custom image.
   }

   /// @notice Storage entry for non-allowed trait combinations and rearranged traits
   struct TraitDescriptor {
      uint8 traitType;
      uint8 trait;
   }

   /// @notice Key: keccak hash of trait type and trait index for which there are non-allowed trait combinations
   mapping(bytes32 => TraitDescriptor[]) public traitExclusions;

   /// @notice Key: keccak hash of trait type and trait index that should be placed below any traits in list
   mapping(bytes32 => TraitDescriptor[]) public traitRearrangement;

   /// @notice A mapping of traits in the format traits[traitType][trait number]. The ordering of trait types corresponds to traitTypes (above).
   mapping(uint8 => mapping(uint8 => Trait)) public traits;

   /// @notice A mapping of custom tokenIds that contain custom tokens.
   mapping(uint256 => Trait) public customs;

   /// @notice Permanently seals the metadata in the contract from being modified by deployer.
   bool public contractsealed;

   string private SVGOpenTag =
      '<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" x="0" y="0" viewBox="0 0 1100 1100" style="enable-background:new 0 0 1100 1100" xml:space="preserve" xmlns:xlink="http://www.w3.org/1999/xlink">';

   address private deployer;

   Terraforms public terraforms = Terraforms(0x4E1f41613c9084FdB9E34E11fAE9412427480e56);

   modifier onlyDeployerWhileUnsealed() {
      require(!contractsealed && msg.sender == deployer, "Not authorized or locked");
      _;
   }

   constructor() public {
      deployer = msg.sender;
   }

   /*
.___  ___.  _______ .___________.    ___       _______       ___   .___________.    ___      
|   \/   | |   ____||           |   /   \     |       \     /   \  |           |   /   \     
|  \  /  | |  |__   `---|  |----`  /  ^  \    |  .--.  |   /  ^  \ `---|  |----`  /  ^  \    
|  |\/|  | |   __|      |  |      /  /_\  \   |  |  |  |  /  /_\  \    |  |      /  /_\  \   
|  |  |  | |  |____     |  |     /  _____  \  |  '--'  | /  _____  \   |  |     /  _____  \  
|__|  |__| |_______|    |__|    /__/     \__\ |_______/ /__/     \__\  |__|    /__/     \__\ 
*/

   /// @notice Returns an ERC721 standard tokenURI
   /// @param tokenId, the desired tokenId to display
   /// @param rawSeed, the raw seed code generated by the seeder contract following mint
   /// @param tokenType, the type of token (one of one or common)
   /// @return output, a base64 encoded JSON string containing the tokenURI (metadata and image)
   function generateTokenURI(
      uint256 tokenId,
      uint256 rawSeed,
      uint256 tokenType
   ) external view returns (string memory) {
      string memory name = string(abi.encodePacked("EtherTerrestrial #", tokenId.toString()));
      string memory description = "EtherTerrestrials are inter-dimensional Extra-Terrestrials who came to Earth's internet to infuse consciousness into all other pixelated Lifeforms. They can be encountered in the form of on-chain characters as interpreted by the existential explorer Kye."; //need to write
      string memory traits_json;
      string memory image;

      if (tokenType == 1) {
         //these tokens do not use a seed
         image = getSvgCustomToken(tokenId);
         traits_json = viewTraitsJSONCustom(tokenId);
      } else if (rawSeed == 0) {
         //if the seed is zero but not a one of one, the token must be unrevealed. Unrevealed image stored at custom index 69.
         image = getSvgCustomToken(69);
         description = "Unrevealed EtherTerrestrial - Refresh Soon";
         traits_json = "[]";
      } else {
         uint8[10] memory seed = processRawSeed(rawSeed);
         image = getSvgFromSeed(seed);
         traits_json = viewTraitsJSON(seed);
      }
      string memory json = Base64.encode(
         bytes(
            string(
               abi.encodePacked(
                  '{"name": "',
                  name,
                  '", "description": "',
                  description,
                  '", "attributes":',
                  traits_json,
                  ',"image": "',
                  "data:image/svg+xml;base64,",
                  Base64.encode(bytes(image)),
                  '"}'
               )
            )
         )
      );

      string memory output = string(abi.encodePacked("data:application/json;base64,", json));
      return output;
   }

   /// @notice Converts a raw seed code into a list of traits
   /// @param rawSeed, the raw seed code generated by the seeder contract following mint
   /// @return seed, a uint8 array containing the finally assigned trait codes for each trait type
   /// @dev For generative tokens, raw seeds are handled according to the following workflow:
   /// 	1. processRawSeed(): perform keccak operation over the raw seed and assign a rarity seed to each trait
   /// 	2. generateSeedFromRarityTables(): runs the results of processRawSeed over rarity tables to determine the traits
   ///   3. enforceRequiredCombinations(): ensures that certain traits are matched with, or prohibited from being matched with certain others.
   function processRawSeed(uint256 rawSeed) public view returns (uint8[10] memory) {
      uint16[10] memory initialSeed;

      for (uint8 i = 0; i < 10; i++) {
         initialSeed[i] = uint16(uint256(keccak256(abi.encodePacked(rawSeed, i))) % 1000);
      }
      uint8[10] memory seed = generateSeedFromRarityTables(initialSeed);
      seed = enforceRequiredCombinations(seed);
      return seed;
   }

   /// @notice Converts an initial rarity seed to a list of traits
   /// @param initialSeed, the initial rarity seed for a given token
   /// @return seed, a uint8 array containing the trait code for each traitType
   function generateSeedFromRarityTables(uint16[10] memory initialSeed) internal view returns (uint8[10] memory) {
      uint8[10] memory seed;
      for (uint8 traitType; traitType < 10; traitType++) {
         uint16[] memory rarityTable = traitTypes[traitType].rarity;
         uint16 upperBound;
         for (uint8 index; index < rarityTable.length; index++) {
            upperBound += rarityTable[index];
            if (initialSeed[traitType] < upperBound) {
               seed[traitType] = index;
               break;
            }
         }
      }
      return seed;
   }

   /// @notice Alters the seed to remove combinations that the artist has determined conflict with one another
   /// @param seed, the post-rarity allocated traits for a token
   /// @return the modified seed
   function enforceRequiredCombinations(uint8[10] memory seed) public view returns (uint8[10] memory) {
      for (uint8 i; i < seed.length; i++) {
         TraitDescriptor[] memory exclusions = traitExclusions[keccak256(abi.encodePacked(i, seed[i]))];
         // check to see if seed contains any trait combinations that are not allowed
         for (uint8 j = 0; j < exclusions.length; j++) {
            // seed has a trait combination that is not allowed, remove combination
            if (seed[exclusions[j].traitType] == exclusions[j].trait) {
               seed[exclusions[j].traitType] = 0;
            }
         }
      }

      // Exclude all of a type for some traits
      if (seed[6] == 6) {
         seed[7] = 0;
      } else if (seed[8] == 1) {
         seed[7] = 0;
      } else if (seed[8] == 7) {
         seed[7] = 0;
      } else if (seed[8] == 8) {
         seed[7] = 0;
      } else if (seed[8] == 9) {
         seed[7] = 0;
      }

      //Add hoodie back if hoodie
      if (seed[8] == 3 || seed[8] == 4 || seed[8] == 6) {
         seed[1] = 1;
      }

      return seed;
   }

   /// @notice Generates an ERC721 standard metadata JSON string for generative tokens
   /// @param seed, the finally allocated traits for a token
   /// @return json, a JSON metadata string
   function viewTraitsJSON(uint8[10] memory seed) public view returns (string memory) {
      string[] memory jsonItems = new string[](11);

      for (uint8 traitType; traitType < 10; traitType++) {
         if (!hiddentrait[traitType]) {
            uint8 traitCode = seed[traitType];
            string memory traitName = traits[traitType][traitCode].name;
            jsonItems[traitType] = string(
               abi.encodePacked(
                  traitType == 0 ? '[{"trait_type":"' : ',{"trait_type":"',
                  traitTypes[traitType].name,
                  '","value":"',
                  traitName,
                  '"}'
               )
            );
         }
      }
      jsonItems[10] = ',{"trait_type":"Life Form","value":"Tripped"}]';

      string memory json;
      for (uint256 i = 0; i < 11; i++) {
         json = string(abi.encodePacked(json, jsonItems[i]));
      }
      return json;
   }

   /// @notice Generates an ERC721 standard metadata JSON string for custom tokens
   /// @param tokenId, the desired tokenId
   /// @return a JSON metadata string
   function viewTraitsJSONCustom(uint256 tokenId) public view returns (string memory) {
      return
         string(
            abi.encodePacked(
               '[{"trait_type":"Cosmic Being","value":"',
               customs[tokenId].name,
               '"},{"trait_type":"Life Form","value":"Tripped"}]'
            )
         );
   }

   /// @notice Generates an unencoded SVG image for a given seed
   /// @param seed, the finally allocated traits for a token
   /// @return an SVG string
   function getSvgFromSeed(uint8[10] memory seed) public view returns (string memory) {
      string[20] memory SVG;

      uint8[20] memory arrangedSeed = getArrangedSeed(seed);
      for (uint8 i; i < arrangedSeed.length; i++) {
        uint8 traitType = arrangedSeed[i];
        // check that slot is not empty
        if (traitType != type(uint8).max) {
          uint8 traitCode = seed[traitType];
          string memory image = traits[traitType][traitCode].imagelen != 0 ? getTraitSVG(traitType, traitCode) : "";
          SVG[i] = image;
        }
      }

      string memory SVGStr;
      for (uint8 i; i < SVG.length; i++) {
         SVGStr = string(abi.encodePacked(SVGStr, SVG[i]));
      }
      return string(abi.encodePacked(SVGOpenTag, SVGStr, "</svg>"));
   }

    /// @notice Gets an arranged seed with the order of trait types to build the SVG
    /// @notice Only rearranges around one trait type (apparel)
    /// @param seed, unarranged seed
    /// @return arranged seed
    function getArrangedSeed(uint8[10] memory seed) public view returns (uint8[20] memory) {
      uint8[20] memory arrangedSeed;

      // initialize arrangedSeed with seed and max int
      for (uint8 i; i < arrangedSeed.length; i++) {
        if (i < seed.length) {
          arrangedSeed[i] = i;
        } else {
          // set extra slots for rearrangements to empty or max uint8
          arrangedSeed[i] = type(uint8).max;
        }
      }

      // rearrange arrangedSeed so certain items are placed ontop of apparel
      TraitDescriptor[] memory rearrangements = traitRearrangement[keccak256(abi.encodePacked(uint8(8), seed[8]))];
      for (uint8 i; i < rearrangements.length; i++) {
        // seed has a rearranagement so update arrangedSeed
        if (seed[rearrangements[i].traitType] == rearrangements[i].trait) {
          // place rearranged trait in its corresponding slot on top of apparel
          arrangedSeed[10 + rearrangements[i].traitType] = rearrangements[i].traitType;
          // trait has been moved so set this spot to empty
          arrangedSeed[rearrangements[i].traitType] = type(uint8).max;
        }
      }

      // Front trait is always on the top
      arrangedSeed[19] = 9;
      arrangedSeed[9] = type(uint8).max;

      return arrangedSeed;
   }

   /// @notice Returns the unencoded SVG image for a given seed
   /// @param tokenId, the tokenId of the custom token
   /// @return an SVG string
   /// @dev token 104's background is an onchain composition of Terraform #3640
   function getSvgCustomToken(uint256 tokenId) public view returns (string memory) {
      return
         string(
            abi.encodePacked(
               SVGOpenTag,
               tokenId == 104
                  ? '<defs><clipPath id="clipPath3"><circle cx="550" cy="550" r="500" /></clipPath></defs><g style="clip-path: url(#clipPath3);"><rect x="0" y="0" width="3000" height="3000" style="stroke: none; fill:none; clip-path: url(#clipPath3);" /><g xmlns="http://www.w3.org/2000/svg" transform="scale(1.51,1) translate(-178)">'
                  : "",
               tokenId == 104 ? terraforms.tokenSVG(3640) : "",
               tokenId == 104 ? "</g></g>" : "",
               decompress(SSTORE2.read(customs[tokenId].imageStore), customs[tokenId].imagelen),
               "</svg>"
            )
         );
   }

   function getTraitSVG(uint8 traitType, uint8 traitCode) public view returns (string memory) {
      return decompress(SSTORE2.read(traits[traitType][traitCode].imageStore), traits[traitType][traitCode].imagelen);
   }

   function decompress(bytes memory input, uint256 len) public pure returns (string memory) {
      (, bytes memory decompressed) = InflateLib.puff(input, len);
      return string(decompressed);
   }

   /*
 _______   _______ .______    __        ______   ____    ____  _______ .______      
|       \ |   ____||   _  \  |  |      /  __  \  \   \  /   / |   ____||   _  \     
|  .--.  ||  |__   |  |_)  | |  |     |  |  |  |  \   \/   /  |  |__   |  |_)  |    
|  |  |  ||   __|  |   ___/  |  |     |  |  |  |   \_    _/   |   __|  |      /     
|  '--'  ||  |____ |  |      |  `----.|  `--'  |     |  |     |  |____ |  |\  \----.
|_______/ |_______|| _|      |_______| \______/      |__|     |_______|| _| `._____|
                                                                                                                                                
*/

   /// @notice Establishes the 10 traitTypes
   function setTraitTypes(TraitType[] memory _traitTypes) external onlyDeployerWhileUnsealed {
      for (uint8 i; i < 10; i++) {
         traitTypes[i] = _traitTypes[i];
      }
   }

   /// @notice Establishes traits for a single traitType
   /// @dev Images stored previously via SSTORE2 in prior deployment of this contract (prior to repairing rearrangement logic) address 0xf30448d4cff17e02656fc6575c4c64417191adbc
   function setTraits(
      uint8 _traitType,
      Trait[] memory _traits,
      uint8[] memory _traitNumber
   ) external onlyDeployerWhileUnsealed {
      require(_traits.length == _traitNumber.length);
      for (uint8 i; i < _traits.length; i++) {
         traits[_traitType][_traitNumber[i]] = _traits[i];
      }
   }

   function setHiddenTraits(uint8[] memory _traitTypes, bool _hidden) external onlyDeployerWhileUnsealed {
      for (uint8 i; i < _traitTypes.length; i++) hiddentrait[_traitTypes[i]] = _hidden;
   }

   /// @notice Establishes the custom token art
   /// @dev Images stored previously via SSTORE2 in prior deployment of this contract (prior to repairing rearrangement logic) address 0xf30448d4cff17e02656fc6575c4c64417191adbc
   function setCustom(
      uint256[] memory _tokenIds,
      Trait[] memory _oneOfOnes
   ) external onlyDeployerWhileUnsealed {
      require(_tokenIds.length == _oneOfOnes.length);
      for (uint256 i; i < _oneOfOnes.length; i++) {
         customs[_tokenIds[i]] = _oneOfOnes[i];
      }
   }

   /// @notice Set a trait exclusion rule
   /// @param traitType, the trait type index
   /// @param trait, the trait index
   /// @param exclusions, all unallowed combinations
   function setTraitExclusions(
      uint8 traitType,
      uint8 trait,
      TraitDescriptor[] memory exclusions
   ) external onlyDeployerWhileUnsealed {
      bytes32 traitHash = keccak256(abi.encodePacked(traitType, trait));
      delete traitExclusions[traitHash];
      for (uint8 i = 0; i < exclusions.length; i++) {
         traitExclusions[traitHash].push(exclusions[i]);
      }
   }

   /// @notice Set a trait rearrangement rule
   /// @param traitType, the trait type index
   /// @param trait, the trait index
   /// @param rearrangements, all traits that should be placed above base trait
   function setTraitRearrangements(
      uint8 traitType,
      uint8 trait,
      TraitDescriptor[] memory rearrangements
   ) external onlyDeployerWhileUnsealed {
      bytes32 traitHash = keccak256(abi.encodePacked(traitType, trait));
      delete traitRearrangement[traitHash];
      for (uint8 i = 0; i < rearrangements.length; i++) {
         traitRearrangement[traitHash].push(rearrangements[i]);
      }
   }

   /// @notice IRREVERSIBLY SEALS THE CONTRACT FROM BEING MODIFIED
   function sealContract() external onlyDeployerWhileUnsealed {
      contractsealed = true;
   }
}

File 2 of 6 : InflateLib.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity >=0.8.0 <0.9.0;

/// https://github.com/adlerjohn/inflate-sol
/// @notice Based on https://github.com/madler/zlib/blob/master/contrib/puff
library InflateLib {
   // Maximum bits in a code
   uint256 constant MAXBITS = 15;
   // Maximum number of literal/length codes
   uint256 constant MAXLCODES = 286;
   // Maximum number of distance codes
   uint256 constant MAXDCODES = 30;
   // Maximum codes lengths to read
   uint256 constant MAXCODES = (MAXLCODES + MAXDCODES);
   // Number of fixed literal/length codes
   uint256 constant FIXLCODES = 288;

   // Error codes
   enum ErrorCode {
      ERR_NONE, // 0 successful inflate
      ERR_NOT_TERMINATED, // 1 available inflate data did not terminate
      ERR_OUTPUT_EXHAUSTED, // 2 output space exhausted before completing inflate
      ERR_INVALID_BLOCK_TYPE, // 3 invalid block type (type == 3)
      ERR_STORED_LENGTH_NO_MATCH, // 4 stored block length did not match one's complement
      ERR_TOO_MANY_LENGTH_OR_DISTANCE_CODES, // 5 dynamic block code description: too many length or distance codes
      ERR_CODE_LENGTHS_CODES_INCOMPLETE, // 6 dynamic block code description: code lengths codes incomplete
      ERR_REPEAT_NO_FIRST_LENGTH, // 7 dynamic block code description: repeat lengths with no first length
      ERR_REPEAT_MORE, // 8 dynamic block code description: repeat more than specified lengths
      ERR_INVALID_LITERAL_LENGTH_CODE_LENGTHS, // 9 dynamic block code description: invalid literal/length code lengths
      ERR_INVALID_DISTANCE_CODE_LENGTHS, // 10 dynamic block code description: invalid distance code lengths
      ERR_MISSING_END_OF_BLOCK, // 11 dynamic block code description: missing end-of-block code
      ERR_INVALID_LENGTH_OR_DISTANCE_CODE, // 12 invalid literal/length or distance code in fixed or dynamic block
      ERR_DISTANCE_TOO_FAR, // 13 distance is too far back in fixed or dynamic block
      ERR_CONSTRUCT // 14 internal: error in construct()
   }

   // Input and output state
   struct State {
      //////////////////
      // Output state //
      //////////////////
      // Output buffer
      bytes output;
      // Bytes written to out so far
      uint256 outcnt;
      /////////////////
      // Input state //
      /////////////////
      // Input buffer
      bytes input;
      // Bytes read so far
      uint256 incnt;
      ////////////////
      // Temp state //
      ////////////////
      // Bit buffer
      uint256 bitbuf;
      // Number of bits in bit buffer
      uint256 bitcnt;
      //////////////////////////
      // Static Huffman codes //
      //////////////////////////
      Huffman lencode;
      Huffman distcode;
   }

   // Huffman code decoding tables
   struct Huffman {
      uint256[] counts;
      uint256[] symbols;
   }

   function bits(State memory s, uint256 need) private pure returns (ErrorCode, uint256) {
      // Bit accumulator (can use up to 20 bits)
      uint256 val;

      // Load at least need bits into val
      val = s.bitbuf;
      while (s.bitcnt < need) {
         if (s.incnt == s.input.length) {
            // Out of input
            return (ErrorCode.ERR_NOT_TERMINATED, 0);
         }

         // Load eight bits
         val |= uint256(uint8(s.input[s.incnt++])) << s.bitcnt;
         s.bitcnt += 8;
      }

      // Drop need bits and update buffer, always zero to seven bits left
      s.bitbuf = val >> need;
      s.bitcnt -= need;

      // Return need bits, zeroing the bits above that
      uint256 ret = (val & ((1 << need) - 1));
      return (ErrorCode.ERR_NONE, ret);
   }

   function _stored(State memory s) private pure returns (ErrorCode) {
      // Length of stored block
      uint256 len;

      // Discard leftover bits from current byte (assumes s.bitcnt < 8)
      s.bitbuf = 0;
      s.bitcnt = 0;

      // Get length and check against its one's complement
      if (s.incnt + 4 > s.input.length) {
         // Not enough input
         return ErrorCode.ERR_NOT_TERMINATED;
      }
      len = uint256(uint8(s.input[s.incnt++]));
      len |= uint256(uint8(s.input[s.incnt++])) << 8;

      if (uint8(s.input[s.incnt++]) != (~len & 0xFF) || uint8(s.input[s.incnt++]) != ((~len >> 8) & 0xFF)) {
         // Didn't match complement!
         return ErrorCode.ERR_STORED_LENGTH_NO_MATCH;
      }

      // Copy len bytes from in to out
      if (s.incnt + len > s.input.length) {
         // Not enough input
         return ErrorCode.ERR_NOT_TERMINATED;
      }
      if (s.outcnt + len > s.output.length) {
         // Not enough output space
         return ErrorCode.ERR_OUTPUT_EXHAUSTED;
      }
      while (len != 0) {
         // Note: Solidity reverts on underflow, so we decrement here
         len -= 1;
         s.output[s.outcnt++] = s.input[s.incnt++];
      }

      // Done with a valid stored block
      return ErrorCode.ERR_NONE;
   }

   function _decode(State memory s, Huffman memory h) private pure returns (ErrorCode, uint256) {
      // Current number of bits in code
      uint256 len;
      // Len bits being decoded
      uint256 code = 0;
      // First code of length len
      uint256 first = 0;
      // Number of codes of length len
      uint256 count;
      // Index of first code of length len in symbol table
      uint256 index = 0;
      // Error code
      ErrorCode err;

      for (len = 1; len <= MAXBITS; len++) {
         // Get next bit
         uint256 tempCode;
         (err, tempCode) = bits(s, 1);
         if (err != ErrorCode.ERR_NONE) {
            return (err, 0);
         }
         code |= tempCode;
         count = h.counts[len];

         // If length len, return symbol
         if (code < first + count) {
            return (ErrorCode.ERR_NONE, h.symbols[index + (code - first)]);
         }
         // Else update for next length
         index += count;
         first += count;
         first <<= 1;
         code <<= 1;
      }

      // Ran out of codes
      return (ErrorCode.ERR_INVALID_LENGTH_OR_DISTANCE_CODE, 0);
   }

   function _construct(
      Huffman memory h,
      uint256[] memory lengths,
      uint256 n,
      uint256 start
   ) private pure returns (ErrorCode) {
      // Current symbol when stepping through lengths[]
      uint256 symbol;
      // Current length when stepping through h.counts[]
      uint256 len;
      // Number of possible codes left of current length
      uint256 left;
      // Offsets in symbol table for each length
      uint256[MAXBITS + 1] memory offs;

      // Count number of codes of each length
      for (len = 0; len <= MAXBITS; len++) {
         h.counts[len] = 0;
      }
      for (symbol = 0; symbol < n; symbol++) {
         // Assumes lengths are within bounds
         h.counts[lengths[start + symbol]]++;
      }
      // No codes!
      if (h.counts[0] == n) {
         // Complete, but decode() will fail
         return (ErrorCode.ERR_NONE);
      }

      // Check for an over-subscribed or incomplete set of lengths

      // One possible code of zero length
      left = 1;

      for (len = 1; len <= MAXBITS; len++) {
         // One more bit, double codes left
         left <<= 1;
         if (left < h.counts[len]) {
            // Over-subscribed--return error
            return ErrorCode.ERR_CONSTRUCT;
         }
         // Deduct count from possible codes

         left -= h.counts[len];
      }

      // Generate offsets into symbol table for each length for sorting
      offs[1] = 0;
      for (len = 1; len < MAXBITS; len++) {
         offs[len + 1] = offs[len] + h.counts[len];
      }

      // Put symbols in table sorted by length, by symbol order within each length
      for (symbol = 0; symbol < n; symbol++) {
         if (lengths[start + symbol] != 0) {
            h.symbols[offs[lengths[start + symbol]]++] = symbol;
         }
      }

      // Left > 0 means incomplete
      return left > 0 ? ErrorCode.ERR_CONSTRUCT : ErrorCode.ERR_NONE;
   }

   function _codes(
      State memory s,
      Huffman memory lencode,
      Huffman memory distcode
   ) private pure returns (ErrorCode) {
      // Decoded symbol
      uint256 symbol;
      // Length for copy
      uint256 len;
      // Distance for copy
      uint256 dist;
      // TODO Solidity doesn't support constant arrays, but these are fixed at compile-time
      // Size base for length codes 257..285
      uint16[29] memory lens = [
         3,
         4,
         5,
         6,
         7,
         8,
         9,
         10,
         11,
         13,
         15,
         17,
         19,
         23,
         27,
         31,
         35,
         43,
         51,
         59,
         67,
         83,
         99,
         115,
         131,
         163,
         195,
         227,
         258
      ];
      // Extra bits for length codes 257..285
      uint8[29] memory lext = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0];
      // Offset base for distance codes 0..29
      uint16[30] memory dists = [
         1,
         2,
         3,
         4,
         5,
         7,
         9,
         13,
         17,
         25,
         33,
         49,
         65,
         97,
         129,
         193,
         257,
         385,
         513,
         769,
         1025,
         1537,
         2049,
         3073,
         4097,
         6145,
         8193,
         12289,
         16385,
         24577
      ];
      // Extra bits for distance codes 0..29
      uint8[30] memory dext = [0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13];
      // Error code
      ErrorCode err;

      // Decode literals and length/distance pairs
      while (symbol != 256) {
         (err, symbol) = _decode(s, lencode);
         if (err != ErrorCode.ERR_NONE) {
            // Invalid symbol
            return err;
         }

         if (symbol < 256) {
            // Literal: symbol is the byte
            // Write out the literal
            if (s.outcnt == s.output.length) {
               return ErrorCode.ERR_OUTPUT_EXHAUSTED;
            }
            s.output[s.outcnt] = bytes1(uint8(symbol));
            s.outcnt++;
         } else if (symbol > 256) {
            uint256 tempBits;
            // Length
            // Get and compute length
            symbol -= 257;
            if (symbol >= 29) {
               // Invalid fixed code
               return ErrorCode.ERR_INVALID_LENGTH_OR_DISTANCE_CODE;
            }

            (err, tempBits) = bits(s, lext[symbol]);
            if (err != ErrorCode.ERR_NONE) {
               return err;
            }
            len = lens[symbol] + tempBits;

            // Get and check distance
            (err, symbol) = _decode(s, distcode);
            if (err != ErrorCode.ERR_NONE) {
               // Invalid symbol
               return err;
            }
            (err, tempBits) = bits(s, dext[symbol]);
            if (err != ErrorCode.ERR_NONE) {
               return err;
            }
            dist = dists[symbol] + tempBits;
            if (dist > s.outcnt) {
               // Distance too far back
               return ErrorCode.ERR_DISTANCE_TOO_FAR;
            }

            // Copy length bytes from distance bytes back
            if (s.outcnt + len > s.output.length) {
               return ErrorCode.ERR_OUTPUT_EXHAUSTED;
            }
            while (len != 0) {
               // Note: Solidity reverts on underflow, so we decrement here
               len -= 1;
               s.output[s.outcnt] = s.output[s.outcnt - dist];
               s.outcnt++;
            }
         } else {
            s.outcnt += len;
         }
      }

      // Done with a valid fixed or dynamic block
      return ErrorCode.ERR_NONE;
   }

   function _build_fixed(State memory s) private pure returns (ErrorCode) {
      // Build fixed Huffman tables
      // TODO this is all a compile-time constant
      uint256 symbol;
      uint256[] memory lengths = new uint256[](FIXLCODES);

      // Literal/length table
      for (symbol = 0; symbol < 144; symbol++) {
         lengths[symbol] = 8;
      }
      for (; symbol < 256; symbol++) {
         lengths[symbol] = 9;
      }
      for (; symbol < 280; symbol++) {
         lengths[symbol] = 7;
      }
      for (; symbol < FIXLCODES; symbol++) {
         lengths[symbol] = 8;
      }

      _construct(s.lencode, lengths, FIXLCODES, 0);

      // Distance table
      for (symbol = 0; symbol < MAXDCODES; symbol++) {
         lengths[symbol] = 5;
      }

      _construct(s.distcode, lengths, MAXDCODES, 0);

      return ErrorCode.ERR_NONE;
   }

   function _fixed(State memory s) private pure returns (ErrorCode) {
      // Decode data until end-of-block code
      return _codes(s, s.lencode, s.distcode);
   }

   function _build_dynamic_lengths(State memory s) private pure returns (ErrorCode, uint256[] memory) {
      uint256 ncode;
      // Index of lengths[]
      uint256 index;
      // Descriptor code lengths
      uint256[] memory lengths = new uint256[](MAXCODES);
      // Error code
      ErrorCode err;
      // Permutation of code length codes
      uint8[19] memory order = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15];

      (err, ncode) = bits(s, 4);
      if (err != ErrorCode.ERR_NONE) {
         return (err, lengths);
      }
      ncode += 4;

      // Read code length code lengths (really), missing lengths are zero
      for (index = 0; index < ncode; index++) {
         (err, lengths[order[index]]) = bits(s, 3);
         if (err != ErrorCode.ERR_NONE) {
            return (err, lengths);
         }
      }
      for (; index < 19; index++) {
         lengths[order[index]] = 0;
      }

      return (ErrorCode.ERR_NONE, lengths);
   }

   function _build_dynamic(State memory s)
      private
      pure
      returns (
         ErrorCode,
         Huffman memory,
         Huffman memory
      )
   {
      // Number of lengths in descriptor
      uint256 nlen;
      uint256 ndist;
      // Index of lengths[]
      uint256 index;
      // Error code
      ErrorCode err;
      // Descriptor code lengths
      uint256[] memory lengths = new uint256[](MAXCODES);
      // Length and distance codes
      Huffman memory lencode = Huffman(new uint256[](MAXBITS + 1), new uint256[](MAXLCODES));
      Huffman memory distcode = Huffman(new uint256[](MAXBITS + 1), new uint256[](MAXDCODES));
      uint256 tempBits;

      // Get number of lengths in each table, check lengths
      (err, nlen) = bits(s, 5);
      if (err != ErrorCode.ERR_NONE) {
         return (err, lencode, distcode);
      }
      nlen += 257;
      (err, ndist) = bits(s, 5);
      if (err != ErrorCode.ERR_NONE) {
         return (err, lencode, distcode);
      }
      ndist += 1;

      if (nlen > MAXLCODES || ndist > MAXDCODES) {
         // Bad counts
         return (ErrorCode.ERR_TOO_MANY_LENGTH_OR_DISTANCE_CODES, lencode, distcode);
      }

      (err, lengths) = _build_dynamic_lengths(s);
      if (err != ErrorCode.ERR_NONE) {
         return (err, lencode, distcode);
      }

      // Build huffman table for code lengths codes (use lencode temporarily)
      err = _construct(lencode, lengths, 19, 0);
      if (err != ErrorCode.ERR_NONE) {
         // Require complete code set here
         return (ErrorCode.ERR_CODE_LENGTHS_CODES_INCOMPLETE, lencode, distcode);
      }

      // Read length/literal and distance code length tables
      index = 0;
      while (index < nlen + ndist) {
         // Decoded value
         uint256 symbol;
         // Last length to repeat
         uint256 len;

         (err, symbol) = _decode(s, lencode);
         if (err != ErrorCode.ERR_NONE) {
            // Invalid symbol
            return (err, lencode, distcode);
         }

         if (symbol < 16) {
            // Length in 0..15
            lengths[index++] = symbol;
         } else {
            // Repeat instruction
            // Assume repeating zeros
            len = 0;
            if (symbol == 16) {
               // Repeat last length 3..6 times
               if (index == 0) {
                  // No last length!
                  return (ErrorCode.ERR_REPEAT_NO_FIRST_LENGTH, lencode, distcode);
               }
               // Last length
               len = lengths[index - 1];
               (err, tempBits) = bits(s, 2);
               if (err != ErrorCode.ERR_NONE) {
                  return (err, lencode, distcode);
               }
               symbol = 3 + tempBits;
            } else if (symbol == 17) {
               // Repeat zero 3..10 times
               (err, tempBits) = bits(s, 3);
               if (err != ErrorCode.ERR_NONE) {
                  return (err, lencode, distcode);
               }
               symbol = 3 + tempBits;
            } else {
               // == 18, repeat zero 11..138 times
               (err, tempBits) = bits(s, 7);
               if (err != ErrorCode.ERR_NONE) {
                  return (err, lencode, distcode);
               }
               symbol = 11 + tempBits;
            }

            if (index + symbol > nlen + ndist) {
               // Too many lengths!
               return (ErrorCode.ERR_REPEAT_MORE, lencode, distcode);
            }
            while (symbol != 0) {
               // Note: Solidity reverts on underflow, so we decrement here
               symbol -= 1;

               // Repeat last or zero symbol times
               lengths[index++] = len;
            }
         }
      }

      // Check for end-of-block code -- there better be one!
      if (lengths[256] == 0) {
         return (ErrorCode.ERR_MISSING_END_OF_BLOCK, lencode, distcode);
      }

      // Build huffman table for literal/length codes
      err = _construct(lencode, lengths, nlen, 0);
      if (
         err != ErrorCode.ERR_NONE &&
         (err == ErrorCode.ERR_NOT_TERMINATED || err == ErrorCode.ERR_OUTPUT_EXHAUSTED || nlen != lencode.counts[0] + lencode.counts[1])
      ) {
         // Incomplete code ok only for single length 1 code
         return (ErrorCode.ERR_INVALID_LITERAL_LENGTH_CODE_LENGTHS, lencode, distcode);
      }

      // Build huffman table for distance codes
      err = _construct(distcode, lengths, ndist, nlen);
      if (
         err != ErrorCode.ERR_NONE &&
         (err == ErrorCode.ERR_NOT_TERMINATED || err == ErrorCode.ERR_OUTPUT_EXHAUSTED || ndist != distcode.counts[0] + distcode.counts[1])
      ) {
         // Incomplete code ok only for single length 1 code
         return (ErrorCode.ERR_INVALID_DISTANCE_CODE_LENGTHS, lencode, distcode);
      }

      return (ErrorCode.ERR_NONE, lencode, distcode);
   }

   function _dynamic(State memory s) private pure returns (ErrorCode) {
      // Length and distance codes
      Huffman memory lencode;
      Huffman memory distcode;
      // Error code
      ErrorCode err;

      (err, lencode, distcode) = _build_dynamic(s);
      if (err != ErrorCode.ERR_NONE) {
         return err;
      }

      // Decode data until end-of-block code
      return _codes(s, lencode, distcode);
   }

   function puff(bytes memory source, uint256 destlen) internal pure returns (ErrorCode, bytes memory) {
      // Input/output state
      State memory s = State(
         new bytes(destlen),
         0,
         source,
         0,
         0,
         0,
         Huffman(new uint256[](MAXBITS + 1), new uint256[](FIXLCODES)),
         Huffman(new uint256[](MAXBITS + 1), new uint256[](MAXDCODES))
      );
      // Temp: last bit
      uint256 last;
      // Temp: block type bit
      uint256 t;
      // Error code
      ErrorCode err;

      // Build fixed Huffman tables
      err = _build_fixed(s);
      if (err != ErrorCode.ERR_NONE) {
         return (err, s.output);
      }

      // Process blocks until last block or error
      while (last == 0) {
         // One if last block
         (err, last) = bits(s, 1);
         if (err != ErrorCode.ERR_NONE) {
            return (err, s.output);
         }

         // Block type 0..3
         (err, t) = bits(s, 2);
         if (err != ErrorCode.ERR_NONE) {
            return (err, s.output);
         }

         err = (t == 0 ? _stored(s) : (t == 1 ? _fixed(s) : (t == 2 ? _dynamic(s) : ErrorCode.ERR_INVALID_BLOCK_TYPE)));
         // type == 3, invalid

         if (err != ErrorCode.ERR_NONE) {
            // Return with error
            break;
         }
      }

      return (err, s.output);
   }
}

File 3 of 6 : Strings.sol
library Strings {
   function toString(uint256 value) internal pure returns (string memory) {
      // Inspired by OraclizeAPI's implementation - MIT licence
      // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

      if (value == 0) {
         return "0";
      }
      uint256 temp = value;
      uint256 digits;
      while (temp != 0) {
         digits++;
         temp /= 10;
      }
      bytes memory buffer = new bytes(digits);
      while (value != 0) {
         digits -= 1;
         buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
         value /= 10;
      }
      return string(buffer);
   }
}

File 4 of 6 : Base64.sol
// SPDX-License-Identifier: MIT
/// @title Base64
/// @notice Provides a function for encoding some bytes in base64
/// @author Brecht Devos <[email protected]>

library Base64 {
   string internal constant TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

   function encode(bytes memory data) internal pure returns (string memory) {
      if (data.length == 0) return "";

      // load the table into memory
      string memory table = TABLE;

      // multiply by 4/3 rounded up
      uint256 encodedLen = 4 * ((data.length + 2) / 3);

      // add some extra buffer at the end required for the writing
      string memory result = new string(encodedLen + 32);

      assembly {
         // set the actual output length
         mstore(result, encodedLen)

         // prepare the lookup table
         let tablePtr := add(table, 1)

         // input ptr
         let dataPtr := data
         let endPtr := add(dataPtr, mload(data))

         // result ptr, jump over length
         let resultPtr := add(result, 32)

         // run over the input, 3 bytes at a time
         for {

         } lt(dataPtr, endPtr) {

         } {
            dataPtr := add(dataPtr, 3)

            // read 3 bytes
            let input := mload(dataPtr)

            // write 4 characters
            mstore(resultPtr, shl(248, mload(add(tablePtr, and(shr(18, input), 0x3F)))))
            resultPtr := add(resultPtr, 1)
            mstore(resultPtr, shl(248, mload(add(tablePtr, and(shr(12, input), 0x3F)))))
            resultPtr := add(resultPtr, 1)
            mstore(resultPtr, shl(248, mload(add(tablePtr, and(shr(6, input), 0x3F)))))
            resultPtr := add(resultPtr, 1)
            mstore(resultPtr, shl(248, mload(add(tablePtr, and(input, 0x3F)))))
            resultPtr := add(resultPtr, 1)
         }

         // padding with '='
         switch mod(mload(data), 3)
         case 1 {
            mstore(sub(resultPtr, 2), shl(240, 0x3d3d))
         }
         case 2 {
            mstore(sub(resultPtr, 1), shl(248, 0x3d))
         }
      }

      return result;
   }
}

File 5 of 6 : SSTORE2.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "./utils/Bytecode.sol";

/**
  @title A key-value storage with auto-generated keys for storing chunks of data with a lower write & read cost.
  @author Agustin Aguilar <[email protected]>

  Readme: https://github.com/0xsequence/sstore2#readme
*/
library SSTORE2 {
  error WriteError();

  /**
    @notice Stores `_data` and returns `pointer` as key for later retrieval
    @dev The pointer is a contract address with `_data` as code
    @param _data to be written
    @return pointer Pointer to the written `_data`
  */
  function write(bytes memory _data) internal returns (address pointer) {
    // Append 00 to _data so contract can't be called
    // Build init code
    bytes memory code = Bytecode.creationCodeFor(
      abi.encodePacked(
        hex'00',
        _data
      )
    );

    // Deploy contract using create
    assembly { pointer := create(0, add(code, 32), mload(code)) }

    // Address MUST be non-zero
    if (pointer == address(0)) revert WriteError();
  }

  /**
    @notice Reads the contents of the `_pointer` code as data, skips the first byte 
    @dev The function is intended for reading pointers generated by `write`
    @param _pointer to be read
    @return data read from `_pointer` contract
  */
  function read(address _pointer) internal view returns (bytes memory) {
    return Bytecode.codeAt(_pointer, 1, type(uint256).max);
  }

  /**
    @notice Reads the contents of the `_pointer` code as data, skips the first byte 
    @dev The function is intended for reading pointers generated by `write`
    @param _pointer to be read
    @param _start number of bytes to skip
    @return data read from `_pointer` contract
  */
  function read(address _pointer, uint256 _start) internal view returns (bytes memory) {
    return Bytecode.codeAt(_pointer, _start + 1, type(uint256).max);
  }

  /**
    @notice Reads the contents of the `_pointer` code as data, skips the first byte 
    @dev The function is intended for reading pointers generated by `write`
    @param _pointer to be read
    @param _start number of bytes to skip
    @param _end index before which to end extraction
    @return data read from `_pointer` contract
  */
  function read(address _pointer, uint256 _start, uint256 _end) internal view returns (bytes memory) {
    return Bytecode.codeAt(_pointer, _start + 1, _end + 1);
  }
}

File 6 of 6 : Bytecode.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;


library Bytecode {
  error InvalidCodeAtRange(uint256 _size, uint256 _start, uint256 _end);

  /**
    @notice Generate a creation code that results on a contract with `_code` as bytecode
    @param _code The returning value of the resulting `creationCode`
    @return creationCode (constructor) for new contract
  */
  function creationCodeFor(bytes memory _code) internal pure returns (bytes memory) {
    /*
      0x00    0x63         0x63XXXXXX  PUSH4 _code.length  size
      0x01    0x80         0x80        DUP1                size size
      0x02    0x60         0x600e      PUSH1 14            14 size size
      0x03    0x60         0x6000      PUSH1 00            0 14 size size
      0x04    0x39         0x39        CODECOPY            size
      0x05    0x60         0x6000      PUSH1 00            0 size
      0x06    0xf3         0xf3        RETURN
      <CODE>
    */

    return abi.encodePacked(
      hex"63",
      uint32(_code.length),
      hex"80_60_0E_60_00_39_60_00_F3",
      _code
    );
  }

  /**
    @notice Returns the size of the code on a given address
    @param _addr Address that may or may not contain code
    @return size of the code on the given `_addr`
  */
  function codeSize(address _addr) internal view returns (uint256 size) {
    assembly { size := extcodesize(_addr) }
  }

  /**
    @notice Returns the code of a given address
    @dev It will fail if `_end < _start`
    @param _addr Address that may or may not contain code
    @param _start number of bytes of code to skip on read
    @param _end index before which to end extraction
    @return oCode read from `_addr` deployed bytecode

    Forked from: https://gist.github.com/KardanovIR/fe98661df9338c842b4a30306d507fbd
  */
  function codeAt(address _addr, uint256 _start, uint256 _end) internal view returns (bytes memory oCode) {
    uint256 csize = codeSize(_addr);
    if (csize == 0) return bytes("");

    if (_start > csize) return bytes("");
    if (_end < _start) revert InvalidCodeAtRange(csize, _start, _end); 

    unchecked {
      uint256 reqSize = _end - _start;
      uint256 maxSize = csize - _start;

      uint256 size = maxSize < reqSize ? maxSize : reqSize;

      assembly {
        // allocate output byte array - this could also be done without assembly
        // by using o_code = new bytes(size)
        oCode := mload(0x40)
        // new "memory end" including padding
        mstore(0x40, add(oCode, and(add(add(size, 0x20), 0x1f), not(0x1f))))
        // store length in memory
        mstore(oCode, size)
        // actually retrieve the code, this needs assembly
        extcodecopy(_addr, add(oCode, 0x20), _start, size)
      }
    }
  }
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 2000
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"_size","type":"uint256"},{"internalType":"uint256","name":"_start","type":"uint256"},{"internalType":"uint256","name":"_end","type":"uint256"}],"name":"InvalidCodeAtRange","type":"error"},{"inputs":[],"name":"contractsealed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"customs","outputs":[{"internalType":"address","name":"imageStore","type":"address"},{"internalType":"uint96","name":"imagelen","type":"uint96"},{"internalType":"string","name":"name","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"input","type":"bytes"},{"internalType":"uint256","name":"len","type":"uint256"}],"name":"decompress","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint8[10]","name":"seed","type":"uint8[10]"}],"name":"enforceRequiredCombinations","outputs":[{"internalType":"uint8[10]","name":"","type":"uint8[10]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"rawSeed","type":"uint256"},{"internalType":"uint256","name":"tokenType","type":"uint256"}],"name":"generateTokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8[10]","name":"seed","type":"uint8[10]"}],"name":"getArrangedSeed","outputs":[{"internalType":"uint8[20]","name":"","type":"uint8[20]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getSvgCustomToken","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8[10]","name":"seed","type":"uint8[10]"}],"name":"getSvgFromSeed","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"traitType","type":"uint8"},{"internalType":"uint8","name":"traitCode","type":"uint8"}],"name":"getTraitSVG","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"rawSeed","type":"uint256"}],"name":"processRawSeed","outputs":[{"internalType":"uint8[10]","name":"","type":"uint8[10]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sealContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"},{"components":[{"internalType":"address","name":"imageStore","type":"address"},{"internalType":"uint96","name":"imagelen","type":"uint96"},{"internalType":"string","name":"name","type":"string"}],"internalType":"struct EthTerrestrialsV2Descriptor.Trait[]","name":"_oneOfOnes","type":"tuple[]"}],"name":"setCustom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8[]","name":"_traitTypes","type":"uint8[]"},{"internalType":"bool","name":"_hidden","type":"bool"}],"name":"setHiddenTraits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"traitType","type":"uint8"},{"internalType":"uint8","name":"trait","type":"uint8"},{"components":[{"internalType":"uint8","name":"traitType","type":"uint8"},{"internalType":"uint8","name":"trait","type":"uint8"}],"internalType":"struct EthTerrestrialsV2Descriptor.TraitDescriptor[]","name":"exclusions","type":"tuple[]"}],"name":"setTraitExclusions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"traitType","type":"uint8"},{"internalType":"uint8","name":"trait","type":"uint8"},{"components":[{"internalType":"uint8","name":"traitType","type":"uint8"},{"internalType":"uint8","name":"trait","type":"uint8"}],"internalType":"struct EthTerrestrialsV2Descriptor.TraitDescriptor[]","name":"rearrangements","type":"tuple[]"}],"name":"setTraitRearrangements","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"uint16[]","name":"rarity","type":"uint16[]"}],"internalType":"struct EthTerrestrialsV2Descriptor.TraitType[]","name":"_traitTypes","type":"tuple[]"}],"name":"setTraitTypes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"_traitType","type":"uint8"},{"components":[{"internalType":"address","name":"imageStore","type":"address"},{"internalType":"uint96","name":"imagelen","type":"uint96"},{"internalType":"string","name":"name","type":"string"}],"internalType":"struct EthTerrestrialsV2Descriptor.Trait[]","name":"_traits","type":"tuple[]"},{"internalType":"uint8[]","name":"_traitNumber","type":"uint8[]"}],"name":"setTraits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"terraforms","outputs":[{"internalType":"contract Terraforms","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"traitExclusions","outputs":[{"internalType":"uint8","name":"traitType","type":"uint8"},{"internalType":"uint8","name":"trait","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"traitRearrangement","outputs":[{"internalType":"uint8","name":"traitType","type":"uint8"},{"internalType":"uint8","name":"trait","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"","type":"uint8"}],"name":"traitTypes","outputs":[{"internalType":"string","name":"name","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"","type":"uint8"},{"internalType":"uint8","name":"","type":"uint8"}],"name":"traits","outputs":[{"internalType":"address","name":"imageStore","type":"address"},{"internalType":"uint96","name":"imagelen","type":"uint96"},{"internalType":"string","name":"name","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8[10]","name":"seed","type":"uint8[10]"}],"name":"viewTraitsJSON","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"viewTraitsJSONCustom","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]

61018060405260d36080818152906200546260a03980516200002a9160079160209091019062000077565b50600980546001600160a01b031916734e1f41613c9084fdb9e34e11fae9412427480e561790553480156200005e57600080fd5b50600880546001600160a01b031916331790556200015a565b82805462000085906200011d565b90600052602060002090601f016020900481019282620000a95760008555620000f4565b82601f10620000c457805160ff1916838001178555620000f4565b82800160010185558215620000f4579182015b82811115620000f4578251825591602001919060010190620000d7565b506200010292915062000106565b5090565b5b8082111562000102576000815560010162000107565b600181811c908216806200013257607f821691505b602082108114156200015457634e487b7160e01b600052602260045260246000fd5b50919050565b6152f8806200016a6000396000f3fe608060405234801561001057600080fd5b50600436106101985760003560e01c8063891d03a5116100e3578063b7b215821161008c578063c7d4abea11610066578063c7d4abea14610390578063ce530a9a146103a3578063e4183897146103c057600080fd5b8063b7b215821461034a578063bcdfb0b91461036a578063c023c0eb1461037d57600080fd5b80639ddbb3cf116100bd5780639ddbb3cf14610311578063aa7ee7f814610324578063b116347b1461033757600080fd5b8063891d03a5146102d8578063955bfb53146102eb5780639ad9a4cb146102fe57600080fd5b80635347bcbc1161014557806363c113cf1161011f57806363c113cf146102aa57806368bd580e146102bd578063791a1631146102c557600080fd5b80635347bcbc1461024c5780635623bf8b1461025f5780635af325bc1461027f57600080fd5b80631ed8ef10116101765780631ed8ef10146101f757806331862ada1461021757806338c7bcf11461022a57600080fd5b80631771d1001461019d5780631e36d5b4146101b25780631e38323d146101e4575b600080fd5b6101b06101ab3660046144ab565b6103d3565b005b6101c56101c0366004614502565b6104ad565b6040805160ff9384168152929091166020830152015b60405180910390f35b6101b06101f23660046146f2565b6104e8565b61020a61020536600461441b565b610652565b6040516101db9190614d50565b61020a610225366004614524565b610902565b61023d6102383660046146bf565b610919565b6040516101db93929190614cb9565b61023d61025a3660046145eb565b6109ea565b61027261026d36600461441b565b610a2d565b6040516101db9190614cef565b600954610292906001600160a01b031681565b6040516001600160a01b0390911681526020016101db565b6102726102b83660046145eb565b610cfb565b6101b0610dd5565b61020a6102d336600461441b565b610e4d565b61020a6102e6366004614604565b610fd9565b6101b06102f93660046146f2565b611143565b61020a61030c3660046145eb565b6112a6565b6101c561031f366004614502565b6112e4565b6101b061033236600461435b565b611300565b6101b061034536600461464b565b611429565b61035d61035836600461441b565b61157b565b6040516101db9190614d24565b61020a6103783660046146bf565b611850565b61020a61038b3660046145eb565b6118c3565b61020a61039e366004614630565b611a6e565b6006546103b09060ff1681565b60405190151581526020016101db565b6101b06103ce3660046141db565b611b0c565b60065460ff161580156103f057506008546001600160a01b031633145b6104415760405162461bcd60e51b815260206004820152601860248201527f4e6f7420617574686f72697a6564206f72206c6f636b6564000000000000000060448201526064015b60405180910390fd5b60005b82518160ff1610156104a8578160016000858460ff168151811061046a5761046a614fc8565b60209081029190910181015160ff168252810191909152604001600020805460ff1916911515919091179055806104a081614f52565b915050610444565b505050565b600360205281600052604060002081815481106104c957600080fd5b60009182526020909120015460ff808216935061010090910416905082565b60065460ff1615801561050557506008546001600160a01b031633145b6105515760405162461bcd60e51b815260206004820152601860248201527f4e6f7420617574686f72697a6564206f72206c6f636b656400000000000000006044820152606401610438565b6040517fff0000000000000000000000000000000000000000000000000000000000000060f885811b8216602084015284901b16602182015260009060220160408051601f198184030181529181528151602092830120600081815260039093529082209092506105c191613dfc565b60005b82518160ff16101561064b5760008281526003602052604090208351849060ff84169081106105f5576105f5614fc8565b6020908102919091018101518254600181018455600093845292829020815193018054919092015160ff9081166101000261ffff199092169316929092179190911790558061064381614f52565b9150506105c4565b5050505050565b60408051600b808252610180820190925260609160009190816020015b606081526020019060019003908161066f57905050905060005b600a8160ff1610156108645760ff80821660009081526001602052604090205416610852576000848260ff16600a81106106c5576106c5614fc8565b6020908102919091015160ff808516600090815260048452604080822092841682529190935282206001018054919350906106ff90614efc565b80601f016020809104026020016040519081016040528092919081815260200182805461072b90614efc565b80156107785780601f1061074d57610100808354040283529160200191610778565b820191906000526020600020905b81548152906001019060200180831161075b57829003601f168201915b505050505090508260ff166000146107c5576040518060400160405280601081526020017f2c7b2274726169745f74797065223a22000000000000000000000000000000008152506107fc565b6040518060400160405280601081526020017f5b7b2274726169745f74797065223a22000000000000000000000000000000008152505b60ff84166000908152602081815260409182902091516108209392918591016148d2565b604051602081830303815290604052848460ff168151811061084457610844614fc8565b602002602001018190525050505b8061085c81614f52565b915050610689565b506040518060600160405280602e8152602001614ff5602e913981600a8151811061089157610891614fc8565b6020026020010181905250606060005b600b8110156108fa57818382815181106108bd576108bd614fc8565b60200260200101516040516020016108d69291906148a3565b604051602081830303815290604052915080806108f290614f37565b9150506108a1565b509392505050565b606060006109108484611bfe565b95945050505050565b6004602090815260009283526040808420909152908252902080546001820180546001600160a01b03831693600160a01b9093046bffffffffffffffffffffffff1692919061096790614efc565b80601f016020809104026020016040519081016040528092919081815260200182805461099390614efc565b80156109e05780601f106109b5576101008083540402835291602001916109e0565b820191906000526020600020905b8154815290600101906020018083116109c357829003601f168201915b5050505050905083565b600560205260009081526040902080546001820180546001600160a01b03831693600160a01b9093046bffffffffffffffffffffffff1692919061096790614efc565b610a35613e1d565b60005b600a8160ff161015610c195760006002600083868560ff16600a8110610a6057610a60614fc8565b6020020151604051602001610aac92919060f892831b7fff0000000000000000000000000000000000000000000000000000000000000090811682529190921b16600182015260020190565b604051602081830303815290604052805190602001208152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b82821015610b31576000848152602090819020604080518082019091529084015460ff80821683526101009091041681830152825260019092019101610af0565b50505050905060005b81518160ff161015610c0457818160ff1681518110610b5b57610b5b614fc8565b60200260200101516020015160ff1685838360ff1681518110610b8057610b80614fc8565b60200260200101516000015160ff16600a8110610b9f57610b9f614fc8565b602002015160ff161415610bf257600085838360ff1681518110610bc557610bc5614fc8565b60200260200101516000015160ff16600a8110610be457610be4614fc8565b60ff90921660209290920201525b80610bfc81614f52565b915050610b3a565b50508080610c1190614f52565b915050610a38565b5060c082015160ff1660061415610c425760008260075b60ff9092166020929092020152610cb2565b816008602002015160ff1660011415610c5f576000826007610c30565b816008602002015160ff1660071415610c7c576000826007610c30565b61010082015160ff1660081415610c97576000826007610c30565b816008602002015160ff1660091415610cb257600060e08301525b816008602002015160ff1660031480610cd55750816008602002015160ff166004145b80610cea5750816008602002015160ff166006145b15610cf757600160208301525b5090565b610d03613e1d565b610d0b613e1d565b60005b600a8160ff161015610db6576103e88482604051602001610d5e92919091825260f81b7fff0000000000000000000000000000000000000000000000000000000000000016602082015260210190565b6040516020818303038152906040528051906020012060001c610d819190614f72565b828260ff16600a8110610d9657610d96614fc8565b61ffff909216602092909202015280610dae81614f52565b915050610d0e565b506000610dc282611eb2565b9050610dcd81610a2d565b949350505050565b60065460ff16158015610df257506008546001600160a01b031633145b610e3e5760405162461bcd60e51b815260206004820152601860248201527f4e6f7420617574686f72697a6564206f72206c6f636b656400000000000000006044820152606401610438565b6006805460ff19166001179055565b6060610e57613e3c565b6000610e628461157b565b905060005b60148160ff161015610f49576000828260ff1660148110610e8a57610e8a614fc8565b6020020151905060ff80821614610f36576000868260ff16600a8110610eb257610eb2614fc8565b6020908102919091015160ff8481166000908152600484526040808220928416825291909352822054909250600160a01b90046bffffffffffffffffffffffff16610f0c5760405180602001604052806000815250610f16565b610f168383611850565b905080868560ff1660148110610f2e57610f2e614fc8565b602002015250505b5080610f4181614f52565b915050610e67565b50606060005b60148160ff161015610fab5781848260ff1660148110610f7157610f71614fc8565b6020020151604051602001610f879291906148a3565b60405160208183030381529060405291508080610fa390614f52565b915050610f4f565b50600781604051602001610fc09291906149e8565b6040516020818303038152906040529350505050919050565b60606000610fe685612015565b604051602001610ff69190614c74565b60408051601f19818403018152610120830190915260fe8083529092506000919061515b60208301399050606080856001141561104857611036886118c3565b9050611041886112a6565b91506110d6565b866110b15761105760456118c3565b90506040518060600160405280602a8152602001615299602a913992506040518060400160405280600281526020017f5b5d00000000000000000000000000000000000000000000000000000000000081525091506110d6565b60006110bc88610cfb565b90506110c781610e4d565b91506110d281610652565b9250505b600061110e8585856110e786612147565b6040516020016110fa9493929190614ae0565b604051602081830303815290604052612147565b90506000816040516020016111239190614c2f565b60408051601f1981840301815291905296505050505050505b9392505050565b60065460ff1615801561116057506008546001600160a01b031633145b6111ac5760405162461bcd60e51b815260206004820152601860248201527f4e6f7420617574686f72697a6564206f72206c6f636b656400000000000000006044820152606401610438565b6040517fff0000000000000000000000000000000000000000000000000000000000000060f885811b8216602084015284901b16602182015260009060220160408051601f1981840301815291815281516020928301206000818152600290935290822090925061121c91613dfc565b60005b82518160ff16101561064b5760008281526002602052604090208351849060ff841690811061125057611250614fc8565b6020908102919091018101518254600181018455600093845292829020815193018054919092015160ff9081166101000261ffff199092169316929092179190911790558061129e81614f52565b91505061121f565b6060600560008381526020019081526020016000206001016040516020016112ce9190614a35565b6040516020818303038152906040529050919050565b600260205281600052604060002081815481106104c957600080fd5b60065460ff1615801561131d57506008546001600160a01b031633145b6113695760405162461bcd60e51b815260206004820152601860248201527f4e6f7420617574686f72697a6564206f72206c6f636b656400000000000000006044820152606401610438565b805182511461137757600080fd5b60005b81518110156104a85781818151811061139557611395614fc8565b6020026020010151600560008584815181106113b3576113b3614fc8565b60209081029190910181015182528181019290925260409081016000208351848401516bffffffffffffffffffffffff16600160a01b026001600160a01b03909116178155908301518051919261141292600185019290910190613e64565b50905050808061142190614f37565b91505061137a565b60065460ff1615801561144657506008546001600160a01b031633145b6114925760405162461bcd60e51b815260206004820152601860248201527f4e6f7420617574686f72697a6564206f72206c6f636b656400000000000000006044820152606401610438565b80518251146114a057600080fd5b60005b82518160ff16101561157557828160ff16815181106114c4576114c4614fc8565b6020026020010151600460008660ff1660ff1681526020019081526020016000206000848460ff16815181106114fc576114fc614fc8565b60209081029190910181015160ff1682528181019290925260409081016000208351848401516bffffffffffffffffffffffff16600160a01b026001600160a01b03909116178155908301518051919261155e92600185019290910190613e64565b50905050808061156d90614f52565b9150506114a3565b50505050565b611583613ee4565b61158b613ee4565b60005b60148160ff16101561160557600a8160ff1610156115ce5780828260ff16601481106115bc576115bc614fc8565b60ff90921660209290920201526115f3565b60ff828260ff16601481106115e5576115e5614fc8565b60ff90921660209290920201525b806115fd81614f52565b91505061158e565b506101008301516040517f0800000000000000000000000000000000000000000000000000000000000000602082015260f89190911b7fff000000000000000000000000000000000000000000000000000000000000001660218201526000906003908290602201604051602081830303815290604052805190602001208152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b828210156116f2576000848152602090819020604080518082019091529084015460ff808216835261010090910416818301528252600190920191016116b1565b50505050905060005b81518160ff16101561183857818160ff168151811061171c5761171c614fc8565b60200260200101516020015160ff1685838360ff168151811061174157611741614fc8565b60200260200101516000015160ff16600a811061176057611760614fc8565b602002015160ff16141561182657818160ff168151811061178357611783614fc8565b60200260200101516000015183838360ff16815181106117a5576117a5614fc8565b602002602001015160000151600a6117bd9190614e61565b60ff16601481106117d0576117d0614fc8565b602002019060ff16908160ff168152505060ff83838360ff16815181106117f9576117f9614fc8565b60200260200101516000015160ff166014811061181857611818614fc8565b60ff90921660209290920201525b8061183081614f52565b9150506116fb565b5050600961026082015260ff61012082015292915050565b60ff80831660009081526004602090815260408083209385168352929052205460609061113c90611889906001600160a01b0316612304565b60ff858116600090815260046020908152604080832093881683529290522054600160a01b90046bffffffffffffffffffffffff16610902565b60606007826068146118e45760405180602001604052806000815250611901565b604051806101600160405280610138815260200161502361013891395b8360681461191e57604051806020016040528060008152506119b8565b6009546040517f9bac5f7a000000000000000000000000000000000000000000000000000000008152610e3860048201526001600160a01b0390911690639bac5f7a9060240160006040518083038186803b15801561197c57600080fd5b505afa158015611990573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526119b8919081019061457d565b846068146119d55760405180602001604052806000815250611a0c565b6040518060400160405280600881526020017f3c2f673e3c2f673e0000000000000000000000000000000000000000000000008152505b600086815260056020526040902054611a5a90611a31906001600160a01b0316612304565b600088815260056020526040902054600160a01b90046bffffffffffffffffffffffff16610902565b6040516020016112ce95949392919061495f565b600060208190529081526040902080548190611a8990614efc565b80601f0160208091040260200160405190810160405280929190818152602001828054611ab590614efc565b8015611b025780601f10611ad757610100808354040283529160200191611b02565b820191906000526020600020905b815481529060010190602001808311611ae557829003601f168201915b5050505050905081565b60065460ff16158015611b2957506008546001600160a01b031633145b611b755760405162461bcd60e51b815260206004820152601860248201527f4e6f7420617574686f72697a6564206f72206c6f636b656400000000000000006044820152606401610438565b60005b600a8160ff161015611bfa57818160ff1681518110611b9957611b99614fc8565b60209081029190910181015160ff83166000908152808352604090208151805192939192611bca9284920190613e64565b506020828101518051611be39260018501920190613f03565b509050508080611bf290614f52565b915050611b78565b5050565b6000606060006040518061010001604052808567ffffffffffffffff811115611c2957611c29614fde565b6040519080825280601f01601f191660200182016040528015611c53576020820181803683370190505b508152602001600081526020018681526020016000815260200160008152602001600081526020016040518060400160405280600f6001611c949190614e49565b67ffffffffffffffff811115611cac57611cac614fde565b604051908082528060200260200182016040528015611cd5578160200160208202803683370190505b5081526040805161012080825261242082019092526020928301929091908201612400803683370190505081525081526020016040518060400160405280600f6001611d219190614e49565b67ffffffffffffffff811115611d3957611d39614fde565b604051908082528060200260200182016040528015611d62578160200160208202803683370190505b50815260408051601e8082526103e0820190925260209283019290919082016103c08036833750505090529052905060008080611d9e8461231a565b9050600081600e811115611db457611db4614fb2565b14611dc9579251929450919250611eab915050565b82611ea057611dd98460016124a4565b93509050600081600e811115611df157611df1614fb2565b14611e06579251929450919250611eab915050565b611e118460026124a4565b92509050600081600e811115611e2957611e29614fb2565b14611e3e579251929450919250611eab915050565b8115611e725781600114611e695781600214611e5b576003611e7b565b611e6484612575565b611e7b565b611e64846125e6565b611e7b846125fb565b9050600081600e811115611e9157611e91614fb2565b14611e9b57611ea0565b611dc9565b925192945091925050505b9250929050565b611eba613e1d565b611ec2613e1d565b60005b600a8160ff16101561200e5760ff811660009081526020818152604080832060010180548251818502810185019093528083529192909190830182828015611f5457602002820191906000526020600020906000905b82829054906101000a900461ffff1661ffff1681526020019060020190602082600101049283019260010382029150808411611f1b5790505b505050505090506000805b82518160ff161015611ff857828160ff1681518110611f8057611f80614fc8565b602002602001015182611f939190614e2c565b91508161ffff16878560ff16600a8110611faf57611faf614fc8565b602002015161ffff161015611fe65780858560ff16600a8110611fd457611fd4614fc8565b60ff9092166020929092020152611ff8565b80611ff081614f52565b915050611f5f565b505050808061200690614f52565b915050611ec5565b5092915050565b60608161205557505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b811561207f578061206981614f37565b91506120789050600a83614e86565b9150612059565b60008167ffffffffffffffff81111561209a5761209a614fde565b6040519080825280601f01601f1916602001820160405280156120c4576020820181803683370190505b5090505b8415610dcd576120d9600183614eb9565b91506120e6600a86614f72565b6120f1906030614e49565b60f81b81838151811061210657612106614fc8565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350612140600a86614e86565b94506120c8565b606081516000141561216757505060408051602081019091526000815290565b600060405180606001604052806040815260200161525960409139905060006003845160026121969190614e49565b6121a09190614e86565b6121ab906004614e9a565b905060006121ba826020614e49565b67ffffffffffffffff8111156121d2576121d2614fde565b6040519080825280601f01601f1916602001820160405280156121fc576020820181803683370190505b509050818152600183018586518101602084015b8183101561226a5760039283018051603f601282901c811687015160f890811b8552600c83901c8216880151811b6001860152600683901c8216880151811b60028601529116860151901b93820193909352600401612210565b60038951066001811461228457600281146122ce576122f6565b7f3d3d0000000000000000000000000000000000000000000000000000000000007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe8301526122f6565b7f3d000000000000000000000000000000000000000000000000000000000000006000198301525b509398975050505050505050565b6060612314826001600019612823565b92915050565b604080516101208082526124208201909252600091829182916020820161240080368337019050509050600091505b609082101561238357600881838151811061236657612366614fc8565b60209081029190910101528161237b81614f37565b925050612349565b6101008210156123be5760098183815181106123a1576123a1614fc8565b6020908102919091010152816123b681614f37565b925050612383565b6101188210156123f95760078183815181106123dc576123dc614fc8565b6020908102919091010152816123f181614f37565b9250506123be565b61012082101561243457600881838151811061241757612417614fc8565b60209081029190910101528161242c81614f37565b9250506123f9565b6124478460c001518261012060006128ed565b50600091505b601e82101561248757600581838151811061246a5761246a614fc8565b60209081029190910101528161247f81614f37565b92505061244d565b6124998460e0015182601e60006128ed565b506000949350505050565b608082015160009081905b838560a00151101561253857846040015151856060015114156124da57600160009250925050611eab565b60a08501516040860151606087018051906124f482614f37565b90528151811061250657612506614fc8565b602001015160f81c60f81b60f81c60ff16901b8117905060088560a0018181516125309190614e49565b9052506124af565b80841c608086015260a085018051859190612554908390614eb9565b9052506000612566600180871b614eb9565b60009792169550909350505050565b6000612594604051806040016040528060608152602001606081525090565b604080518082019091526060808252602082015260006125b385612bb6565b90945092509050600081600e8111156125ce576125ce614fb2565b146125db57949350505050565b61091085848461326f565b6000612314828360c001518460e0015161326f565b60006080820181905260a082018190526040820151516060830151829190612624906004614e49565b11156126335750600192915050565b60408301516060840180519061264882614f37565b90528151811061265a5761265a614fc8565b0160200151604084015160608501805160f89390931c93506008929061267f82614f37565b90528151811061269157612691614fc8565b602001015160f81c60f81b60f81c60ff16901b81179050801960ff1683604001518460600180518091906126c490614f37565b9052815181106126d6576126d6614fc8565b016020015160f81c1415806127215750604083015160608401805160ff841960081c16929161270482614f37565b90528151811061271657612716614fc8565b016020015160f81c14155b1561272f5750600492915050565b8260400151518184606001516127459190614e49565b11156127545750600192915050565b8251516020840151612767908390614e49565b11156127765750600292915050565b801561281a57612787600182614eb9565b905082604001518360600180518091906127a090614f37565b9052815181106127b2576127b2614fc8565b602001015160f81c60f81b83600001518460200180518091906127d490614f37565b9052815181106127e6576127e6614fc8565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350612776565b50600092915050565b6060833b8061284257505060408051602081019091526000815261113c565b8084111561286057505060408051602081019091526000815261113c565b838310156128ab576040517f2c4a89fa000000000000000000000000000000000000000000000000000000008152600481018290526024810185905260448101849052606401610438565b83830384820360008282106128c057826128c2565b815b60408051603f8301601f19168101909152818152955090508087602087018a3c505050509392505050565b6000806000806128fb613fa7565b600092505b600f831161293d5760008960000151848151811061292057612920614fc8565b60209081029190910101528261293581614f37565b935050612900565b600093505b868410156129a9578851886129578689614e49565b8151811061296757612967614fc8565b60200260200101518151811061297f5761297f614fc8565b60200260200101805180919061299490614f37565b905250836129a181614f37565b945050612942565b8689600001516000815181106129c1576129c1614fc8565b602002602001015114156129dc576000945050505050610dcd565b60019150600192505b600f8311612a5f578851805160019390931b9284908110612a0857612a08614fc8565b6020026020010151821015612a2457600e945050505050610dcd565b8851805184908110612a3857612a38614fc8565b602002602001015182612a4b9190614eb9565b915082612a5781614f37565b9350506129e5565b60006020820152600192505b600f831015612ae4578851805184908110612a8857612a88614fc8565b6020026020010151818460108110612aa257612aa2614fc8565b6020020151612ab19190614e49565b81612abd856001614e49565b60108110612acd57612acd614fc8565b602002015282612adc81614f37565b935050612a6b565b600093505b86841015612b975787612afc8588614e49565b81518110612b0c57612b0c614fc8565b6020026020010151600014612b855760208901518490828a612b2e848b614e49565b81518110612b3e57612b3e614fc8565b602002602001015160108110612b5657612b56614fc8565b60200201805190612b6682614f37565b905281518110612b7857612b78614fc8565b6020026020010181815250505b83612b8f81614f37565b945050612ae9565b60008211612ba6576000612ba9565b600e5b9998505050505050505050565b6000612bd5604051806040016040528060608152602001606081525090565b6040805180820190915260608082526020820152600080808080612bfc601e61011e614e49565b67ffffffffffffffff811115612c1457612c14614fde565b604051908082528060200260200182016040528015612c3d578160200160208202803683370190505b50905060006040518060400160405280600f6001612c5b9190614e49565b67ffffffffffffffff811115612c7357612c73614fde565b604051908082528060200260200182016040528015612c9c578160200160208202803683370190505b5081526040805161011e8082526123e0820190925260209283019290919082016123c08036833701905050815250905060006040518060400160405280600f6001612ce79190614e49565b67ffffffffffffffff811115612cff57612cff614fde565b604051908082528060200260200182016040528015612d28578160200160208202803683370190505b50815260408051601e8082526103e0820190925260209283019290919082016103c080368337505050905290506000612d628c60056124a4565b98509450600085600e811115612d7a57612d7a614fb2565b14612d92575092985096509094506132689350505050565b612d9e61010189614e49565b9750612dab8c60056124a4565b97509450600085600e811115612dc357612dc3614fb2565b14612ddb575092985096509094506132689350505050565b612de6600188614e49565b965061011e881180612df85750601e87115b15612e125750600599509097509550613268945050505050565b612e1b8c613aca565b9095509350600085600e811115612e3457612e34614fb2565b14612e4c575092985096509094506132689350505050565b612e5a8385601360006128ed565b9450600085600e811115612e7057612e70614fb2565b14612e8a5750600699509097509550613268945050505050565b600095505b612e998789614e49565b86101561309257600080612ead8e86613ced565b9097509150600087600e811115612ec657612ec6614fb2565b14612ee05750949a50919850965061326895505050505050565b6010821015612f1857818689612ef581614f37565b9a5081518110612f0757612f07614fc8565b60200260200101818152505061308b565b5060006010821415612fb75787612f41575060079b509299509097506132689650505050505050565b85612f4d60018a614eb9565b81518110612f5d57612f5d614fc8565b60200260200101519050612f728e60026124a4565b9097509250600087600e811115612f8b57612f8b614fb2565b14612fa55750949a50919850965061326895505050505050565b612fb0836003614e49565b9150613017565b8160111415612fcb57612f728e60036124a4565b612fd68e60076124a4565b9097509250600087600e811115612fef57612fef614fb2565b146130095750949a50919850965061326895505050505050565b61301483600b614e49565b91505b613021898b614e49565b61302b838a614e49565b1115613049575060089b509299509097506132689650505050505050565b811561308b5761305a600183614eb9565b915080868961306881614f37565b9a508151811061307a5761307a614fc8565b602002602001018181525050613049565b5050612e8f565b83610100815181106130a6576130a6614fc8565b6020026020010151600014156130cb5750600b99509097509550613268945050505050565b6130d883858a60006128ed565b9450600085600e8111156130ee576130ee614fb2565b141580156131785750600185600e81111561310b5761310b614fb2565b14806131285750600285600e81111561312657613126614fb2565b145b80613178575082518051600190811061314357613143614fc8565b6020026020010151836000015160008151811061316257613162614fc8565b60200260200101516131749190614e49565b8814155b156131925750600999509097509550613268945050505050565b61319e8285898b6128ed565b9450600085600e8111156131b4576131b4614fb2565b1415801561323e5750600185600e8111156131d1576131d1614fb2565b14806131ee5750600285600e8111156131ec576131ec614fb2565b145b8061323e575081518051600190811061320957613209614fc8565b6020026020010151826000015160008151811061322857613228614fc8565b602002602001015161323a9190614e49565b8714155b156132585750600a99509097509550613268945050505050565b5060009950909750955050505050505b9193909250565b6000806000806000604051806103a00160405280600361ffff168152602001600461ffff168152602001600561ffff168152602001600661ffff168152602001600761ffff168152602001600861ffff168152602001600961ffff168152602001600a61ffff168152602001600b61ffff168152602001600d61ffff168152602001600f61ffff168152602001601161ffff168152602001601361ffff168152602001601761ffff168152602001601b61ffff168152602001601f61ffff168152602001602361ffff168152602001602b61ffff168152602001603361ffff168152602001603b61ffff168152602001604361ffff168152602001605361ffff168152602001606361ffff168152602001607361ffff168152602001608361ffff16815260200160a361ffff16815260200160c361ffff16815260200160e361ffff16815260200161010261ffff1681525090506000604051806103a00160405280600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600160ff168152602001600160ff168152602001600160ff168152602001600160ff168152602001600260ff168152602001600260ff168152602001600260ff168152602001600260ff168152602001600360ff168152602001600360ff168152602001600360ff168152602001600360ff168152602001600460ff168152602001600460ff168152602001600460ff168152602001600460ff168152602001600560ff168152602001600560ff168152602001600560ff168152602001600560ff168152602001600060ff1681525090506000604051806103c00160405280600161ffff168152602001600261ffff168152602001600361ffff168152602001600461ffff168152602001600561ffff168152602001600761ffff168152602001600961ffff168152602001600d61ffff168152602001601161ffff168152602001601961ffff168152602001602161ffff168152602001603161ffff168152602001604161ffff168152602001606161ffff168152602001608161ffff16815260200160c161ffff16815260200161010161ffff16815260200161018161ffff16815260200161020161ffff16815260200161030161ffff16815260200161040161ffff16815260200161060161ffff16815260200161080161ffff168152602001610c0161ffff16815260200161100161ffff16815260200161180161ffff16815260200161200161ffff16815260200161300161ffff16815260200161400161ffff16815260200161600161ffff1681525090506000604051806103c00160405280600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600160ff168152602001600160ff168152602001600260ff168152602001600260ff168152602001600360ff168152602001600360ff168152602001600460ff168152602001600460ff168152602001600560ff168152602001600560ff168152602001600660ff168152602001600660ff168152602001600760ff168152602001600760ff168152602001600860ff168152602001600860ff168152602001600960ff168152602001600960ff168152602001600a60ff168152602001600a60ff168152602001600b60ff168152602001600b60ff168152602001600c60ff168152602001600c60ff168152602001600d60ff168152602001600d60ff16815250905060005b8761010014613ab8576137a98c8c613ced565b98509050600081600e8111156137c1576137c1614fb2565b146137d557975061113c9650505050505050565b610100881015613863578b515160208d015114156137fe5760029850505050505050505061113c565b8760f81b8c600001518d602001518151811061381c5761381c614fc8565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060208c0180519061385b82614f37565b905250613796565b610100881115613aa657600061387b6101018a614eb9565b9850601d891061389757600c995050505050505050505061113c565b6138ba8d868b601d81106138ad576138ad614fc8565b602002015160ff166124a4565b9092509050600082600e8111156138d3576138d3614fb2565b146138e85750975061113c9650505050505050565b80868a601d81106138fb576138fb614fc8565b602002015161ffff1661390e9190614e49565b975061391a8d8c613ced565b99509150600082600e81111561393257613932614fb2565b146139475750975061113c9650505050505050565b61395d8d848b601e81106138ad576138ad614fc8565b9092509050600082600e81111561397657613976614fb2565b1461398b5750975061113c9650505050505050565b80848a601e811061399e5761399e614fc8565b602002015161ffff166139b19190614e49565b96508c602001518711156139d157600d995050505050505050505061113c565b8c515160208e01516139e4908a90614e49565b11156139fc576002995050505050505050505061113c565b8715613aa057613a0d600189614eb9565b97508c60000151878e60200151613a249190614eb9565b81518110613a3457613a34614fc8565b602001015160f81c60f81b8d600001518e6020015181518110613a5957613a59614fc8565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060208d01805190613a9882614f37565b9052506139fc565b50613796565b868c60200181815161385b9190614e49565b5060009b9a5050505050505050505050565b60006060818080613ade601e61011e614e49565b67ffffffffffffffff811115613af657613af6614fde565b604051908082528060200260200182016040528015613b1f578160200160208202803683370190505b506040805161026081018252601081526011602082015260129181019190915260006060820181905260086080830152600760a0830152600960c0830152600660e0830152600a6101008301526005610120830152600b61014083015260046101608301819052600c61018084015260036101a0840152600d6101c084015260026101e0840152600e6102008401526001610220840152600f61024084015292935091613bcd9089906124a4565b95509150600082600e811115613be557613be5614fb2565b14613bf65750969095509350505050565b613c01600486614e49565b9450600093505b84841015613c8a57613c1b8860036124a4565b84838760138110613c2e57613c2e614fc8565b602002015160ff1681518110613c4657613c46614fc8565b60209081029190910101529150600082600e811115613c6757613c67614fb2565b14613c785750969095509350505050565b83613c8281614f37565b945050613c08565b6013841015613cdd57600083828660138110613ca857613ca8614fc8565b602002015160ff1681518110613cc057613cc0614fc8565b602090810291909101015283613cd581614f37565b945050613c8a565b5060009791965090945050505050565b600080600181808080805b600f8611613de9576000613d0d8b60016124a4565b9092509050600082600e811115613d2657613d26614fb2565b14613d3d5750965060009550611eab945050505050565b895180519682179688908110613d5557613d55614fc8565b602002602001015193508385613d6b9190614e49565b861015613db65760208a0151600090613d848789614eb9565b613d8e9086614e49565b81518110613d9e57613d9e614fc8565b60200260200101519850985050505050505050611eab565b613dc08484614e49565b9250613dcc8486614e49565b600196871b961b9450869050613de181614f37565b965050613cf8565b50600c9960009950975050505050505050565b5080546000825590600052602060002090810190613e1a9190613fc6565b50565b604051806101400160405280600a906020820280368337509192915050565b6040518061028001604052806014905b6060815260200190600190039081613e4c5790505090565b828054613e7090614efc565b90600052602060002090601f016020900481019282613e925760008555613ed8565b82601f10613eab57805160ff1916838001178555613ed8565b82800160010185558215613ed8579182015b82811115613ed8578251825591602001919060010190613ebd565b50610cf7929150613fe0565b6040518061028001604052806014906020820280368337509192915050565b82805482825590600052602060002090600f01601090048101928215613ed85791602002820160005b83821115613f6c57835183826101000a81548161ffff021916908361ffff1602179055509260200192600201602081600101049283019260010302613f2c565b8015613f9a5782816101000a81549061ffff0219169055600201602081600101049283019260010302613f6c565b5050610cf7929150613fe0565b6040518061020001604052806010906020820280368337509192915050565b5b80821115610cf757805461ffff19168155600101613fc7565b5b80821115610cf75760008155600101613fe1565b600061400861400384614e04565b614daf565b905082815283838301111561401c57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261404457600080fd5b8135602061405461400383614de0565b80838252828201915082860187848660051b890101111561407457600080fd5b60005b8581101561413157813567ffffffffffffffff8082111561409757600080fd5b818a019150606080601f19848e030112156140b157600080fd5b6140b9614d63565b888401356001600160a01b03811681146140d257600080fd5b81526040848101356bffffffffffffffffffffffff811681146140f457600080fd5b828b015291840135918383111561410a57600080fd5b6141188e8b858801016141a5565b9082015287525050509284019290840190600101614077565b5090979650505050505050565b600082601f83011261414f57600080fd5b8135602061415f61400383614de0565b80838252828201915082860187848660051b890101111561417f57600080fd5b60005b8581101561413157614193826141c5565b84529284019290840190600101614182565b600082601f8301126141b657600080fd5b61113c83833560208501613ff5565b803560ff811681146141d657600080fd5b919050565b600060208083850312156141ee57600080fd5b67ffffffffffffffff808435111561420557600080fd5b8335840185601f82011261421857600080fd5b6142256140038235614de0565b808235825284820191508483018886853560051b860101111561424757600080fd5b60005b843581101561434d57858235111561426157600080fd5b813585016040601f19828d0301121561427957600080fd5b614281614d8c565b8789830135111561429157600080fd5b6142a28c8a8b8501358501016141a5565b815287604083013511156142b557600080fd5b6040820135820191508b603f8301126142cd57600080fd5b888201356142dd61400382614de0565b808282528b82019150604085018f60408560051b88010111156142ff57600080fd5b600095505b8386101561433357803561ffff81161461431d57600080fd5b8035835260019590950194918c01918c01614304565b50838c01525050855250928601929086019060010161424a565b509098975050505050505050565b6000806040838503121561436e57600080fd5b823567ffffffffffffffff8082111561438657600080fd5b818501915085601f83011261439a57600080fd5b813560206143aa61400383614de0565b8083825282820191508286018a848660051b89010111156143ca57600080fd5b600096505b848710156143ed5780358352600196909601959183019183016143cf565b509650508601359250508082111561440457600080fd5b5061441185828601614033565b9150509250929050565b600061014080838503121561442f57600080fd5b83601f84011261443e57600080fd5b60405181810181811067ffffffffffffffff8211171561446057614460614fde565b604052808483810187101561447457600080fd5b600093505b600a8410156144a05761448b816141c5565b82526001939093019260209182019101614479565b509095945050505050565b600080604083850312156144be57600080fd5b823567ffffffffffffffff8111156144d557600080fd5b6144e18582860161413e565b925050602083013580151581146144f757600080fd5b809150509250929050565b6000806040838503121561451557600080fd5b50508035926020909101359150565b6000806040838503121561453757600080fd5b823567ffffffffffffffff81111561454e57600080fd5b8301601f8101851361455f57600080fd5b61456e85823560208401613ff5565b95602094909401359450505050565b60006020828403121561458f57600080fd5b815167ffffffffffffffff8111156145a657600080fd5b8201601f810184136145b757600080fd5b80516145c561400382614e04565b8181528560208385010111156145da57600080fd5b610910826020830160208601614ed0565b6000602082840312156145fd57600080fd5b5035919050565b60008060006060848603121561461957600080fd5b505081359360208301359350604090920135919050565b60006020828403121561464257600080fd5b61113c826141c5565b60008060006060848603121561466057600080fd5b614669846141c5565b9250602084013567ffffffffffffffff8082111561468657600080fd5b61469287838801614033565b935060408601359150808211156146a857600080fd5b506146b58682870161413e565b9150509250925092565b600080604083850312156146d257600080fd5b6146db836141c5565b91506146e9602084016141c5565b90509250929050565b60008060006060848603121561470757600080fd5b614710846141c5565b9250602061471f8186016141c5565b925060408086013567ffffffffffffffff81111561473c57600080fd5b8601601f8101881361474d57600080fd5b803561475b61400382614de0565b8082825285820191508584018b878560061b870101111561477b57600080fd5b60009450845b848110156147cb5786828e031215614797578586fd5b61479f614d8c565b6147a8836141c5565b81526147b58984016141c5565b818a015284529287019290860190600101614781565b50508096505050505050509250925092565b600081518084526147f5816020860160208601614ed0565b601f01601f19169290920160200192915050565b8054600090600181811c908083168061482357607f831692505b602080841082141561484557634e487b7160e01b600052602260045260246000fd5b818015614859576001811461486a57614897565b60ff19861689528489019650614897565b60008881526020902060005b8681101561488f5781548b820152908501908301614876565b505084890196505b50505050505092915050565b600083516148b5818460208801614ed0565b8351908301906148c9818360208801614ed0565b01949350505050565b600084516148e4818460208901614ed0565b6148f081840186614809565b90507f222c2276616c7565223a220000000000000000000000000000000000000000008152835161492881600b840160208801614ed0565b7f227d000000000000000000000000000000000000000000000000000000000000600b9290910191820152600d0195945050505050565b600061496b8288614809565b865161497b818360208b01614ed0565b865191019061498e818360208a01614ed0565b85519101906149a1818360208901614ed0565b84519101906149b4818360208801614ed0565b7f3c2f7376673e00000000000000000000000000000000000000000000000000009101908152600601979650505050505050565b60006149f48285614809565b8351614a04818360208801614ed0565b7f3c2f7376673e00000000000000000000000000000000000000000000000000009101908152600601949350505050565b7f5b7b2274726169745f74797065223a22436f736d6963204265696e67222c227681527f616c7565223a220000000000000000000000000000000000000000000000000060208201526000614a8d6027830184614809565b7f227d2c7b2274726169745f74797065223a224c69666520466f726d222c22766181527f6c7565223a2254726970706564227d5d0000000000000000000000000000000060208201526030019392505050565b7f7b226e616d65223a202200000000000000000000000000000000000000000000815260008551614b1881600a850160208a01614ed0565b7f222c20226465736372697074696f6e223a202200000000000000000000000000600a918401918201528551614b5581601d840160208a01614ed0565b7f222c202261747472696275746573223a00000000000000000000000000000000601d92909101918201528451614b9381602d840160208901614ed0565b7f2c22696d616765223a2022000000000000000000000000000000000000000000602d92909101918201527f646174613a696d6167652f7376672b786d6c3b6261736536342c00000000000060388201528351614bf7816052840160208801614ed0565b7f227d000000000000000000000000000000000000000000000000000000000000605292909101918201526054019695505050505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c000000815260008251614c6781601d850160208701614ed0565b91909101601d0192915050565b7f4574686572546572726573747269616c20230000000000000000000000000000815260008251614cac816012850160208701614ed0565b9190910160120192915050565b6001600160a01b03841681526bffffffffffffffffffffffff8316602082015260606040820152600061091060608301846147dd565b6101408101818360005b600a811015614d1b57815160ff16835260209283019290910190600101614cf9565b50505092915050565b6102808101818360005b6014811015614d1b57815160ff16835260209283019290910190600101614d2e565b60208152600061113c60208301846147dd565b6040516060810167ffffffffffffffff81118282101715614d8657614d86614fde565b60405290565b6040805190810167ffffffffffffffff81118282101715614d8657614d86614fde565b604051601f8201601f1916810167ffffffffffffffff81118282101715614dd857614dd8614fde565b604052919050565b600067ffffffffffffffff821115614dfa57614dfa614fde565b5060051b60200190565b600067ffffffffffffffff821115614e1e57614e1e614fde565b50601f01601f191660200190565b600061ffff8083168185168083038211156148c9576148c9614f86565b60008219821115614e5c57614e5c614f86565b500190565b600060ff821660ff84168060ff03821115614e7e57614e7e614f86565b019392505050565b600082614e9557614e95614f9c565b500490565b6000816000190483118215151615614eb457614eb4614f86565b500290565b600082821015614ecb57614ecb614f86565b500390565b60005b83811015614eeb578181015183820152602001614ed3565b838111156115755750506000910152565b600181811c90821680614f1057607f821691505b60208210811415614f3157634e487b7160e01b600052602260045260246000fd5b50919050565b6000600019821415614f4b57614f4b614f86565b5060010190565b600060ff821660ff811415614f6957614f69614f86565b60010192915050565b600082614f8157614f81614f9c565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fdfe2c7b2274726169745f74797065223a224c69666520466f726d222c2276616c7565223a2254726970706564227d5d3c646566733e3c636c6970506174682069643d22636c69705061746833223e3c636972636c652063783d22353530222063793d223535302220723d2235303022202f3e3c2f636c6970506174683e3c2f646566733e3c67207374796c653d22636c69702d706174683a2075726c2823636c69705061746833293b223e3c7265637420783d22302220793d2230222077696474683d223330303022206865696768743d223330303022207374796c653d227374726f6b653a206e6f6e653b2066696c6c3a6e6f6e653b20636c69702d706174683a2075726c2823636c69705061746833293b22202f3e3c6720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207472616e73666f726d3d227363616c6528312e35312c3129207472616e736c617465282d31373829223e4574686572546572726573747269616c732061726520696e7465722d64696d656e73696f6e616c2045787472612d546572726573747269616c732077686f2063616d6520746f204561727468277320696e7465726e657420746f20696e6675736520636f6e7363696f75736e65737320696e746f20616c6c206f7468657220706978656c61746564204c696665666f726d732e20546865792063616e20626520656e636f756e746572656420696e2074686520666f726d206f66206f6e2d636861696e206368617261637465727320617320696e74657270726574656420627920746865206578697374656e7469616c206578706c6f726572204b79652e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f556e72657665616c6564204574686572546572726573747269616c202d205265667265736820536f6f6ea2646970667358221220e40062abf4c2f2d880455663de53ed342a1324b6682dd38c7b7bd66b83a52dd464736f6c634300080700333c7376672076657273696f6e3d22312e31222069643d224c617965725f312220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220783d22302220793d2230222076696577426f783d223020302031313030203131303022207374796c653d22656e61626c652d6261636b67726f756e643a6e657720302030203131303020313130302220786d6c3a73706163653d2270726573657276652220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101985760003560e01c8063891d03a5116100e3578063b7b215821161008c578063c7d4abea11610066578063c7d4abea14610390578063ce530a9a146103a3578063e4183897146103c057600080fd5b8063b7b215821461034a578063bcdfb0b91461036a578063c023c0eb1461037d57600080fd5b80639ddbb3cf116100bd5780639ddbb3cf14610311578063aa7ee7f814610324578063b116347b1461033757600080fd5b8063891d03a5146102d8578063955bfb53146102eb5780639ad9a4cb146102fe57600080fd5b80635347bcbc1161014557806363c113cf1161011f57806363c113cf146102aa57806368bd580e146102bd578063791a1631146102c557600080fd5b80635347bcbc1461024c5780635623bf8b1461025f5780635af325bc1461027f57600080fd5b80631ed8ef10116101765780631ed8ef10146101f757806331862ada1461021757806338c7bcf11461022a57600080fd5b80631771d1001461019d5780631e36d5b4146101b25780631e38323d146101e4575b600080fd5b6101b06101ab3660046144ab565b6103d3565b005b6101c56101c0366004614502565b6104ad565b6040805160ff9384168152929091166020830152015b60405180910390f35b6101b06101f23660046146f2565b6104e8565b61020a61020536600461441b565b610652565b6040516101db9190614d50565b61020a610225366004614524565b610902565b61023d6102383660046146bf565b610919565b6040516101db93929190614cb9565b61023d61025a3660046145eb565b6109ea565b61027261026d36600461441b565b610a2d565b6040516101db9190614cef565b600954610292906001600160a01b031681565b6040516001600160a01b0390911681526020016101db565b6102726102b83660046145eb565b610cfb565b6101b0610dd5565b61020a6102d336600461441b565b610e4d565b61020a6102e6366004614604565b610fd9565b6101b06102f93660046146f2565b611143565b61020a61030c3660046145eb565b6112a6565b6101c561031f366004614502565b6112e4565b6101b061033236600461435b565b611300565b6101b061034536600461464b565b611429565b61035d61035836600461441b565b61157b565b6040516101db9190614d24565b61020a6103783660046146bf565b611850565b61020a61038b3660046145eb565b6118c3565b61020a61039e366004614630565b611a6e565b6006546103b09060ff1681565b60405190151581526020016101db565b6101b06103ce3660046141db565b611b0c565b60065460ff161580156103f057506008546001600160a01b031633145b6104415760405162461bcd60e51b815260206004820152601860248201527f4e6f7420617574686f72697a6564206f72206c6f636b6564000000000000000060448201526064015b60405180910390fd5b60005b82518160ff1610156104a8578160016000858460ff168151811061046a5761046a614fc8565b60209081029190910181015160ff168252810191909152604001600020805460ff1916911515919091179055806104a081614f52565b915050610444565b505050565b600360205281600052604060002081815481106104c957600080fd5b60009182526020909120015460ff808216935061010090910416905082565b60065460ff1615801561050557506008546001600160a01b031633145b6105515760405162461bcd60e51b815260206004820152601860248201527f4e6f7420617574686f72697a6564206f72206c6f636b656400000000000000006044820152606401610438565b6040517fff0000000000000000000000000000000000000000000000000000000000000060f885811b8216602084015284901b16602182015260009060220160408051601f198184030181529181528151602092830120600081815260039093529082209092506105c191613dfc565b60005b82518160ff16101561064b5760008281526003602052604090208351849060ff84169081106105f5576105f5614fc8565b6020908102919091018101518254600181018455600093845292829020815193018054919092015160ff9081166101000261ffff199092169316929092179190911790558061064381614f52565b9150506105c4565b5050505050565b60408051600b808252610180820190925260609160009190816020015b606081526020019060019003908161066f57905050905060005b600a8160ff1610156108645760ff80821660009081526001602052604090205416610852576000848260ff16600a81106106c5576106c5614fc8565b6020908102919091015160ff808516600090815260048452604080822092841682529190935282206001018054919350906106ff90614efc565b80601f016020809104026020016040519081016040528092919081815260200182805461072b90614efc565b80156107785780601f1061074d57610100808354040283529160200191610778565b820191906000526020600020905b81548152906001019060200180831161075b57829003601f168201915b505050505090508260ff166000146107c5576040518060400160405280601081526020017f2c7b2274726169745f74797065223a22000000000000000000000000000000008152506107fc565b6040518060400160405280601081526020017f5b7b2274726169745f74797065223a22000000000000000000000000000000008152505b60ff84166000908152602081815260409182902091516108209392918591016148d2565b604051602081830303815290604052848460ff168151811061084457610844614fc8565b602002602001018190525050505b8061085c81614f52565b915050610689565b506040518060600160405280602e8152602001614ff5602e913981600a8151811061089157610891614fc8565b6020026020010181905250606060005b600b8110156108fa57818382815181106108bd576108bd614fc8565b60200260200101516040516020016108d69291906148a3565b604051602081830303815290604052915080806108f290614f37565b9150506108a1565b509392505050565b606060006109108484611bfe565b95945050505050565b6004602090815260009283526040808420909152908252902080546001820180546001600160a01b03831693600160a01b9093046bffffffffffffffffffffffff1692919061096790614efc565b80601f016020809104026020016040519081016040528092919081815260200182805461099390614efc565b80156109e05780601f106109b5576101008083540402835291602001916109e0565b820191906000526020600020905b8154815290600101906020018083116109c357829003601f168201915b5050505050905083565b600560205260009081526040902080546001820180546001600160a01b03831693600160a01b9093046bffffffffffffffffffffffff1692919061096790614efc565b610a35613e1d565b60005b600a8160ff161015610c195760006002600083868560ff16600a8110610a6057610a60614fc8565b6020020151604051602001610aac92919060f892831b7fff0000000000000000000000000000000000000000000000000000000000000090811682529190921b16600182015260020190565b604051602081830303815290604052805190602001208152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b82821015610b31576000848152602090819020604080518082019091529084015460ff80821683526101009091041681830152825260019092019101610af0565b50505050905060005b81518160ff161015610c0457818160ff1681518110610b5b57610b5b614fc8565b60200260200101516020015160ff1685838360ff1681518110610b8057610b80614fc8565b60200260200101516000015160ff16600a8110610b9f57610b9f614fc8565b602002015160ff161415610bf257600085838360ff1681518110610bc557610bc5614fc8565b60200260200101516000015160ff16600a8110610be457610be4614fc8565b60ff90921660209290920201525b80610bfc81614f52565b915050610b3a565b50508080610c1190614f52565b915050610a38565b5060c082015160ff1660061415610c425760008260075b60ff9092166020929092020152610cb2565b816008602002015160ff1660011415610c5f576000826007610c30565b816008602002015160ff1660071415610c7c576000826007610c30565b61010082015160ff1660081415610c97576000826007610c30565b816008602002015160ff1660091415610cb257600060e08301525b816008602002015160ff1660031480610cd55750816008602002015160ff166004145b80610cea5750816008602002015160ff166006145b15610cf757600160208301525b5090565b610d03613e1d565b610d0b613e1d565b60005b600a8160ff161015610db6576103e88482604051602001610d5e92919091825260f81b7fff0000000000000000000000000000000000000000000000000000000000000016602082015260210190565b6040516020818303038152906040528051906020012060001c610d819190614f72565b828260ff16600a8110610d9657610d96614fc8565b61ffff909216602092909202015280610dae81614f52565b915050610d0e565b506000610dc282611eb2565b9050610dcd81610a2d565b949350505050565b60065460ff16158015610df257506008546001600160a01b031633145b610e3e5760405162461bcd60e51b815260206004820152601860248201527f4e6f7420617574686f72697a6564206f72206c6f636b656400000000000000006044820152606401610438565b6006805460ff19166001179055565b6060610e57613e3c565b6000610e628461157b565b905060005b60148160ff161015610f49576000828260ff1660148110610e8a57610e8a614fc8565b6020020151905060ff80821614610f36576000868260ff16600a8110610eb257610eb2614fc8565b6020908102919091015160ff8481166000908152600484526040808220928416825291909352822054909250600160a01b90046bffffffffffffffffffffffff16610f0c5760405180602001604052806000815250610f16565b610f168383611850565b905080868560ff1660148110610f2e57610f2e614fc8565b602002015250505b5080610f4181614f52565b915050610e67565b50606060005b60148160ff161015610fab5781848260ff1660148110610f7157610f71614fc8565b6020020151604051602001610f879291906148a3565b60405160208183030381529060405291508080610fa390614f52565b915050610f4f565b50600781604051602001610fc09291906149e8565b6040516020818303038152906040529350505050919050565b60606000610fe685612015565b604051602001610ff69190614c74565b60408051601f19818403018152610120830190915260fe8083529092506000919061515b60208301399050606080856001141561104857611036886118c3565b9050611041886112a6565b91506110d6565b866110b15761105760456118c3565b90506040518060600160405280602a8152602001615299602a913992506040518060400160405280600281526020017f5b5d00000000000000000000000000000000000000000000000000000000000081525091506110d6565b60006110bc88610cfb565b90506110c781610e4d565b91506110d281610652565b9250505b600061110e8585856110e786612147565b6040516020016110fa9493929190614ae0565b604051602081830303815290604052612147565b90506000816040516020016111239190614c2f565b60408051601f1981840301815291905296505050505050505b9392505050565b60065460ff1615801561116057506008546001600160a01b031633145b6111ac5760405162461bcd60e51b815260206004820152601860248201527f4e6f7420617574686f72697a6564206f72206c6f636b656400000000000000006044820152606401610438565b6040517fff0000000000000000000000000000000000000000000000000000000000000060f885811b8216602084015284901b16602182015260009060220160408051601f1981840301815291815281516020928301206000818152600290935290822090925061121c91613dfc565b60005b82518160ff16101561064b5760008281526002602052604090208351849060ff841690811061125057611250614fc8565b6020908102919091018101518254600181018455600093845292829020815193018054919092015160ff9081166101000261ffff199092169316929092179190911790558061129e81614f52565b91505061121f565b6060600560008381526020019081526020016000206001016040516020016112ce9190614a35565b6040516020818303038152906040529050919050565b600260205281600052604060002081815481106104c957600080fd5b60065460ff1615801561131d57506008546001600160a01b031633145b6113695760405162461bcd60e51b815260206004820152601860248201527f4e6f7420617574686f72697a6564206f72206c6f636b656400000000000000006044820152606401610438565b805182511461137757600080fd5b60005b81518110156104a85781818151811061139557611395614fc8565b6020026020010151600560008584815181106113b3576113b3614fc8565b60209081029190910181015182528181019290925260409081016000208351848401516bffffffffffffffffffffffff16600160a01b026001600160a01b03909116178155908301518051919261141292600185019290910190613e64565b50905050808061142190614f37565b91505061137a565b60065460ff1615801561144657506008546001600160a01b031633145b6114925760405162461bcd60e51b815260206004820152601860248201527f4e6f7420617574686f72697a6564206f72206c6f636b656400000000000000006044820152606401610438565b80518251146114a057600080fd5b60005b82518160ff16101561157557828160ff16815181106114c4576114c4614fc8565b6020026020010151600460008660ff1660ff1681526020019081526020016000206000848460ff16815181106114fc576114fc614fc8565b60209081029190910181015160ff1682528181019290925260409081016000208351848401516bffffffffffffffffffffffff16600160a01b026001600160a01b03909116178155908301518051919261155e92600185019290910190613e64565b50905050808061156d90614f52565b9150506114a3565b50505050565b611583613ee4565b61158b613ee4565b60005b60148160ff16101561160557600a8160ff1610156115ce5780828260ff16601481106115bc576115bc614fc8565b60ff90921660209290920201526115f3565b60ff828260ff16601481106115e5576115e5614fc8565b60ff90921660209290920201525b806115fd81614f52565b91505061158e565b506101008301516040517f0800000000000000000000000000000000000000000000000000000000000000602082015260f89190911b7fff000000000000000000000000000000000000000000000000000000000000001660218201526000906003908290602201604051602081830303815290604052805190602001208152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b828210156116f2576000848152602090819020604080518082019091529084015460ff808216835261010090910416818301528252600190920191016116b1565b50505050905060005b81518160ff16101561183857818160ff168151811061171c5761171c614fc8565b60200260200101516020015160ff1685838360ff168151811061174157611741614fc8565b60200260200101516000015160ff16600a811061176057611760614fc8565b602002015160ff16141561182657818160ff168151811061178357611783614fc8565b60200260200101516000015183838360ff16815181106117a5576117a5614fc8565b602002602001015160000151600a6117bd9190614e61565b60ff16601481106117d0576117d0614fc8565b602002019060ff16908160ff168152505060ff83838360ff16815181106117f9576117f9614fc8565b60200260200101516000015160ff166014811061181857611818614fc8565b60ff90921660209290920201525b8061183081614f52565b9150506116fb565b5050600961026082015260ff61012082015292915050565b60ff80831660009081526004602090815260408083209385168352929052205460609061113c90611889906001600160a01b0316612304565b60ff858116600090815260046020908152604080832093881683529290522054600160a01b90046bffffffffffffffffffffffff16610902565b60606007826068146118e45760405180602001604052806000815250611901565b604051806101600160405280610138815260200161502361013891395b8360681461191e57604051806020016040528060008152506119b8565b6009546040517f9bac5f7a000000000000000000000000000000000000000000000000000000008152610e3860048201526001600160a01b0390911690639bac5f7a9060240160006040518083038186803b15801561197c57600080fd5b505afa158015611990573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526119b8919081019061457d565b846068146119d55760405180602001604052806000815250611a0c565b6040518060400160405280600881526020017f3c2f673e3c2f673e0000000000000000000000000000000000000000000000008152505b600086815260056020526040902054611a5a90611a31906001600160a01b0316612304565b600088815260056020526040902054600160a01b90046bffffffffffffffffffffffff16610902565b6040516020016112ce95949392919061495f565b600060208190529081526040902080548190611a8990614efc565b80601f0160208091040260200160405190810160405280929190818152602001828054611ab590614efc565b8015611b025780601f10611ad757610100808354040283529160200191611b02565b820191906000526020600020905b815481529060010190602001808311611ae557829003601f168201915b5050505050905081565b60065460ff16158015611b2957506008546001600160a01b031633145b611b755760405162461bcd60e51b815260206004820152601860248201527f4e6f7420617574686f72697a6564206f72206c6f636b656400000000000000006044820152606401610438565b60005b600a8160ff161015611bfa57818160ff1681518110611b9957611b99614fc8565b60209081029190910181015160ff83166000908152808352604090208151805192939192611bca9284920190613e64565b506020828101518051611be39260018501920190613f03565b509050508080611bf290614f52565b915050611b78565b5050565b6000606060006040518061010001604052808567ffffffffffffffff811115611c2957611c29614fde565b6040519080825280601f01601f191660200182016040528015611c53576020820181803683370190505b508152602001600081526020018681526020016000815260200160008152602001600081526020016040518060400160405280600f6001611c949190614e49565b67ffffffffffffffff811115611cac57611cac614fde565b604051908082528060200260200182016040528015611cd5578160200160208202803683370190505b5081526040805161012080825261242082019092526020928301929091908201612400803683370190505081525081526020016040518060400160405280600f6001611d219190614e49565b67ffffffffffffffff811115611d3957611d39614fde565b604051908082528060200260200182016040528015611d62578160200160208202803683370190505b50815260408051601e8082526103e0820190925260209283019290919082016103c08036833750505090529052905060008080611d9e8461231a565b9050600081600e811115611db457611db4614fb2565b14611dc9579251929450919250611eab915050565b82611ea057611dd98460016124a4565b93509050600081600e811115611df157611df1614fb2565b14611e06579251929450919250611eab915050565b611e118460026124a4565b92509050600081600e811115611e2957611e29614fb2565b14611e3e579251929450919250611eab915050565b8115611e725781600114611e695781600214611e5b576003611e7b565b611e6484612575565b611e7b565b611e64846125e6565b611e7b846125fb565b9050600081600e811115611e9157611e91614fb2565b14611e9b57611ea0565b611dc9565b925192945091925050505b9250929050565b611eba613e1d565b611ec2613e1d565b60005b600a8160ff16101561200e5760ff811660009081526020818152604080832060010180548251818502810185019093528083529192909190830182828015611f5457602002820191906000526020600020906000905b82829054906101000a900461ffff1661ffff1681526020019060020190602082600101049283019260010382029150808411611f1b5790505b505050505090506000805b82518160ff161015611ff857828160ff1681518110611f8057611f80614fc8565b602002602001015182611f939190614e2c565b91508161ffff16878560ff16600a8110611faf57611faf614fc8565b602002015161ffff161015611fe65780858560ff16600a8110611fd457611fd4614fc8565b60ff9092166020929092020152611ff8565b80611ff081614f52565b915050611f5f565b505050808061200690614f52565b915050611ec5565b5092915050565b60608161205557505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b811561207f578061206981614f37565b91506120789050600a83614e86565b9150612059565b60008167ffffffffffffffff81111561209a5761209a614fde565b6040519080825280601f01601f1916602001820160405280156120c4576020820181803683370190505b5090505b8415610dcd576120d9600183614eb9565b91506120e6600a86614f72565b6120f1906030614e49565b60f81b81838151811061210657612106614fc8565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350612140600a86614e86565b94506120c8565b606081516000141561216757505060408051602081019091526000815290565b600060405180606001604052806040815260200161525960409139905060006003845160026121969190614e49565b6121a09190614e86565b6121ab906004614e9a565b905060006121ba826020614e49565b67ffffffffffffffff8111156121d2576121d2614fde565b6040519080825280601f01601f1916602001820160405280156121fc576020820181803683370190505b509050818152600183018586518101602084015b8183101561226a5760039283018051603f601282901c811687015160f890811b8552600c83901c8216880151811b6001860152600683901c8216880151811b60028601529116860151901b93820193909352600401612210565b60038951066001811461228457600281146122ce576122f6565b7f3d3d0000000000000000000000000000000000000000000000000000000000007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe8301526122f6565b7f3d000000000000000000000000000000000000000000000000000000000000006000198301525b509398975050505050505050565b6060612314826001600019612823565b92915050565b604080516101208082526124208201909252600091829182916020820161240080368337019050509050600091505b609082101561238357600881838151811061236657612366614fc8565b60209081029190910101528161237b81614f37565b925050612349565b6101008210156123be5760098183815181106123a1576123a1614fc8565b6020908102919091010152816123b681614f37565b925050612383565b6101188210156123f95760078183815181106123dc576123dc614fc8565b6020908102919091010152816123f181614f37565b9250506123be565b61012082101561243457600881838151811061241757612417614fc8565b60209081029190910101528161242c81614f37565b9250506123f9565b6124478460c001518261012060006128ed565b50600091505b601e82101561248757600581838151811061246a5761246a614fc8565b60209081029190910101528161247f81614f37565b92505061244d565b6124998460e0015182601e60006128ed565b506000949350505050565b608082015160009081905b838560a00151101561253857846040015151856060015114156124da57600160009250925050611eab565b60a08501516040860151606087018051906124f482614f37565b90528151811061250657612506614fc8565b602001015160f81c60f81b60f81c60ff16901b8117905060088560a0018181516125309190614e49565b9052506124af565b80841c608086015260a085018051859190612554908390614eb9565b9052506000612566600180871b614eb9565b60009792169550909350505050565b6000612594604051806040016040528060608152602001606081525090565b604080518082019091526060808252602082015260006125b385612bb6565b90945092509050600081600e8111156125ce576125ce614fb2565b146125db57949350505050565b61091085848461326f565b6000612314828360c001518460e0015161326f565b60006080820181905260a082018190526040820151516060830151829190612624906004614e49565b11156126335750600192915050565b60408301516060840180519061264882614f37565b90528151811061265a5761265a614fc8565b0160200151604084015160608501805160f89390931c93506008929061267f82614f37565b90528151811061269157612691614fc8565b602001015160f81c60f81b60f81c60ff16901b81179050801960ff1683604001518460600180518091906126c490614f37565b9052815181106126d6576126d6614fc8565b016020015160f81c1415806127215750604083015160608401805160ff841960081c16929161270482614f37565b90528151811061271657612716614fc8565b016020015160f81c14155b1561272f5750600492915050565b8260400151518184606001516127459190614e49565b11156127545750600192915050565b8251516020840151612767908390614e49565b11156127765750600292915050565b801561281a57612787600182614eb9565b905082604001518360600180518091906127a090614f37565b9052815181106127b2576127b2614fc8565b602001015160f81c60f81b83600001518460200180518091906127d490614f37565b9052815181106127e6576127e6614fc8565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350612776565b50600092915050565b6060833b8061284257505060408051602081019091526000815261113c565b8084111561286057505060408051602081019091526000815261113c565b838310156128ab576040517f2c4a89fa000000000000000000000000000000000000000000000000000000008152600481018290526024810185905260448101849052606401610438565b83830384820360008282106128c057826128c2565b815b60408051603f8301601f19168101909152818152955090508087602087018a3c505050509392505050565b6000806000806128fb613fa7565b600092505b600f831161293d5760008960000151848151811061292057612920614fc8565b60209081029190910101528261293581614f37565b935050612900565b600093505b868410156129a9578851886129578689614e49565b8151811061296757612967614fc8565b60200260200101518151811061297f5761297f614fc8565b60200260200101805180919061299490614f37565b905250836129a181614f37565b945050612942565b8689600001516000815181106129c1576129c1614fc8565b602002602001015114156129dc576000945050505050610dcd565b60019150600192505b600f8311612a5f578851805160019390931b9284908110612a0857612a08614fc8565b6020026020010151821015612a2457600e945050505050610dcd565b8851805184908110612a3857612a38614fc8565b602002602001015182612a4b9190614eb9565b915082612a5781614f37565b9350506129e5565b60006020820152600192505b600f831015612ae4578851805184908110612a8857612a88614fc8565b6020026020010151818460108110612aa257612aa2614fc8565b6020020151612ab19190614e49565b81612abd856001614e49565b60108110612acd57612acd614fc8565b602002015282612adc81614f37565b935050612a6b565b600093505b86841015612b975787612afc8588614e49565b81518110612b0c57612b0c614fc8565b6020026020010151600014612b855760208901518490828a612b2e848b614e49565b81518110612b3e57612b3e614fc8565b602002602001015160108110612b5657612b56614fc8565b60200201805190612b6682614f37565b905281518110612b7857612b78614fc8565b6020026020010181815250505b83612b8f81614f37565b945050612ae9565b60008211612ba6576000612ba9565b600e5b9998505050505050505050565b6000612bd5604051806040016040528060608152602001606081525090565b6040805180820190915260608082526020820152600080808080612bfc601e61011e614e49565b67ffffffffffffffff811115612c1457612c14614fde565b604051908082528060200260200182016040528015612c3d578160200160208202803683370190505b50905060006040518060400160405280600f6001612c5b9190614e49565b67ffffffffffffffff811115612c7357612c73614fde565b604051908082528060200260200182016040528015612c9c578160200160208202803683370190505b5081526040805161011e8082526123e0820190925260209283019290919082016123c08036833701905050815250905060006040518060400160405280600f6001612ce79190614e49565b67ffffffffffffffff811115612cff57612cff614fde565b604051908082528060200260200182016040528015612d28578160200160208202803683370190505b50815260408051601e8082526103e0820190925260209283019290919082016103c080368337505050905290506000612d628c60056124a4565b98509450600085600e811115612d7a57612d7a614fb2565b14612d92575092985096509094506132689350505050565b612d9e61010189614e49565b9750612dab8c60056124a4565b97509450600085600e811115612dc357612dc3614fb2565b14612ddb575092985096509094506132689350505050565b612de6600188614e49565b965061011e881180612df85750601e87115b15612e125750600599509097509550613268945050505050565b612e1b8c613aca565b9095509350600085600e811115612e3457612e34614fb2565b14612e4c575092985096509094506132689350505050565b612e5a8385601360006128ed565b9450600085600e811115612e7057612e70614fb2565b14612e8a5750600699509097509550613268945050505050565b600095505b612e998789614e49565b86101561309257600080612ead8e86613ced565b9097509150600087600e811115612ec657612ec6614fb2565b14612ee05750949a50919850965061326895505050505050565b6010821015612f1857818689612ef581614f37565b9a5081518110612f0757612f07614fc8565b60200260200101818152505061308b565b5060006010821415612fb75787612f41575060079b509299509097506132689650505050505050565b85612f4d60018a614eb9565b81518110612f5d57612f5d614fc8565b60200260200101519050612f728e60026124a4565b9097509250600087600e811115612f8b57612f8b614fb2565b14612fa55750949a50919850965061326895505050505050565b612fb0836003614e49565b9150613017565b8160111415612fcb57612f728e60036124a4565b612fd68e60076124a4565b9097509250600087600e811115612fef57612fef614fb2565b146130095750949a50919850965061326895505050505050565b61301483600b614e49565b91505b613021898b614e49565b61302b838a614e49565b1115613049575060089b509299509097506132689650505050505050565b811561308b5761305a600183614eb9565b915080868961306881614f37565b9a508151811061307a5761307a614fc8565b602002602001018181525050613049565b5050612e8f565b83610100815181106130a6576130a6614fc8565b6020026020010151600014156130cb5750600b99509097509550613268945050505050565b6130d883858a60006128ed565b9450600085600e8111156130ee576130ee614fb2565b141580156131785750600185600e81111561310b5761310b614fb2565b14806131285750600285600e81111561312657613126614fb2565b145b80613178575082518051600190811061314357613143614fc8565b6020026020010151836000015160008151811061316257613162614fc8565b60200260200101516131749190614e49565b8814155b156131925750600999509097509550613268945050505050565b61319e8285898b6128ed565b9450600085600e8111156131b4576131b4614fb2565b1415801561323e5750600185600e8111156131d1576131d1614fb2565b14806131ee5750600285600e8111156131ec576131ec614fb2565b145b8061323e575081518051600190811061320957613209614fc8565b6020026020010151826000015160008151811061322857613228614fc8565b602002602001015161323a9190614e49565b8714155b156132585750600a99509097509550613268945050505050565b5060009950909750955050505050505b9193909250565b6000806000806000604051806103a00160405280600361ffff168152602001600461ffff168152602001600561ffff168152602001600661ffff168152602001600761ffff168152602001600861ffff168152602001600961ffff168152602001600a61ffff168152602001600b61ffff168152602001600d61ffff168152602001600f61ffff168152602001601161ffff168152602001601361ffff168152602001601761ffff168152602001601b61ffff168152602001601f61ffff168152602001602361ffff168152602001602b61ffff168152602001603361ffff168152602001603b61ffff168152602001604361ffff168152602001605361ffff168152602001606361ffff168152602001607361ffff168152602001608361ffff16815260200160a361ffff16815260200160c361ffff16815260200160e361ffff16815260200161010261ffff1681525090506000604051806103a00160405280600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600160ff168152602001600160ff168152602001600160ff168152602001600160ff168152602001600260ff168152602001600260ff168152602001600260ff168152602001600260ff168152602001600360ff168152602001600360ff168152602001600360ff168152602001600360ff168152602001600460ff168152602001600460ff168152602001600460ff168152602001600460ff168152602001600560ff168152602001600560ff168152602001600560ff168152602001600560ff168152602001600060ff1681525090506000604051806103c00160405280600161ffff168152602001600261ffff168152602001600361ffff168152602001600461ffff168152602001600561ffff168152602001600761ffff168152602001600961ffff168152602001600d61ffff168152602001601161ffff168152602001601961ffff168152602001602161ffff168152602001603161ffff168152602001604161ffff168152602001606161ffff168152602001608161ffff16815260200160c161ffff16815260200161010161ffff16815260200161018161ffff16815260200161020161ffff16815260200161030161ffff16815260200161040161ffff16815260200161060161ffff16815260200161080161ffff168152602001610c0161ffff16815260200161100161ffff16815260200161180161ffff16815260200161200161ffff16815260200161300161ffff16815260200161400161ffff16815260200161600161ffff1681525090506000604051806103c00160405280600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600160ff168152602001600160ff168152602001600260ff168152602001600260ff168152602001600360ff168152602001600360ff168152602001600460ff168152602001600460ff168152602001600560ff168152602001600560ff168152602001600660ff168152602001600660ff168152602001600760ff168152602001600760ff168152602001600860ff168152602001600860ff168152602001600960ff168152602001600960ff168152602001600a60ff168152602001600a60ff168152602001600b60ff168152602001600b60ff168152602001600c60ff168152602001600c60ff168152602001600d60ff168152602001600d60ff16815250905060005b8761010014613ab8576137a98c8c613ced565b98509050600081600e8111156137c1576137c1614fb2565b146137d557975061113c9650505050505050565b610100881015613863578b515160208d015114156137fe5760029850505050505050505061113c565b8760f81b8c600001518d602001518151811061381c5761381c614fc8565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060208c0180519061385b82614f37565b905250613796565b610100881115613aa657600061387b6101018a614eb9565b9850601d891061389757600c995050505050505050505061113c565b6138ba8d868b601d81106138ad576138ad614fc8565b602002015160ff166124a4565b9092509050600082600e8111156138d3576138d3614fb2565b146138e85750975061113c9650505050505050565b80868a601d81106138fb576138fb614fc8565b602002015161ffff1661390e9190614e49565b975061391a8d8c613ced565b99509150600082600e81111561393257613932614fb2565b146139475750975061113c9650505050505050565b61395d8d848b601e81106138ad576138ad614fc8565b9092509050600082600e81111561397657613976614fb2565b1461398b5750975061113c9650505050505050565b80848a601e811061399e5761399e614fc8565b602002015161ffff166139b19190614e49565b96508c602001518711156139d157600d995050505050505050505061113c565b8c515160208e01516139e4908a90614e49565b11156139fc576002995050505050505050505061113c565b8715613aa057613a0d600189614eb9565b97508c60000151878e60200151613a249190614eb9565b81518110613a3457613a34614fc8565b602001015160f81c60f81b8d600001518e6020015181518110613a5957613a59614fc8565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060208d01805190613a9882614f37565b9052506139fc565b50613796565b868c60200181815161385b9190614e49565b5060009b9a5050505050505050505050565b60006060818080613ade601e61011e614e49565b67ffffffffffffffff811115613af657613af6614fde565b604051908082528060200260200182016040528015613b1f578160200160208202803683370190505b506040805161026081018252601081526011602082015260129181019190915260006060820181905260086080830152600760a0830152600960c0830152600660e0830152600a6101008301526005610120830152600b61014083015260046101608301819052600c61018084015260036101a0840152600d6101c084015260026101e0840152600e6102008401526001610220840152600f61024084015292935091613bcd9089906124a4565b95509150600082600e811115613be557613be5614fb2565b14613bf65750969095509350505050565b613c01600486614e49565b9450600093505b84841015613c8a57613c1b8860036124a4565b84838760138110613c2e57613c2e614fc8565b602002015160ff1681518110613c4657613c46614fc8565b60209081029190910101529150600082600e811115613c6757613c67614fb2565b14613c785750969095509350505050565b83613c8281614f37565b945050613c08565b6013841015613cdd57600083828660138110613ca857613ca8614fc8565b602002015160ff1681518110613cc057613cc0614fc8565b602090810291909101015283613cd581614f37565b945050613c8a565b5060009791965090945050505050565b600080600181808080805b600f8611613de9576000613d0d8b60016124a4565b9092509050600082600e811115613d2657613d26614fb2565b14613d3d5750965060009550611eab945050505050565b895180519682179688908110613d5557613d55614fc8565b602002602001015193508385613d6b9190614e49565b861015613db65760208a0151600090613d848789614eb9565b613d8e9086614e49565b81518110613d9e57613d9e614fc8565b60200260200101519850985050505050505050611eab565b613dc08484614e49565b9250613dcc8486614e49565b600196871b961b9450869050613de181614f37565b965050613cf8565b50600c9960009950975050505050505050565b5080546000825590600052602060002090810190613e1a9190613fc6565b50565b604051806101400160405280600a906020820280368337509192915050565b6040518061028001604052806014905b6060815260200190600190039081613e4c5790505090565b828054613e7090614efc565b90600052602060002090601f016020900481019282613e925760008555613ed8565b82601f10613eab57805160ff1916838001178555613ed8565b82800160010185558215613ed8579182015b82811115613ed8578251825591602001919060010190613ebd565b50610cf7929150613fe0565b6040518061028001604052806014906020820280368337509192915050565b82805482825590600052602060002090600f01601090048101928215613ed85791602002820160005b83821115613f6c57835183826101000a81548161ffff021916908361ffff1602179055509260200192600201602081600101049283019260010302613f2c565b8015613f9a5782816101000a81549061ffff0219169055600201602081600101049283019260010302613f6c565b5050610cf7929150613fe0565b6040518061020001604052806010906020820280368337509192915050565b5b80821115610cf757805461ffff19168155600101613fc7565b5b80821115610cf75760008155600101613fe1565b600061400861400384614e04565b614daf565b905082815283838301111561401c57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261404457600080fd5b8135602061405461400383614de0565b80838252828201915082860187848660051b890101111561407457600080fd5b60005b8581101561413157813567ffffffffffffffff8082111561409757600080fd5b818a019150606080601f19848e030112156140b157600080fd5b6140b9614d63565b888401356001600160a01b03811681146140d257600080fd5b81526040848101356bffffffffffffffffffffffff811681146140f457600080fd5b828b015291840135918383111561410a57600080fd5b6141188e8b858801016141a5565b9082015287525050509284019290840190600101614077565b5090979650505050505050565b600082601f83011261414f57600080fd5b8135602061415f61400383614de0565b80838252828201915082860187848660051b890101111561417f57600080fd5b60005b8581101561413157614193826141c5565b84529284019290840190600101614182565b600082601f8301126141b657600080fd5b61113c83833560208501613ff5565b803560ff811681146141d657600080fd5b919050565b600060208083850312156141ee57600080fd5b67ffffffffffffffff808435111561420557600080fd5b8335840185601f82011261421857600080fd5b6142256140038235614de0565b808235825284820191508483018886853560051b860101111561424757600080fd5b60005b843581101561434d57858235111561426157600080fd5b813585016040601f19828d0301121561427957600080fd5b614281614d8c565b8789830135111561429157600080fd5b6142a28c8a8b8501358501016141a5565b815287604083013511156142b557600080fd5b6040820135820191508b603f8301126142cd57600080fd5b888201356142dd61400382614de0565b808282528b82019150604085018f60408560051b88010111156142ff57600080fd5b600095505b8386101561433357803561ffff81161461431d57600080fd5b8035835260019590950194918c01918c01614304565b50838c01525050855250928601929086019060010161424a565b509098975050505050505050565b6000806040838503121561436e57600080fd5b823567ffffffffffffffff8082111561438657600080fd5b818501915085601f83011261439a57600080fd5b813560206143aa61400383614de0565b8083825282820191508286018a848660051b89010111156143ca57600080fd5b600096505b848710156143ed5780358352600196909601959183019183016143cf565b509650508601359250508082111561440457600080fd5b5061441185828601614033565b9150509250929050565b600061014080838503121561442f57600080fd5b83601f84011261443e57600080fd5b60405181810181811067ffffffffffffffff8211171561446057614460614fde565b604052808483810187101561447457600080fd5b600093505b600a8410156144a05761448b816141c5565b82526001939093019260209182019101614479565b509095945050505050565b600080604083850312156144be57600080fd5b823567ffffffffffffffff8111156144d557600080fd5b6144e18582860161413e565b925050602083013580151581146144f757600080fd5b809150509250929050565b6000806040838503121561451557600080fd5b50508035926020909101359150565b6000806040838503121561453757600080fd5b823567ffffffffffffffff81111561454e57600080fd5b8301601f8101851361455f57600080fd5b61456e85823560208401613ff5565b95602094909401359450505050565b60006020828403121561458f57600080fd5b815167ffffffffffffffff8111156145a657600080fd5b8201601f810184136145b757600080fd5b80516145c561400382614e04565b8181528560208385010111156145da57600080fd5b610910826020830160208601614ed0565b6000602082840312156145fd57600080fd5b5035919050565b60008060006060848603121561461957600080fd5b505081359360208301359350604090920135919050565b60006020828403121561464257600080fd5b61113c826141c5565b60008060006060848603121561466057600080fd5b614669846141c5565b9250602084013567ffffffffffffffff8082111561468657600080fd5b61469287838801614033565b935060408601359150808211156146a857600080fd5b506146b58682870161413e565b9150509250925092565b600080604083850312156146d257600080fd5b6146db836141c5565b91506146e9602084016141c5565b90509250929050565b60008060006060848603121561470757600080fd5b614710846141c5565b9250602061471f8186016141c5565b925060408086013567ffffffffffffffff81111561473c57600080fd5b8601601f8101881361474d57600080fd5b803561475b61400382614de0565b8082825285820191508584018b878560061b870101111561477b57600080fd5b60009450845b848110156147cb5786828e031215614797578586fd5b61479f614d8c565b6147a8836141c5565b81526147b58984016141c5565b818a015284529287019290860190600101614781565b50508096505050505050509250925092565b600081518084526147f5816020860160208601614ed0565b601f01601f19169290920160200192915050565b8054600090600181811c908083168061482357607f831692505b602080841082141561484557634e487b7160e01b600052602260045260246000fd5b818015614859576001811461486a57614897565b60ff19861689528489019650614897565b60008881526020902060005b8681101561488f5781548b820152908501908301614876565b505084890196505b50505050505092915050565b600083516148b5818460208801614ed0565b8351908301906148c9818360208801614ed0565b01949350505050565b600084516148e4818460208901614ed0565b6148f081840186614809565b90507f222c2276616c7565223a220000000000000000000000000000000000000000008152835161492881600b840160208801614ed0565b7f227d000000000000000000000000000000000000000000000000000000000000600b9290910191820152600d0195945050505050565b600061496b8288614809565b865161497b818360208b01614ed0565b865191019061498e818360208a01614ed0565b85519101906149a1818360208901614ed0565b84519101906149b4818360208801614ed0565b7f3c2f7376673e00000000000000000000000000000000000000000000000000009101908152600601979650505050505050565b60006149f48285614809565b8351614a04818360208801614ed0565b7f3c2f7376673e00000000000000000000000000000000000000000000000000009101908152600601949350505050565b7f5b7b2274726169745f74797065223a22436f736d6963204265696e67222c227681527f616c7565223a220000000000000000000000000000000000000000000000000060208201526000614a8d6027830184614809565b7f227d2c7b2274726169745f74797065223a224c69666520466f726d222c22766181527f6c7565223a2254726970706564227d5d0000000000000000000000000000000060208201526030019392505050565b7f7b226e616d65223a202200000000000000000000000000000000000000000000815260008551614b1881600a850160208a01614ed0565b7f222c20226465736372697074696f6e223a202200000000000000000000000000600a918401918201528551614b5581601d840160208a01614ed0565b7f222c202261747472696275746573223a00000000000000000000000000000000601d92909101918201528451614b9381602d840160208901614ed0565b7f2c22696d616765223a2022000000000000000000000000000000000000000000602d92909101918201527f646174613a696d6167652f7376672b786d6c3b6261736536342c00000000000060388201528351614bf7816052840160208801614ed0565b7f227d000000000000000000000000000000000000000000000000000000000000605292909101918201526054019695505050505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c000000815260008251614c6781601d850160208701614ed0565b91909101601d0192915050565b7f4574686572546572726573747269616c20230000000000000000000000000000815260008251614cac816012850160208701614ed0565b9190910160120192915050565b6001600160a01b03841681526bffffffffffffffffffffffff8316602082015260606040820152600061091060608301846147dd565b6101408101818360005b600a811015614d1b57815160ff16835260209283019290910190600101614cf9565b50505092915050565b6102808101818360005b6014811015614d1b57815160ff16835260209283019290910190600101614d2e565b60208152600061113c60208301846147dd565b6040516060810167ffffffffffffffff81118282101715614d8657614d86614fde565b60405290565b6040805190810167ffffffffffffffff81118282101715614d8657614d86614fde565b604051601f8201601f1916810167ffffffffffffffff81118282101715614dd857614dd8614fde565b604052919050565b600067ffffffffffffffff821115614dfa57614dfa614fde565b5060051b60200190565b600067ffffffffffffffff821115614e1e57614e1e614fde565b50601f01601f191660200190565b600061ffff8083168185168083038211156148c9576148c9614f86565b60008219821115614e5c57614e5c614f86565b500190565b600060ff821660ff84168060ff03821115614e7e57614e7e614f86565b019392505050565b600082614e9557614e95614f9c565b500490565b6000816000190483118215151615614eb457614eb4614f86565b500290565b600082821015614ecb57614ecb614f86565b500390565b60005b83811015614eeb578181015183820152602001614ed3565b838111156115755750506000910152565b600181811c90821680614f1057607f821691505b60208210811415614f3157634e487b7160e01b600052602260045260246000fd5b50919050565b6000600019821415614f4b57614f4b614f86565b5060010190565b600060ff821660ff811415614f6957614f69614f86565b60010192915050565b600082614f8157614f81614f9c565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fdfe2c7b2274726169745f74797065223a224c69666520466f726d222c2276616c7565223a2254726970706564227d5d3c646566733e3c636c6970506174682069643d22636c69705061746833223e3c636972636c652063783d22353530222063793d223535302220723d2235303022202f3e3c2f636c6970506174683e3c2f646566733e3c67207374796c653d22636c69702d706174683a2075726c2823636c69705061746833293b223e3c7265637420783d22302220793d2230222077696474683d223330303022206865696768743d223330303022207374796c653d227374726f6b653a206e6f6e653b2066696c6c3a6e6f6e653b20636c69702d706174683a2075726c2823636c69705061746833293b22202f3e3c6720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207472616e73666f726d3d227363616c6528312e35312c3129207472616e736c617465282d31373829223e4574686572546572726573747269616c732061726520696e7465722d64696d656e73696f6e616c2045787472612d546572726573747269616c732077686f2063616d6520746f204561727468277320696e7465726e657420746f20696e6675736520636f6e7363696f75736e65737320696e746f20616c6c206f7468657220706978656c61746564204c696665666f726d732e20546865792063616e20626520656e636f756e746572656420696e2074686520666f726d206f66206f6e2d636861696e206368617261637465727320617320696e74657270726574656420627920746865206578697374656e7469616c206578706c6f726572204b79652e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f556e72657665616c6564204574686572546572726573747269616c202d205265667265736820536f6f6ea2646970667358221220e40062abf4c2f2d880455663de53ed342a1324b6682dd38c7b7bd66b83a52dd464736f6c63430008070033

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  ]

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.