ETH Price: $3,102.48 (+1.14%)
Gas: 13 Gwei

AlphaDogs (AD)
 

Overview

TokenID

1132514408859392

Total Transfers

-

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-
Loading...
Loading
Loading...
Loading
Loading...
Loading

OVERVIEW

CC0 Genesis Collection with Staking, Tokens and Genetic Breeding. (591 staked as of June 30)

# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
AlphaDogs

Compiler Version
v0.8.14+commit.80d49f37

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 15 : AlphaDogs.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.14;

import {Ownable} from "@openzeppelin/access/Ownable.sol";
import {Strings} from "@openzeppelin/utils/Strings.sol";
import {MerkleProof} from "@openzeppelin/utils/cryptography/MerkleProof.sol";
import {ReentrancyGuard} from "@solmate/utils/ReentrancyGuard.sol";

import {IAlphaToken} from "$/interfaces/IAlphaToken.sol";
import {IAlphaDogs} from "$/interfaces/IAlphaDogs.sol";
import {IAlphaDogsAttributes} from "$/interfaces/IAlphaDogsAttributes.sol";

import {Genetics} from "$/libraries/Genetics.sol";
import {Gene} from "$/libraries/Gene.sol";
import {ERC721} from "$/ERC721.sol";

/// @title  AlphaDogs
/// @author Aleph Retamal <github.com/alephao>, Gustavo Tiago <github.com/gutiago>
contract AlphaDogs is IAlphaDogs, ERC721, Ownable, ReentrancyGuard {
    using Gene for uint256;
    using Strings for uint160;
    // ========================================
    // Immutable
    // ========================================

    address private constant BLACKHOLE = address(0);

    /// @notice amount of $ALPHA a staked genesis dog earn per day
    uint256 public constant GENESIS_TOKEN_PER_DAY = 10 ether;

    /// @notice amount of $ALPHA a staked puppy dog earn per day
    uint256 public constant PUPPY_TOKEN_PER_DAY = 2.5 ether;

    /// @notice price in $ALPHA to breed
    uint256 public constant BREEDING_PRICE = 600 ether;

    /// @notice price in $ALPHA to update name or lore of a dog
    uint256 public constant UPDATE_PRICE = 100 ether;

    /// @notice max amount of genesis tokens
    uint32 public immutable maxGenesis;

    /// @notice max amount of puppy tokens
    uint32 public immutable maxPuppies;

    /// @notice address of the $ALPHA ERC20
    IAlphaToken public immutable alphaToken;

    /// @notice merkle tree root for allow-list
    bytes32 public immutable merkleRoot;

    /// @notice number of reserved genesis tokens for wallets in the allow-list
    uint32 public immutable maxReserved;

    // ========================================
    // Mutable
    // ========================================

    /// @notice if the mint function is open
    bool public isSaleActive = false;

    /// @notice if supply should be reserved for allow-list
    bool public isSupplyReserved = true;

    /// @notice amount of genesis minted so far not via allow-list
    uint32 public genesisNonReservedSupply = 0;

    /// @notice amount of genesis minted so far via allow-list
    uint32 public genesisReservedSupply = 0;

    /// @notice amount of puppied minted so far
    uint32 public puppySupply = 0;

    /// @notice map from dog id to custom Name and Lore
    mapping(uint256 => CustomMetadata) internal metadata;

    /// @notice map from dog id to its staked state
    mapping(uint256 => Stake) public getStake;

    /// @notice check if an address already minted
    mapping(address => bool) public didMint;

    /// @notice address of the AlphaDogsAttributes contract
    IAlphaDogsAttributes public attributes;

    // ========================================
    // Constructor
    // ========================================

    constructor(
        uint32 _maxGenesis,
        uint32 _maxPuppies,
        uint32 _maxReserved,
        IAlphaToken _alphaToken,
        IAlphaDogsAttributes _attributes,
        bytes32 _merkleRoot
    ) ERC721("AlphaDogs", "AD") {
        maxGenesis = _maxGenesis;
        maxPuppies = _maxPuppies;
        maxReserved = _maxReserved;
        alphaToken = _alphaToken;
        attributes = _attributes;
        merkleRoot = _merkleRoot;
    }

    // ========================================
    // Modifiers
    // ========================================

    modifier dogzOwner(uint256 id) {
        if (ownerOf[id] != msg.sender) revert InvalidTokenOwner();
        _;
    }

    modifier whenSaleIsActive() {
        if (!isSaleActive) revert NotActive();
        _;
    }

    // " and \ are not valid
    modifier isValidString(string calldata value) {
        bytes memory str = bytes(value);

        for (uint256 i; i < str.length; i++) {
            bytes1 char = str[i];
            if ((char == 0x22) || (char == 0x5c)) revert InvalidChar();
        }
        _;
    }

    // ========================================
    // Owner only
    // ========================================

    function setIsSaleActive(bool _isSaleActive) external onlyOwner {
        if (isSaleActive == _isSaleActive) revert NotChanged();
        isSaleActive = _isSaleActive;
    }

    function setIsSupplyReserved(bool _isSupplyReserved) external onlyOwner {
        if (isSupplyReserved == _isSupplyReserved) revert NotChanged();
        isSupplyReserved = _isSupplyReserved;
    }

    // ========================================
    // Change NFT Data
    // ========================================

    function setName(uint256 id, string calldata newName)
        external
        override
        dogzOwner(id)
        isValidString(newName)
    {
        bytes memory n = bytes(newName);

        if (n.length > 25) revert InvalidNameLength();
        if (keccak256(n) == keccak256(bytes(metadata[id].name)))
            revert InvalidSameValue();

        metadata[id].name = newName;
        alphaToken.burn(msg.sender, UPDATE_PRICE);
        emit NameChanged(id, newName);
    }

    function setLore(uint256 id, string calldata newLore)
        external
        override
        dogzOwner(id)
        isValidString(newLore)
    {
        bytes memory n = bytes(newLore);

        if (keccak256(n) == keccak256(bytes(metadata[id].lore)))
            revert InvalidSameValue();

        metadata[id].lore = newLore;
        alphaToken.burn(msg.sender, UPDATE_PRICE);
        emit LoreChanged(id, newLore);
    }

    // ========================================
    // Breeding
    // ========================================

    function breed(uint256 mom, uint256 dad)
        external
        override
        dogzOwner(mom)
        dogzOwner(dad)
    {
        if (genesisLeft() != 0) revert NotActive();

        uint256 mintIndex = puppySupply;
        if (mintIndex == maxPuppies) revert InsufficientTokensAvailable();
        if (Gene.isPuppy(mom) || Gene.isPuppy(dad))
            revert FusionWithPuppyForbidden();
        if (mom == dad) revert FusionWithSameParentsForbidden();

        unchecked {
            puppySupply++;
        }

        uint256 puppyId = _generatePuppyTokenIdWithNoCollision(
            mom,
            dad,
            random(mintIndex)
        );
        alphaToken.burn(msg.sender, BREEDING_PRICE);
        //slither-disable-next-line reentrancy-no-eth
        _mint(msg.sender, puppyId);

        emit Breeded(puppyId, mom, dad);
    }

    function _generatePuppyTokenIdWithNoCollision(
        uint256 mom,
        uint256 dad,
        uint256 seed
    ) internal view returns (uint256 tokenId) {
        tokenId = Genetics.uniformCrossOver(mom, dad, seed);
        uint256 i = 3;
        while (ownerOf[tokenId] != BLACKHOLE) {
            tokenId = Genetics.incrementByte(tokenId, i);
            unchecked {
                i++;
            }
        }
    }

    // ========================================
    // Stake / Unstake
    // ========================================

    function stake(uint256[] calldata tokenIds) external override {
        if (tokenIds.length == 0) revert InvalidInput();
        if (msg.sender == address(0)) revert InvalidSender();

        uint256 tokenId;
        for (uint256 i = 0; i < tokenIds.length; ) {
            tokenId = tokenIds[i];
            // No need to check ownership since transferFrom already checks that
            // and the caller of this function should be the token Owner
            getStake[tokenId] = Stake(msg.sender, uint96(block.timestamp));
            _transfer(msg.sender, address(this), tokenId);
            emit Staked(tokenId);

            unchecked {
                ++i;
            }
        }
    }

    function unstake(uint256[] calldata tokenIds) external override {
        _claim(tokenIds, true);
    }

    function claim(uint256[] calldata tokenIds) external override {
        _claim(tokenIds, false);
    }

    function _claim(uint256[] calldata tokenIds, bool shouldUnstake) internal {
        if (tokenIds.length == 0) revert InvalidInput();
        if (msg.sender == address(0)) revert InvalidSender();

        // total rewards amount to claim
        uint256 totalRewards;

        // loop variables

        // rewards for current genzee in the loop below
        uint256 rewards;

        // current genzeeid in the loop below
        uint256 tokenId;

        // staking information for the current genzee in the loop below
        Stake memory stakeInfo;

        for (uint256 i = 0; i < tokenIds.length; ) {
            tokenId = tokenIds[i];
            stakeInfo = getStake[tokenId];

            if (stakeInfo.owner != msg.sender) revert InvalidTokenOwner();

            uint256 tokensPerDay = tokenId.isPuppy()
                ? PUPPY_TOKEN_PER_DAY
                : GENESIS_TOKEN_PER_DAY;

            rewards = stakeInfo.stakedAt > 1
                ? ((tokensPerDay * (block.timestamp - stakeInfo.stakedAt)) /
                    1 days)
                : 0;
            totalRewards += rewards;

            if (shouldUnstake) {
                getStake[tokenId] = Stake(BLACKHOLE, 1);
                _transfer(address(this), msg.sender, tokenId);
                emit Unstaked(tokenId, rewards);
            } else {
                //slither-disable-next-line incorrect-equality
                if (rewards == 0) revert InvalidAmountToClaim();
                getStake[tokenId].stakedAt = uint96(block.timestamp);
                emit ClaimedTokens(tokenId, rewards);
            }

            unchecked {
                ++i;
            }
        }

        //slither-disable-next-line incorrect-equality
        if (totalRewards == 0) return;
        alphaToken.mint(msg.sender, totalRewards);
    }

    // ========================================
    // Mint
    // ========================================

    function _generateTokenIdWithNoCollision(uint256 seed)
        internal
        view
        returns (uint256 tokenId)
    {
        tokenId = Genetics.generateGenes(seed);
        uint256 i = 3;
        while (ownerOf[tokenId] != BLACKHOLE) {
            tokenId = Genetics.incrementByte(tokenId, i);
            unchecked {
                i++;
            }
        }
    }

    function premint(bytes32[] calldata proof) external whenSaleIsActive {
        uint256 reservedSupply = genesisReservedSupply;

        if (didMint[msg.sender]) revert TokenLimitReached();
        if (reservedSupply + 2 > maxReserved)
            revert InsufficientReservedTokensAvailable();
        if (reservedSupply + genesisNonReservedSupply + 2 > maxGenesis)
            revert InsufficientTokensAvailable();

        bytes32 leaf = keccak256(
            abi.encodePacked(uint160(msg.sender).toHexString(20))
        );
        bool isProofValid = MerkleProof.verify(proof, merkleRoot, leaf);
        if (!isProofValid) revert InvalidMerkleProof();

        didMint[msg.sender] = true;

        unchecked {
            uint256 mintIndex = genesisSupply();
            genesisReservedSupply += 2;
            _safeMint(
                msg.sender,
                _generateTokenIdWithNoCollision(random(mintIndex + 1))
            );
            _safeMint(
                msg.sender,
                _generateTokenIdWithNoCollision(random(mintIndex + 2))
            );
        }
    }

    function mint() external whenSaleIsActive {
        // Can only mint once per address
        if (didMint[msg.sender]) {
            revert TokenLimitReached();
        }

        uint256 reservedSupply = genesisReservedSupply;
        uint256 nonReservedSupply = genesisNonReservedSupply;

        if (reservedSupply + nonReservedSupply + 2 > maxGenesis)
            revert InsufficientTokensAvailable();

        // When minting, if isSupplyReserved is on, public minters won't be able
        // to mint the amount reserved for allow-listed wallets
        if (
            isSupplyReserved && nonReservedSupply + 2 > maxGenesis - maxReserved
        ) {
            revert InsufficientNonReservedTokensAvailable();
        }

        didMint[msg.sender] = true;

        unchecked {
            uint256 mintIndex = genesisSupply();
            genesisNonReservedSupply += 2;
            _safeMint(
                msg.sender,
                _generateTokenIdWithNoCollision(random(mintIndex + 1))
            );
            _safeMint(
                msg.sender,
                _generateTokenIdWithNoCollision(random(mintIndex + 2))
            );
        }
    }

    function random(uint256 nonce) internal view returns (uint256) {
        return
            uint256(
                keccak256(
                    abi.encodePacked(
                        tx.origin, // solhint-disable-line avoid-tx-origin
                        tx.gasprice,
                        nonce,
                        block.number,
                        block.timestamp
                    )
                )
            );
    }

    // ========================================
    // View
    // ========================================

    function genesisSupply() public view returns (uint32) {
        unchecked {
            return genesisReservedSupply + genesisNonReservedSupply;
        }
    }

    /// @notice amount of tokens left to be minted
    function genesisLeft() public view returns (uint32) {
        unchecked {
            return maxGenesis - genesisSupply();
        }
    }

    /// @notice amount do puppies left to be created
    function puppyTokensLeft() external view returns (uint32) {
        unchecked {
            return maxPuppies - puppySupply;
        }
    }

    /// @notice total supply of nfts
    function totalSupply() external view returns (uint32) {
        unchecked {
            return genesisSupply() + puppySupply;
        }
    }

    function getMetadata(uint256 id)
        external
        view
        override
        returns (CustomMetadata memory)
    {
        return metadata[id];
    }

    // ========================================
    // Overrides
    // ========================================

    function tokenURI(uint256 id)
        public
        view
        override(ERC721)
        returns (string memory)
    {
        if (ownerOf[id] == BLACKHOLE) revert InvalidTokenID();
        CustomMetadata memory md = metadata[id];
        return attributes.tokenURI(id, bytes(md.name), md.lore);
    }
}

File 2 of 15 : Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

File 3 of 15 : Strings.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)

pragma solidity ^0.8.0;

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        // Inspired by OraclizeAPI's implementation - MIT licence
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

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

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0x00";
        }
        uint256 temp = value;
        uint256 length = 0;
        while (temp != 0) {
            length++;
            temp >>= 8;
        }
        return toHexString(value, length);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _HEX_SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }
}

File 4 of 15 : MerkleProof.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/cryptography/MerkleProof.sol)

pragma solidity ^0.8.0;

/**
 * @dev These functions deal with verification of Merkle Trees proofs.
 *
 * The proofs can be generated using the JavaScript library
 * https://github.com/miguelmota/merkletreejs[merkletreejs].
 * Note: the hashing algorithm should be keccak256 and pair sorting should be enabled.
 *
 * See `test/utils/cryptography/MerkleProof.test.js` for some examples.
 */
library MerkleProof {
    /**
     * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
     * defined by `root`. For this, a `proof` must be provided, containing
     * sibling hashes on the branch from the leaf to the root of the tree. Each
     * pair of leaves and each pair of pre-images are assumed to be sorted.
     */
    function verify(
        bytes32[] memory proof,
        bytes32 root,
        bytes32 leaf
    ) internal pure returns (bool) {
        return processProof(proof, leaf) == root;
    }

    /**
     * @dev Returns the rebuilt hash obtained by traversing a Merklee tree up
     * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
     * hash matches the root of the tree. When processing the proof, the pairs
     * of leafs & pre-images are assumed to be sorted.
     *
     * _Available since v4.4._
     */
    function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {
        bytes32 computedHash = leaf;
        for (uint256 i = 0; i < proof.length; i++) {
            bytes32 proofElement = proof[i];
            if (computedHash <= proofElement) {
                // Hash(current computed hash + current element of the proof)
                computedHash = _efficientHash(computedHash, proofElement);
            } else {
                // Hash(current element of the proof + current computed hash)
                computedHash = _efficientHash(proofElement, computedHash);
            }
        }
        return computedHash;
    }

    function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {
        assembly {
            mstore(0x00, a)
            mstore(0x20, b)
            value := keccak256(0x00, 0x40)
        }
    }
}

File 5 of 15 : ReentrancyGuard.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Gas optimized reentrancy protection for smart contracts.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/ReentrancyGuard.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/security/ReentrancyGuard.sol)
abstract contract ReentrancyGuard {
    uint256 private locked = 1;

    modifier nonReentrant() {
        require(locked == 1, "REENTRANCY");

        locked = 2;

        _;

        locked = 1;
    }
}

File 6 of 15 : IAlphaToken.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.14;

interface IAlphaToken {
    /// @dev 0x36a1c33f
    error NotChanged();
    /// @dev 0x3d693ada
    error NotAllowed();

    function mint(address addr, uint256 amount) external;

    function burn(address from, uint256 amount) external;
}

File 7 of 15 : IAlphaDogs.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.14;

import {IAlphaDogsEvents} from "./IAlphaDogsEvents.sol";
import {IAlphaDogsErrors} from "./IAlphaDogsErrors.sol";

interface IAlphaDogs is IAlphaDogsEvents, IAlphaDogsErrors {
    struct CustomMetadata {
        string name;
        string lore;
    }

    struct Stake {
        address owner;
        uint96 stakedAt;
    }

    // mapping(uint256 => CustomMetadata) getMetadata;
    function getMetadata(uint256 id)
        external
        view
        returns (CustomMetadata memory);

    function setName(uint256 id, string calldata newName) external;

    function setLore(uint256 id, string calldata newLore) external;

    function stake(uint256[] calldata tokenIds) external;

    function unstake(uint256[] calldata tokenIds) external;

    function claim(uint256[] calldata tokenIds) external;

    function premint(bytes32[] calldata proof) external;

    function mint() external;

    function breed(uint256 mom, uint256 dad) external;
}

File 8 of 15 : IAlphaDogsAttributes.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.14;

interface IAlphaDogsAttributes {
    function tokenURI(
        uint256 id,
        bytes memory name,
        string memory lore
    ) external view returns (string memory);
}

File 9 of 15 : Genetics.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.14;

import {Chromossomes} from "./Chromossomes.sol";

/// @title  AlphaDogs Genetics Library
/// @author Aleph Retamal <github.com/alephao>, Gustavo Tiago <github.com/gutiago>
/// @notice Library containing functions for creating and manipulating genes.
///
/// ### Creating a new gene
///
/// • When creating a new gene, we get a pseudo-random seed derive other seeds for each trait
/// • We're using A.J. Walker Alias Algorithm to pick traits with pre-defined rarity table
///   these are the weird hard-coded arrays in the `seedTo{Trait}` functions
/// • Note: we use a pseudo-random seed, meaning that the result can be somewhat manipulated
///   by mad-scientists of the chain.
///
/// ### Breeding
///
/// • For breeding we use uniform cross-over algorithm which is commonly used
///   in genetic algorithms. We walk throught each chromossome, picking from either mom or dad.
library Genetics {
    /// @dev    Generate genes from a seed
    ///
    ///         • Start with                  0x0
    ///         • Add background chromossome  0x77 = 0x0 + 0x77
    ///         • Shift 1 byte to the left    0x7700 = 0x77 << 8
    ///         • Add fur chromossome         0x7766 = 0x7700 + 0x66
    ///         • Same for each chromossome
    function generateGenes(uint256 seed) internal pure returns (uint256 genes) {
        genes |= Chromossomes.seedToBackground(seed);
        genes <<= 8;

        genes |= Chromossomes.seedToFur(seed);
        genes <<= 8;

        genes |= Chromossomes.seedToNeck(seed);
        genes <<= 8;

        genes |= Chromossomes.seedToEyes(seed);
        genes <<= 8;

        genes |= Chromossomes.seedToHat(seed);
        genes <<= 8;

        genes |= Chromossomes.seedToMouth(seed);
        genes <<= 8;

        genes |= Chromossomes.seedToNosering(seed);
    }

    /// @dev Increments the gene i in n (big endian/from right to left)
    ///
    /// ### Examples
    ///
    /// • incrementByte(0x110000, 0) = 0x110001
    /// • incrementByte(0x110000, 1) = 0x110100
    /// • incrementByte(0x110000, 2) = 0x120000
    ///
    /// ### A more readable version of the code
    ///
    /// unchecked {
    ///   uint256 shift = (i % 7) * 8;
    ///   uint256 mask = 0xFF << shift;
    ///   uint256 trait = gene & mask;
    ///   uint256 traitRaw = trait >> shift;
    ///   uint256 newTrait = (traitRaw + 1) % [4, 28, 11, 70, 36, 10, 21][i];
    ///   uint256 tokenIdWithoutOldTrait = ~mask & gene;
    ///   uint256 newGene = tokenIdWithoutOldTrait | (newTrait << shift);
    /// }
    ///
    /// ### Step by step explanation
    ///
    /// Explaining this for devs that look into other contracts to learn stuff like myself
    ///
    /// ### Glossary
    /// • Every 2 positions in an hexadecimal representation of a number = 1 byte
    ///   E.g.: In 0x112233, 11 is a byte, 22 is another byte, 33 is another byte
    /// • Zeros on the left can be ignored so 0x00011 = 0x11, using them here to make
    ///   it easier to see the math
    /// • 1 byte = 8 bits, so 0x1 << 8 will move 1 byte to the left (2 positions) resulting in 0x100
    ///
    /// In this example we have 0x1111221111 and want to increment `22` to `23`
    ///
    /// 1. Create a mask to get only the 22
    ///
    /// 0x1111221111 (gene)
    /// AND
    /// 0x0000FF0000 (mask)
    /// =
    /// 0x0000220000 (result)
    ///
    /// 2. Shift the byte "22" to the least significant byte, so we can increment
    ///
    /// 0x220000 >> (8 * 2) = 0x22
    ///
    /// 3. Increment
    ///
    /// 0x22 + 1 = 0x23. We're also checking against the amount of variants a trait has, that's why
    /// we're doing (byte + 1) % [X, X, X][i]
    ///
    /// 4. Move the byte back to its original position
    ///
    /// 0x23 << (8 * 2) = 0x230000
    ///
    /// 5. Invert the original mask to get all original bytes except the position we're manipulating
    ///
    /// ~0x0000FF0000 = 0xFFFF00FFFF
    ///
    /// 0xFFFF00FFFF
    /// AND
    /// 0x1111221111
    /// =
    /// 0x1111001111
    ///
    /// 6. Put the incremented byte back in the original value
    ///
    /// 0x1111001111
    /// OR
    /// 0x0000230000
    /// =
    /// 0x1111231111
    function incrementByte(uint256 gene, uint256 i)
        internal
        pure
        returns (uint256)
    {
        unchecked {
            // Number of bytes to shift, should be between 0 and 7
            uint256 shift = (i % 7) * 8;

            // Create the mask to do all the stuff mentioned in natspec
            uint256 mask = 0xFF << shift;
            return
                (~mask & gene) |
                (((((gene & mask) >> shift) + 1) %
                    [4, 28, 11, 70, 36, 10, 21][i % 7]) << shift);
        }
    }

    /// @dev    Uniform cross-over two "uint7", returns a "uint8" because a child has an extra byte
    /// @param  mom genes from mom
    /// @param  dad genes from dad
    /// @param  seed the seed is used to pick chromossomes between dad and mom.
    ///
    /// @dev If a specific byte in the seed is even, picks mom, otherwise picks dad.
    ///
    /// ### Examples
    ///
    /// • uniformCrossOver(0x11111111111111, 0x22222222222222, 0x0) = 0x0111111111111111
    /// • uniformCrossOver(0x11111111111111, 0x22222222222222, 0x1) = 0x0111111111111122
    /// • uniformCrossOver(0x11111111111111, 0x22222222222222, 0x0101) = 0x0111111111112222
    /// • uniformCrossOver(0x11111111111111, 0x22222222222222, 0x010101) = 0x0111111111222222
    /// • uniformCrossOver(0x11111111111111, 0x22222222222222, 0x01000100010001) = 0x0122112211221122
    function uniformCrossOver(
        uint256 mom,
        uint256 dad,
        uint256 seed
    ) internal pure returns (uint256) {
        unchecked {
            uint256 child = 0x0100000000000000;
            for (uint256 i = 0; i < 7; i++) {
                // Choose mom or dad to pick the chromossome from
                // If the byte on seed is even, pick mom
                uint256 chromossome = ((seed >> (8 * i)) & 0xFF) % 2 == 0
                    ? mom
                    : dad;

                // Create a mask to pick only the current byte/chromossome
                // E.g.: 3rd byte = 0xFF0000
                uint256 mask = 0xFF << (8 * i);

                // Add byte/chromossome to the child
                child |= (chromossome & mask);
            }

            return child;
        }
    }
}

File 10 of 15 : Gene.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.14;

/// @title  AlphaDogs Gene Library
/// @author Aleph Retamal <github.com/alephao>
/// @notice Library containing functions for querying info about a gene.
library Gene {
    /// @notice A gene is puppy if its 8th byte is greater than 0
    function isPuppy(uint256 gene) internal pure returns (bool) {
        return (gene & 0xFF00000000000000) > 0;
    }

    /// @notice Get a specific chromossome in a gene, first position is 0
    function getChromossome(uint256 gene, uint32 position)
        internal
        pure
        returns (uint256)
    {
        unchecked {
            uint32 shift = 8 * position;
            return (gene & (0xFF << shift)) >> shift;
        }
    }

    function getBackground(uint256 gene) internal pure returns (uint256) {
        return getChromossome(gene, 6);
    }

    function getFur(uint256 gene) internal pure returns (uint256) {
        return getChromossome(gene, 5);
    }

    function getNeck(uint256 gene) internal pure returns (uint256) {
        return getChromossome(gene, 4);
    }

    function getEyes(uint256 gene) internal pure returns (uint256) {
        return getChromossome(gene, 3);
    }

    function getHat(uint256 gene) internal pure returns (uint256) {
        return getChromossome(gene, 2);
    }

    function getMouth(uint256 gene) internal pure returns (uint256) {
        return getChromossome(gene, 1);
    }

    function getNosering(uint256 gene) internal pure returns (uint256) {
        return getChromossome(gene, 0);
    }
}

File 11 of 15 : ERC721.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.14;

// solhint-disable

/// @notice A modified version of Solmate's ERC721 (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC721.sol)
/// @author Solmate, Aleph Retamal <github.com/alephao>
/// @dev Note that balanceOf does not revert if passed the zero address, in defiance of the ERC.
abstract contract ERC721 {
    /*///////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event Transfer(
        address indexed from,
        address indexed to,
        uint256 indexed id
    );

    event Approval(
        address indexed owner,
        address indexed spender,
        uint256 indexed id
    );

    event ApprovalForAll(
        address indexed owner,
        address indexed operator,
        bool approved
    );

    /*///////////////////////////////////////////////////////////////
                          METADATA STORAGE/LOGIC
    //////////////////////////////////////////////////////////////*/

    string public name;

    string public symbol;

    function tokenURI(uint256 id) public view virtual returns (string memory);

    /*///////////////////////////////////////////////////////////////
                            ERC721 STORAGE                        
    //////////////////////////////////////////////////////////////*/

    mapping(address => uint256) public balanceOf;

    mapping(uint256 => address) public ownerOf;

    mapping(uint256 => address) public getApproved;

    mapping(address => mapping(address => bool)) public isApprovedForAll;

    /*///////////////////////////////////////////////////////////////
                              CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    constructor(string memory _name, string memory _symbol) {
        name = _name;
        symbol = _symbol;
    }

    /*///////////////////////////////////////////////////////////////
                              ERC721 LOGIC
    //////////////////////////////////////////////////////////////*/

    function approve(address spender, uint256 id) public virtual {
        address owner = ownerOf[id];

        require(
            msg.sender == owner || isApprovedForAll[owner][msg.sender],
            "NOT_AUTHORIZED"
        );

        getApproved[id] = spender;

        emit Approval(owner, spender, id);
    }

    function setApprovalForAll(address operator, bool approved) public virtual {
        isApprovedForAll[msg.sender][operator] = approved;

        emit ApprovalForAll(msg.sender, operator, approved);
    }

    function _transfer(
        address from,
        address to,
        uint256 id
    ) internal {
        require(from == ownerOf[id], "WRONG_FROM");

        // Underflow of the sender's balance is impossible because we check for
        // ownership above and the recipient's balance can't realistically overflow.
        unchecked {
            balanceOf[from]--;
            balanceOf[to]++;
        }

        ownerOf[id] = to;

        delete getApproved[id];

        emit Transfer(from, to, id);
    }

    function transferFrom(
        address from,
        address to,
        uint256 id
    ) public virtual {
        require(to != address(0), "INVALID_RECIPIENT");

        require(
            msg.sender == from ||
                msg.sender == getApproved[id] ||
                isApprovedForAll[from][msg.sender],
            "NOT_AUTHORIZED"
        );

        _transfer(from, to, id);
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 id
    ) public virtual {
        transferFrom(from, to, id);

        require(
            to.code.length == 0 ||
                ERC721TokenReceiver(to).onERC721Received(
                    msg.sender,
                    from,
                    id,
                    ""
                ) ==
                ERC721TokenReceiver.onERC721Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 id,
        bytes memory data
    ) public virtual {
        transferFrom(from, to, id);

        require(
            to.code.length == 0 ||
                ERC721TokenReceiver(to).onERC721Received(
                    msg.sender,
                    from,
                    id,
                    data
                ) ==
                ERC721TokenReceiver.onERC721Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    /*///////////////////////////////////////////////////////////////
                              ERC165 LOGIC
    //////////////////////////////////////////////////////////////*/

    function supportsInterface(bytes4 interfaceId)
        public
        pure
        virtual
        returns (bool)
    {
        return
            interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165
            interfaceId == 0x80ac58cd || // ERC165 Interface ID for ERC721
            interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata
    }

    /*///////////////////////////////////////////////////////////////
                       INTERNAL MINT/BURN LOGIC
    //////////////////////////////////////////////////////////////*/

    function _mint(address to, uint256 id) internal virtual {
        require(to != address(0), "INVALID_RECIPIENT");

        require(ownerOf[id] == address(0), "ALREADY_MINTED");

        // Counter overflow is incredibly unrealistic.
        unchecked {
            balanceOf[to]++;
        }

        ownerOf[id] = to;

        emit Transfer(address(0), to, id);
    }

    function _burn(uint256 id) internal virtual {
        address owner = ownerOf[id];

        require(ownerOf[id] != address(0), "NOT_MINTED");

        // Ownership check above ensures no underflow.
        unchecked {
            balanceOf[owner]--;
        }

        delete ownerOf[id];

        delete getApproved[id];

        emit Transfer(owner, address(0), id);
    }

    /*///////////////////////////////////////////////////////////////
                       INTERNAL SAFE MINT LOGIC
    //////////////////////////////////////////////////////////////*/

    function _safeMint(address to, uint256 id) internal virtual {
        _mint(to, id);

        require(
            to.code.length == 0 ||
                ERC721TokenReceiver(to).onERC721Received(
                    msg.sender,
                    address(0),
                    id,
                    ""
                ) ==
                ERC721TokenReceiver.onERC721Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    function _safeMint(
        address to,
        uint256 id,
        bytes memory data
    ) internal virtual {
        _mint(to, id);

        require(
            to.code.length == 0 ||
                ERC721TokenReceiver(to).onERC721Received(
                    msg.sender,
                    address(0),
                    id,
                    data
                ) ==
                ERC721TokenReceiver.onERC721Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }
}

/// @notice A generic interface for a contract which properly accepts ERC721 tokens.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC721.sol)
interface ERC721TokenReceiver {
    function onERC721Received(
        address operator,
        address from,
        uint256 id,
        bytes calldata data
    ) external returns (bytes4);
}

File 12 of 15 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

File 13 of 15 : IAlphaDogsEvents.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.14;

interface IAlphaDogsEvents {
    event NameChanged(uint256 indexed id, string name);
    event LoreChanged(uint256 indexed id, string lore);
    event Breeded(uint256 indexed child, uint256 mom, uint256 dad);
    event Staked(uint256 indexed id);
    event Unstaked(uint256 indexed id, uint256 amount);
    event ClaimedTokens(uint256 indexed id, uint256 amount);
}

File 14 of 15 : IAlphaDogsErrors.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.14;

interface IAlphaDogsErrors {
    /// @dev 0x2783839d
    error InsufficientTokensAvailable();
    /// @dev 0x154e0758
    error InsufficientReservedTokensAvailable();
    /// @dev 0x8152a42e
    error InsufficientNonReservedTokensAvailable();
    /// @dev 0x53bb24f9
    error TokenLimitReached();
    /// @dev 0xb05e92fa
    error InvalidMerkleProof();
    /// @dev 0x2c5211c6
    error InvalidAmount();
    /// @dev 0x50e55ae1
    error InvalidAmountToClaim();
    /// @dev 0x6aa2a937
    error InvalidTokenID();
    /// @dev 0x1ae3550b
    error InvalidNameLength();
    /// @dev 0x8a0fcaee
    error InvalidSameValue();
    /// @dev 0x2a7c6b6e
    error InvalidTokenOwner();
    /// @dev 0x8e8ede30
    error FusionWithSameParentsForbidden();
    /// @dev 0x6d074376
    error FusionWithPuppyForbidden();
    /// @dev 0x36a1c33f
    error NotChanged();
    /// @dev 0x80cb55e2
    error NotActive();
    /// @dev 0xb4fa3fb3
    error InvalidInput();
    /// @dev 0xddb5de5e
    error InvalidSender();
    /// @dev 0x21029e82
    error InvalidChar();
}

File 15 of 15 : Chromossomes.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.14;

// Generated code. Do not modify!

/// @title  AlphaDogs Chromossome Generator Library
/// @author Aleph Retamal <github.com/alephao>
/// @notice Library containing functions to pick AlphaDogs chromossomes from an uint256 seed.
library Chromossomes {
    // Each of those seedTo{Trait} function select 4 bytes from the seed
    // and use those selected bytes to pick a trait using the A.J. Walker
    // algorithm. The rarity and aliases are calculated beforehand.

    function seedToBackground(uint256 seed) internal pure returns (uint256) {
        unchecked {
            uint256 traitSeed = (seed >> 16) & 0xFFFF;
            uint256 trait = traitSeed % 21;
            if (
                traitSeed >> 8 <
                [
                    154,
                    222,
                    166,
                    200,
                    150,
                    333,
                    97,
                    158,
                    33,
                    162,
                    44,
                    170,
                    93,
                    234,
                    123,
                    94,
                    345,
                    134,
                    66,
                    255,
                    99
                ][trait]
            ) return trait;
            return
                [
                    1,
                    20,
                    1,
                    2,
                    1,
                    3,
                    3,
                    3,
                    5,
                    5,
                    13,
                    9,
                    16,
                    11,
                    16,
                    16,
                    13,
                    16,
                    19,
                    16,
                    19
                ][trait];
        }
    }

    function seedToFur(uint256 seed) internal pure returns (uint256) {
        unchecked {
            uint256 traitSeed = (seed >> 32) & 0xFFFF;
            uint256 trait = traitSeed % 12;
            if (
                traitSeed >> 8 <
                [44, 345, 299, 450, 460, 88, 166, 177, 369, 470, 188, 277][
                    trait
                ]
            ) return trait;
            return [3, 11, 1, 2, 3, 4, 9, 9, 4, 8, 9, 9][trait];
        }
    }

    function seedToNeck(uint256 seed) internal pure returns (uint256) {
        unchecked {
            uint256 traitSeed = (seed >> 48) & 0xFFFF;
            uint256 trait = traitSeed % 34;
            if (
                traitSeed >> 8 <
                [
                    140,
                    333,
                    147,
                    134,
                    878,
                    92,
                    53,
                    100,
                    25,
                    115,
                    90,
                    122,
                    40,
                    6,
                    9,
                    130,
                    3,
                    5,
                    222,
                    4,
                    45,
                    52,
                    57,
                    23,
                    98,
                    50,
                    48,
                    95,
                    27,
                    21,
                    55,
                    47,
                    32,
                    35
                ][trait]
            ) return trait;
            return
                [
                    33,
                    0,
                    1,
                    2,
                    3,
                    0,
                    1,
                    4,
                    1,
                    7,
                    1,
                    9,
                    1,
                    2,
                    4,
                    11,
                    4,
                    4,
                    15,
                    4,
                    4,
                    4,
                    4,
                    4,
                    4,
                    4,
                    4,
                    4,
                    4,
                    4,
                    9,
                    15,
                    18,
                    18
                ][trait];
        }
    }

    function seedToEyes(uint256 seed) internal pure returns (uint256) {
        unchecked {
            uint256 traitSeed = (seed >> 64) & 0xFFFF;
            uint256 trait = traitSeed % 43;
            if (
                traitSeed >> 8 <
                [
                    30,
                    21,
                    89,
                    7,
                    500,
                    135,
                    52,
                    59,
                    125,
                    88,
                    22,
                    81,
                    120,
                    228,
                    15,
                    90,
                    32,
                    39,
                    17,
                    83,
                    42,
                    12,
                    82,
                    100,
                    84,
                    20,
                    58,
                    56,
                    28,
                    180,
                    40,
                    35,
                    54,
                    55,
                    86,
                    85,
                    24,
                    53,
                    240,
                    80,
                    44,
                    26,
                    16
                ][trait]
            ) return trait;
            return
                [
                    4,
                    4,
                    42,
                    4,
                    2,
                    4,
                    4,
                    4,
                    5,
                    8,
                    4,
                    9,
                    11,
                    12,
                    4,
                    13,
                    4,
                    4,
                    5,
                    15,
                    8,
                    12,
                    19,
                    22,
                    23,
                    13,
                    13,
                    13,
                    13,
                    24,
                    22,
                    29,
                    29,
                    29,
                    29,
                    34,
                    35,
                    38,
                    35,
                    38,
                    38,
                    38,
                    39
                ][trait];
        }
    }

    function seedToHat(uint256 seed) internal pure returns (uint256) {
        unchecked {
            uint256 traitSeed = (seed >> 80) & 0xFFFF;
            uint256 trait = traitSeed % 68;
            if (
                traitSeed >> 8 <
                [
                    18,
                    4,
                    30,
                    35,
                    28,
                    45,
                    46,
                    25,
                    48,
                    22,
                    20,
                    1260,
                    38,
                    43,
                    24,
                    59,
                    38,
                    29,
                    56,
                    30,
                    7,
                    18,
                    25,
                    23,
                    58,
                    42,
                    22,
                    9,
                    6,
                    15,
                    35,
                    22,
                    12,
                    66,
                    27,
                    27,
                    44,
                    46,
                    37,
                    11,
                    28,
                    38,
                    15,
                    42,
                    40,
                    60,
                    37,
                    28,
                    53,
                    50,
                    15,
                    12,
                    5,
                    40,
                    30,
                    8,
                    18,
                    49,
                    48,
                    29,
                    30,
                    10,
                    44,
                    3,
                    35,
                    35,
                    46,
                    35
                ][trait]
            ) return trait;
            return
                [
                    11,
                    11,
                    11,
                    11,
                    11,
                    11,
                    11,
                    11,
                    11,
                    11,
                    11,
                    67,
                    11,
                    11,
                    11,
                    11,
                    11,
                    11,
                    15,
                    11,
                    11,
                    11,
                    11,
                    11,
                    18,
                    11,
                    11,
                    11,
                    11,
                    11,
                    11,
                    11,
                    11,
                    24,
                    11,
                    11,
                    11,
                    11,
                    11,
                    11,
                    11,
                    11,
                    11,
                    11,
                    11,
                    33,
                    11,
                    11,
                    45,
                    48,
                    11,
                    11,
                    11,
                    11,
                    11,
                    11,
                    11,
                    11,
                    11,
                    11,
                    11,
                    11,
                    11,
                    18,
                    33,
                    33,
                    45,
                    49
                ][trait];
        }
    }

    function seedToMouth(uint256 seed) internal pure returns (uint256) {
        unchecked {
            uint256 traitSeed = (seed >> 96) & 0xFFFF;
            uint256 trait = traitSeed % 18;
            if (
                traitSeed >> 8 <
                [
                    156,
                    96,
                    1480,
                    48,
                    333,
                    96,
                    84,
                    32,
                    156,
                    72,
                    24,
                    60,
                    72,
                    84,
                    120,
                    120,
                    168,
                    132
                ][trait]
            ) return trait;
            return
                [2, 2, 17, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4][trait];
        }
    }

    function seedToNosering(uint256 seed) internal pure returns (uint256) {
        unchecked {
            uint256 traitSeed = (seed >> 112) & 0xFFFF;
            uint256 trait = traitSeed % 4;
            if (traitSeed >> 8 < [3201, 12, 84, 36][trait]) return trait;
            return [3, 0, 0, 0][trait];
        }
    }
}

Settings
{
  "remappings": [
    "$/=src/",
    "@ds-test/=lib/ds-test/src/",
    "@forge-std/=lib/forge-std/src/",
    "@hevm/=lib/hevm/src/",
    "@openzeppelin/=lib/openzeppelin-contracts/contracts/",
    "@solmate/=lib/solmate/src/",
    "ds-test/=lib/ds-test/src/",
    "forge-std/=lib/forge-std/src/",
    "hardhat/=node_modules/hardhat/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/",
    "solmate/=lib/solmate/src/",
    "src/=src/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "london",
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"uint32","name":"_maxGenesis","type":"uint32"},{"internalType":"uint32","name":"_maxPuppies","type":"uint32"},{"internalType":"uint32","name":"_maxReserved","type":"uint32"},{"internalType":"contract IAlphaToken","name":"_alphaToken","type":"address"},{"internalType":"contract IAlphaDogsAttributes","name":"_attributes","type":"address"},{"internalType":"bytes32","name":"_merkleRoot","type":"bytes32"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"FusionWithPuppyForbidden","type":"error"},{"inputs":[],"name":"FusionWithSameParentsForbidden","type":"error"},{"inputs":[],"name":"InsufficientNonReservedTokensAvailable","type":"error"},{"inputs":[],"name":"InsufficientReservedTokensAvailable","type":"error"},{"inputs":[],"name":"InsufficientTokensAvailable","type":"error"},{"inputs":[],"name":"InvalidAmount","type":"error"},{"inputs":[],"name":"InvalidAmountToClaim","type":"error"},{"inputs":[],"name":"InvalidChar","type":"error"},{"inputs":[],"name":"InvalidInput","type":"error"},{"inputs":[],"name":"InvalidMerkleProof","type":"error"},{"inputs":[],"name":"InvalidNameLength","type":"error"},{"inputs":[],"name":"InvalidSameValue","type":"error"},{"inputs":[],"name":"InvalidSender","type":"error"},{"inputs":[],"name":"InvalidTokenID","type":"error"},{"inputs":[],"name":"InvalidTokenOwner","type":"error"},{"inputs":[],"name":"NotActive","type":"error"},{"inputs":[],"name":"NotChanged","type":"error"},{"inputs":[],"name":"TokenLimitReached","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"child","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"mom","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"dad","type":"uint256"}],"name":"Breeded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ClaimedTokens","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"string","name":"lore","type":"string"}],"name":"LoreChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"string","name":"name","type":"string"}],"name":"NameChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Unstaked","type":"event"},{"inputs":[],"name":"BREEDING_PRICE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GENESIS_TOKEN_PER_DAY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PUPPY_TOKEN_PER_DAY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UPDATE_PRICE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"alphaToken","outputs":[{"internalType":"contract IAlphaToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"attributes","outputs":[{"internalType":"contract IAlphaDogsAttributes","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"mom","type":"uint256"},{"internalType":"uint256","name":"dad","type":"uint256"}],"name":"breed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"didMint","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"genesisLeft","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"genesisNonReservedSupply","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"genesisReservedSupply","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"genesisSupply","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getMetadata","outputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"lore","type":"string"}],"internalType":"struct IAlphaDogs.CustomMetadata","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"getStake","outputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint96","name":"stakedAt","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isSaleActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isSupplyReserved","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxGenesis","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxPuppies","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxReserved","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"merkleRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"premint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"puppySupply","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"puppyTokensLeft","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_isSaleActive","type":"bool"}],"name":"setIsSaleActive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_isSupplyReserved","type":"bool"}],"name":"setIsSupplyReserved","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"string","name":"newLore","type":"string"}],"name":"setLore","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"string","name":"newName","type":"string"}],"name":"setName","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"unstake","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6101206040526001600755600880546001600160701b0319166101001790553480156200002b57600080fd5b5060405162004482380380620044828339810160408190526200004e9162000243565b6040805180820182526009815268416c706861446f677360b81b602080830191825283518085019094526002845261105160f21b90840152815191929162000099916000916200016a565b508051620000af9060019060208401906200016a565b505050620000cc620000c66200011460201b60201c565b62000118565b63ffffffff95861660805293851660a05291909316610100526001600160a01b0392831660c052600c8054919093166001600160a01b03199091161790915560e052620002fe565b3390565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b8280546200017890620002c2565b90600052602060002090601f0160209004810192826200019c5760008555620001e7565b82601f10620001b757805160ff1916838001178555620001e7565b82800160010185558215620001e7579182015b82811115620001e7578251825591602001919060010190620001ca565b50620001f5929150620001f9565b5090565b5b80821115620001f55760008155600101620001fa565b805163ffffffff811681146200022557600080fd5b919050565b6001600160a01b03811681146200024057600080fd5b50565b60008060008060008060c087890312156200025d57600080fd5b620002688762000210565b9550620002786020880162000210565b9450620002886040880162000210565b935060608701516200029a816200022a565b6080880151909350620002ad816200022a565b8092505060a087015190509295509295509295565b600181811c90821680620002d757607f821691505b602082108103620002f857634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e051610100516140e46200039e6000396000818161060901528181610b5e0152610ce00152600081816103be0152610dfe0152600081816105490152818161119201528181611aad01528181611de001526125300152600081816104c60152818161071301526119b101526000818161049f01528181610af301528181610b7f01528181610d34015261137501526140e46000f3fe608060405234801561001057600080fd5b50600436106102a05760003560e01c8063715018a611610167578063b88d4fde116100ce578063e449f34111610087578063e449f34114610738578063e86b0b2c1461074b578063e985e9c51461075b578063f2fde38b14610789578063fc2567e51461079c578063fe55932a146107ab57600080fd5b8063b88d4fde14610653578063c87b56dd14610666578063ce325bf814610679578063d2d65ff5146106db578063d9ecad7b146106ee578063dd5d7bf51461070157600080fd5b806395d89b411161012057806395d89b41146105c9578063a22cb465146105d1578063a574cea4146105e4578063a9898fd914610604578063ad851b1a1461062b578063ae06eeaa1461063d57600080fd5b8063715018a61461056b578063740954e1146105735780638b1658f71461058a5780638d91371d146105925780638da5cb5b146105a557806393e1ea41146105b657600080fd5b806341bf25371161020b5780635fabe446116101c45780635fabe4461461049a578063623b49c4146104c15780636352211e146104e85780636ba4c1381461051157806370a082311461052457806370b4c9e01461054457600080fd5b806341bf25371461042457806342842e0e146104335780634bbf179b146104465780635398d31214610466578063564566a81461047d5780635a2d6dd51461048a57600080fd5b806318160ddd1161025d57806318160ddd14610353578063202ee58c1461039357806323b872dd146103a65780632eb4a7ab146103b95780633241e917146103ee5780633ef628a31461041157600080fd5b806301ffc9a7146102a557806306fdde03146102cd578063081812fc146102e2578063095ea7b3146103235780630fbf0a93146103385780631249c58b1461034b575b600080fd5b6102b86102b33660046138ed565b6107be565b60405190151581526020015b60405180910390f35b6102d5610810565b6040516102c49190613962565b61030b6102f0366004613975565b6004602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020016102c4565b6103366103313660046139aa565b61089e565b005b610336610346366004613a20565b610985565b610336610a82565b61037e60085462010000810463ffffffff908116600160301b8304821601600160501b909204160190565b60405163ffffffff90911681526020016102c4565b6103366103a1366004613a20565b610c73565b6103366103b4366004613a62565b610ee6565b6103e07f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020016102c4565b6102b86103fc366004613a9e565b600b6020526000908152604090205460ff1681565b61033661041f366004613ab9565b610fd3565b6103e06722b1c8c1227a000081565b610336610441366004613a62565b61123a565b60085462010000810463ffffffff908116600160301b909204160161037e565b60085461037e90600160501b900463ffffffff1681565b6008546102b89060ff1681565b6103e068056bc75e2d6310000081565b61037e7f000000000000000000000000000000000000000000000000000000000000000081565b61037e7f000000000000000000000000000000000000000000000000000000000000000081565b61030b6104f6366004613975565b6003602052600090815260409020546001600160a01b031681565b61033661051f366004613a20565b61130a565b6103e0610532366004613a9e565b60026020526000908152604090205481565b61030b7f000000000000000000000000000000000000000000000000000000000000000081565b61033661131a565b60085461037e90600160301b900463ffffffff1681565b61037e611350565b6103366105a0366004613b45565b61139a565b6006546001600160a01b031661030b565b600c5461030b906001600160a01b031681565b6102d5611411565b6103366105df366004613b60565b61141e565b6105f76105f2366004613975565b61148a565b6040516102c49190613b93565b61037e7f000000000000000000000000000000000000000000000000000000000000000081565b6008546102b890610100900460ff1681565b60085461037e9062010000900463ffffffff1681565b610336610661366004613c44565b6115e0565b6102d5610674366004613975565b61169c565b6106b4610687366004613975565b600a602052600090815260409020546001600160a01b03811690600160a01b90046001600160601b031682565b604080516001600160a01b0390931683526001600160601b039091166020830152016102c4565b6103366106e9366004613b45565b611896565b6103366106fc366004613cef565b6118fe565b600854600160501b900463ffffffff167f00000000000000000000000000000000000000000000000000000000000000000361037e565b610336610746366004613a20565b611b5e565b6103e0682086ac35105260000081565b6102b8610769366004613d11565b600560209081526000928352604080842090915290825290205460ff1681565b610336610797366004613a9e565b611b6a565b6103e0678ac7230489e8000081565b6103366107b9366004613ab9565b611c05565b60006301ffc9a760e01b6001600160e01b0319831614806107ef57506380ac58cd60e01b6001600160e01b03198316145b8061080a5750635b5e139f60e01b6001600160e01b03198316145b92915050565b6000805461081d90613d3b565b80601f016020809104026020016040519081016040528092919081815260200182805461084990613d3b565b80156108965780601f1061086b57610100808354040283529160200191610896565b820191906000526020600020905b81548152906001019060200180831161087957829003601f168201915b505050505081565b6000818152600360205260409020546001600160a01b0316338114806108e757506001600160a01b038116600090815260056020908152604080832033845290915290205460ff165b6109295760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b60448201526064015b60405180910390fd5b60008281526004602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b60008190036109a75760405163b4fa3fb360e01b815260040160405180910390fd5b336109c557604051636edaef2f60e11b815260040160405180910390fd5b6000805b82811015610a7c578383828181106109e3576109e3613d6f565b604080518082018252338082526001600160601b03428116602084810191825295860297909701356000818152600a9096529390942091519551909316600160a01b026001600160a01b039590951694909417909355919350610a499190503084611e76565b60405182907feebbaa86c348cb664e392b180fd0ff2e1998af9fa833ef69a778cb0b42d3ca2790600090a26001016109c9565b50505050565b60085460ff16610aa557604051634065aaf160e11b815260040160405180910390fd5b336000908152600b602052604090205460ff1615610ad6576040516353bb24f960e01b815260040160405180910390fd5b60085463ffffffff600160301b82048116916201000090048116907f000000000000000000000000000000000000000000000000000000000000000016610b1d8284613d9b565b610b28906002613d9b565b1115610b4757604051632783839d60e01b815260040160405180910390fd5b600854610100900460ff168015610bb65750610ba37f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000613db3565b63ffffffff16610bb4826002613d9b565b115b15610bd4576040516340a9521760e11b815260040160405180910390fd5b336000908152600b60205260408120805460ff19166001179055610c0f600854600160301b810463ffffffff90811662010000909204160190565b6008805465ffffffff0000198116600263ffffffff6201000093849004811691909101811690920217909155169050610c5b33610c56610c5160018501611f5b565b611fb3565b611ffa565b610c6e33610c56610c5184600201611f5b565b505050565b60085460ff16610c9657604051634065aaf160e11b815260040160405180910390fd5b600854336000908152600b6020526040902054600160301b90910463ffffffff169060ff1615610cd9576040516353bb24f960e01b815260040160405180910390fd5b63ffffffff7f000000000000000000000000000000000000000000000000000000000000000016610d0b826002613d9b565b1115610d2a576040516302a9c0eb60e31b815260040160405180910390fd5b60085463ffffffff7f0000000000000000000000000000000000000000000000000000000000000000811691610d6891620100009091041683613d9b565b610d73906002613d9b565b1115610d9257604051632783839d60e01b815260040160405180910390fd5b6000610d9f3360146120c6565b604051602001610daf9190613dd8565b6040516020818303038152906040528051906020012090506000610e298585808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152507f000000000000000000000000000000000000000000000000000000000000000092508691506122629050565b905080610e495760405163582f497d60e11b815260040160405180910390fd5b336000908152600b60205260408120805460ff19166001179055610e84600854600160301b810463ffffffff90811662010000909204160190565b6008805469ffffffff000000000000198116600263ffffffff600160301b93849004811691909101811690920217909155169050610ecb33610c56610c5160018501611f5b565b610ede33610c56610c5184600201611f5b565b505050505050565b6001600160a01b038216610f305760405162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b6044820152606401610920565b336001600160a01b0384161480610f5d57506000818152600460205260409020546001600160a01b031633145b80610f8b57506001600160a01b038316600090815260056020908152604080832033845290915290205460ff165b610fc85760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b6044820152606401610920565b610c6e838383611e76565b60008381526003602052604090205483906001600160a01b0316331461100c5760405163153e35b760e11b815260040160405180910390fd5b8282600082828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052509394505050505b81518110156110c757600082828151811061106657611066613d6f565b01602001516001600160f81b0319169050601160f91b8114806110965750601760fa1b6001600160f81b03198216145b156110b4576040516310814f4160e11b815260040160405180910390fd5b50806110bf81613df4565b915050611049565b50600086868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052508c81526009602052604090819020905194955061112394600190910193509150613e0d9050565b604051809103902081805190602001200361115157604051634507e57760e11b815260040160405180910390fd5b600088815260096020526040902061116d90600101888861383e565b50604051632770a7eb60e21b815233600482015268056bc75e2d6310000060248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690639dc29fac90604401600060405180830381600087803b1580156111de57600080fd5b505af11580156111f2573d6000803e3d6000fd5b50505050877f1d83c2282d074aad212f8c5d02271066bf42c603a85c4c9e4f07d1eb8c1998218888604051611228929190613ea8565b60405180910390a25050505050505050565b611245838383610ee6565b6001600160a01b0382163b15806112ee5750604051630a85bd0160e11b8082523360048301526001600160a01b03858116602484015260448301849052608060648401526000608484015290919084169063150b7a029060a4016020604051808303816000875af11580156112be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112e29190613ed7565b6001600160e01b031916145b610c6e5760405162461bcd60e51b815260040161092090613ef4565b61131682826000612278565b5050565b6006546001600160a01b031633146113445760405162461bcd60e51b815260040161092090613f1e565b61134e600061259d565b565b6000611373600854600160301b810463ffffffff90811662010000909204160190565b7f000000000000000000000000000000000000000000000000000000000000000003905090565b6006546001600160a01b031633146113c45760405162461bcd60e51b815260040161092090613f1e565b801515600860019054906101000a900460ff161515036113f7576040516336a1c33f60e01b815260040160405180910390fd5b600880549115156101000261ff0019909216919091179055565b6001805461081d90613d3b565b3360008181526005602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60408051808201909152606080825260208201526000828152600960205260409081902081518083019092528054829082906114c590613d3b565b80601f01602080910402602001604051908101604052809291908181526020018280546114f190613d3b565b801561153e5780601f106115135761010080835404028352916020019161153e565b820191906000526020600020905b81548152906001019060200180831161152157829003601f168201915b5050505050815260200160018201805461155790613d3b565b80601f016020809104026020016040519081016040528092919081815260200182805461158390613d3b565b80156115d05780601f106115a5576101008083540402835291602001916115d0565b820191906000526020600020905b8154815290600101906020018083116115b357829003601f168201915b5050505050815250509050919050565b6115eb848484610ee6565b6001600160a01b0383163b15806116805750604051630a85bd0160e11b808252906001600160a01b0385169063150b7a0290611631903390899088908890600401613f53565b6020604051808303816000875af1158015611650573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116749190613ed7565b6001600160e01b031916145b610a7c5760405162461bcd60e51b815260040161092090613ef4565b6000818152600360205260409020546060906001600160a01b03166116d457604051636aa2a93760e01b815260040160405180910390fd5b60008281526009602052604080822081518083019092528054829082906116fa90613d3b565b80601f016020809104026020016040519081016040528092919081815260200182805461172690613d3b565b80156117735780601f1061174857610100808354040283529160200191611773565b820191906000526020600020905b81548152906001019060200180831161175657829003601f168201915b5050505050815260200160018201805461178c90613d3b565b80601f01602080910402602001604051908101604052809291908181526020018280546117b890613d3b565b80156118055780601f106117da57610100808354040283529160200191611805565b820191906000526020600020905b8154815290600101906020018083116117e857829003601f168201915b505050919092525050600c54825160208401516040516328de0f2f60e01b81529495506001600160a01b03909216936328de0f2f935061184a92889291600401613f90565b600060405180830381865afa158015611867573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261188f9190810190613fbb565b9392505050565b6006546001600160a01b031633146118c05760405162461bcd60e51b815260040161092090613f1e565b60085481151560ff9091161515036118eb576040516336a1c33f60e01b815260040160405180910390fd5b6008805460ff1916911515919091179055565b60008281526003602052604090205482906001600160a01b031633146119375760405163153e35b760e11b815260040160405180910390fd5b60008281526003602052604090205482906001600160a01b031633146119705760405163153e35b760e11b815260040160405180910390fd5b611978611350565b63ffffffff161561199c57604051634065aaf160e11b815260040160405180910390fd5b60085463ffffffff600160501b9091048116907f00000000000000000000000000000000000000000000000000000000000000001681036119f057604051632783839d60e01b815260040160405180910390fd5b60ff60381b8516151580611a09575060ff60381b841615155b15611a2757604051633683a1bb60e11b815260040160405180910390fd5b838503611a47576040516308e8ede360e41b815260040160405180910390fd5b60088054600163ffffffff600160501b808404821692909201160263ffffffff60501b199091161790556000611a868686611a8185611f5b565b6125ef565b604051632770a7eb60e21b8152336004820152682086ac35105260000060248201529091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690639dc29fac90604401600060405180830381600087803b158015611af957600080fd5b505af1158015611b0d573d6000803e3d6000fd5b50505050611b1b338261263a565b604080518781526020810187905282917fbd17f74f642cef9b3214e44a57847f2240c00de2a13ef51b84a7a1c7fc2e1a38910160405180910390a2505050505050565b61131682826001612278565b6006546001600160a01b03163314611b945760405162461bcd60e51b815260040161092090613f1e565b6001600160a01b038116611bf95760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610920565b611c028161259d565b50565b60008381526003602052604090205483906001600160a01b03163314611c3e5760405163153e35b760e11b815260040160405180910390fd5b8282600082828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052509394505050505b8151811015611cf9576000828281518110611c9857611c98613d6f565b01602001516001600160f81b0319169050601160f91b811480611cc85750601760fa1b6001600160f81b03198216145b15611ce6576040516310814f4160e11b815260040160405180910390fd5b5080611cf181613df4565b915050611c7b565b50600086868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250508251929350505060191015611d5857604051631ae3550b60e01b815260040160405180910390fd5b600088815260096020526040908190209051611d749190613e0d565b6040518091039020818051906020012003611da257604051634507e57760e11b815260040160405180910390fd5b6000888152600960205260409020611dbb90888861383e565b50604051632770a7eb60e21b815233600482015268056bc75e2d6310000060248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690639dc29fac90604401600060405180830381600087803b158015611e2c57600080fd5b505af1158015611e40573d6000803e3d6000fd5b50505050877f8edfa912e70e283a8ef6d6f52cd1faef9690ff989eff2f11a134e8478ba7b28b8888604051611228929190613ea8565b6000818152600360205260409020546001600160a01b03848116911614611ecc5760405162461bcd60e51b815260206004820152600a60248201526957524f4e475f46524f4d60b01b6044820152606401610920565b6001600160a01b0380841660008181526002602090815260408083208054600019019055938616808352848320805460010190558583526003825284832080546001600160a01b03199081168317909155600490925284832080549092169091559251849392917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6040516bffffffffffffffffffffffff193260601b1660208201523a60348201526054810182905243607482015242609482015260009060b40160408051601f19818403018152919052805160209091012092915050565b6000611fbe82612745565b905060035b6000828152600360205260409020546001600160a01b031615611ff457611fea82826127a4565b9150600101611fc3565b50919050565b612004828261263a565b6001600160a01b0382163b15806120aa5750604051630a85bd0160e11b80825233600483015260006024830181905260448301849052608060648401526084830152906001600160a01b0384169063150b7a029060a4016020604051808303816000875af115801561207a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061209e9190613ed7565b6001600160e01b031916145b6113165760405162461bcd60e51b815260040161092090613ef4565b606060006120d5836002614029565b6120e0906002613d9b565b67ffffffffffffffff8111156120f8576120f8613bd5565b6040519080825280601f01601f191660200182016040528015612122576020820181803683370190505b509050600360fc1b8160008151811061213d5761213d613d6f565b60200101906001600160f81b031916908160001a905350600f60fb1b8160018151811061216c5761216c613d6f565b60200101906001600160f81b031916908160001a9053506000612190846002614029565b61219b906001613d9b565b90505b6001811115612213576f181899199a1a9b1b9c1cb0b131b232b360811b85600f16601081106121cf576121cf613d6f565b1a60f81b8282815181106121e5576121e5613d6f565b60200101906001600160f81b031916908160001a90535060049490941c9361220c81614048565b905061219e565b50831561188f5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610920565b60008261226f8584612830565b14949350505050565b600082900361229a5760405163b4fa3fb360e01b815260040160405180910390fd5b336122b857604051636edaef2f60e11b815260040160405180910390fd5b60408051808201909152600080825260208201819052908190819060005b86811015612502578787828181106122f0576122f0613d6f565b602090810292909201356000818152600a84526040908190208151808301909252546001600160a01b038116808352600160a01b9091046001600160601b031694820194909452909550935050331461235c5760405163153e35b760e11b815260040160405180910390fd5b600060ff60381b841661237757678ac7230489e80000612381565b6722b1c8c1227a00005b9050600183602001516001600160601b03161161239f5760006123d0565b6201518083602001516001600160601b0316426123bc919061405f565b6123c69083614029565b6123d0919061408c565b94506123dc8587613d9b565b9550861561247557604080518082018252600080825260016020808401918252888352600a9052929020905191516001600160601b0316600160a01b026001600160a01b0392909216919091179055612436303386611e76565b837ffe67007f52a1bf967323b00fd406f9028a8e8a88aec274e07a63b2fabacc64a78660405161246891815260200190565b60405180910390a26124f9565b84600003612496576040516350e55ae160e01b815260040160405180910390fd5b6000848152600a602090815260409182902080546001600160a01b0316600160a01b426001600160601b031602179055905186815285917f3484600735cc885760c6630a1ae8b9f01413e27ab9b4b8535ea9da57dda6e6b9910160405180910390a25b506001016122d6565b50836000036125145750505050505050565b6040516340c10f1960e01b8152336004820152602481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340c10f1990604401600060405180830381600087803b15801561257c57600080fd5b505af1158015612590573d6000803e3d6000fd5b5050505050505050505050565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006125fc84848461289c565b905060035b6000828152600360205260409020546001600160a01b0316156126325761262882826127a4565b9150600101612601565b509392505050565b6001600160a01b0382166126845760405162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b6044820152606401610920565b6000818152600360205260409020546001600160a01b0316156126da5760405162461bcd60e51b815260206004820152600e60248201526d1053149150511657d3525395115160921b6044820152606401610920565b6001600160a01b038216600081815260026020908152604080832080546001019055848352600390915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6000612750826128ea565b1760081b61275d82612aa6565b1760081b61276a82612bc7565b1760081b61277782612e52565b1760081b61278482613162565b1760081b61279182613626565b1760081b61279e826137a2565b17919050565b6040805160e08101825260048152601c6020820152600b918101919091526046606082015260246080820152600a60a0820152601560c0820152600090600860078085069182029260ff841b928492811061280157612801613d6f565b602002015160ff166001878416851c018161281e5761281e614076565b06901b85821916179250505092915050565b600081815b845181101561263257600085828151811061285257612852613d6f565b602002602001015190508083116128785760008381526020829052604090209250612889565b600081815260208490526040902092505b508061289481613df4565b915050612835565b6000670100000000000000815b60078110156128e157600060016008830286901c16156128c957856128cb565b865b60ff600884021b169290921791506001016128a9565b50949350505050565b600061ffff601083901c1681601582604080516102a081018252609a815260de602082015260a69181019190915260c860608201526096608082015261014d60a0820152606160c0820152609e60e0820152602161010082015260a2610120820152602c61014082015260aa610160820152605d61018082015260ea6101a0820152607b6101c0820152605e6101e08201526101596102008201526086610220820152604261024082015260ff6102608201526063610280820152919006915081601581106129bb576129bb613d6f565b602002015161ffff16600883901c10156129d6579392505050565b604080516102a081018252600180825260146020830152918101829052600260608201526080810191909152600360a0820181905260c0820181905260e082015260056101008201819052610120820152600d6101408201819052600961016083015260106101808301819052600b6101a08401526101c083018190526101e083018190526102008301919091526102208201819052601361024083018190526102608301919091526102808201528160158110612a9657612a96613d6f565b602002015160ff16949350505050565b600061ffff602083901c1681600c826040805161018081018252602c8152610159602082015261012b918101919091526101c260608201526101cc6080820152605860a082015260a660c082015260b160e08201526101716101008201526101d661012082015260bc610140820152610115610160820152919006915081600c8110612b3457612b34613d6f565b602002015161ffff16600883901c1015612b4f579392505050565b60408051610180810182526003808252600b6020830152600192820192909252600260608201526080810191909152600460a08201819052600960c0830181905260e083018190526101008301919091526008610120830152610140820181905261016082015281600c8110612a9657612a96613d6f565b600061ffff603083901c16816022826040805161044081018252608c815261014d6020808301919091526093928201929092526086606082015261036e6080820152605c60a0820152603560c0820152606460e082015260196101008201526073610120820152605a610140820152607a610160820152602861018082015260066101a082015260096101c082015260826101e08201526003610200820152600561022082015260de6102408201526004610260820152602d61028082015260346102a082015260396102c082015260176102e0820152606261030082015260326103208201526030610340820152605f610360820152601b61038082015260156103a082015260376103c0820152602f6103e0820152610400810191909152602361042082015291900691508160228110612d0557612d05613d6f565b602002015161ffff16600883901c1015612d20579392505050565b60408051610440810182526021815260006020820181905260019282018390526002606083018190526003608084015260a083019190915260c08201839052600460e08301819052610100830184905260076101208401526101408301849052600961016084018190526101808401949094526101a08301919091526101c08201819052600b6101e083015261020082018190526102208201819052600f6102408301819052610260830182905261028083018290526102a083018290526102c083018290526102e08301829052610300830182905261032083018290526103408301829052610360830182905261038083018290526103a08301919091526103c08201929092526103e0810191909152601261040082018190526104208201528160228110612a9657612a96613d6f565b6040805161056081018252601e81526015602080830191909152605982840152600760608301526101f46080830152608760a0830152603460c0830152603b60e0830152607d610100830152605861012083015260166101408301526051610160830152607861018083015260e46101a0830152600f6101c0830152605a6101e0830152610200820152602761022082015260116102408201526053610260820152602a610280820152600c6102a082015260526102c082015260646102e082015260546103008201526014610320820152603a6103408201526038610360820152601c61038082015260b46103a082015260286103c082015260236103e08201526036610400820152603761042082015260566104408201526055610460820152601861048082015260356104a082015260f06104c082015260506104e0820152602c610500820152601a610520820152601061054082015260009183901c61ffff1690602b808306919082908110612fce57612fce613d6f565b602002015161ffff16600883901c1015612fe9579392505050565b6040805161056081018252600480825260208201819052602a92820192909252606081018290526002608082015260a0810182905260c0810182905260e08101829052600561010082018190526008610120830181905261014083018490526009610160840152600b610180840152600c6101a084018190526101c08401859052600d6101e085018190526102008501869052610220850195909552610240840192909252600f6102608401526102808301526102a082015260136102c082015260166102e08201819052601761030083015261032082018390526103408201839052610360820183905261038082019290925260186103a08201526103c0810191909152601d6103e082018190526104008201819052610420820181905261044082015260226104608201526023610480820181905260266104a083018190526104c08301919091526104e082018190526105008201819052610520820152602761054082015281602b8110612a9657612a96613d6f565b600061ffff605083901c16816044826040805161088081018252601280825260046020830152601e928201839052602360608301819052601c60808401819052602d60a0850152602e60c08501819052601960e08601819052603061010087018190526016610120880181905260146101408901526104ec61016089015260266101808901819052602b6101a08a015260186101c08a0152603b6101e08a01526102008901819052601d6102208a0181905260386102408b01526102608a018b905260076102808b01526102a08a018990526102c08a019490945260176102e08a0152603a6103008a0152602a6103208a018190526103408a0183905260096103608b015260066103808b0152600f6103a08b018190526103c08b018990526103e08b0193909352600c6104008b0181905260426104208c0152601b6104408c018190526104608c0152602c6104808c018190526104a08c0188905260256104c08d01819052600b6104e08e01526105008d018a90526105208d01949094526105408c018590526105608c019290925260286105808c01819052603c6105a08d01526105c08c01939093526105e08b019790975260356106008b015260326106208b01526106408a019290925261066089019590955260056106808901526106a08801949094526106c0870188905260086106e08801526107008701959095526031610720870152610740860194909452610760850193909352610780840194909452600a6107a08401526107c083019390935260036107e083015261080082018390526108208201839052610840820152610860810191909152919006915081604481106133d3576133d3613d6f565b602002015161ffff16600883901c10156133ee579392505050565b6040805161088081018252600b80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052604361016082015261018081018290526101a081018290526101c081018290526101e0810182905261020081018290526102208101829052600f610240820152610260810182905261028081018290526102a081018290526102c081018290526102e081018290526012610300820181905261032082018390526103408201839052610360820183905261038082018390526103a082018390526103c082018390526103e08201839052610400820183905260186104208301526104408201839052610460820183905261048082018390526104a082018390526104c082018390526104e082018390526105008201839052610520820183905261054082018390526105608201839052610580820183905260216105a083018190526105c083018490526105e08301849052602d610600840181905260306106208501526106408401859052610660840185905261068084018590526106a084018590526106c084018590526106e08401859052610700840185905261072084018590526107408401859052610760840185905261078084018590526107a084018590526107c08401949094526107e0830191909152610800820181905261082082015261084081019190915260316108608201528160448110612a9657612a96613d6f565b600061ffff606083901c16816012826040805161024081018252609c808252606060208084018290526105c89484019490945260308184015261014d608084015260a0830152605460c0830181905260e0830193909352610100820152604861012082018190526018610140830152603c6101608301526101808201526101a081019190915260786101c082018190526101e082015260a86102008201526084610220820152919006915081601281106136e2576136e2613d6f565b602002015161ffff16600883901c10156136fd579392505050565b6040805161024081018252600280825260208201819052601192820192909252606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081019190915260046101c082018190526101e0820181905261020082018190526102208201528160128110612a9657612a96613d6f565b600061ffff607083901c168160048260408051608081018252610c818152600c602082015260549181019190915260246060820152919006915081600481106137ed576137ed613d6f565b602002015161ffff16600883901c1015613808579392505050565b604080516080810182526003815260006020820181905291810182905260608101919091528160048110612a9657612a96613d6f565b82805461384a90613d3b565b90600052602060002090601f01602090048101928261386c57600085556138b2565b82601f106138855782800160ff198235161785556138b2565b828001600101855582156138b2579182015b828111156138b2578235825591602001919060010190613897565b506138be9291506138c2565b5090565b5b808211156138be57600081556001016138c3565b6001600160e01b031981168114611c0257600080fd5b6000602082840312156138ff57600080fd5b813561188f816138d7565b60005b8381101561392557818101518382015260200161390d565b83811115610a7c5750506000910152565b6000815180845261394e81602086016020860161390a565b601f01601f19169290920160200192915050565b60208152600061188f6020830184613936565b60006020828403121561398757600080fd5b5035919050565b80356001600160a01b03811681146139a557600080fd5b919050565b600080604083850312156139bd57600080fd5b6139c68361398e565b946020939093013593505050565b60008083601f8401126139e657600080fd5b50813567ffffffffffffffff8111156139fe57600080fd5b6020830191508360208260051b8501011115613a1957600080fd5b9250929050565b60008060208385031215613a3357600080fd5b823567ffffffffffffffff811115613a4a57600080fd5b613a56858286016139d4565b90969095509350505050565b600080600060608486031215613a7757600080fd5b613a808461398e565b9250613a8e6020850161398e565b9150604084013590509250925092565b600060208284031215613ab057600080fd5b61188f8261398e565b600080600060408486031215613ace57600080fd5b83359250602084013567ffffffffffffffff80821115613aed57600080fd5b818601915086601f830112613b0157600080fd5b813581811115613b1057600080fd5b876020828501011115613b2257600080fd5b6020830194508093505050509250925092565b803580151581146139a557600080fd5b600060208284031215613b5757600080fd5b61188f82613b35565b60008060408385031215613b7357600080fd5b613b7c8361398e565b9150613b8a60208401613b35565b90509250929050565b602081526000825160406020840152613baf6060840182613936565b90506020840151601f19848303016040850152613bcc8282613936565b95945050505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715613c1457613c14613bd5565b604052919050565b600067ffffffffffffffff821115613c3657613c36613bd5565b50601f01601f191660200190565b60008060008060808587031215613c5a57600080fd5b613c638561398e565b9350613c716020860161398e565b925060408501359150606085013567ffffffffffffffff811115613c9457600080fd5b8501601f81018713613ca557600080fd5b8035613cb8613cb382613c1c565b613beb565b818152886020838501011115613ccd57600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b60008060408385031215613d0257600080fd5b50508035926020909101359150565b60008060408385031215613d2457600080fd5b613d2d8361398e565b9150613b8a6020840161398e565b600181811c90821680613d4f57607f821691505b602082108103611ff457634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60008219821115613dae57613dae613d85565b500190565b600063ffffffff83811690831681811015613dd057613dd0613d85565b039392505050565b60008251613dea81846020870161390a565b9190910192915050565b600060018201613e0657613e06613d85565b5060010190565b600080835481600182811c915080831680613e2957607f831692505b60208084108203613e4857634e487b7160e01b86526022600452602486fd5b818015613e5c5760018114613e6d57613e9a565b60ff19861689528489019650613e9a565b60008a81526020902060005b86811015613e925781548b820152908501908301613e79565b505084890196505b509498975050505050505050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b600060208284031215613ee957600080fd5b815161188f816138d7565b60208082526010908201526f155394d0519157d49150d2541251539560821b604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090613f8690830184613936565b9695505050505050565b838152606060208201526000613fa96060830185613936565b8281036040840152613f868185613936565b600060208284031215613fcd57600080fd5b815167ffffffffffffffff811115613fe457600080fd5b8201601f81018413613ff557600080fd5b8051614003613cb382613c1c565b81815285602083850101111561401857600080fd5b613bcc82602083016020860161390a565b600081600019048311821515161561404357614043613d85565b500290565b60008161405757614057613d85565b506000190190565b60008282101561407157614071613d85565b500390565b634e487b7160e01b600052601260045260246000fd5b6000826140a957634e487b7160e01b600052601260045260246000fd5b50049056fea2646970667358221220b40d1322c89947cfe2e1c7b1ed3d78eda2ae0ea7cb554347b1ad5bc87fb7b41764736f6c634300080e00330000000000000000000000000000000000000000000000000000000000000d480000000000000000000000000000000000000000000000000000000000001a900000000000000000000000000000000000000000000000000000000000000af000000000000000000000000009a8fb018326a4647488ccb340c211f510a466d3000000000000000000000000e681ae8707182c2464a5d35d7da0571a6dbcc0a7f7e1834c49033499873f3d2f07bb694a1df120ee02569685aad60cf86424718c

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106102a05760003560e01c8063715018a611610167578063b88d4fde116100ce578063e449f34111610087578063e449f34114610738578063e86b0b2c1461074b578063e985e9c51461075b578063f2fde38b14610789578063fc2567e51461079c578063fe55932a146107ab57600080fd5b8063b88d4fde14610653578063c87b56dd14610666578063ce325bf814610679578063d2d65ff5146106db578063d9ecad7b146106ee578063dd5d7bf51461070157600080fd5b806395d89b411161012057806395d89b41146105c9578063a22cb465146105d1578063a574cea4146105e4578063a9898fd914610604578063ad851b1a1461062b578063ae06eeaa1461063d57600080fd5b8063715018a61461056b578063740954e1146105735780638b1658f71461058a5780638d91371d146105925780638da5cb5b146105a557806393e1ea41146105b657600080fd5b806341bf25371161020b5780635fabe446116101c45780635fabe4461461049a578063623b49c4146104c15780636352211e146104e85780636ba4c1381461051157806370a082311461052457806370b4c9e01461054457600080fd5b806341bf25371461042457806342842e0e146104335780634bbf179b146104465780635398d31214610466578063564566a81461047d5780635a2d6dd51461048a57600080fd5b806318160ddd1161025d57806318160ddd14610353578063202ee58c1461039357806323b872dd146103a65780632eb4a7ab146103b95780633241e917146103ee5780633ef628a31461041157600080fd5b806301ffc9a7146102a557806306fdde03146102cd578063081812fc146102e2578063095ea7b3146103235780630fbf0a93146103385780631249c58b1461034b575b600080fd5b6102b86102b33660046138ed565b6107be565b60405190151581526020015b60405180910390f35b6102d5610810565b6040516102c49190613962565b61030b6102f0366004613975565b6004602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020016102c4565b6103366103313660046139aa565b61089e565b005b610336610346366004613a20565b610985565b610336610a82565b61037e60085462010000810463ffffffff908116600160301b8304821601600160501b909204160190565b60405163ffffffff90911681526020016102c4565b6103366103a1366004613a20565b610c73565b6103366103b4366004613a62565b610ee6565b6103e07ff7e1834c49033499873f3d2f07bb694a1df120ee02569685aad60cf86424718c81565b6040519081526020016102c4565b6102b86103fc366004613a9e565b600b6020526000908152604090205460ff1681565b61033661041f366004613ab9565b610fd3565b6103e06722b1c8c1227a000081565b610336610441366004613a62565b61123a565b60085462010000810463ffffffff908116600160301b909204160161037e565b60085461037e90600160501b900463ffffffff1681565b6008546102b89060ff1681565b6103e068056bc75e2d6310000081565b61037e7f0000000000000000000000000000000000000000000000000000000000000d4881565b61037e7f0000000000000000000000000000000000000000000000000000000000001a9081565b61030b6104f6366004613975565b6003602052600090815260409020546001600160a01b031681565b61033661051f366004613a20565b61130a565b6103e0610532366004613a9e565b60026020526000908152604090205481565b61030b7f00000000000000000000000009a8fb018326a4647488ccb340c211f510a466d381565b61033661131a565b60085461037e90600160301b900463ffffffff1681565b61037e611350565b6103366105a0366004613b45565b61139a565b6006546001600160a01b031661030b565b600c5461030b906001600160a01b031681565b6102d5611411565b6103366105df366004613b60565b61141e565b6105f76105f2366004613975565b61148a565b6040516102c49190613b93565b61037e7f0000000000000000000000000000000000000000000000000000000000000af081565b6008546102b890610100900460ff1681565b60085461037e9062010000900463ffffffff1681565b610336610661366004613c44565b6115e0565b6102d5610674366004613975565b61169c565b6106b4610687366004613975565b600a602052600090815260409020546001600160a01b03811690600160a01b90046001600160601b031682565b604080516001600160a01b0390931683526001600160601b039091166020830152016102c4565b6103366106e9366004613b45565b611896565b6103366106fc366004613cef565b6118fe565b600854600160501b900463ffffffff167f0000000000000000000000000000000000000000000000000000000000001a900361037e565b610336610746366004613a20565b611b5e565b6103e0682086ac35105260000081565b6102b8610769366004613d11565b600560209081526000928352604080842090915290825290205460ff1681565b610336610797366004613a9e565b611b6a565b6103e0678ac7230489e8000081565b6103366107b9366004613ab9565b611c05565b60006301ffc9a760e01b6001600160e01b0319831614806107ef57506380ac58cd60e01b6001600160e01b03198316145b8061080a5750635b5e139f60e01b6001600160e01b03198316145b92915050565b6000805461081d90613d3b565b80601f016020809104026020016040519081016040528092919081815260200182805461084990613d3b565b80156108965780601f1061086b57610100808354040283529160200191610896565b820191906000526020600020905b81548152906001019060200180831161087957829003601f168201915b505050505081565b6000818152600360205260409020546001600160a01b0316338114806108e757506001600160a01b038116600090815260056020908152604080832033845290915290205460ff165b6109295760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b60448201526064015b60405180910390fd5b60008281526004602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b60008190036109a75760405163b4fa3fb360e01b815260040160405180910390fd5b336109c557604051636edaef2f60e11b815260040160405180910390fd5b6000805b82811015610a7c578383828181106109e3576109e3613d6f565b604080518082018252338082526001600160601b03428116602084810191825295860297909701356000818152600a9096529390942091519551909316600160a01b026001600160a01b039590951694909417909355919350610a499190503084611e76565b60405182907feebbaa86c348cb664e392b180fd0ff2e1998af9fa833ef69a778cb0b42d3ca2790600090a26001016109c9565b50505050565b60085460ff16610aa557604051634065aaf160e11b815260040160405180910390fd5b336000908152600b602052604090205460ff1615610ad6576040516353bb24f960e01b815260040160405180910390fd5b60085463ffffffff600160301b82048116916201000090048116907f0000000000000000000000000000000000000000000000000000000000000d4816610b1d8284613d9b565b610b28906002613d9b565b1115610b4757604051632783839d60e01b815260040160405180910390fd5b600854610100900460ff168015610bb65750610ba37f0000000000000000000000000000000000000000000000000000000000000af07f0000000000000000000000000000000000000000000000000000000000000d48613db3565b63ffffffff16610bb4826002613d9b565b115b15610bd4576040516340a9521760e11b815260040160405180910390fd5b336000908152600b60205260408120805460ff19166001179055610c0f600854600160301b810463ffffffff90811662010000909204160190565b6008805465ffffffff0000198116600263ffffffff6201000093849004811691909101811690920217909155169050610c5b33610c56610c5160018501611f5b565b611fb3565b611ffa565b610c6e33610c56610c5184600201611f5b565b505050565b60085460ff16610c9657604051634065aaf160e11b815260040160405180910390fd5b600854336000908152600b6020526040902054600160301b90910463ffffffff169060ff1615610cd9576040516353bb24f960e01b815260040160405180910390fd5b63ffffffff7f0000000000000000000000000000000000000000000000000000000000000af016610d0b826002613d9b565b1115610d2a576040516302a9c0eb60e31b815260040160405180910390fd5b60085463ffffffff7f0000000000000000000000000000000000000000000000000000000000000d48811691610d6891620100009091041683613d9b565b610d73906002613d9b565b1115610d9257604051632783839d60e01b815260040160405180910390fd5b6000610d9f3360146120c6565b604051602001610daf9190613dd8565b6040516020818303038152906040528051906020012090506000610e298585808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152507ff7e1834c49033499873f3d2f07bb694a1df120ee02569685aad60cf86424718c92508691506122629050565b905080610e495760405163582f497d60e11b815260040160405180910390fd5b336000908152600b60205260408120805460ff19166001179055610e84600854600160301b810463ffffffff90811662010000909204160190565b6008805469ffffffff000000000000198116600263ffffffff600160301b93849004811691909101811690920217909155169050610ecb33610c56610c5160018501611f5b565b610ede33610c56610c5184600201611f5b565b505050505050565b6001600160a01b038216610f305760405162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b6044820152606401610920565b336001600160a01b0384161480610f5d57506000818152600460205260409020546001600160a01b031633145b80610f8b57506001600160a01b038316600090815260056020908152604080832033845290915290205460ff165b610fc85760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b6044820152606401610920565b610c6e838383611e76565b60008381526003602052604090205483906001600160a01b0316331461100c5760405163153e35b760e11b815260040160405180910390fd5b8282600082828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052509394505050505b81518110156110c757600082828151811061106657611066613d6f565b01602001516001600160f81b0319169050601160f91b8114806110965750601760fa1b6001600160f81b03198216145b156110b4576040516310814f4160e11b815260040160405180910390fd5b50806110bf81613df4565b915050611049565b50600086868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052508c81526009602052604090819020905194955061112394600190910193509150613e0d9050565b604051809103902081805190602001200361115157604051634507e57760e11b815260040160405180910390fd5b600088815260096020526040902061116d90600101888861383e565b50604051632770a7eb60e21b815233600482015268056bc75e2d6310000060248201527f00000000000000000000000009a8fb018326a4647488ccb340c211f510a466d36001600160a01b031690639dc29fac90604401600060405180830381600087803b1580156111de57600080fd5b505af11580156111f2573d6000803e3d6000fd5b50505050877f1d83c2282d074aad212f8c5d02271066bf42c603a85c4c9e4f07d1eb8c1998218888604051611228929190613ea8565b60405180910390a25050505050505050565b611245838383610ee6565b6001600160a01b0382163b15806112ee5750604051630a85bd0160e11b8082523360048301526001600160a01b03858116602484015260448301849052608060648401526000608484015290919084169063150b7a029060a4016020604051808303816000875af11580156112be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112e29190613ed7565b6001600160e01b031916145b610c6e5760405162461bcd60e51b815260040161092090613ef4565b61131682826000612278565b5050565b6006546001600160a01b031633146113445760405162461bcd60e51b815260040161092090613f1e565b61134e600061259d565b565b6000611373600854600160301b810463ffffffff90811662010000909204160190565b7f0000000000000000000000000000000000000000000000000000000000000d4803905090565b6006546001600160a01b031633146113c45760405162461bcd60e51b815260040161092090613f1e565b801515600860019054906101000a900460ff161515036113f7576040516336a1c33f60e01b815260040160405180910390fd5b600880549115156101000261ff0019909216919091179055565b6001805461081d90613d3b565b3360008181526005602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60408051808201909152606080825260208201526000828152600960205260409081902081518083019092528054829082906114c590613d3b565b80601f01602080910402602001604051908101604052809291908181526020018280546114f190613d3b565b801561153e5780601f106115135761010080835404028352916020019161153e565b820191906000526020600020905b81548152906001019060200180831161152157829003601f168201915b5050505050815260200160018201805461155790613d3b565b80601f016020809104026020016040519081016040528092919081815260200182805461158390613d3b565b80156115d05780601f106115a5576101008083540402835291602001916115d0565b820191906000526020600020905b8154815290600101906020018083116115b357829003601f168201915b5050505050815250509050919050565b6115eb848484610ee6565b6001600160a01b0383163b15806116805750604051630a85bd0160e11b808252906001600160a01b0385169063150b7a0290611631903390899088908890600401613f53565b6020604051808303816000875af1158015611650573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116749190613ed7565b6001600160e01b031916145b610a7c5760405162461bcd60e51b815260040161092090613ef4565b6000818152600360205260409020546060906001600160a01b03166116d457604051636aa2a93760e01b815260040160405180910390fd5b60008281526009602052604080822081518083019092528054829082906116fa90613d3b565b80601f016020809104026020016040519081016040528092919081815260200182805461172690613d3b565b80156117735780601f1061174857610100808354040283529160200191611773565b820191906000526020600020905b81548152906001019060200180831161175657829003601f168201915b5050505050815260200160018201805461178c90613d3b565b80601f01602080910402602001604051908101604052809291908181526020018280546117b890613d3b565b80156118055780601f106117da57610100808354040283529160200191611805565b820191906000526020600020905b8154815290600101906020018083116117e857829003601f168201915b505050919092525050600c54825160208401516040516328de0f2f60e01b81529495506001600160a01b03909216936328de0f2f935061184a92889291600401613f90565b600060405180830381865afa158015611867573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261188f9190810190613fbb565b9392505050565b6006546001600160a01b031633146118c05760405162461bcd60e51b815260040161092090613f1e565b60085481151560ff9091161515036118eb576040516336a1c33f60e01b815260040160405180910390fd5b6008805460ff1916911515919091179055565b60008281526003602052604090205482906001600160a01b031633146119375760405163153e35b760e11b815260040160405180910390fd5b60008281526003602052604090205482906001600160a01b031633146119705760405163153e35b760e11b815260040160405180910390fd5b611978611350565b63ffffffff161561199c57604051634065aaf160e11b815260040160405180910390fd5b60085463ffffffff600160501b9091048116907f0000000000000000000000000000000000000000000000000000000000001a901681036119f057604051632783839d60e01b815260040160405180910390fd5b60ff60381b8516151580611a09575060ff60381b841615155b15611a2757604051633683a1bb60e11b815260040160405180910390fd5b838503611a47576040516308e8ede360e41b815260040160405180910390fd5b60088054600163ffffffff600160501b808404821692909201160263ffffffff60501b199091161790556000611a868686611a8185611f5b565b6125ef565b604051632770a7eb60e21b8152336004820152682086ac35105260000060248201529091507f00000000000000000000000009a8fb018326a4647488ccb340c211f510a466d36001600160a01b031690639dc29fac90604401600060405180830381600087803b158015611af957600080fd5b505af1158015611b0d573d6000803e3d6000fd5b50505050611b1b338261263a565b604080518781526020810187905282917fbd17f74f642cef9b3214e44a57847f2240c00de2a13ef51b84a7a1c7fc2e1a38910160405180910390a2505050505050565b61131682826001612278565b6006546001600160a01b03163314611b945760405162461bcd60e51b815260040161092090613f1e565b6001600160a01b038116611bf95760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610920565b611c028161259d565b50565b60008381526003602052604090205483906001600160a01b03163314611c3e5760405163153e35b760e11b815260040160405180910390fd5b8282600082828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052509394505050505b8151811015611cf9576000828281518110611c9857611c98613d6f565b01602001516001600160f81b0319169050601160f91b811480611cc85750601760fa1b6001600160f81b03198216145b15611ce6576040516310814f4160e11b815260040160405180910390fd5b5080611cf181613df4565b915050611c7b565b50600086868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250508251929350505060191015611d5857604051631ae3550b60e01b815260040160405180910390fd5b600088815260096020526040908190209051611d749190613e0d565b6040518091039020818051906020012003611da257604051634507e57760e11b815260040160405180910390fd5b6000888152600960205260409020611dbb90888861383e565b50604051632770a7eb60e21b815233600482015268056bc75e2d6310000060248201527f00000000000000000000000009a8fb018326a4647488ccb340c211f510a466d36001600160a01b031690639dc29fac90604401600060405180830381600087803b158015611e2c57600080fd5b505af1158015611e40573d6000803e3d6000fd5b50505050877f8edfa912e70e283a8ef6d6f52cd1faef9690ff989eff2f11a134e8478ba7b28b8888604051611228929190613ea8565b6000818152600360205260409020546001600160a01b03848116911614611ecc5760405162461bcd60e51b815260206004820152600a60248201526957524f4e475f46524f4d60b01b6044820152606401610920565b6001600160a01b0380841660008181526002602090815260408083208054600019019055938616808352848320805460010190558583526003825284832080546001600160a01b03199081168317909155600490925284832080549092169091559251849392917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6040516bffffffffffffffffffffffff193260601b1660208201523a60348201526054810182905243607482015242609482015260009060b40160408051601f19818403018152919052805160209091012092915050565b6000611fbe82612745565b905060035b6000828152600360205260409020546001600160a01b031615611ff457611fea82826127a4565b9150600101611fc3565b50919050565b612004828261263a565b6001600160a01b0382163b15806120aa5750604051630a85bd0160e11b80825233600483015260006024830181905260448301849052608060648401526084830152906001600160a01b0384169063150b7a029060a4016020604051808303816000875af115801561207a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061209e9190613ed7565b6001600160e01b031916145b6113165760405162461bcd60e51b815260040161092090613ef4565b606060006120d5836002614029565b6120e0906002613d9b565b67ffffffffffffffff8111156120f8576120f8613bd5565b6040519080825280601f01601f191660200182016040528015612122576020820181803683370190505b509050600360fc1b8160008151811061213d5761213d613d6f565b60200101906001600160f81b031916908160001a905350600f60fb1b8160018151811061216c5761216c613d6f565b60200101906001600160f81b031916908160001a9053506000612190846002614029565b61219b906001613d9b565b90505b6001811115612213576f181899199a1a9b1b9c1cb0b131b232b360811b85600f16601081106121cf576121cf613d6f565b1a60f81b8282815181106121e5576121e5613d6f565b60200101906001600160f81b031916908160001a90535060049490941c9361220c81614048565b905061219e565b50831561188f5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610920565b60008261226f8584612830565b14949350505050565b600082900361229a5760405163b4fa3fb360e01b815260040160405180910390fd5b336122b857604051636edaef2f60e11b815260040160405180910390fd5b60408051808201909152600080825260208201819052908190819060005b86811015612502578787828181106122f0576122f0613d6f565b602090810292909201356000818152600a84526040908190208151808301909252546001600160a01b038116808352600160a01b9091046001600160601b031694820194909452909550935050331461235c5760405163153e35b760e11b815260040160405180910390fd5b600060ff60381b841661237757678ac7230489e80000612381565b6722b1c8c1227a00005b9050600183602001516001600160601b03161161239f5760006123d0565b6201518083602001516001600160601b0316426123bc919061405f565b6123c69083614029565b6123d0919061408c565b94506123dc8587613d9b565b9550861561247557604080518082018252600080825260016020808401918252888352600a9052929020905191516001600160601b0316600160a01b026001600160a01b0392909216919091179055612436303386611e76565b837ffe67007f52a1bf967323b00fd406f9028a8e8a88aec274e07a63b2fabacc64a78660405161246891815260200190565b60405180910390a26124f9565b84600003612496576040516350e55ae160e01b815260040160405180910390fd5b6000848152600a602090815260409182902080546001600160a01b0316600160a01b426001600160601b031602179055905186815285917f3484600735cc885760c6630a1ae8b9f01413e27ab9b4b8535ea9da57dda6e6b9910160405180910390a25b506001016122d6565b50836000036125145750505050505050565b6040516340c10f1960e01b8152336004820152602481018590527f00000000000000000000000009a8fb018326a4647488ccb340c211f510a466d36001600160a01b0316906340c10f1990604401600060405180830381600087803b15801561257c57600080fd5b505af1158015612590573d6000803e3d6000fd5b5050505050505050505050565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006125fc84848461289c565b905060035b6000828152600360205260409020546001600160a01b0316156126325761262882826127a4565b9150600101612601565b509392505050565b6001600160a01b0382166126845760405162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b6044820152606401610920565b6000818152600360205260409020546001600160a01b0316156126da5760405162461bcd60e51b815260206004820152600e60248201526d1053149150511657d3525395115160921b6044820152606401610920565b6001600160a01b038216600081815260026020908152604080832080546001019055848352600390915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6000612750826128ea565b1760081b61275d82612aa6565b1760081b61276a82612bc7565b1760081b61277782612e52565b1760081b61278482613162565b1760081b61279182613626565b1760081b61279e826137a2565b17919050565b6040805160e08101825260048152601c6020820152600b918101919091526046606082015260246080820152600a60a0820152601560c0820152600090600860078085069182029260ff841b928492811061280157612801613d6f565b602002015160ff166001878416851c018161281e5761281e614076565b06901b85821916179250505092915050565b600081815b845181101561263257600085828151811061285257612852613d6f565b602002602001015190508083116128785760008381526020829052604090209250612889565b600081815260208490526040902092505b508061289481613df4565b915050612835565b6000670100000000000000815b60078110156128e157600060016008830286901c16156128c957856128cb565b865b60ff600884021b169290921791506001016128a9565b50949350505050565b600061ffff601083901c1681601582604080516102a081018252609a815260de602082015260a69181019190915260c860608201526096608082015261014d60a0820152606160c0820152609e60e0820152602161010082015260a2610120820152602c61014082015260aa610160820152605d61018082015260ea6101a0820152607b6101c0820152605e6101e08201526101596102008201526086610220820152604261024082015260ff6102608201526063610280820152919006915081601581106129bb576129bb613d6f565b602002015161ffff16600883901c10156129d6579392505050565b604080516102a081018252600180825260146020830152918101829052600260608201526080810191909152600360a0820181905260c0820181905260e082015260056101008201819052610120820152600d6101408201819052600961016083015260106101808301819052600b6101a08401526101c083018190526101e083018190526102008301919091526102208201819052601361024083018190526102608301919091526102808201528160158110612a9657612a96613d6f565b602002015160ff16949350505050565b600061ffff602083901c1681600c826040805161018081018252602c8152610159602082015261012b918101919091526101c260608201526101cc6080820152605860a082015260a660c082015260b160e08201526101716101008201526101d661012082015260bc610140820152610115610160820152919006915081600c8110612b3457612b34613d6f565b602002015161ffff16600883901c1015612b4f579392505050565b60408051610180810182526003808252600b6020830152600192820192909252600260608201526080810191909152600460a08201819052600960c0830181905260e083018190526101008301919091526008610120830152610140820181905261016082015281600c8110612a9657612a96613d6f565b600061ffff603083901c16816022826040805161044081018252608c815261014d6020808301919091526093928201929092526086606082015261036e6080820152605c60a0820152603560c0820152606460e082015260196101008201526073610120820152605a610140820152607a610160820152602861018082015260066101a082015260096101c082015260826101e08201526003610200820152600561022082015260de6102408201526004610260820152602d61028082015260346102a082015260396102c082015260176102e0820152606261030082015260326103208201526030610340820152605f610360820152601b61038082015260156103a082015260376103c0820152602f6103e0820152610400810191909152602361042082015291900691508160228110612d0557612d05613d6f565b602002015161ffff16600883901c1015612d20579392505050565b60408051610440810182526021815260006020820181905260019282018390526002606083018190526003608084015260a083019190915260c08201839052600460e08301819052610100830184905260076101208401526101408301849052600961016084018190526101808401949094526101a08301919091526101c08201819052600b6101e083015261020082018190526102208201819052600f6102408301819052610260830182905261028083018290526102a083018290526102c083018290526102e08301829052610300830182905261032083018290526103408301829052610360830182905261038083018290526103a08301919091526103c08201929092526103e0810191909152601261040082018190526104208201528160228110612a9657612a96613d6f565b6040805161056081018252601e81526015602080830191909152605982840152600760608301526101f46080830152608760a0830152603460c0830152603b60e0830152607d610100830152605861012083015260166101408301526051610160830152607861018083015260e46101a0830152600f6101c0830152605a6101e0830152610200820152602761022082015260116102408201526053610260820152602a610280820152600c6102a082015260526102c082015260646102e082015260546103008201526014610320820152603a6103408201526038610360820152601c61038082015260b46103a082015260286103c082015260236103e08201526036610400820152603761042082015260566104408201526055610460820152601861048082015260356104a082015260f06104c082015260506104e0820152602c610500820152601a610520820152601061054082015260009183901c61ffff1690602b808306919082908110612fce57612fce613d6f565b602002015161ffff16600883901c1015612fe9579392505050565b6040805161056081018252600480825260208201819052602a92820192909252606081018290526002608082015260a0810182905260c0810182905260e08101829052600561010082018190526008610120830181905261014083018490526009610160840152600b610180840152600c6101a084018190526101c08401859052600d6101e085018190526102008501869052610220850195909552610240840192909252600f6102608401526102808301526102a082015260136102c082015260166102e08201819052601761030083015261032082018390526103408201839052610360820183905261038082019290925260186103a08201526103c0810191909152601d6103e082018190526104008201819052610420820181905261044082015260226104608201526023610480820181905260266104a083018190526104c08301919091526104e082018190526105008201819052610520820152602761054082015281602b8110612a9657612a96613d6f565b600061ffff605083901c16816044826040805161088081018252601280825260046020830152601e928201839052602360608301819052601c60808401819052602d60a0850152602e60c08501819052601960e08601819052603061010087018190526016610120880181905260146101408901526104ec61016089015260266101808901819052602b6101a08a015260186101c08a0152603b6101e08a01526102008901819052601d6102208a0181905260386102408b01526102608a018b905260076102808b01526102a08a018990526102c08a019490945260176102e08a0152603a6103008a0152602a6103208a018190526103408a0183905260096103608b015260066103808b0152600f6103a08b018190526103c08b018990526103e08b0193909352600c6104008b0181905260426104208c0152601b6104408c018190526104608c0152602c6104808c018190526104a08c0188905260256104c08d01819052600b6104e08e01526105008d018a90526105208d01949094526105408c018590526105608c019290925260286105808c01819052603c6105a08d01526105c08c01939093526105e08b019790975260356106008b015260326106208b01526106408a019290925261066089019590955260056106808901526106a08801949094526106c0870188905260086106e08801526107008701959095526031610720870152610740860194909452610760850193909352610780840194909452600a6107a08401526107c083019390935260036107e083015261080082018390526108208201839052610840820152610860810191909152919006915081604481106133d3576133d3613d6f565b602002015161ffff16600883901c10156133ee579392505050565b6040805161088081018252600b80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052604361016082015261018081018290526101a081018290526101c081018290526101e0810182905261020081018290526102208101829052600f610240820152610260810182905261028081018290526102a081018290526102c081018290526102e081018290526012610300820181905261032082018390526103408201839052610360820183905261038082018390526103a082018390526103c082018390526103e08201839052610400820183905260186104208301526104408201839052610460820183905261048082018390526104a082018390526104c082018390526104e082018390526105008201839052610520820183905261054082018390526105608201839052610580820183905260216105a083018190526105c083018490526105e08301849052602d610600840181905260306106208501526106408401859052610660840185905261068084018590526106a084018590526106c084018590526106e08401859052610700840185905261072084018590526107408401859052610760840185905261078084018590526107a084018590526107c08401949094526107e0830191909152610800820181905261082082015261084081019190915260316108608201528160448110612a9657612a96613d6f565b600061ffff606083901c16816012826040805161024081018252609c808252606060208084018290526105c89484019490945260308184015261014d608084015260a0830152605460c0830181905260e0830193909352610100820152604861012082018190526018610140830152603c6101608301526101808201526101a081019190915260786101c082018190526101e082015260a86102008201526084610220820152919006915081601281106136e2576136e2613d6f565b602002015161ffff16600883901c10156136fd579392505050565b6040805161024081018252600280825260208201819052601192820192909252606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081019190915260046101c082018190526101e0820181905261020082018190526102208201528160128110612a9657612a96613d6f565b600061ffff607083901c168160048260408051608081018252610c818152600c602082015260549181019190915260246060820152919006915081600481106137ed576137ed613d6f565b602002015161ffff16600883901c1015613808579392505050565b604080516080810182526003815260006020820181905291810182905260608101919091528160048110612a9657612a96613d6f565b82805461384a90613d3b565b90600052602060002090601f01602090048101928261386c57600085556138b2565b82601f106138855782800160ff198235161785556138b2565b828001600101855582156138b2579182015b828111156138b2578235825591602001919060010190613897565b506138be9291506138c2565b5090565b5b808211156138be57600081556001016138c3565b6001600160e01b031981168114611c0257600080fd5b6000602082840312156138ff57600080fd5b813561188f816138d7565b60005b8381101561392557818101518382015260200161390d565b83811115610a7c5750506000910152565b6000815180845261394e81602086016020860161390a565b601f01601f19169290920160200192915050565b60208152600061188f6020830184613936565b60006020828403121561398757600080fd5b5035919050565b80356001600160a01b03811681146139a557600080fd5b919050565b600080604083850312156139bd57600080fd5b6139c68361398e565b946020939093013593505050565b60008083601f8401126139e657600080fd5b50813567ffffffffffffffff8111156139fe57600080fd5b6020830191508360208260051b8501011115613a1957600080fd5b9250929050565b60008060208385031215613a3357600080fd5b823567ffffffffffffffff811115613a4a57600080fd5b613a56858286016139d4565b90969095509350505050565b600080600060608486031215613a7757600080fd5b613a808461398e565b9250613a8e6020850161398e565b9150604084013590509250925092565b600060208284031215613ab057600080fd5b61188f8261398e565b600080600060408486031215613ace57600080fd5b83359250602084013567ffffffffffffffff80821115613aed57600080fd5b818601915086601f830112613b0157600080fd5b813581811115613b1057600080fd5b876020828501011115613b2257600080fd5b6020830194508093505050509250925092565b803580151581146139a557600080fd5b600060208284031215613b5757600080fd5b61188f82613b35565b60008060408385031215613b7357600080fd5b613b7c8361398e565b9150613b8a60208401613b35565b90509250929050565b602081526000825160406020840152613baf6060840182613936565b90506020840151601f19848303016040850152613bcc8282613936565b95945050505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715613c1457613c14613bd5565b604052919050565b600067ffffffffffffffff821115613c3657613c36613bd5565b50601f01601f191660200190565b60008060008060808587031215613c5a57600080fd5b613c638561398e565b9350613c716020860161398e565b925060408501359150606085013567ffffffffffffffff811115613c9457600080fd5b8501601f81018713613ca557600080fd5b8035613cb8613cb382613c1c565b613beb565b818152886020838501011115613ccd57600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b60008060408385031215613d0257600080fd5b50508035926020909101359150565b60008060408385031215613d2457600080fd5b613d2d8361398e565b9150613b8a6020840161398e565b600181811c90821680613d4f57607f821691505b602082108103611ff457634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60008219821115613dae57613dae613d85565b500190565b600063ffffffff83811690831681811015613dd057613dd0613d85565b039392505050565b60008251613dea81846020870161390a565b9190910192915050565b600060018201613e0657613e06613d85565b5060010190565b600080835481600182811c915080831680613e2957607f831692505b60208084108203613e4857634e487b7160e01b86526022600452602486fd5b818015613e5c5760018114613e6d57613e9a565b60ff19861689528489019650613e9a565b60008a81526020902060005b86811015613e925781548b820152908501908301613e79565b505084890196505b509498975050505050505050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b600060208284031215613ee957600080fd5b815161188f816138d7565b60208082526010908201526f155394d0519157d49150d2541251539560821b604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090613f8690830184613936565b9695505050505050565b838152606060208201526000613fa96060830185613936565b8281036040840152613f868185613936565b600060208284031215613fcd57600080fd5b815167ffffffffffffffff811115613fe457600080fd5b8201601f81018413613ff557600080fd5b8051614003613cb382613c1c565b81815285602083850101111561401857600080fd5b613bcc82602083016020860161390a565b600081600019048311821515161561404357614043613d85565b500290565b60008161405757614057613d85565b506000190190565b60008282101561407157614071613d85565b500390565b634e487b7160e01b600052601260045260246000fd5b6000826140a957634e487b7160e01b600052601260045260246000fd5b50049056fea2646970667358221220b40d1322c89947cfe2e1c7b1ed3d78eda2ae0ea7cb554347b1ad5bc87fb7b41764736f6c634300080e0033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

0000000000000000000000000000000000000000000000000000000000000d480000000000000000000000000000000000000000000000000000000000001a900000000000000000000000000000000000000000000000000000000000000af000000000000000000000000009a8fb018326a4647488ccb340c211f510a466d3000000000000000000000000e681ae8707182c2464a5d35d7da0571a6dbcc0a7f7e1834c49033499873f3d2f07bb694a1df120ee02569685aad60cf86424718c

-----Decoded View---------------
Arg [0] : _maxGenesis (uint32): 3400
Arg [1] : _maxPuppies (uint32): 6800
Arg [2] : _maxReserved (uint32): 2800
Arg [3] : _alphaToken (address): 0x09A8fB018326A4647488CCB340C211f510A466d3
Arg [4] : _attributes (address): 0xe681aE8707182c2464A5d35D7dA0571A6dBCc0A7
Arg [5] : _merkleRoot (bytes32): 0xf7e1834c49033499873f3d2f07bb694a1df120ee02569685aad60cf86424718c

-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000d48
Arg [1] : 0000000000000000000000000000000000000000000000000000000000001a90
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000af0
Arg [3] : 00000000000000000000000009a8fb018326a4647488ccb340c211f510a466d3
Arg [4] : 000000000000000000000000e681ae8707182c2464a5d35d7da0571a6dbcc0a7
Arg [5] : f7e1834c49033499873f3d2f07bb694a1df120ee02569685aad60cf86424718c


Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]

A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.