Sophon Testnet

Token

Sophon Achievement Badges (SAB)
ERC721

Overview

Max Total Supply

3 SAB

Holders

2

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-
Balance
2 SAB
0xe5b06bfd663c94005b8b159cd320fd7976549f9b
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.

Contract Source Code Verified (Exact Match)

Contract Name:
SophonBadgeNFT

Compiler Version
v0.8.27+commit.40a35a09

ZkSolc Version
v1.5.7

Optimization Enabled:
Yes with Mode 3

Other Settings:
cancun EvmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 22 : SophonBadgeNFT.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.27;

import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
import "@ethereum-attestation-service/eas-contracts/contracts/resolver/SchemaResolver.sol";

// TODO: Use Custom errors

/**
 * @title SophonBadgeNFT
 * @dev Soulbound achievement badges using EAS for verification
 */
contract SophonBadgeNFT is ERC721Enumerable, Ownable, SchemaResolver {
    using Strings for uint256;
    
    uint256 private _nextTokenId; // token ID counter (manually managed)
    
    struct BadgeInfo {
        uint256 badgeType;
        uint256 level;
        bool active;
    }
    
    mapping(uint256 => string) public badgeTypeNames;
    string private _baseTokenURI;
    
    mapping(uint256 => mapping(uint256 => BadgeInfo)) public badgeInfos; // badge type => level => badge info
    mapping(uint256 => BadgeInfo) public tokenToBadgeInfo; // tokenId => badge info
    mapping(address => mapping(uint256 => mapping(uint256 => bool))) public claimed; // to track claimed badges
    mapping(address => mapping(uint256 => mapping(uint256 => uint256))) public userBadgeTokenIds; // to track which badge tokenId a user has for a badge type/level
    
    event BadgeClaimed(address indexed user, uint256 badgeType, uint256 level, uint256 tokenId);
    event BadgeAdded(uint256 badgeType, uint256 level, string name);
    event BaseURIUpdated(string newBaseURI);
    
    /**
     * @dev Constructor
     * @param initialOwner Owner of the contract
     * @param easContractAddress Address of the EAS contract
     * @param baseURI Base URI for badge metadata
     */
    constructor(
        address initialOwner,
        address easContractAddress,
        string memory baseURI
    ) 
        ERC721("Sophon Achievement Badges", "SAB") 
        Ownable(initialOwner)
        SchemaResolver(IEAS(easContractAddress))
    {
        _baseTokenURI = baseURI;
        
        // Initialize default badge type names
        badgeTypeNames[0] = "Explorer";
        badgeTypeNames[1] = "Bridger";
        badgeTypeNames[2] = "Farmer";
        badgeTypeNames[3] = "Guardian";
        badgeTypeNames[4] = "Sender";
        badgeTypeNames[5] = "NFT Collector";
        badgeTypeNames[6] = "Asset Holder";
        badgeTypeNames[7] = "Badge Collector";
        badgeTypeNames[8] = "Early Bird";
    }
    
    /**
     * @dev Add or update a badge type and level
     */
    function addBadge(
        uint256 badgeType,
        uint256 level,
        bool active
    ) external onlyOwner {
        badgeInfos[badgeType][level] = BadgeInfo({
            badgeType: badgeType,
            level: level,
            active: active
        });
        
        emit BadgeAdded(badgeType, level, badgeTypeNames[badgeType]);
    }
    
    function setBadgeTypeName(uint256 badgeType, string calldata name) external onlyOwner {
        badgeTypeNames[badgeType] = name;
    }
    
    function setBaseURI(string calldata baseURI) external onlyOwner {
        _baseTokenURI = baseURI;
        emit BaseURIUpdated(baseURI);
    }
    
    /**
     * @dev Implementation of attestation callback (from SchemaResolver)
     * This is called by EAS when an attestation with our schema is made
     */
    function onAttest(
        Attestation calldata attestation,
        uint256 /* value */
    ) internal override returns (bool) {
        (uint256 badgeType, uint256 level) = abi.decode(attestation.data, (uint256, uint256));
        
        if (!badgeInfos[badgeType][level].active) revert("Badge not active");

        address recipient = attestation.recipient;
        if (claimed[recipient][badgeType][level]) revert("Badge already claimed");
        
        // mark as claimed
        claimed[recipient][badgeType][level] = true;
        
        // mint the badge NFT
        uint256 tokenId = _nextTokenId;
        _nextTokenId++;
        
        _safeMint(recipient, tokenId);
        
        // store badge info for this token
        tokenToBadgeInfo[tokenId] = BadgeInfo({
            badgeType: badgeType,
            level: level,
            active: true
        });
        
        // store user's token ID for this badge
        userBadgeTokenIds[recipient][badgeType][level] = tokenId;
        
        emit BadgeClaimed(recipient, badgeType, level, tokenId);
        
        return true;
    }
    
    /**
     * @dev Implementation of revocation callback (from SchemaResolver)
     * This prevents attestation revocation
     */
    function onRevoke(
        Attestation calldata /* attestation */,
        uint256 /* value */
    ) internal pure override returns (bool) {
        // We don't allow revocation of badge attestations
        return false;
    }
    
    /**
     * @dev Check if a user can claim a badge (for frontend use)
     */
    function canClaim(
        address user,
        uint256 badgeType,
        uint256 level
    ) external view returns (bool) {
        return badgeInfos[badgeType][level].active && !claimed[user][badgeType][level];
    }
    
    /**
     * @dev Check if the resolver accepts payments
     */
    function isPayable() public pure override returns (bool) {
        return false;
    }
    
    /**
     * @dev Override tokenURI to return badge-specific metadata
     */
    function tokenURI(uint256 tokenId) public view override returns (string memory) {
        if (!_exists(tokenId)) revert("Token does not exist");
        
        BadgeInfo memory info = tokenToBadgeInfo[tokenId];
        
        return string(abi.encodePacked(
            _baseTokenURI, 
            "badge-type-", 
            info.badgeType.toString(), 
            "-level-", 
            info.level.toString(), 
            ".json"
        ));
    }
    
    /**
     * @dev Get a user's badge tokens
     */
    function getUserBadges(address user) external view returns (uint256[] memory, uint256[] memory) {
        uint256 balance = balanceOf(user);
        uint256[] memory badgeTypes = new uint256[](balance);
        uint256[] memory levels = new uint256[](balance);
        
        for (uint256 i = 0; i < balance; i++) {
            uint256 tokenId = tokenOfOwnerByIndex(user, i);
            BadgeInfo memory info = tokenToBadgeInfo[tokenId];
            
            badgeTypes[i] = info.badgeType;
            levels[i] = info.level;
        }
        
        return (badgeTypes, levels);
    }
    
    /**
     * @dev Check if a token exists
     */
    function _exists(uint256 tokenId) internal view returns (bool) {
        return _ownerOf(tokenId) != address(0);
    }
    
    /**
     * @dev Override _update to make tokens soulbound (non-transferable)
     */
    function _update(
        address to,
        uint256 tokenId,
        address auth
    ) internal override returns (address) {
        address from = _ownerOf(tokenId);
        
        // if this is a transfer (not a mint) then revert
        if (from != address(0)) {
            revert("Badge is soulbound and cannot be transferred");
        }
        
        // allow minting to proceed
        return super._update(to, tokenId, auth);
    }
    
    /**
     * @dev Override approve to disable approvals
     */
    function approve(address to, uint256 tokenId) public override(ERC721, IERC721) {
        revert("Badge is soulbound and cannot be approved for transfer");
    }
    
    /**
     * @dev Override setApprovalForAll to disable approvals
     */
    function setApprovalForAll(address operator, bool approved) public override(ERC721, IERC721) {
        revert("Badge is soulbound and cannot be approved for transfer");
    }
}

File 2 of 22 : ERC721Enumerable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/ERC721Enumerable.sol)

pragma solidity ^0.8.20;

import {ERC721} from "../ERC721.sol";
import {IERC721Enumerable} from "./IERC721Enumerable.sol";
import {IERC165} from "../../../utils/introspection/ERC165.sol";

/**
 * @dev This implements an optional extension of {ERC721} defined in the EIP that adds enumerability
 * of all the token ids in the contract as well as all token ids owned by each account.
 *
 * CAUTION: `ERC721` extensions that implement custom `balanceOf` logic, such as `ERC721Consecutive`,
 * interfere with enumerability and should not be used together with `ERC721Enumerable`.
 */
abstract contract ERC721Enumerable is ERC721, IERC721Enumerable {
    mapping(address owner => mapping(uint256 index => uint256)) private _ownedTokens;
    mapping(uint256 tokenId => uint256) private _ownedTokensIndex;

    uint256[] private _allTokens;
    mapping(uint256 tokenId => uint256) private _allTokensIndex;

    /**
     * @dev An `owner`'s token query was out of bounds for `index`.
     *
     * NOTE: The owner being `address(0)` indicates a global out of bounds index.
     */
    error ERC721OutOfBoundsIndex(address owner, uint256 index);

    /**
     * @dev Batch mint is not allowed.
     */
    error ERC721EnumerableForbiddenBatchMint();

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) {
        return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId);
    }

    /**
     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
     */
    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual returns (uint256) {
        if (index >= balanceOf(owner)) {
            revert ERC721OutOfBoundsIndex(owner, index);
        }
        return _ownedTokens[owner][index];
    }

    /**
     * @dev See {IERC721Enumerable-totalSupply}.
     */
    function totalSupply() public view virtual returns (uint256) {
        return _allTokens.length;
    }

    /**
     * @dev See {IERC721Enumerable-tokenByIndex}.
     */
    function tokenByIndex(uint256 index) public view virtual returns (uint256) {
        if (index >= totalSupply()) {
            revert ERC721OutOfBoundsIndex(address(0), index);
        }
        return _allTokens[index];
    }

    /**
     * @dev See {ERC721-_update}.
     */
    function _update(address to, uint256 tokenId, address auth) internal virtual override returns (address) {
        address previousOwner = super._update(to, tokenId, auth);

        if (previousOwner == address(0)) {
            _addTokenToAllTokensEnumeration(tokenId);
        } else if (previousOwner != to) {
            _removeTokenFromOwnerEnumeration(previousOwner, tokenId);
        }
        if (to == address(0)) {
            _removeTokenFromAllTokensEnumeration(tokenId);
        } else if (previousOwner != to) {
            _addTokenToOwnerEnumeration(to, tokenId);
        }

        return previousOwner;
    }

    /**
     * @dev Private function to add a token to this extension's ownership-tracking data structures.
     * @param to address representing the new owner of the given token ID
     * @param tokenId uint256 ID of the token to be added to the tokens list of the given address
     */
    function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
        uint256 length = balanceOf(to) - 1;
        _ownedTokens[to][length] = tokenId;
        _ownedTokensIndex[tokenId] = length;
    }

    /**
     * @dev Private function to add a token to this extension's token tracking data structures.
     * @param tokenId uint256 ID of the token to be added to the tokens list
     */
    function _addTokenToAllTokensEnumeration(uint256 tokenId) private {
        _allTokensIndex[tokenId] = _allTokens.length;
        _allTokens.push(tokenId);
    }

    /**
     * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that
     * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for
     * gas optimizations e.g. when performing a transfer operation (avoiding double writes).
     * This has O(1) time complexity, but alters the order of the _ownedTokens array.
     * @param from address representing the previous owner of the given token ID
     * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address
     */
    function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {
        // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and
        // then delete the last slot (swap and pop).

        uint256 lastTokenIndex = balanceOf(from);
        uint256 tokenIndex = _ownedTokensIndex[tokenId];

        // When the token to delete is the last token, the swap operation is unnecessary
        if (tokenIndex != lastTokenIndex) {
            uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];

            _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
            _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
        }

        // This also deletes the contents at the last position of the array
        delete _ownedTokensIndex[tokenId];
        delete _ownedTokens[from][lastTokenIndex];
    }

    /**
     * @dev Private function to remove a token from this extension's token tracking data structures.
     * This has O(1) time complexity, but alters the order of the _allTokens array.
     * @param tokenId uint256 ID of the token to be removed from the tokens list
     */
    function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {
        // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and
        // then delete the last slot (swap and pop).

        uint256 lastTokenIndex = _allTokens.length - 1;
        uint256 tokenIndex = _allTokensIndex[tokenId];

        // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so
        // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding
        // an 'if' statement (like in _removeTokenFromOwnerEnumeration)
        uint256 lastTokenId = _allTokens[lastTokenIndex];

        _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
        _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index

        // This also deletes the contents at the last position of the array
        delete _allTokensIndex[tokenId];
        _allTokens.pop();
    }

    /**
     * See {ERC721-_increaseBalance}. We need that to account tokens that were minted in batch
     */
    function _increaseBalance(address account, uint128 amount) internal virtual override {
        if (amount > 0) {
            revert ERC721EnumerableForbiddenBatchMint();
        }
        super._increaseBalance(account, amount);
    }
}

File 3 of 22 : IERC721.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721.sol)

pragma solidity ^0.8.20;

import {IERC165} from "../../utils/introspection/IERC165.sol";

/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721 is IERC165 {
    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev Returns the number of tokens in ``owner``'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon
     *   a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or
     *   {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon
     *   a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(address from, address to, uint256 tokenId) external;

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
     * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
     * understand this adds an external call which potentially creates a reentrancy vulnerability.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 tokenId) external;

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function approve(address to, uint256 tokenId) external;

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the address zero.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool approved) external;

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(address owner, address operator) external view returns (bool);
}

File 4 of 22 : Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)

pragma solidity ^0.8.20;

import {Context} from "../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.
 *
 * The initial owner is set to the address provided by the deployer. 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;

    /**
     * @dev The caller account is not authorized to perform an operation.
     */
    error OwnableUnauthorizedAccount(address account);

    /**
     * @dev The owner is not a valid owner account. (eg. `address(0)`)
     */
    error OwnableInvalidOwner(address owner);

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

    /**
     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
     */
    constructor(address initialOwner) {
        if (initialOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(initialOwner);
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

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

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        if (owner() != _msgSender()) {
            revert OwnableUnauthorizedAccount(_msgSender());
        }
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby disabling 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 {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _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 5 of 22 : Strings.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol)

pragma solidity ^0.8.20;

import {Math} from "./math/Math.sol";
import {SignedMath} from "./math/SignedMath.sol";

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant HEX_DIGITS = "0123456789abcdef";
    uint8 private constant ADDRESS_LENGTH = 20;

    /**
     * @dev The `value` string doesn't fit in the specified `length`.
     */
    error StringsInsufficientHexLength(uint256 value, uint256 length);

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        unchecked {
            uint256 length = Math.log10(value) + 1;
            string memory buffer = new string(length);
            uint256 ptr;
            /// @solidity memory-safe-assembly
            assembly {
                ptr := add(buffer, add(32, length))
            }
            while (true) {
                ptr--;
                /// @solidity memory-safe-assembly
                assembly {
                    mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))
                }
                value /= 10;
                if (value == 0) break;
            }
            return buffer;
        }
    }

    /**
     * @dev Converts a `int256` to its ASCII `string` decimal representation.
     */
    function toStringSigned(int256 value) internal pure returns (string memory) {
        return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value)));
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        unchecked {
            return toHexString(value, Math.log256(value) + 1);
        }
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        uint256 localValue = value;
        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_DIGITS[localValue & 0xf];
            localValue >>= 4;
        }
        if (localValue != 0) {
            revert StringsInsufficientHexLength(value, length);
        }
        return string(buffer);
    }

    /**
     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal
     * representation.
     */
    function toHexString(address addr) internal pure returns (string memory) {
        return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH);
    }

    /**
     * @dev Returns true if the two strings are equal.
     */
    function equal(string memory a, string memory b) internal pure returns (bool) {
        return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b));
    }
}

File 6 of 22 : SchemaResolver.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.4;

import { AccessDenied, InvalidEAS, InvalidLength, uncheckedInc } from "./../Common.sol";
import { IEAS, Attestation } from "./../IEAS.sol";
import { Semver } from "./../Semver.sol";
import { ISchemaResolver } from "./ISchemaResolver.sol";

/// @title SchemaResolver
/// @notice The base schema resolver contract.
abstract contract SchemaResolver is ISchemaResolver, Semver {
    error InsufficientValue();
    error NotPayable();

    // The global EAS contract.
    IEAS internal immutable _eas;

    /// @dev Creates a new resolver.
    /// @param eas The address of the global EAS contract.
    constructor(IEAS eas) Semver(1, 3, 0) {
        if (address(eas) == address(0)) {
            revert InvalidEAS();
        }

        _eas = eas;
    }

    /// @dev Ensures that only the EAS contract can make this call.
    modifier onlyEAS() {
        _onlyEAS();

        _;
    }

    /// @inheritdoc ISchemaResolver
    function isPayable() public pure virtual returns (bool) {
        return false;
    }

    /// @dev ETH callback.
    receive() external payable virtual {
        if (!isPayable()) {
            revert NotPayable();
        }
    }

    /// @inheritdoc ISchemaResolver
    function attest(Attestation calldata attestation) external payable onlyEAS returns (bool) {
        return onAttest(attestation, msg.value);
    }

    /// @inheritdoc ISchemaResolver
    function multiAttest(
        Attestation[] calldata attestations,
        uint256[] calldata values
    ) external payable onlyEAS returns (bool) {
        uint256 length = attestations.length;
        if (length != values.length) {
            revert InvalidLength();
        }

        // We are keeping track of the remaining ETH amount that can be sent to resolvers and will keep deducting
        // from it to verify that there isn't any attempt to send too much ETH to resolvers. Please note that unless
        // some ETH was stuck in the contract by accident (which shouldn't happen in normal conditions), it won't be
        // possible to send too much ETH anyway.
        uint256 remainingValue = msg.value;

        for (uint256 i = 0; i < length; i = uncheckedInc(i)) {
            // Ensure that the attester/revoker doesn't try to spend more than available.
            uint256 value = values[i];
            if (value > remainingValue) {
                revert InsufficientValue();
            }

            // Forward the attestation to the underlying resolver and return false in case it isn't approved.
            if (!onAttest(attestations[i], value)) {
                return false;
            }

            unchecked {
                // Subtract the ETH amount, that was provided to this attestation, from the global remaining ETH amount.
                remainingValue -= value;
            }
        }

        return true;
    }

    /// @inheritdoc ISchemaResolver
    function revoke(Attestation calldata attestation) external payable onlyEAS returns (bool) {
        return onRevoke(attestation, msg.value);
    }

    /// @inheritdoc ISchemaResolver
    function multiRevoke(
        Attestation[] calldata attestations,
        uint256[] calldata values
    ) external payable onlyEAS returns (bool) {
        uint256 length = attestations.length;
        if (length != values.length) {
            revert InvalidLength();
        }

        // We are keeping track of the remaining ETH amount that can be sent to resolvers and will keep deducting
        // from it to verify that there isn't any attempt to send too much ETH to resolvers. Please note that unless
        // some ETH was stuck in the contract by accident (which shouldn't happen in normal conditions), it won't be
        // possible to send too much ETH anyway.
        uint256 remainingValue = msg.value;

        for (uint256 i = 0; i < length; i = uncheckedInc(i)) {
            // Ensure that the attester/revoker doesn't try to spend more than available.
            uint256 value = values[i];
            if (value > remainingValue) {
                revert InsufficientValue();
            }

            // Forward the revocation to the underlying resolver and return false in case it isn't approved.
            if (!onRevoke(attestations[i], value)) {
                return false;
            }

            unchecked {
                // Subtract the ETH amount, that was provided to this attestation, from the global remaining ETH amount.
                remainingValue -= value;
            }
        }

        return true;
    }

    /// @notice A resolver callback that should be implemented by child contracts.
    /// @param attestation The new attestation.
    /// @param value An explicit ETH amount that was sent to the resolver. Please note that this value is verified in
    ///     both attest() and multiAttest() callbacks EAS-only callbacks and that in case of multi attestations, it'll
    ///     usually hold that msg.value != value, since msg.value aggregated the sent ETH amounts for all the
    ///     attestations in the batch.
    /// @return Whether the attestation is valid.
    function onAttest(Attestation calldata attestation, uint256 value) internal virtual returns (bool);

    /// @notice Processes an attestation revocation and verifies if it can be revoked.
    /// @param attestation The existing attestation to be revoked.
    /// @param value An explicit ETH amount that was sent to the resolver. Please note that this value is verified in
    ///     both revoke() and multiRevoke() callbacks EAS-only callbacks and that in case of multi attestations, it'll
    ///     usually hold that msg.value != value, since msg.value aggregated the sent ETH amounts for all the
    ///     attestations in the batch.
    /// @return Whether the attestation can be revoked.
    function onRevoke(Attestation calldata attestation, uint256 value) internal virtual returns (bool);

    /// @dev Ensures that only the EAS contract can make this call.
    function _onlyEAS() private view {
        if (msg.sender != address(_eas)) {
            revert AccessDenied();
        }
    }
}

File 7 of 22 : ERC721.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/ERC721.sol)

pragma solidity ^0.8.20;

import {IERC721} from "./IERC721.sol";
import {IERC721Receiver} from "./IERC721Receiver.sol";
import {IERC721Metadata} from "./extensions/IERC721Metadata.sol";
import {Context} from "../../utils/Context.sol";
import {Strings} from "../../utils/Strings.sol";
import {IERC165, ERC165} from "../../utils/introspection/ERC165.sol";
import {IERC721Errors} from "../../interfaces/draft-IERC6093.sol";

/**
 * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
 * the Metadata extension, but not including the Enumerable extension, which is available separately as
 * {ERC721Enumerable}.
 */
abstract contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Errors {
    using Strings for uint256;

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    mapping(uint256 tokenId => address) private _owners;

    mapping(address owner => uint256) private _balances;

    mapping(uint256 tokenId => address) private _tokenApprovals;

    mapping(address owner => mapping(address operator => bool)) private _operatorApprovals;

    /**
     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
        return
            interfaceId == type(IERC721).interfaceId ||
            interfaceId == type(IERC721Metadata).interfaceId ||
            super.supportsInterface(interfaceId);
    }

    /**
     * @dev See {IERC721-balanceOf}.
     */
    function balanceOf(address owner) public view virtual returns (uint256) {
        if (owner == address(0)) {
            revert ERC721InvalidOwner(address(0));
        }
        return _balances[owner];
    }

    /**
     * @dev See {IERC721-ownerOf}.
     */
    function ownerOf(uint256 tokenId) public view virtual returns (address) {
        return _requireOwned(tokenId);
    }

    /**
     * @dev See {IERC721Metadata-name}.
     */
    function name() public view virtual returns (string memory) {
        return _name;
    }

    /**
     * @dev See {IERC721Metadata-symbol}.
     */
    function symbol() public view virtual returns (string memory) {
        return _symbol;
    }

    /**
     * @dev See {IERC721Metadata-tokenURI}.
     */
    function tokenURI(uint256 tokenId) public view virtual returns (string memory) {
        _requireOwned(tokenId);

        string memory baseURI = _baseURI();
        return bytes(baseURI).length > 0 ? string.concat(baseURI, tokenId.toString()) : "";
    }

    /**
     * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
     * token will be the concatenation of the `baseURI` and the `tokenId`. Empty
     * by default, can be overridden in child contracts.
     */
    function _baseURI() internal view virtual returns (string memory) {
        return "";
    }

    /**
     * @dev See {IERC721-approve}.
     */
    function approve(address to, uint256 tokenId) public virtual {
        _approve(to, tokenId, _msgSender());
    }

    /**
     * @dev See {IERC721-getApproved}.
     */
    function getApproved(uint256 tokenId) public view virtual returns (address) {
        _requireOwned(tokenId);

        return _getApproved(tokenId);
    }

    /**
     * @dev See {IERC721-setApprovalForAll}.
     */
    function setApprovalForAll(address operator, bool approved) public virtual {
        _setApprovalForAll(_msgSender(), operator, approved);
    }

    /**
     * @dev See {IERC721-isApprovedForAll}.
     */
    function isApprovedForAll(address owner, address operator) public view virtual returns (bool) {
        return _operatorApprovals[owner][operator];
    }

    /**
     * @dev See {IERC721-transferFrom}.
     */
    function transferFrom(address from, address to, uint256 tokenId) public virtual {
        if (to == address(0)) {
            revert ERC721InvalidReceiver(address(0));
        }
        // Setting an "auth" arguments enables the `_isAuthorized` check which verifies that the token exists
        // (from != 0). Therefore, it is not needed to verify that the return value is not 0 here.
        address previousOwner = _update(to, tokenId, _msgSender());
        if (previousOwner != from) {
            revert ERC721IncorrectOwner(from, tokenId, previousOwner);
        }
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(address from, address to, uint256 tokenId) public {
        safeTransferFrom(from, to, tokenId, "");
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual {
        transferFrom(from, to, tokenId);
        _checkOnERC721Received(from, to, tokenId, data);
    }

    /**
     * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist
     *
     * IMPORTANT: Any overrides to this function that add ownership of tokens not tracked by the
     * core ERC721 logic MUST be matched with the use of {_increaseBalance} to keep balances
     * consistent with ownership. The invariant to preserve is that for any address `a` the value returned by
     * `balanceOf(a)` must be equal to the number of tokens such that `_ownerOf(tokenId)` is `a`.
     */
    function _ownerOf(uint256 tokenId) internal view virtual returns (address) {
        return _owners[tokenId];
    }

    /**
     * @dev Returns the approved address for `tokenId`. Returns 0 if `tokenId` is not minted.
     */
    function _getApproved(uint256 tokenId) internal view virtual returns (address) {
        return _tokenApprovals[tokenId];
    }

    /**
     * @dev Returns whether `spender` is allowed to manage `owner`'s tokens, or `tokenId` in
     * particular (ignoring whether it is owned by `owner`).
     *
     * WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this
     * assumption.
     */
    function _isAuthorized(address owner, address spender, uint256 tokenId) internal view virtual returns (bool) {
        return
            spender != address(0) &&
            (owner == spender || isApprovedForAll(owner, spender) || _getApproved(tokenId) == spender);
    }

    /**
     * @dev Checks if `spender` can operate on `tokenId`, assuming the provided `owner` is the actual owner.
     * Reverts if `spender` does not have approval from the provided `owner` for the given token or for all its assets
     * the `spender` for the specific `tokenId`.
     *
     * WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this
     * assumption.
     */
    function _checkAuthorized(address owner, address spender, uint256 tokenId) internal view virtual {
        if (!_isAuthorized(owner, spender, tokenId)) {
            if (owner == address(0)) {
                revert ERC721NonexistentToken(tokenId);
            } else {
                revert ERC721InsufficientApproval(spender, tokenId);
            }
        }
    }

    /**
     * @dev Unsafe write access to the balances, used by extensions that "mint" tokens using an {ownerOf} override.
     *
     * NOTE: the value is limited to type(uint128).max. This protect against _balance overflow. It is unrealistic that
     * a uint256 would ever overflow from increments when these increments are bounded to uint128 values.
     *
     * WARNING: Increasing an account's balance using this function tends to be paired with an override of the
     * {_ownerOf} function to resolve the ownership of the corresponding tokens so that balances and ownership
     * remain consistent with one another.
     */
    function _increaseBalance(address account, uint128 value) internal virtual {
        unchecked {
            _balances[account] += value;
        }
    }

    /**
     * @dev Transfers `tokenId` from its current owner to `to`, or alternatively mints (or burns) if the current owner
     * (or `to`) is the zero address. Returns the owner of the `tokenId` before the update.
     *
     * The `auth` argument is optional. If the value passed is non 0, then this function will check that
     * `auth` is either the owner of the token, or approved to operate on the token (by the owner).
     *
     * Emits a {Transfer} event.
     *
     * NOTE: If overriding this function in a way that tracks balances, see also {_increaseBalance}.
     */
    function _update(address to, uint256 tokenId, address auth) internal virtual returns (address) {
        address from = _ownerOf(tokenId);

        // Perform (optional) operator check
        if (auth != address(0)) {
            _checkAuthorized(from, auth, tokenId);
        }

        // Execute the update
        if (from != address(0)) {
            // Clear approval. No need to re-authorize or emit the Approval event
            _approve(address(0), tokenId, address(0), false);

            unchecked {
                _balances[from] -= 1;
            }
        }

        if (to != address(0)) {
            unchecked {
                _balances[to] += 1;
            }
        }

        _owners[tokenId] = to;

        emit Transfer(from, to, tokenId);

        return from;
    }

    /**
     * @dev Mints `tokenId` and transfers it to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
     *
     * Requirements:
     *
     * - `tokenId` must not exist.
     * - `to` cannot be the zero address.
     *
     * Emits a {Transfer} event.
     */
    function _mint(address to, uint256 tokenId) internal {
        if (to == address(0)) {
            revert ERC721InvalidReceiver(address(0));
        }
        address previousOwner = _update(to, tokenId, address(0));
        if (previousOwner != address(0)) {
            revert ERC721InvalidSender(address(0));
        }
    }

    /**
     * @dev Mints `tokenId`, transfers it to `to` and checks for `to` acceptance.
     *
     * Requirements:
     *
     * - `tokenId` must not exist.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function _safeMint(address to, uint256 tokenId) internal {
        _safeMint(to, tokenId, "");
    }

    /**
     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
     */
    function _safeMint(address to, uint256 tokenId, bytes memory data) internal virtual {
        _mint(to, tokenId);
        _checkOnERC721Received(address(0), to, tokenId, data);
    }

    /**
     * @dev Destroys `tokenId`.
     * The approval is cleared when the token is burned.
     * This is an internal function that does not check if the sender is authorized to operate on the token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     *
     * Emits a {Transfer} event.
     */
    function _burn(uint256 tokenId) internal {
        address previousOwner = _update(address(0), tokenId, address(0));
        if (previousOwner == address(0)) {
            revert ERC721NonexistentToken(tokenId);
        }
    }

    /**
     * @dev Transfers `tokenId` from `from` to `to`.
     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     *
     * Emits a {Transfer} event.
     */
    function _transfer(address from, address to, uint256 tokenId) internal {
        if (to == address(0)) {
            revert ERC721InvalidReceiver(address(0));
        }
        address previousOwner = _update(to, tokenId, address(0));
        if (previousOwner == address(0)) {
            revert ERC721NonexistentToken(tokenId);
        } else if (previousOwner != from) {
            revert ERC721IncorrectOwner(from, tokenId, previousOwner);
        }
    }

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking that contract recipients
     * are aware of the ERC721 standard to prevent tokens from being forever locked.
     *
     * `data` is additional data, it has no specified format and it is sent in call to `to`.
     *
     * This internal function is like {safeTransferFrom} in the sense that it invokes
     * {IERC721Receiver-onERC721Received} on the receiver, and can be used to e.g.
     * implement alternative mechanisms to perform token transfer, such as signature-based.
     *
     * Requirements:
     *
     * - `tokenId` token must exist and be owned by `from`.
     * - `to` cannot be the zero address.
     * - `from` cannot be the zero address.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function _safeTransfer(address from, address to, uint256 tokenId) internal {
        _safeTransfer(from, to, tokenId, "");
    }

    /**
     * @dev Same as {xref-ERC721-_safeTransfer-address-address-uint256-}[`_safeTransfer`], with an additional `data` parameter which is
     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
     */
    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual {
        _transfer(from, to, tokenId);
        _checkOnERC721Received(from, to, tokenId, data);
    }

    /**
     * @dev Approve `to` to operate on `tokenId`
     *
     * The `auth` argument is optional. If the value passed is non 0, then this function will check that `auth` is
     * either the owner of the token, or approved to operate on all tokens held by this owner.
     *
     * Emits an {Approval} event.
     *
     * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.
     */
    function _approve(address to, uint256 tokenId, address auth) internal {
        _approve(to, tokenId, auth, true);
    }

    /**
     * @dev Variant of `_approve` with an optional flag to enable or disable the {Approval} event. The event is not
     * emitted in the context of transfers.
     */
    function _approve(address to, uint256 tokenId, address auth, bool emitEvent) internal virtual {
        // Avoid reading the owner unless necessary
        if (emitEvent || auth != address(0)) {
            address owner = _requireOwned(tokenId);

            // We do not use _isAuthorized because single-token approvals should not be able to call approve
            if (auth != address(0) && owner != auth && !isApprovedForAll(owner, auth)) {
                revert ERC721InvalidApprover(auth);
            }

            if (emitEvent) {
                emit Approval(owner, to, tokenId);
            }
        }

        _tokenApprovals[tokenId] = to;
    }

    /**
     * @dev Approve `operator` to operate on all of `owner` tokens
     *
     * Requirements:
     * - operator can't be the address zero.
     *
     * Emits an {ApprovalForAll} event.
     */
    function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {
        if (operator == address(0)) {
            revert ERC721InvalidOperator(operator);
        }
        _operatorApprovals[owner][operator] = approved;
        emit ApprovalForAll(owner, operator, approved);
    }

    /**
     * @dev Reverts if the `tokenId` doesn't have a current owner (it hasn't been minted, or it has been burned).
     * Returns the owner.
     *
     * Overrides to ownership logic should be done to {_ownerOf}.
     */
    function _requireOwned(uint256 tokenId) internal view returns (address) {
        address owner = _ownerOf(tokenId);
        if (owner == address(0)) {
            revert ERC721NonexistentToken(tokenId);
        }
        return owner;
    }

    /**
     * @dev Private function to invoke {IERC721Receiver-onERC721Received} on a target address. This will revert if the
     * recipient doesn't accept the token transfer. The call is not executed if the target address is not a contract.
     *
     * @param from address representing the previous owner of the given token ID
     * @param to target address that will receive the tokens
     * @param tokenId uint256 ID of the token to be transferred
     * @param data bytes optional data to send along with the call
     */
    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory data) private {
        if (to.code.length > 0) {
            try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {
                if (retval != IERC721Receiver.onERC721Received.selector) {
                    revert ERC721InvalidReceiver(to);
                }
            } catch (bytes memory reason) {
                if (reason.length == 0) {
                    revert ERC721InvalidReceiver(to);
                } else {
                    /// @solidity memory-safe-assembly
                    assembly {
                        revert(add(32, reason), mload(reason))
                    }
                }
            }
        }
    }
}

File 8 of 22 : IERC721Enumerable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/IERC721Enumerable.sol)

pragma solidity ^0.8.20;

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

/**
 * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Enumerable is IERC721 {
    /**
     * @dev Returns the total amount of tokens stored by the contract.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.
     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
     */
    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);

    /**
     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
     * Use along with {totalSupply} to enumerate all tokens.
     */
    function tokenByIndex(uint256 index) external view returns (uint256);
}

File 9 of 22 : ERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)

pragma solidity ^0.8.20;

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

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

File 10 of 22 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)

pragma solidity ^0.8.20;

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

File 11 of 22 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;

/**
 * @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;
    }

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}

File 12 of 22 : Math.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol)

pragma solidity ^0.8.20;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    /**
     * @dev Muldiv operation overflow.
     */
    error MathOverflowedMulDiv();

    enum Rounding {
        Floor, // Toward negative infinity
        Ceil, // Toward positive infinity
        Trunc, // Toward zero
        Expand // Away from zero
    }

    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, with an overflow flag.
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b > a) return (false, 0);
            return (true, a - b);
        }
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
            // benefit is lost if 'b' is also tested.
            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
            if (a == 0) return (true, 0);
            uint256 c = a * b;
            if (c / a != b) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a / b);
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a % b);
        }
    }

    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds towards infinity instead
     * of rounding towards zero.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        if (b == 0) {
            // Guarantee the same behavior as in a regular Solidity division.
            return a / b;
        }

        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a == 0 ? 0 : (a - 1) / b + 1;
    }

    /**
     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or
     * denominator == 0.
     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by
     * Uniswap Labs also under MIT license.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2^256 + prod0.
            uint256 prod0 = x * y; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                // Solidity will revert if denominator == 0, unlike the div opcode on its own.
                // The surrounding unchecked block does not change this fact.
                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            if (denominator <= prod1) {
                revert MathOverflowedMulDiv();
            }

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator.
            // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.

            uint256 twos = denominator & (0 - denominator);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also
            // works in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /**
     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
        uint256 result = mulDiv(x, y, denominator);
        if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) {
            result += 1;
        }
        return result;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded
     * towards zero.
     *
     * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
        //
        // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
        //
        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
        //
        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1 << (log2(a) >> 1);

        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
        // into the expected uint128 result.
        unchecked {
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            return min(result, a / result);
        }
    }

    /**
     * @notice Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = sqrt(a);
            return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2 of a positive value rounded towards zero.
     * Returns 0 if given 0.
     */
    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 128;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 64;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 32;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 16;
            }
            if (value >> 8 > 0) {
                value >>= 8;
                result += 8;
            }
            if (value >> 4 > 0) {
                value >>= 4;
                result += 4;
            }
            if (value >> 2 > 0) {
                value >>= 2;
                result += 2;
            }
            if (value >> 1 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log2(value);
            return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10 of a positive value rounded towards zero.
     * Returns 0 if given 0.
     */
    function log10(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >= 10 ** 64) {
                value /= 10 ** 64;
                result += 64;
            }
            if (value >= 10 ** 32) {
                value /= 10 ** 32;
                result += 32;
            }
            if (value >= 10 ** 16) {
                value /= 10 ** 16;
                result += 16;
            }
            if (value >= 10 ** 8) {
                value /= 10 ** 8;
                result += 8;
            }
            if (value >= 10 ** 4) {
                value /= 10 ** 4;
                result += 4;
            }
            if (value >= 10 ** 2) {
                value /= 10 ** 2;
                result += 2;
            }
            if (value >= 10 ** 1) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log10(value);
            return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 256 of a positive value rounded towards zero.
     * Returns 0 if given 0.
     *
     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
     */
    function log256(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 16;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 8;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 4;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 2;
            }
            if (value >> 8 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log256(value);
            return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0);
        }
    }

    /**
     * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.
     */
    function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {
        return uint8(rounding) % 2 == 1;
    }
}

File 13 of 22 : SignedMath.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol)

pragma solidity ^0.8.20;

/**
 * @dev Standard signed math utilities missing in the Solidity language.
 */
library SignedMath {
    /**
     * @dev Returns the largest of two signed numbers.
     */
    function max(int256 a, int256 b) internal pure returns (int256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two signed numbers.
     */
    function min(int256 a, int256 b) internal pure returns (int256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two signed numbers without overflow.
     * The result is rounded towards zero.
     */
    function average(int256 a, int256 b) internal pure returns (int256) {
        // Formula from the book "Hacker's Delight"
        int256 x = (a & b) + ((a ^ b) >> 1);
        return x + (int256(uint256(x) >> 255) & (a ^ b));
    }

    /**
     * @dev Returns the absolute unsigned value of a signed value.
     */
    function abs(int256 n) internal pure returns (uint256) {
        unchecked {
            // must be unchecked in order to support `n = type(int256).min`
            return uint256(n >= 0 ? n : -n);
        }
    }
}

File 14 of 22 : Common.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

// A representation of an empty/uninitialized UID.
bytes32 constant EMPTY_UID = 0;

// A zero expiration represents an non-expiring attestation.
uint64 constant NO_EXPIRATION_TIME = 0;

error AccessDenied();
error DeadlineExpired();
error InvalidEAS();
error InvalidLength();
error InvalidSignature();
error NotFound();

/// @notice A struct representing ECDSA signature data.
struct Signature {
    uint8 v; // The recovery ID.
    bytes32 r; // The x-coordinate of the nonce R.
    bytes32 s; // The signature data.
}

/// @notice A struct representing a single attestation.
struct Attestation {
    bytes32 uid; // A unique identifier of the attestation.
    bytes32 schema; // The unique identifier of the schema.
    uint64 time; // The time when the attestation was created (Unix timestamp).
    uint64 expirationTime; // The time when the attestation expires (Unix timestamp).
    uint64 revocationTime; // The time when the attestation was revoked (Unix timestamp).
    bytes32 refUID; // The UID of the related attestation.
    address recipient; // The recipient of the attestation.
    address attester; // The attester/sender of the attestation.
    bool revocable; // Whether the attestation is revocable.
    bytes data; // Custom attestation data.
}

/// @notice A helper function to work with unchecked iterators in loops.
function uncheckedInc(uint256 i) pure returns (uint256 j) {
    unchecked {
        j = i + 1;
    }
}

File 15 of 22 : IEAS.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { ISchemaRegistry } from "./ISchemaRegistry.sol";
import { ISemver } from "./ISemver.sol";
import { Attestation, Signature } from "./Common.sol";

/// @notice A struct representing the arguments of the attestation request.
struct AttestationRequestData {
    address recipient; // The recipient of the attestation.
    uint64 expirationTime; // The time when the attestation expires (Unix timestamp).
    bool revocable; // Whether the attestation is revocable.
    bytes32 refUID; // The UID of the related attestation.
    bytes data; // Custom attestation data.
    uint256 value; // An explicit ETH amount to send to the resolver. This is important to prevent accidental user errors.
}

/// @notice A struct representing the full arguments of the attestation request.
struct AttestationRequest {
    bytes32 schema; // The unique identifier of the schema.
    AttestationRequestData data; // The arguments of the attestation request.
}

/// @notice A struct representing the full arguments of the full delegated attestation request.
struct DelegatedAttestationRequest {
    bytes32 schema; // The unique identifier of the schema.
    AttestationRequestData data; // The arguments of the attestation request.
    Signature signature; // The ECDSA signature data.
    address attester; // The attesting account.
    uint64 deadline; // The deadline of the signature/request.
}

/// @notice A struct representing the full arguments of the multi attestation request.
struct MultiAttestationRequest {
    bytes32 schema; // The unique identifier of the schema.
    AttestationRequestData[] data; // The arguments of the attestation request.
}

/// @notice A struct representing the full arguments of the delegated multi attestation request.
struct MultiDelegatedAttestationRequest {
    bytes32 schema; // The unique identifier of the schema.
    AttestationRequestData[] data; // The arguments of the attestation requests.
    Signature[] signatures; // The ECDSA signatures data. Please note that the signatures are assumed to be signed with increasing nonces.
    address attester; // The attesting account.
    uint64 deadline; // The deadline of the signature/request.
}

/// @notice A struct representing the arguments of the revocation request.
struct RevocationRequestData {
    bytes32 uid; // The UID of the attestation to revoke.
    uint256 value; // An explicit ETH amount to send to the resolver. This is important to prevent accidental user errors.
}

/// @notice A struct representing the full arguments of the revocation request.
struct RevocationRequest {
    bytes32 schema; // The unique identifier of the schema.
    RevocationRequestData data; // The arguments of the revocation request.
}

/// @notice A struct representing the arguments of the full delegated revocation request.
struct DelegatedRevocationRequest {
    bytes32 schema; // The unique identifier of the schema.
    RevocationRequestData data; // The arguments of the revocation request.
    Signature signature; // The ECDSA signature data.
    address revoker; // The revoking account.
    uint64 deadline; // The deadline of the signature/request.
}

/// @notice A struct representing the full arguments of the multi revocation request.
struct MultiRevocationRequest {
    bytes32 schema; // The unique identifier of the schema.
    RevocationRequestData[] data; // The arguments of the revocation request.
}

/// @notice A struct representing the full arguments of the delegated multi revocation request.
struct MultiDelegatedRevocationRequest {
    bytes32 schema; // The unique identifier of the schema.
    RevocationRequestData[] data; // The arguments of the revocation requests.
    Signature[] signatures; // The ECDSA signatures data. Please note that the signatures are assumed to be signed with increasing nonces.
    address revoker; // The revoking account.
    uint64 deadline; // The deadline of the signature/request.
}

/// @title IEAS
/// @notice EAS - Ethereum Attestation Service interface.
interface IEAS is ISemver {
    /// @notice Emitted when an attestation has been made.
    /// @param recipient The recipient of the attestation.
    /// @param attester The attesting account.
    /// @param uid The UID of the new attestation.
    /// @param schemaUID The UID of the schema.
    event Attested(address indexed recipient, address indexed attester, bytes32 uid, bytes32 indexed schemaUID);

    /// @notice Emitted when an attestation has been revoked.
    /// @param recipient The recipient of the attestation.
    /// @param attester The attesting account.
    /// @param schemaUID The UID of the schema.
    /// @param uid The UID the revoked attestation.
    event Revoked(address indexed recipient, address indexed attester, bytes32 uid, bytes32 indexed schemaUID);

    /// @notice Emitted when a data has been timestamped.
    /// @param data The data.
    /// @param timestamp The timestamp.
    event Timestamped(bytes32 indexed data, uint64 indexed timestamp);

    /// @notice Emitted when a data has been revoked.
    /// @param revoker The address of the revoker.
    /// @param data The data.
    /// @param timestamp The timestamp.
    event RevokedOffchain(address indexed revoker, bytes32 indexed data, uint64 indexed timestamp);

    /// @notice Returns the address of the global schema registry.
    /// @return The address of the global schema registry.
    function getSchemaRegistry() external view returns (ISchemaRegistry);

    /// @notice Attests to a specific schema.
    /// @param request The arguments of the attestation request.
    /// @return The UID of the new attestation.
    ///
    /// Example:
    ///     attest({
    ///         schema: "0facc36681cbe2456019c1b0d1e7bedd6d1d40f6f324bf3dd3a4cef2999200a0",
    ///         data: {
    ///             recipient: "0xdEADBeAFdeAdbEafdeadbeafDeAdbEAFdeadbeaf",
    ///             expirationTime: 0,
    ///             revocable: true,
    ///             refUID: "0x0000000000000000000000000000000000000000000000000000000000000000",
    ///             data: "0xF00D",
    ///             value: 0
    ///         }
    ///     })
    function attest(AttestationRequest calldata request) external payable returns (bytes32);

    /// @notice Attests to a specific schema via the provided ECDSA signature.
    /// @param delegatedRequest The arguments of the delegated attestation request.
    /// @return The UID of the new attestation.
    ///
    /// Example:
    ///     attestByDelegation({
    ///         schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc',
    ///         data: {
    ///             recipient: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
    ///             expirationTime: 1673891048,
    ///             revocable: true,
    ///             refUID: '0x0000000000000000000000000000000000000000000000000000000000000000',
    ///             data: '0x1234',
    ///             value: 0
    ///         },
    ///         signature: {
    ///             v: 28,
    ///             r: '0x148c...b25b',
    ///             s: '0x5a72...be22'
    ///         },
    ///         attester: '0xc5E8740aD971409492b1A63Db8d83025e0Fc427e',
    ///         deadline: 1673891048
    ///     })
    function attestByDelegation(
        DelegatedAttestationRequest calldata delegatedRequest
    ) external payable returns (bytes32);

    /// @notice Attests to multiple schemas.
    /// @param multiRequests The arguments of the multi attestation requests. The requests should be grouped by distinct
    ///     schema ids to benefit from the best batching optimization.
    /// @return The UIDs of the new attestations.
    ///
    /// Example:
    ///     multiAttest([{
    ///         schema: '0x33e9094830a5cba5554d1954310e4fbed2ef5f859ec1404619adea4207f391fd',
    ///         data: [{
    ///             recipient: '0xdEADBeAFdeAdbEafdeadbeafDeAdbEAFdeadbeaf',
    ///             expirationTime: 1673891048,
    ///             revocable: true,
    ///             refUID: '0x0000000000000000000000000000000000000000000000000000000000000000',
    ///             data: '0x1234',
    ///             value: 1000
    ///         },
    ///         {
    ///             recipient: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
    ///             expirationTime: 0,
    ///             revocable: false,
    ///             refUID: '0x480df4a039efc31b11bfdf491b383ca138b6bde160988222a2a3509c02cee174',
    ///             data: '0x00',
    ///             value: 0
    ///         }],
    ///     },
    ///     {
    ///         schema: '0x5ac273ce41e3c8bfa383efe7c03e54c5f0bff29c9f11ef6ffa930fc84ca32425',
    ///         data: [{
    ///             recipient: '0xdEADBeAFdeAdbEafdeadbeafDeAdbEAFdeadbeaf',
    ///             expirationTime: 0,
    ///             revocable: true,
    ///             refUID: '0x75bf2ed8dca25a8190c50c52db136664de25b2449535839008ccfdab469b214f',
    ///             data: '0x12345678',
    ///             value: 0
    ///         },
    ///     }])
    function multiAttest(MultiAttestationRequest[] calldata multiRequests) external payable returns (bytes32[] memory);

    /// @notice Attests to multiple schemas using via provided ECDSA signatures.
    /// @param multiDelegatedRequests The arguments of the delegated multi attestation requests. The requests should be
    ///     grouped by distinct schema ids to benefit from the best batching optimization.
    /// @return The UIDs of the new attestations.
    ///
    /// Example:
    ///     multiAttestByDelegation([{
    ///         schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc',
    ///         data: [{
    ///             recipient: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
    ///             expirationTime: 1673891048,
    ///             revocable: true,
    ///             refUID: '0x0000000000000000000000000000000000000000000000000000000000000000',
    ///             data: '0x1234',
    ///             value: 0
    ///         },
    ///         {
    ///             recipient: '0xdEADBeAFdeAdbEafdeadbeafDeAdbEAFdeadbeaf',
    ///             expirationTime: 0,
    ///             revocable: false,
    ///             refUID: '0x0000000000000000000000000000000000000000000000000000000000000000',
    ///             data: '0x00',
    ///             value: 0
    ///         }],
    ///         signatures: [{
    ///             v: 28,
    ///             r: '0x148c...b25b',
    ///             s: '0x5a72...be22'
    ///         },
    ///         {
    ///             v: 28,
    ///             r: '0x487s...67bb',
    ///             s: '0x12ad...2366'
    ///         }],
    ///         attester: '0x1D86495b2A7B524D747d2839b3C645Bed32e8CF4',
    ///         deadline: 1673891048
    ///     }])
    function multiAttestByDelegation(
        MultiDelegatedAttestationRequest[] calldata multiDelegatedRequests
    ) external payable returns (bytes32[] memory);

    /// @notice Revokes an existing attestation to a specific schema.
    /// @param request The arguments of the revocation request.
    ///
    /// Example:
    ///     revoke({
    ///         schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc',
    ///         data: {
    ///             uid: '0x101032e487642ee04ee17049f99a70590c735b8614079fc9275f9dd57c00966d',
    ///             value: 0
    ///         }
    ///     })
    function revoke(RevocationRequest calldata request) external payable;

    /// @notice Revokes an existing attestation to a specific schema via the provided ECDSA signature.
    /// @param delegatedRequest The arguments of the delegated revocation request.
    ///
    /// Example:
    ///     revokeByDelegation({
    ///         schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc',
    ///         data: {
    ///             uid: '0xcbbc12102578c642a0f7b34fe7111e41afa25683b6cd7b5a14caf90fa14d24ba',
    ///             value: 0
    ///         },
    ///         signature: {
    ///             v: 27,
    ///             r: '0xb593...7142',
    ///             s: '0x0f5b...2cce'
    ///         },
    ///         revoker: '0x244934dd3e31bE2c81f84ECf0b3E6329F5381992',
    ///         deadline: 1673891048
    ///     })
    function revokeByDelegation(DelegatedRevocationRequest calldata delegatedRequest) external payable;

    /// @notice Revokes existing attestations to multiple schemas.
    /// @param multiRequests The arguments of the multi revocation requests. The requests should be grouped by distinct
    ///     schema ids to benefit from the best batching optimization.
    ///
    /// Example:
    ///     multiRevoke([{
    ///         schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc',
    ///         data: [{
    ///             uid: '0x211296a1ca0d7f9f2cfebf0daaa575bea9b20e968d81aef4e743d699c6ac4b25',
    ///             value: 1000
    ///         },
    ///         {
    ///             uid: '0xe160ac1bd3606a287b4d53d5d1d6da5895f65b4b4bab6d93aaf5046e48167ade',
    ///             value: 0
    ///         }],
    ///     },
    ///     {
    ///         schema: '0x5ac273ce41e3c8bfa383efe7c03e54c5f0bff29c9f11ef6ffa930fc84ca32425',
    ///         data: [{
    ///             uid: '0x053d42abce1fd7c8fcddfae21845ad34dae287b2c326220b03ba241bc5a8f019',
    ///             value: 0
    ///         },
    ///     }])
    function multiRevoke(MultiRevocationRequest[] calldata multiRequests) external payable;

    /// @notice Revokes existing attestations to multiple schemas via provided ECDSA signatures.
    /// @param multiDelegatedRequests The arguments of the delegated multi revocation attestation requests. The requests
    ///     should be grouped by distinct schema ids to benefit from the best batching optimization.
    ///
    /// Example:
    ///     multiRevokeByDelegation([{
    ///         schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc',
    ///         data: [{
    ///             uid: '0x211296a1ca0d7f9f2cfebf0daaa575bea9b20e968d81aef4e743d699c6ac4b25',
    ///             value: 1000
    ///         },
    ///         {
    ///             uid: '0xe160ac1bd3606a287b4d53d5d1d6da5895f65b4b4bab6d93aaf5046e48167ade',
    ///             value: 0
    ///         }],
    ///         signatures: [{
    ///             v: 28,
    ///             r: '0x148c...b25b',
    ///             s: '0x5a72...be22'
    ///         },
    ///         {
    ///             v: 28,
    ///             r: '0x487s...67bb',
    ///             s: '0x12ad...2366'
    ///         }],
    ///         revoker: '0x244934dd3e31bE2c81f84ECf0b3E6329F5381992',
    ///         deadline: 1673891048
    ///     }])
    function multiRevokeByDelegation(
        MultiDelegatedRevocationRequest[] calldata multiDelegatedRequests
    ) external payable;

    /// @notice Timestamps the specified bytes32 data.
    /// @param data The data to timestamp.
    /// @return The timestamp the data was timestamped with.
    function timestamp(bytes32 data) external returns (uint64);

    /// @notice Timestamps the specified multiple bytes32 data.
    /// @param data The data to timestamp.
    /// @return The timestamp the data was timestamped with.
    function multiTimestamp(bytes32[] calldata data) external returns (uint64);

    /// @notice Revokes the specified bytes32 data.
    /// @param data The data to timestamp.
    /// @return The timestamp the data was revoked with.
    function revokeOffchain(bytes32 data) external returns (uint64);

    /// @notice Revokes the specified multiple bytes32 data.
    /// @param data The data to timestamp.
    /// @return The timestamp the data was revoked with.
    function multiRevokeOffchain(bytes32[] calldata data) external returns (uint64);

    /// @notice Returns an existing attestation by UID.
    /// @param uid The UID of the attestation to retrieve.
    /// @return The attestation data members.
    function getAttestation(bytes32 uid) external view returns (Attestation memory);

    /// @notice Checks whether an attestation exists.
    /// @param uid The UID of the attestation to retrieve.
    /// @return Whether an attestation exists.
    function isAttestationValid(bytes32 uid) external view returns (bool);

    /// @notice Returns the timestamp that the specified data was timestamped with.
    /// @param data The data to query.
    /// @return The timestamp the data was timestamped with.
    function getTimestamp(bytes32 data) external view returns (uint64);

    /// @notice Returns the timestamp that the specified data was timestamped with.
    /// @param data The data to query.
    /// @return The timestamp the data was timestamped with.
    function getRevokeOffchain(address revoker, bytes32 data) external view returns (uint64);
}

File 16 of 22 : Semver.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.4;

import { Strings } from "@openzeppelin/contracts/utils/Strings.sol";

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

/// @title Semver
/// @notice A simple contract for managing contract versions.
contract Semver is ISemver {
    // Contract's major version number.
    uint256 private immutable _major;

    // Contract's minor version number.
    uint256 private immutable _minor;

    // Contract's patch version number.
    uint256 private immutable _patch;

    /// @dev Create a new Semver instance.
    /// @param major Major version number.
    /// @param minor Minor version number.
    /// @param patch Patch version number.
    constructor(uint256 major, uint256 minor, uint256 patch) {
        _major = major;
        _minor = minor;
        _patch = patch;
    }

    /// @notice Returns the full semver contract version.
    /// @return Semver contract version as a string.
    function version() external view returns (string memory) {
        return
            string(
                abi.encodePacked(Strings.toString(_major), ".", Strings.toString(_minor), ".", Strings.toString(_patch))
            );
    }
}

File 17 of 22 : ISchemaResolver.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { Attestation } from "./../Common.sol";
import { ISemver } from "./../ISemver.sol";

/// @title ISchemaResolver
/// @notice The interface of an optional schema resolver.
interface ISchemaResolver is ISemver {
    /// @notice Checks if the resolver can be sent ETH.
    /// @return Whether the resolver supports ETH transfers.
    function isPayable() external pure returns (bool);

    /// @notice Processes an attestation and verifies whether it's valid.
    /// @param attestation The new attestation.
    /// @return Whether the attestation is valid.
    function attest(Attestation calldata attestation) external payable returns (bool);

    /// @notice Processes multiple attestations and verifies whether they are valid.
    /// @param attestations The new attestations.
    /// @param values Explicit ETH amounts which were sent with each attestation.
    /// @return Whether all the attestations are valid.
    function multiAttest(
        Attestation[] calldata attestations,
        uint256[] calldata values
    ) external payable returns (bool);

    /// @notice Processes an attestation revocation and verifies if it can be revoked.
    /// @param attestation The existing attestation to be revoked.
    /// @return Whether the attestation can be revoked.
    function revoke(Attestation calldata attestation) external payable returns (bool);

    /// @notice Processes revocation of multiple attestation and verifies they can be revoked.
    /// @param attestations The existing attestations to be revoked.
    /// @param values Explicit ETH amounts which were sent with each revocation.
    /// @return Whether the attestations can be revoked.
    function multiRevoke(
        Attestation[] calldata attestations,
        uint256[] calldata values
    ) external payable returns (bool);
}

File 18 of 22 : IERC721Receiver.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721Receiver.sol)

pragma solidity ^0.8.20;

/**
 * @title ERC721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC721 asset contracts.
 */
interface IERC721Receiver {
    /**
     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
     * by `operator` from `from`, this function is called.
     *
     * It must return its Solidity selector to confirm the token transfer.
     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be
     * reverted.
     *
     * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
     */
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

File 19 of 22 : IERC721Metadata.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/IERC721Metadata.sol)

pragma solidity ^0.8.20;

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

/**
 * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Metadata is IERC721 {
    /**
     * @dev Returns the token collection name.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the token collection symbol.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
     */
    function tokenURI(uint256 tokenId) external view returns (string memory);
}

File 20 of 22 : draft-IERC6093.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol)
pragma solidity ^0.8.20;

/**
 * @dev Standard ERC20 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens.
 */
interface IERC20Errors {
    /**
     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param balance Current balance for the interacting account.
     * @param needed Minimum amount required to perform a transfer.
     */
    error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC20InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC20InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.
     * @param spender Address that may be allowed to operate on tokens without being their owner.
     * @param allowance Amount of tokens a `spender` is allowed to operate with.
     * @param needed Minimum amount required to perform a transfer.
     */
    error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC20InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `spender` to be approved. Used in approvals.
     * @param spender Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC20InvalidSpender(address spender);
}

/**
 * @dev Standard ERC721 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens.
 */
interface IERC721Errors {
    /**
     * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20.
     * Used in balance queries.
     * @param owner Address of the current owner of a token.
     */
    error ERC721InvalidOwner(address owner);

    /**
     * @dev Indicates a `tokenId` whose `owner` is the zero address.
     * @param tokenId Identifier number of a token.
     */
    error ERC721NonexistentToken(uint256 tokenId);

    /**
     * @dev Indicates an error related to the ownership over a particular token. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param tokenId Identifier number of a token.
     * @param owner Address of the current owner of a token.
     */
    error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC721InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC721InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     * @param tokenId Identifier number of a token.
     */
    error ERC721InsufficientApproval(address operator, uint256 tokenId);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC721InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC721InvalidOperator(address operator);
}

/**
 * @dev Standard ERC1155 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens.
 */
interface IERC1155Errors {
    /**
     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param balance Current balance for the interacting account.
     * @param needed Minimum amount required to perform a transfer.
     * @param tokenId Identifier number of a token.
     */
    error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC1155InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC1155InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     * @param owner Address of the current owner of a token.
     */
    error ERC1155MissingApprovalForAll(address operator, address owner);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC1155InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC1155InvalidOperator(address operator);

    /**
     * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.
     * Used in batch transfers.
     * @param idsLength Length of the array of token identifiers
     * @param valuesLength Length of the array of token amounts
     */
    error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}

File 21 of 22 : ISchemaRegistry.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

import { ISchemaResolver } from "./resolver/ISchemaResolver.sol";

/// @notice A struct representing a record for a submitted schema.
struct SchemaRecord {
    bytes32 uid; // The unique identifier of the schema.
    ISchemaResolver resolver; // Optional schema resolver.
    bool revocable; // Whether the schema allows revocations explicitly.
    string schema; // Custom specification of the schema (e.g., an ABI).
}

/// @title ISchemaRegistry
/// @notice The interface of global attestation schemas for the Ethereum Attestation Service protocol.
interface ISchemaRegistry is ISemver {
    /// @notice Emitted when a new schema has been registered
    /// @param uid The schema UID.
    /// @param registerer The address of the account used to register the schema.
    /// @param schema The schema data.
    event Registered(bytes32 indexed uid, address indexed registerer, SchemaRecord schema);

    /// @notice Submits and reserves a new schema
    /// @param schema The schema data schema.
    /// @param resolver An optional schema resolver.
    /// @param revocable Whether the schema allows revocations explicitly.
    /// @return The UID of the new schema.
    function register(string calldata schema, ISchemaResolver resolver, bool revocable) external returns (bytes32);

    /// @notice Returns an existing schema by UID
    /// @param uid The UID of the schema to retrieve.
    /// @return The schema data members.
    function getSchema(bytes32 uid) external view returns (SchemaRecord memory);
}

File 22 of 22 : ISemver.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/// @title ISemver
/// @notice A semver interface.
interface ISemver {
    /// @notice Returns the full semver contract version.
    /// @return Semver contract version as a string.
    function version() external view returns (string memory);
}

Settings
{
  "viaIR": false,
  "codegen": "yul",
  "remappings": [
    "@openzeppelin/=node_modules/@openzeppelin/",
    "@erc721a/=deps/erc721a/contracts/",
    "forge-std/=lib/forge-std/src/",
    "@ethereum-attestation-service/=node_modules/@ethereum-attestation-service/"
  ],
  "evmVersion": "cancun",
  "outputSelection": {
    "*": {
      "*": [
        "abi",
        "metadata"
      ],
      "": [
        "ast"
      ]
    }
  },
  "optimizer": {
    "enabled": true,
    "mode": "3",
    "fallback_to_optimizing_for_size": false,
    "disable_system_request_memoization": true
  },
  "metadata": {},
  "libraries": {},
  "detectMissingLibraries": false,
  "enableEraVMExtensions": false,
  "forceEVMLA": false
}

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"initialOwner","type":"address"},{"internalType":"address","name":"easContractAddress","type":"address"},{"internalType":"string","name":"baseURI","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessDenied","type":"error"},{"inputs":[],"name":"ERC721EnumerableForbiddenBatchMint","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC721IncorrectOwner","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721InsufficientApproval","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC721InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"ERC721InvalidOperator","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"ERC721InvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC721InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC721InvalidSender","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721NonexistentToken","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"ERC721OutOfBoundsIndex","type":"error"},{"inputs":[],"name":"InsufficientValue","type":"error"},{"inputs":[],"name":"InvalidEAS","type":"error"},{"inputs":[],"name":"InvalidLength","type":"error"},{"inputs":[],"name":"NotPayable","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","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":false,"internalType":"uint256","name":"badgeType","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"level","type":"uint256"},{"indexed":false,"internalType":"string","name":"name","type":"string"}],"name":"BadgeAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"badgeType","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"level","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"BadgeClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"newBaseURI","type":"string"}],"name":"BaseURIUpdated","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":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"uint256","name":"badgeType","type":"uint256"},{"internalType":"uint256","name":"level","type":"uint256"},{"internalType":"bool","name":"active","type":"bool"}],"name":"addBadge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"uid","type":"bytes32"},{"internalType":"bytes32","name":"schema","type":"bytes32"},{"internalType":"uint64","name":"time","type":"uint64"},{"internalType":"uint64","name":"expirationTime","type":"uint64"},{"internalType":"uint64","name":"revocationTime","type":"uint64"},{"internalType":"bytes32","name":"refUID","type":"bytes32"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"address","name":"attester","type":"address"},{"internalType":"bool","name":"revocable","type":"bool"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct Attestation","name":"attestation","type":"tuple"}],"name":"attest","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"badgeInfos","outputs":[{"internalType":"uint256","name":"badgeType","type":"uint256"},{"internalType":"uint256","name":"level","type":"uint256"},{"internalType":"bool","name":"active","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"badgeTypeNames","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"badgeType","type":"uint256"},{"internalType":"uint256","name":"level","type":"uint256"}],"name":"canClaim","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"claimed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getUserBadges","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isPayable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"uid","type":"bytes32"},{"internalType":"bytes32","name":"schema","type":"bytes32"},{"internalType":"uint64","name":"time","type":"uint64"},{"internalType":"uint64","name":"expirationTime","type":"uint64"},{"internalType":"uint64","name":"revocationTime","type":"uint64"},{"internalType":"bytes32","name":"refUID","type":"bytes32"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"address","name":"attester","type":"address"},{"internalType":"bool","name":"revocable","type":"bool"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct Attestation[]","name":"attestations","type":"tuple[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"multiAttest","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"uid","type":"bytes32"},{"internalType":"bytes32","name":"schema","type":"bytes32"},{"internalType":"uint64","name":"time","type":"uint64"},{"internalType":"uint64","name":"expirationTime","type":"uint64"},{"internalType":"uint64","name":"revocationTime","type":"uint64"},{"internalType":"bytes32","name":"refUID","type":"bytes32"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"address","name":"attester","type":"address"},{"internalType":"bool","name":"revocable","type":"bool"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct Attestation[]","name":"attestations","type":"tuple[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"multiRevoke","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"payable","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":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"uid","type":"bytes32"},{"internalType":"bytes32","name":"schema","type":"bytes32"},{"internalType":"uint64","name":"time","type":"uint64"},{"internalType":"uint64","name":"expirationTime","type":"uint64"},{"internalType":"uint64","name":"revocationTime","type":"uint64"},{"internalType":"bytes32","name":"refUID","type":"bytes32"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"address","name":"attester","type":"address"},{"internalType":"bool","name":"revocable","type":"bool"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct Attestation","name":"attestation","type":"tuple"}],"name":"revoke","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","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":"tokenId","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":"uint256","name":"badgeType","type":"uint256"},{"internalType":"string","name":"name","type":"string"}],"name":"setBadgeTypeName","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"baseURI","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokenToBadgeInfo","outputs":[{"internalType":"uint256","name":"badgeType","type":"uint256"},{"internalType":"uint256","name":"level","type":"uint256"},{"internalType":"bool","name":"active","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","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":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"userBadgeTokenIds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]

9c4d535b0000000000000000000000000000000000000000000000000000000000000000010005b5bb9539b3fdbe6769f287a6a8ba636fa1cce49d5b44ea701e215ab697000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000299174d47c243b5381c6062abefbff915b601d85000000000000000000000000ef273702f027e5aff29e7553f5dbee8e6e248cab0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002768747470733a2f2f6170692e736f70686f6e2e78797a2f6261646765732f6d657461646174612f00000000000000000000000000000000000000000000000000

Deployed Bytecode

0x0003000000000002000e00000000000200020000000103550000006003100270000005180030019d000005180330019700000001002001900000002c0000c13d0000008004000039000000400040043f000000040030008c0000006d0000413d000000000201043b000000e002200270000005390020009c000000730000a13d0000053a0020009c000000880000213d000005470020009c000000cb0000a13d000005480020009c000002010000a13d000005490020009c000005050000613d0000054a0020009c000004090000613d0000054b0020009c00000cb10000c13d000000240030008c00000cb10000413d0000000002000416000000000002004b00000cb10000c13d0000000401100370000000000101043b000000000010043f0000000c01000039000000200010043f0000004001000039145a14260000040f0000008002000039145a0d140000040f000000800210008a000007380000013d0000010004000039000000400040043f0000000002000416000000000002004b00000cb10000c13d0000001f0230003900000519022001970000010002200039000000400020043f0000001f0530018f0000051a0630019800000100026000390000003e0000613d000000000701034f000000007807043c0000000004840436000000000024004b0000003a0000c13d000000000005004b0000004b0000613d000000000161034f0000000304500210000000000502043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f0000000000120435000000600030008c00000cb10000413d000001000a00043d0000051b00a0009c00000cb10000213d000001200100043d000800000001001d0000051b0010009c00000cb10000213d000001400200043d0000051c0020009c00000cb10000213d0000001f01200039000000000031004b00000000040000190000051d040080410000051d01100197000000000001004b00000000050000190000051d050040410000051d0010009c000000000504c019000000000005004b00000cb10000c13d000001000120003900000000010104330000051c0010009c000002820000a13d0000058f01000041000000000010043f0000004101000039000000040010043f0000056d010000410000145c00010430000000000003004b00000cb10000c13d0000053801000041000000000010043f00000537010000410000145c00010430000005530020009c000000ae0000a13d000005540020009c000001190000a13d000005550020009c000002250000a13d000005560020009c000005400000613d000005570020009c0000049b0000613d000005580020009c00000cb10000c13d000000240030008c00000cb10000413d0000000002000416000000000002004b00000cb10000c13d0000000401100370000000000101043b145a0ee60000040f000004f60000013d0000053b0020009c000000ea0000a13d0000053c0020009c000002190000a13d0000053d0020009c000005210000613d0000053e0020009c000004730000613d0000053f0020009c00000cb10000c13d0000000001000416000000000001004b00000cb10000c13d0000000001030019145a0d040000040f000700000002001d000800000003001d0000051b01100197000000000010043f0000001001000039000000200010043f0000004001000039145a14260000040f0000000702000029000000000020043f000000200010043f0000004001000039145a14260000040f0000000802000029000000000020043f000000200010043f0000004001000039145a14260000040f000000000101041a000000ff001001900000000001000039000000010100c039000004f60000013d000005600020009c0000012e0000213d000005660020009c000002660000213d000005690020009c000004cc0000613d0000056a0020009c00000cb10000c13d0000000001000416000000000001004b00000cb10000c13d000000000200041a000000010320019000000001012002700000007f0110618f0000001f0010008c00000000040000390000000104002039000000000442013f0000000100400190000002130000c13d000000800010043f000000000003004b000007150000613d000000000000043f000000000001004b0000072e0000c13d0000008002000039000007370000013d0000054e0020009c000001ba0000213d000005510020009c000002ad0000613d000005520020009c00000cb10000c13d0000000001000416000000000001004b00000cb10000c13d0000000a01000039000000000201041a0000051b052001970000000003000411000000000035004b0000057f0000c13d0000052602200197000000000021041b0000000001000414000005180010009c0000051801008041000000c00110021000000527011001c70000800d02000039000000030300003900000528040000410000000006000019145a14500000040f000000010020019000000cb10000613d00000000010000190000145b0001042e000005420020009c000001c70000213d000005450020009c000002b80000613d000005460020009c00000cb10000c13d000000240030008c00000cb10000413d0000000002000416000000000002004b00000cb10000c13d0000000401100370000000000101043b000800000001001d000000000010043f0000000201000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f000000010020019000000cb10000613d000000000101043b000000000101041a0000051b00100198000006870000c13d000000400100043d00000044021000390000057d0300004100000000003204350000002402100039000000140300003900000000003204350000057e020000410000000000210435000000040210003900000020030000390000000000320435000005180010009c000005180100804100000040011002100000057f011001c70000145c000104300000055b0020009c000001e40000213d0000055e0020009c000003610000613d0000055f0020009c00000cb10000c13d000000240030008c00000cb10000413d0000000002000416000000000002004b00000cb10000c13d0000000401100370000000000101043b000700000001001d0000051b0010009c00000cb10000213d0000000701000029000000000001004b000006ab0000c13d0000059001000041000004850000013d000005610020009c000002740000213d000005640020009c000004dd0000613d000005650020009c00000cb10000c13d000000640030008c00000cb10000413d0000000002000416000000000002004b00000cb10000c13d0000002402100370000000000202043b000800000002001d0000000402100370000000000202043b000700000002001d0000004401100370000000000101043b000000000001004b0000000002000039000000010200c039000000000021004b00000cb10000c13d0000000a02000039000000000202041a0000051b032001970000000002000411000000000023004b000006240000c13d000000e002000039000000400020043f0000000703000029000000800030043f0000000802000029000000a00020043f000000c00010043f000000000030043f0000000e01000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f000000010020019000000cb10000613d000000000101043b0000000802000029000000000020043f000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f000000010020019000000cb10000613d000000000101043b000000800200043d000000000021041b0000000102100039000000a00300043d000000000032041b0000000201100039000000000201041a0000059b02200197000000c00300043d000000000003004b000000010220c1bf000000000021041b0000000701000029000000000010043f0000000c01000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f000000010020019000000cb10000613d000000000101043b000000400500043d00000040025000390000006003000039000000000032043500000020025000390000000803000029000000000032043500000007020000290000000000250435000000000201041a000000010320019000000001062002700000007f0660618f0000001f0060008c00000000040000390000000104002039000000000442013f0000000100400190000002130000c13d000800000005001d0000006004500039000700000006001d0000000000640435000000000003004b000008970000613d000000000010043f0000000001000414000005180010009c0000051801008041000000c00110021000000523011001c70000801002000039145a14550000040f000000010020019000000cb10000613d0000000706000029000000000006004b00000000020000190000089e0000613d00000008020000290000008003200039000000000101043b00000000020000190000000004320019000000000501041a000000000054043500000001011000390000002002200039000000000062004b000001b20000413d0000089e0000013d0000054f0020009c0000030b0000613d000005500020009c00000cb10000c13d0000000001000416000000000001004b00000cb10000c13d0000000a01000039000000000101041a0000051b01100197000000800010043f0000056f010000410000145b0001042e000005430020009c0000035b0000613d000005440020009c00000cb10000c13d0000000001000416000000000001004b00000cb10000c13d0000000001030019145a0d040000040f000700000002001d000800000003001d0000051b01100197000000000010043f0000001101000039000000200010043f0000004001000039145a14260000040f0000000702000029000000000020043f000000200010043f0000004001000039145a14260000040f0000000802000029000000000020043f000000200010043f0000004001000039145a14260000040f000000000101041a000004f60000013d0000055c0020009c0000036f0000613d0000055d0020009c00000cb10000c13d0000000001000416000000000001004b00000cb10000c13d0000000001030019145a0ce50000040f000800000001001d000700000002001d000600000003001d000000400100043d000500000001001d0000002002000039145a0d4d0000040f00000005010000290000000000010435000000080100002900000007020000290000000603000029145a0d710000040f0000000801000029000000070200002900000006030000290000000504000029145a132f0000040f00000000010000190000145b0001042e0000054c0020009c000003900000613d0000054d0020009c00000cb10000c13d0000000001000416000000000001004b00000cb10000c13d0000000103000039000000000203041a000000010520019000000001012002700000007f0110618f0000001f0010008c00000000060000390000000106002039000000000662013f0000000100600190000005840000613d0000058f01000041000000000010043f0000002201000039000000040010043f0000056d010000410000145c00010430000005400020009c000003ff0000613d000005410020009c00000cb10000c13d0000000001030019145a0d5f0000040f000800000001001d145a0f4d0000040f0000000801000029145a0f670000040f0000000101000039000004f60000013d000005590020009c000004890000613d0000055a0020009c00000cb10000c13d0000000001000416000000000001004b00000cb10000c13d0000000001000412000e00000001001d000d00000000003d0000800501000039000000440300003900000000040004150000000e0440008a00000005044002100000058102000041145a14370000040f145a0f010000040f0000000002000412000c00000002001d000b00200000003d000700000001001d00000000040004150000000c0440008a0000000504400210000080050100003900000581020000410000004403000039145a14370000040f145a0f010000040f0000000002000412000a00000002001d000900400000003d000800000001001d00000000040004150000000a0440008a0000000504400210000080050100003900000581020000410000004403000039145a14370000040f145a0f010000040f000000070300002900000000430304340000059c073001970000001f0530018f000000400d00043d0000002006d00039000000000064004b000005940000813d000000000007004b000002630000613d00000000095400190000000008560019000000200880008a000000200990008a000000000a780019000000000b790019000000000b0b04330000000000ba0435000000200770008c0000025d0000c13d000000000005004b000005a00000c13d000005aa0000013d000005670020009c000004e50000613d000005680020009c00000cb10000c13d000000440030008c00000cb10000413d0000000002000416000000000002004b00000cb10000c13d0000000401100370000000000101043b0000051b0010009c000005150000a13d00000cb10000013d000005620020009c000004fd0000613d000005630020009c00000cb10000c13d000000240030008c00000cb10000413d0000000002000416000000000002004b00000cb10000c13d0000000401100370000000000101043b000000000010043f0000000f01000039000003800000013d0000001f041000390000059c044001970000003f044000390000059c04400197000000400600043d0000000004460019000000000064004b000000000500003900000001050040390000051c0040009c000000670000213d0000000100500190000000670000c13d0000010003300039000000400040043f000600000006001d0000000004160436000700000004001d00000120022000390000000004210019000000000034004b00000cb10000213d0000059c041001970000001f0310018f0000000709000029000000000092004b000006290000813d000000000004004b000002a90000613d00000000063200190000000005390019000000200550008a000000200660008a0000000007450019000000000846001900000000080804330000000000870435000000200440008c000002a30000c13d000000000003004b0000063f0000613d0000000005090019000006350000013d000000240030008c00000cb10000413d0000000002000416000000000002004b00000cb10000c13d0000000401100370000000000101043b0000051b0010009c00000cb10000213d145a0ece0000040f000004f60000013d000000840030008c00000cb10000413d0000000002000416000000000002004b00000cb10000c13d0000000402100370000000000202043b0000051b0020009c00000cb10000213d00000000090200190000002402100370000000000202043b0000051b0020009c00000cb10000213d000000000a0200190000004402100370000000000b02043b0000006402100370000000000402043b0000051c0040009c00000cb10000213d0000002302400039000000000032004b00000cb10000813d0000000405400039000000000251034f000000000202043b0000051c0020009c000000670000213d0000001f072000390000059c077001970000003f077000390000059c07700197000005800070009c000000670000213d0000008007700039000000400070043f000000800020043f00000000042400190000002404400039000000000034004b00000cb10000213d0000002003500039000000000331034f0000059c042001980000001f0520018f000000a001400039000002ee0000613d000000a006000039000000000703034f000000007807043c0000000006860436000000000016004b000002ea0000c13d000000000005004b000002fb0000613d000000000343034f0000000304500210000000000501043300000000054501cf000000000545022f000000000303043b0000010004400089000000000343022f00000000034301cf000000000353019f0000000000310435000000a00120003900000000000104350000000001090019000800000009001d00000000020a001900070000000a001d00000000030b001900060000000b001d145a0d710000040f0000008004000039000000080100002900000007020000290000000603000029145a132f0000040f00000000010000190000145b0001042e000000440030008c00000cb10000413d0000000402100370000000000202043b000800000002001d0000051c0020009c00000cb10000213d00000008020000290000002302200039000000000032004b00000cb10000813d0000000802000029000600040020003d0000000602100360000000000202043b000700000002001d0000051c0020009c00000cb10000213d0000000702000029000000050220021000000008022000290000002402200039000000000032004b00000cb10000213d0000002402100370000000000202043b0000051c0020009c00000cb10000213d0000002304200039000000000034004b00000cb10000813d000400040020003d0000000401100360000000000101043b000500000001001d0000051c0010009c00000cb10000213d0000000501000029000000050110021000000000011200190000002401100039000000000031004b00000cb10000213d0000058101000041000000000010044300000000010004120000000400100443000000600100003900000024001004430000000001000414000005180010009c0000051801008041000000c00110021000000582011001c70000800502000039145a14550000040f0000000100200190000008240000613d000000000101043b0000051b011001970000000002000411000000000012004b000008310000c13d0000000702000029000000050020006c000009570000c13d000000050000006b00000a8a0000613d000000040100002900000020021000390000000201000367000000000221034f000000000202043b0000000003000416000000000032004b00000a760000a13d0000058501000041000000000010043f00000537010000410000145c000104300000000001000416000000000001004b00000cb10000c13d000000800000043f0000056f010000410000145b0001042e000000440030008c00000cb10000413d0000000002000416000000000002004b00000cb10000c13d0000000402100370000000000302043b0000051b0030009c00000cb10000213d0000002401100370000000000201043b0000000001030019145a0e7f0000040f000004f60000013d000000440030008c00000cb10000413d0000000002000416000000000002004b00000cb10000c13d0000002402100370000000000202043b000800000002001d0000000401100370000000000101043b000000000010043f0000000e01000039000000200010043f0000004001000039145a14260000040f0000000802000029000000000020043f000000200010043f0000004001000039145a14260000040f0000000202100039000000000202041a0000000103100039000000000303041a000000000101041a000000800010043f000000a00030043f000000ff002001900000000001000039000000010100c039000000c00010043f0000058d010000410000145b0001042e000000440030008c00000cb10000413d0000000402100370000000000202043b000600000002001d0000051c0020009c00000cb10000213d00000006020000290000002302200039000000000032004b00000cb10000813d00000006020000290000000402200039000000000221034f000000000202043b000800000002001d0000051c0020009c00000cb10000213d00000006020000290000002405200039000000080200002900000005022002100000000002520019000000000032004b00000cb10000213d0000002402100370000000000202043b0000051c0020009c00000cb10000213d0000002304200039000000000034004b00000cb10000813d0000000404200039000000000141034f000000000101043b000500000001001d0000051c0010009c00000cb10000213d000400240020003d000000050100002900000005011002100000000401100029000000000031004b00000cb10000213d000300000005001d0000058101000041000000000010044300000000010004120000000400100443000000600100003900000024001004430000000001000414000005180010009c0000051801008041000000c00110021000000582011001c70000800502000039145a14550000040f0000000100200190000008240000613d000000000101043b0000051b011001970000000002000411000000000012004b000008310000c13d0000000802000029000000050020006c000009570000c13d000000050000006b000003fb0000613d0000000001000416000800000001001d0000000002000019000700000002001d000000050120021000000004031000290000000202000367000000000332034f000000000303043b00080008003000730000000306000029000003570000413d0000000001610019000000000112034f000000000101043b00000006020000290000000002200079000001630220008a0000051d031001970000051d04200197000000000543013f000000000043004b00000000030000190000051d03004041000000000021004b00000000020000190000051d020080410000051d0050009c000000000302c019000000000003004b00000cb10000c13d0000000001610019145a0f670000040f00000007020000290000000102200039000000050020006c000003d90000413d000000400100043d00000001020000390000000000210435000004040000013d0000000001030019145a0d5f0000040f145a0f4d0000040f000000400100043d0000000000010435000005180010009c000005180100804100000040011002100000056b011001c70000145b0001042e000000440030008c00000cb10000413d0000000002000416000000000002004b00000cb10000c13d0000002402100370000000000202043b0000051c0020009c00000cb10000213d0000002304200039000000000034004b00000cb10000813d000700040020003d0000000704100360000000000404043b000800000004001d0000051c0040009c00000cb10000213d0000002404200039000600000004001d0000000802400029000000000032004b00000cb10000213d0000000a02000039000000000202041a0000051b032001970000000002000411000000000023004b000006240000c13d0000000401100370000000000101043b000000000010043f0000000c01000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f000000010020019000000cb10000613d000000000101043b000500000001001d000000000101041a000000010010019000000001031002700000007f0330618f0000001f0030008c00000000020000390000000102002039000000000121013f0000000100100190000002130000c13d000400000003001d000000200030008c0000045f0000413d0000000501000029000000000010043f0000000001000414000005180010009c0000051801008041000000c00110021000000523011001c70000801002000039145a14550000040f000000010020019000000cb10000613d00000008030000290000001f023000390000000502200270000000200030008c0000000002004019000000000301043b00000004010000290000001f01100039000000050110027000000000011300190000000002230019000000000012004b0000045f0000813d000000000002041b0000000102200039000000000012004b0000045b0000413d00000008010000290000001f0010008c000008f60000a13d0000000501000029000000000010043f0000000001000414000005180010009c0000051801008041000000c00110021000000523011001c70000801002000039145a14550000040f000000010020019000000cb10000613d000000200200008a0000000802200180000000000101043b000009da0000c13d0000000003000019000009e50000013d000000240030008c00000cb10000413d0000000002000416000000000002004b00000cb10000c13d0000000401100370000000000601043b0000051b0060009c00000cb10000213d0000000a01000039000000000201041a0000051b052001970000000003000411000000000035004b0000057f0000c13d000000000006004b000007220000c13d0000056e01000041000000000010043f000000040000043f0000056d010000410000145c00010430000000240030008c00000cb10000413d0000000002000416000000000002004b00000cb10000c13d0000000401100370000000000101043b0000000802000039000000000202041a000000000021004b0000061e0000813d145a0ec00000040f0000000302200210000000000101041a000000000121022f000000ff0020008c0000000001002019000004f60000013d000000640030008c00000cb10000413d0000000002000416000000000002004b00000cb10000c13d0000000402100370000000000202043b000800000002001d0000051b0020009c00000cb10000213d0000004402100370000000000202043b000700000002001d0000002401100370000000000101043b000600000001001d000000000010043f0000000e01000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f000000010020019000000cb10000613d000000000101043b0000000702000029000000000020043f000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f000000010020019000000cb10000613d000000000101043b0000000201100039000000000101041a000000ff0010019000000000010000190000074a0000c13d000000010110018f000004f60000013d000000240030008c00000cb10000413d0000000002000416000000000002004b00000cb10000c13d0000000401100370000000000201043b000005950020019800000cb10000c13d0000000101000039000005960020009c0000071b0000213d000005990020009c000004e20000613d0000059a0020009c000004e20000613d0000071f0000013d0000000001000416000000000001004b00000cb10000c13d0000000801000039000000000101041a000000800010043f0000056f010000410000145b0001042e000000240030008c00000cb10000413d0000000002000416000000000002004b00000cb10000c13d0000000401100370000000000101043b000800000001001d145a0ee60000040f0000000801000029000000000010043f0000000401000039000000200010043f0000004001000039145a14260000040f000000000101041a0000051b01100197000000400200043d0000000000120435000005180020009c000005180200804100000040012002100000056b011001c70000145b0001042e0000000001000416000000000001004b00000cb10000c13d0000000001030019145a0ce50000040f145a0d710000040f00000000010000190000145b0001042e000000440030008c00000cb10000413d0000000002000416000000000002004b00000cb10000c13d0000000402100370000000000202043b0000051b0020009c00000cb10000213d0000002401100370000000000101043b000000000001004b0000000002000039000000010200c039000000000021004b00000cb10000c13d0000057e01000041000000800010043f0000002001000039000000840010043f0000003601000039000000a40010043f0000059201000041000000c40010043f0000059301000041000000e40010043f00000594010000410000145c00010430000000440030008c00000cb10000413d0000000002000416000000000002004b00000cb10000c13d0000000402100370000000000202043b0000051b0020009c00000cb10000213d0000002401100370000000000101043b000800000001001d0000051b0010009c00000cb10000213d000000000020043f0000000501000039000000200010043f0000004001000039145a14260000040f0000000802000029000000000020043f000000200010043f0000004001000039145a14260000040f000000000101041a000000ff001001900000000001000039000000010100c039000000800010043f0000056f010000410000145b0001042e000000240030008c00000cb10000413d0000000002000416000000000002004b00000cb10000c13d0000000402100370000000000502043b0000051c0050009c00000cb10000213d0000002302500039000000000032004b00000cb10000813d0000000404500039000000000241034f000000000202043b0000051c0020009c00000cb10000213d00000024065000390000000005620019000000000035004b00000cb10000213d0000000a03000039000000000303041a0000051b053001970000000003000411000000000035004b0000057f0000c13d0000000d05000039000000000305041a000000010030019000000001073002700000007f0770618f0000001f0070008c00000000080000390000000108002039000000000383013f0000000100300190000002130000c13d000000200070008c0000001f03200039000005770000413d000000000050043f0000000508300270000005290880009a000000200020008c0000052a080040410000001f077000390000000507700270000005290770009a000000000078004b000005770000813d000000000008041b0000000108800039000000000078004b000005730000413d0000001f0020008c000008250000a13d000000000050043f0000059c08200198000008b10000c13d0000052a070000410000000009000019000008bb0000013d0000056c01000041000000000010043f000000040030043f0000056d010000410000145c00010430000000800010043f000000000005004b0000070e0000613d000000000030043f000000000001004b000007130000613d00000525020000410000000003000019000000000502041a000000a004300039000000000054043500000001022000390000002003300039000000000013004b0000058c0000413d000007130000013d0000000008760019000000000007004b0000059c0000613d0000000009040019000000009a0904340000000006a60436000000000086004b000005980000c13d000000000005004b000005aa0000613d000000000474001900000000060800190000000305500210000000000706043300000000075701cf000000000757022f00000000040404330000010005500089000000000454022f00000000045401cf000000000474019f00000000004604350000000003d3001900000020043000390000058a050000410000000000540435000000080500002900000000040504330000059c084001970000001f0740018f00000021063000390000002005500039000000000065004b000005c50000813d000000000008004b000005c20000613d000000000a7500190000000009760019000000200990008a000000200aa0008a000000000b890019000000000c8a0019000000000c0c04330000000000cb0435000000200880008c000005bc0000c13d000000000007004b000005d10000c13d000005db0000013d0000000009860019000000000008004b000005cd0000613d000000000a05001900000000ab0a04340000000006b60436000000000096004b000005c90000c13d000000000007004b000005db0000613d000000000585001900000000060900190000000307700210000000000806043300000000087801cf000000000878022f00000000050504330000010007700089000000000575022f00000000057501cf000000000585019f0000000000560435000000000734001900000021037000390000058a040000410000000000430435000000200370003900000000040104330000059c064001970000001f0540018f00000022027000390000002001100039000000000021004b000005f60000813d000000000006004b000005f30000613d00000000085100190000000007520019000000200770008a000000200880008a0000000009670019000000000a680019000000000a0a04330000000000a90435000000200660008c000005ed0000c13d000000000005004b000006020000c13d0000060c0000013d0000000007620019000000000006004b000005fe0000613d000000000801001900000000890804340000000002920436000000000072004b000005fa0000c13d000000000005004b0000060c0000613d000000000161001900000000020700190000000305500210000000000602043300000000065601cf000000000656022f00000000010104330000010005500089000000000151022f00000000015101cf000000000161019f00000000001204350000000001430019000000020210003900000000000204350000000001d100490000001e0210008a00000000002d0435000000020210003900000000010d001900080000000d001d145a0d4d0000040f0000002001000039000000400200043d000700000002001d00000000021204360000000801000029145a0cb30000040f0000000702000029000007410000013d0000058b02000041000000000020043f000000040000043f000000240010043f0000058c010000410000145c000104300000056c01000041000000000010043f000000040020043f0000056d010000410000145c000104300000000005490019000000000004004b000006320000613d0000000006020019000000000709001900000000680604340000000007870436000000000057004b0000062e0000c13d000000000003004b0000063f0000613d00000000024200190000000303300210000000000405043300000000043401cf000000000434022f00000000020204330000010003300089000000000232022f00000000023201cf000000000242019f000000000025043500000000011900190000000000010435000000400700043d0000051e0070009c000000670000213d0000004001700039000000400010043f000000190100003900000000011704360000051f020000410000000000210435000000400500043d0000051e0050009c000000670000213d0000004002500039000000400020043f000000030200003900000000062504360000052002000041000000000026043500000000080704330000051c0080009c000000670000213d000000000200041a000000010420019000000001032002700000007f0330618f0000001f0030008c00000000020000390000000102002039000000000024004b000002130000c13d000300000007001d000100000006001d000400000005001d00020000000a001d000000200030008c000006740000413d0000001f028000390000000502200270000005210220009a000000200080008c0000052202004041000000000000043f0000001f033000390000000503300270000005210330009a000000000032004b000006740000813d000000000002041b0000000102200039000000000032004b000006700000413d000500000008001d0000001f0080008c000007be0000a13d000000000000043f0000000001000414000005180010009c0000051801008041000000c00110021000000523011001c70000801002000039145a14550000040f000000010020019000000cb10000613d000000200200008a0000000502200180000000000101043b000009040000c13d0000002003000039000009110000013d0000000801000029000000000010043f0000000f01000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f000000010020019000000cb10000613d000000400200043d000005700020009c000000670000213d000000000101043b0000006003200039000000400030043f000000000501041a00000000045204360000000103100039000000000303041a000000000034043500000040022000390000000201100039000000000101041a000000ff001001900000000001000039000000010100c0390000000000120435000005710050009c000007770000413d0000004007000039000005710150012a000007800000013d000000000010043f0000000301000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f000000010020019000000cb10000613d000000000101043b000000000101041a000600000001001d0000051c0010009c000000670000213d000000060100002900000005011002100000003f021000390000058e04200197000000400300043d0000000002430019000500000003001d000000000032004b000000000300003900000001030040390000051c0020009c000000670000213d0000000100300190000000670000c13d000000400020043f000000060200002900000005030000290000000002230436000300000002001d0000001f0210018f00000000030000310000000203300367000000000001004b000006db0000613d00000003070000290000000005170019000000000603034f000000006806043c0000000007870436000000000057004b000006d70000c13d000000000002004b000000400500043d0000000004450019000400000005001d000000000054004b000000000500003900000001050040390000051c0040009c000000670000213d0000000100500190000000670000c13d000000400040043f000000060400002900000004050000290000000004450436000200000004001d000000000001004b000006f30000613d00000002040000290000000001140019000000003503043c0000000004540436000000000014004b000006ef0000c13d000000000002004b000000060000006b000008350000c13d000000400200043d000800000002001d00000040010000390000000001120436000700000001001d00000040022000390000000501000029145a0cf70000040f0000000002010019000000080120006a000000070300002900000000001304350000000401000029145a0cf70000040f00000008020000290000000001210049000005180020009c00000518020080410000004002200210000005180010009c00000518010080410000006001100210000000000121019f0000145b0001042e0000059b02200197000000a00020043f000000000001004b000000a0040000390000008004006039000000600240008a000007380000013d0000059b02200197000000a00020043f000000000001004b000000a0020000390000008002006039000007370000013d000005970020009c000004e20000613d000005980020009c000004e20000613d000000800000043f0000056f010000410000145b0001042e0000052602200197000000000262019f000000000021041b0000000001000414000005180010009c0000051801008041000000c00110021000000527011001c70000800d0200003900000003030000390000052804000041000000e50000013d00000522030000410000000004000019000000000503041a000000a002400039000000000052043500000001033000390000002004400039000000000014004b000007300000413d000000600220008a0000008001000039145a0d4d0000040f0000002001000039000000400200043d000800000002001d00000000021204360000008001000039145a0cb30000040f00000008020000290000000001210049000005180010009c00000518010080410000006001100210000005180020009c00000518020080410000004002200210000000000121019f0000145b0001042e0000000801000029000000000010043f0000001001000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f000000010020019000000cb10000613d000000000101043b0000000602000029000000000020043f000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f000000010020019000000cb10000613d000000000101043b0000000702000029000000000020043f000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f000000010020019000000cb10000613d000000000101043b000000000101041a000000ff0010019000000000010000390000000101006039000004ca0000013d000005730050009c0000000001050019000005720110212a00000000070000390000002007002039000005740010009c00000010077081bf0000057501108197000005740110812a000005760010009c00000008077080390000051c01108197000005760110812a000027100010008c00000004077080390000051801108197000027100110811a000000640010008c00000002077080390000ffff0110818f000000640110811a000000090010008c00000001077020390000059c067001970000005f026000390000059c08200197000000400300043d0000000002380019000000000082004b000000000800003900000001080040390000051c0020009c000000670000213d0000000100800190000000670000c13d000000400020043f0000000102700039000000000223043600000020066000390000059c096001980000001f0860018f00000000060000310000000206600367000007aa0000613d0000000009920019000000000a06034f000000000b02001900000000ac0a043c000000000bcb043600000000009b004b000007a60000c13d000000000008004b00000000077300190000002107700039000000090050008c0000000a8550011a0000000308800210000000010770008a00000000090704330000057709900197000005780880021f0000057908800197000000000898019f0000000000870435000007ad0000213d0000000007040433000005710070009c000007ca0000413d0000004008000039000005710470012a000007d30000013d000000050000006b0000000002000019000007c20000613d0000000002010433000000050400002900000003014002100000059d0110027f0000059d01100167000000000112016f0000000102400210000000000121019f0000091f0000013d000005730070009c0000000004070019000005720440212a00000000080000390000002008002039000005740040009c00000010088081bf0000057504408197000005740440812a000005760040009c00000008088080390000051c04408197000005760440812a000027100040008c00000004088080390000051804408197000027100440811a000000640040008c00000002088080390000ffff0440818f000000640440811a000000090040008c00000001088020390000059c098001970000005f049000390000059c0a400197000000400500043d00000000045a00190000000000a4004b000000000a000039000000010a0040390000051c0040009c000000670000213d0000000100a00190000000670000c13d000000400040043f0000000104800039000000000445043600000020099000390000059c0a9001980000001f0990018f000007fa0000613d000000000aa40019000000000b040019000000006c06043c000000000bcb04360000000000ab004b000007f60000c13d000000000009004b00000000068500190000002106600039000000090070008c0000000a8770011a0000000308800210000000010660008a00000000090604330000057709900197000005780880021f0000057908800197000000000898019f0000000000860435000007fd0000213d0000000d08000039000000000708041a000000010970019000000001067002700000007f0660618f0000001f0060008c000000000a000039000000010a002039000000000aa7013f0000000100a00190000002130000c13d000000400e00043d000000000009004b0000095b0000613d000000000080043f000000000006004b0000095e0000613d0000052a070000410000002008e000390000000009000019000000000a980019000000000b07041a0000000000ba043500000001077000390000002009900039000000000069004b0000081c0000413d0000095e0000013d000000000001042f000000000002004b00000000070000190000082a0000613d000000000661034f000000000706043b00000003062002100000059d0660027f0000059d06600167000000000667016f0000000107200210000000000676019f000008c80000013d0000058301000041000000000010043f00000537010000410000145c000104300000801006000039000800000000001d0000000701000029000000000010043f0000000301000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000000002060019145a14550000040f000000010020019000000cb10000613d000000000101043b000000000101041a000000080010006c000009f90000a13d0000000701000029000000000010043f0000000601000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f000000010020019000000cb10000613d000000000101043b0000000802000029000000000020043f000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f000000010020019000000cb10000613d000000000101043b000000000101041a000000000010043f0000000f01000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f000000010020019000000cb10000613d000000400300043d000005700030009c000000670000213d000000000401043b0000006001300039000000400010043f000000000204041a00000000012304360000000105400039000000000505041a000000000051043500000040033000390000000204400039000000000404041a000000ff004001900000000004000039000000010400c0390000000000430435000000050300002900000000030304330000000805000029000000000053004b0000801006000039000009d40000a13d00000005035002100000000304300029000000000024043500000004020000290000000002020433000000000052004b000009d40000a13d0000000202300029000000000101043300000000001204350000000105500039000800000005001d000000060050006c000008370000413d000006f60000013d0000059b01200197000000080200002900000080022000390000000000120435000000070000006b000000200200003900000000020060390000000801000029000005180010009c000005180100804100000040011002100000008002200039000005180020009c00000518020080410000006002200210000000000112019f0000000002000414000005180020009c0000051802008041000000c002200210000000000121019f00000527011001c70000800d0200003900000001030000390000059104000041000008f50000013d0000052a070000410000000009000019000000000a690019000000000aa1034f000000000a0a043b0000000000a7041b00000001077000390000002009900039000000000089004b000008b30000413d000000000028004b000008c60000813d0000000308200210000000f80880018f0000059d0880027f0000059d088001670000000006690019000000000661034f000000000606043b000000000686016f000000000067041b000000010620021000000001066001bf000000000065041b0000002005000039000000800050043f0000002004400039000000000541034f000000a00020043f0000059c062001980000001f0720018f000000c004600039000008d80000613d000000c008000039000000000905034f000000009a09043c0000000008a80436000000000048004b000008d40000c13d000000000007004b000008e50000613d000000000565034f0000000306700210000000000704043300000000076701cf000000000767022f000000000505043b0000010006600089000000000565022f00000000056501cf000000000575019f0000000000540435000000c00220003900000000000204350000059c0130019700000040011000390000006002100210000005860220009a000005870010009c00000588020080410000000001000414000005180010009c0000051801008041000000c00110021000000000012100190000800d0200003900000001030000390000058904000041000000e50000013d000000080000006b0000000001000019000008fd0000613d000000070100002900000020011000390000000201100367000000000101043b000000080400002900000003024002100000059d0220027f0000059d02200167000000000221016f0000000101400210000009f40000013d000000010320008a0000000503300270000000000431001900000020030000390000000104400039000000030600002900000000056300190000000005050433000000000051041b00000020033000390000000101100039000000000041004b0000090a0000c13d000000050020006c0000091c0000813d00000005020000290000000302200210000000f80220018f0000059d0220027f0000059d0220016700000003033000290000000003030433000000000223016f000000000021041b0000000501000029000000010110021000000001011001bf000000000010041b00000004010000290000000001010433000500000001001d0000051c0010009c000000670000213d0000000101000039000000000201041a000000010020019000000001012002700000007f0110618f0000001f0010008c00000000030000390000000103002039000000000232013f0000000100200190000002130000c13d000000200010008c000009430000413d0000000102000039000000000020043f00000005030000290000001f023000390000000502200270000005240220009a000000200030008c00000525020040410000001f011000390000000501100270000005240110009a000000000012004b000009430000813d000000000002041b0000000102200039000000000012004b0000093f0000413d00000005010000290000001f0010008c000009c70000a13d0000000101000039000000000010043f0000000001000414000005180010009c0000051801008041000000c00110021000000523011001c70000801002000039145a14550000040f000000010020019000000cb10000613d000000200200008a0000000502200180000000000101043b00000a010000c13d000000200300003900000a0e0000013d0000058401000041000000000010043f00000537010000410000145c000104300000059b077001970000002008e0003900000000007804350000000007e6001900000020067000390000057a08000041000000000086043500000000030304330000059c093001970000001f0830018f0000002b07700039000000000072004b000009770000813d000000000009004b000009740000613d000000000b820019000000000a870019000000200aa0008a000000200bb0008a000000000c9a0019000000000d9b0019000000000d0d04330000000000dc0435000000200990008c0000096e0000c13d000000000008004b000009830000c13d0000098d0000013d000000000a970019000000000009004b0000097f0000613d000000000b02001900000000bc0b04340000000007c704360000000000a7004b0000097b0000c13d000000000008004b0000098d0000613d000000000292001900000000070a00190000000308800210000000000907043300000000098901cf000000000989022f00000000020204330000010008800089000000000282022f00000000028201cf000000000292019f000000000027043500000000026300190000000b032000390000057b06000041000000000063043500000000030504330000059c063001970000001f0530018f0000001201200039000000000014004b000009a60000813d000000000006004b000009a30000613d00000000085400190000000007510019000000200770008a000000200880008a0000000009670019000000000a680019000000000a0a04330000000000a90435000000200660008c0000099d0000c13d000000000005004b000009b20000c13d000009bc0000013d0000000007610019000000000006004b000009ae0000613d000000000804001900000000890804340000000001910436000000000071004b000009aa0000c13d000000000005004b000009bc0000613d000000000464001900000000010700190000000305500210000000000601043300000000065601cf000000000656022f00000000040404330000010005500089000000000454022f00000000045401cf000000000464019f0000000000410435000000000123001900000012021000390000057c03000041000000000032043500080000000e001d0000000001e10049000000090210008a00000000002e0435000000170210003900000000010e0019000006150000013d000000050000006b0000000001000019000009cc0000613d00000001010000290000000001010433000000050400002900000003024002100000059d0220027f0000059d02200167000000000121016f0000000102400210000000000121019f00000a1c0000013d0000058f01000041000000000010043f0000003201000039000000040010043f0000056d010000410000145c000104300000000204000367000000000300001900000006060000290000000005630019000000000554034f000000000505043b000000000051041b00000001011000390000002003300039000000000023004b000009dd0000413d000000080020006c000009f10000813d00000008020000290000000302200210000000f80220018f0000059d0220027f0000059d0220016700000006033000290000000203300367000000000303043b000000000223016f000000000021041b000000010100003900000008020000290000000102200210000000000112019f0000000502000029000000000012041b00000000010000190000145b0001042e0000058b01000041000000000010043f0000000701000029000000040010043f0000000801000029000000240010043f0000058c010000410000145c00010430000000010320008a0000000503300270000000000431001900000020030000390000000104400039000000040600002900000000056300190000000005050433000000000051041b00000020033000390000000101100039000000000041004b00000a070000c13d000000050020006c00000a190000813d00000005020000290000000302200210000000f80220018f0000059d0220027f0000059d0220016700000004033000290000000003030433000000000223016f000000000021041b0000000501000029000000010110021000000001011001bf0000000102000039000000000012041b00000002010000290000051b06100198000004840000613d0000000a01000039000000000201041a0000052603200197000000000363019f000000000031041b00000000010004140000051b05200197000005180010009c0000051801008041000000c00110021000000527011001c70000800d0200003900000003030000390000052804000041145a14500000040f000000010020019000000cb10000613d0000000101000039000000800010043f0000000301000039000000a00010043f000000c00000043f000000080000006b00000a3d0000c13d0000053601000041000000000010043f00000537010000410000145c000104300000000801000029000000e00010043f00000006010000290000000001010433000800000001001d0000051c0010009c000000670000213d0000000d01000039000000000201041a000000010020019000000001012002700000007f0110618f0000001f0010008c00000000030000390000000103002039000000000232013f0000000100200190000002130000c13d000000200010008c00000a620000413d0000000d02000039000000000020043f00000008030000290000001f023000390000000502200270000005290220009a000000200030008c0000052a020040410000001f011000390000000501100270000005290110009a000000000012004b00000a620000813d000000000002041b0000000102200039000000000012004b00000a5e0000413d00000008010000290000001f0010008c00000a8e0000a13d0000000d01000039000000000010043f0000000001000414000005180010009c0000051801008041000000c00110021000000523011001c70000801002000039145a14550000040f000000010020019000000cb10000613d000000200200008a0000000802200180000000000101043b00000a9b0000c13d000000200300003900000aa80000013d00000006020000290000002002200039000000000121034f000000000101043b00000008020000290000000002200079000001630220008a000000000021004b00000000030000190000051d030080410000051d011001970000051d02200197000000000421013f000000000021004b00000000010000190000051d010040410000051d0040009c000000000103c019000000000001004b00000cb10000c13d000000050000006b00000000010000390000000101006039000004f60000013d000000080000006b000000000100001900000a930000613d00000007010000290000000001010433000000080400002900000003024002100000059d0220027f0000059d02200167000000000121016f0000000102400210000000000121019f00000ab60000013d000000010320008a0000000503300270000000000431001900000020030000390000000104400039000000060600002900000000056300190000000005050433000000000051041b00000020033000390000000101100039000000000041004b00000aa10000c13d000000080020006c00000ab30000813d00000008020000290000000302200210000000f80220018f0000059d0220027f0000059d0220016700000006033000290000000003030433000000000223016f000000000021041b0000000801000029000000010110021000000001011001bf0000000d02000039000000000012041b000000000000043f0000000c01000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f000000010020019000000cb10000613d000000000101043b000800000001001d000000000101041a000000010010019000000001021002700000007f0220618f000700000002001d0000001f0020008c00000000020000390000000102002039000000000121013f0000000100100190000002130000c13d0000000701000029000000200010008c00000aea0000413d0000000801000029000000000010043f0000000001000414000005180010009c0000051801008041000000c00110021000000523011001c70000801002000039145a14550000040f000000010020019000000cb10000613d000000000101043b00000007020000290000001f0220003900000005022002700000000002210019000000000021004b00000aea0000813d000000000001041b0000000101100039000000000021004b00000ae60000413d0000052c010000410000000802000029000000000012041b0000000101000039000000000010043f0000000c01000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f000000010020019000000cb10000613d000000000101043b000800000001001d000000000101041a000000010010019000000001021002700000007f0220618f000700000002001d0000001f0020008c00000000020000390000000102002039000000000121013f0000000100100190000002130000c13d00000007010000290000001f0010008c00000b200000a13d0000000801000029000000000010043f0000000001000414000005180010009c0000051801008041000000c00110021000000523011001c70000801002000039145a14550000040f000000010020019000000cb10000613d000000000101043b00000007020000290000001f0220003900000005022002700000000002210019000000000021004b00000b200000813d000000000001041b0000000101100039000000000021004b00000b1c0000413d0000052d010000410000000802000029000000000012041b0000000201000039000000000010043f0000000c01000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f000000010020019000000cb10000613d000000000101043b000800000001001d000000000101041a000000010010019000000001021002700000007f0220618f000700000002001d0000001f0020008c00000000020000390000000102002039000000000121013f0000000100100190000002130000c13d0000000701000029000000200010008c00000b560000413d0000000801000029000000000010043f0000000001000414000005180010009c0000051801008041000000c00110021000000523011001c70000801002000039145a14550000040f000000010020019000000cb10000613d000000000101043b00000007020000290000001f0220003900000005022002700000000002210019000000000021004b00000b560000813d000000000001041b0000000101100039000000000021004b00000b520000413d0000052e010000410000000802000029000000000012041b0000000301000039000000000010043f0000000c01000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f000000010020019000000cb10000613d000000000101043b000800000001001d000000000101041a000000010010019000000001021002700000007f0220618f000700000002001d0000001f0020008c00000000020000390000000102002039000000000121013f0000000100100190000002130000c13d0000000701000029000000200010008c00000b8c0000413d0000000801000029000000000010043f0000000001000414000005180010009c0000051801008041000000c00110021000000523011001c70000801002000039145a14550000040f000000010020019000000cb10000613d000000000101043b00000007020000290000001f0220003900000005022002700000000002210019000000000021004b00000b8c0000813d000000000001041b0000000101100039000000000021004b00000b880000413d0000052f010000410000000802000029000000000012041b0000000401000039000000000010043f0000000c01000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f000000010020019000000cb10000613d000000000101043b000800000001001d000000000101041a000000010010019000000001021002700000007f0220618f000700000002001d0000001f0020008c00000000020000390000000102002039000000000121013f0000000100100190000002130000c13d0000000701000029000000200010008c00000bc20000413d0000000801000029000000000010043f0000000001000414000005180010009c0000051801008041000000c00110021000000523011001c70000801002000039145a14550000040f000000010020019000000cb10000613d000000000101043b00000007020000290000001f0220003900000005022002700000000002210019000000000021004b00000bc20000813d000000000001041b0000000101100039000000000021004b00000bbe0000413d00000530010000410000000802000029000000000012041b0000000501000039000000000010043f0000000c01000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f000000010020019000000cb10000613d000000000101043b000800000001001d000000000101041a000000010010019000000001021002700000007f0220618f000700000002001d0000001f0020008c00000000020000390000000102002039000000000121013f0000000100100190000002130000c13d0000000701000029000000200010008c00000bf80000413d0000000801000029000000000010043f0000000001000414000005180010009c0000051801008041000000c00110021000000523011001c70000801002000039145a14550000040f000000010020019000000cb10000613d000000000101043b00000007020000290000001f0220003900000005022002700000000002210019000000000021004b00000bf80000813d000000000001041b0000000101100039000000000021004b00000bf40000413d00000531010000410000000802000029000000000012041b0000000601000039000000000010043f0000000c01000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f000000010020019000000cb10000613d000000000101043b000800000001001d000000000101041a000000010010019000000001021002700000007f0220618f000700000002001d0000001f0020008c00000000020000390000000102002039000000000121013f0000000100100190000002130000c13d0000000701000029000000200010008c00000c2e0000413d0000000801000029000000000010043f0000000001000414000005180010009c0000051801008041000000c00110021000000523011001c70000801002000039145a14550000040f000000010020019000000cb10000613d000000000101043b00000007020000290000001f0220003900000005022002700000000002210019000000000021004b00000c2e0000813d000000000001041b0000000101100039000000000021004b00000c2a0000413d00000532010000410000000802000029000000000012041b0000000701000039000000000010043f0000000c01000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f000000010020019000000cb10000613d000000000101043b000800000001001d000000000101041a000000010010019000000001021002700000007f0220618f000700000002001d0000001f0020008c00000000020000390000000102002039000000000121013f0000000100100190000002130000c13d0000000701000029000000200010008c00000c640000413d0000000801000029000000000010043f0000000001000414000005180010009c0000051801008041000000c00110021000000523011001c70000801002000039145a14550000040f000000010020019000000cb10000613d000000000101043b00000007020000290000001f0220003900000005022002700000000002210019000000000021004b00000c640000813d000000000001041b0000000101100039000000000021004b00000c600000413d00000533010000410000000802000029000000000012041b0000000801000039000000000010043f0000000c01000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f000000010020019000000cb10000613d000000000101043b000800000001001d000000000101041a000000010010019000000001021002700000007f0220618f000700000002001d0000001f0020008c00000000020000390000000102002039000000000121013f0000000100100190000002130000c13d0000000701000029000000200010008c00000c9a0000413d0000000801000029000000000010043f0000000001000414000005180010009c0000051801008041000000c00110021000000523011001c70000801002000039145a14550000040f000000010020019000000cb10000613d000000000101043b00000007020000290000001f0220003900000005022002700000000002210019000000000021004b00000c9a0000813d000000000001041b0000000101100039000000000021004b00000c960000413d00000534010000410000000802000029000000000012041b000000800100043d00000140000004430000016000100443000000a00100043d00000020020000390000018000200443000001a0001004430000004001000039000000c00300043d000001c000100443000001e0003004430000006001000039000000e00300043d0000020000100443000002200030044300000100002004430000000401000039000001200010044300000535010000410000145b0001042e00000000010000190000145c00010430000000004301043400000000013204360000059c063001970000001f0530018f000000000014004b00000cc90000813d000000000006004b00000cc50000613d00000000085400190000000007510019000000200770008a000000200880008a0000000009670019000000000a680019000000000a0a04330000000000a90435000000200660008c00000cbf0000c13d000000000005004b00000cdf0000613d000000000701001900000cd50000013d0000000007610019000000000006004b00000cd20000613d00000000080400190000000009010019000000008a0804340000000009a90436000000000079004b00000cce0000c13d000000000005004b00000cdf0000613d00000000046400190000000305500210000000000607043300000000065601cf000000000656022f00000000040404330000010005500089000000000454022f00000000045401cf000000000464019f0000000000470435000000000431001900000000000404350000001f033000390000059c023001970000000001210019000000000001042d0000059e0010009c00000cf50000213d000000630010008c00000cf50000a13d00000002030003670000000401300370000000000101043b0000051b0010009c00000cf50000213d0000002402300370000000000202043b0000051b0020009c00000cf50000213d0000004403300370000000000303043b000000000001042d00000000010000190000145c00010430000000000301001900000000040104330000000001420436000000000004004b00000d030000613d00000000020000190000002003300039000000000503043300000000015104360000000102200039000000000042004b00000cfd0000413d000000000001042d0000059e0010009c00000d120000213d000000630010008c00000d120000a13d00000002030003670000000401300370000000000101043b0000051b0010009c00000d120000213d0000002402300370000000000202043b0000004403300370000000000303043b000000000001042d00000000010000190000145c000104300002000000000002000000000301041a000000010430019000000001063002700000007f0660618f0000001f0060008c00000000050000390000000105002039000000000054004b00000d450000c13d0000000005620436000000000004004b00000d3c0000613d000200000006001d000100000005001d000000000010043f0000000001000414000005180010009c0000051801008041000000c00110021000000523011001c70000801002000039145a14550000040f000000010020019000000d4b0000613d0000000206000029000000000006004b00000d430000613d000000000201043b000000000100001900000001050000290000000003150019000000000402041a000000000043043500000001022000390000002001100039000000000061004b00000d330000413d0000000001150019000000000001042d0000059b013001970000000000150435000000000006004b000000200100003900000000010060390000000001150019000000000001042d0000000101000029000000000001042d0000058f01000041000000000010043f0000002201000039000000040010043f0000056d010000410000145c0001043000000000010000190000145c000104300000001f022000390000059c022001970000000001120019000000000021004b000000000200003900000001020040390000051c0010009c00000d590000213d000000010020019000000d590000c13d000000400010043f000000000001042d0000058f01000041000000000010043f0000004101000039000000040010043f0000056d010000410000145c000104300000059e0010009c00000d6f0000213d000000230010008c00000d6f0000a13d00000004020000390000000202200367000000000202043b0000051c0020009c00000d6f0000213d00000000012100490000059e0010009c00000d6f0000213d000001440010008c00000d6f0000413d0000000401200039000000000001042d00000000010000190000145c000104300004000000000002000200000001001d0003051b0020019c00000e4c0000613d000400000003001d000000000030043f0000000201000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f000000010020019000000e4a0000613d000000000101043b000000000101041a0000051b0010019800000e510000c13d0000000001000411000000000001004b00000dba0000613d000000000000043f0000000501000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f000000010020019000000e4a0000613d000000000101043b00000000020004110000051b02200197000000000020043f000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f000000010020019000000e4a0000613d000000000101043b000000000101041a000000ff0010019000000dba0000c13d0000000401000029000000000010043f0000000401000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f000000010020019000000e4a0000613d000000000101043b000000000101041a0000051b011001970000000002000411000000000021004b00000e790000c13d0000000301000029000000000010043f0000000301000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f000000010020019000000e4a0000613d000000000101043b000000000201041a0000000102200039000000000021041b0000000401000029000000000010043f0000000201000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f000000010020019000000e4a0000613d000000000101043b000000000201041a00000526022001970000000306000029000000000262019f000000000021041b0000000001000414000005180010009c0000051801008041000000c00110021000000527011001c70000800d020000390000000403000039000005a20400004100000000050000190000000407000029145a14500000040f000000010020019000000e4a0000613d0000000801000039000000000101041a000100000001001d0000000401000029000000000010043f0000000901000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f000000010020019000000e4a0000613d000000000101043b0000000102000029000000000021041b000005a30020009c00000e650000813d00000001012000390000000803000039000000000013041b000005a40120009a0000000402000029000000000021041b0000000301000029000000000010043f0000000301000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f000000010020019000000e4a0000613d000000000101043b000000000101041a000100000001001d000000000001004b00000e6b0000613d0000000301000029000000000010043f0000000601000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f000000010020019000000e4a0000613d0000000102000029000000010220008a000000000101043b000300000002001d000000000020043f000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f000000010020019000000e4a0000613d000000000101043b0000000402000029000000000021041b000000000020043f0000000701000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f000000010020019000000e4a0000613d000000000101043b0000000302000029000000000021041b00000002010000290000051b0110019800000e710000c13d000000000001042d00000000010000190000145c00010430000005a601000041000000000010043f000000040000043f0000056d010000410000145c00010430000000400100043d00000064021000390000059f03000041000000000032043500000044021000390000059203000041000000000032043500000024021000390000002c0300003900000000003204350000057e020000410000000000210435000000040210003900000020030000390000000000320435000005180010009c00000518010080410000004001100210000005a0011001c70000145c000104300000058f01000041000000000010043f0000004101000039000000040010043f0000056d010000410000145c000104300000058f01000041000000000010043f0000001101000039000000040010043f0000056d010000410000145c00010430000005a502000041000000000020043f000000040010043f0000000401000029000000240010043f000000440000043f0000057f010000410000145c00010430000005a101000041000000000010043f0000000401000029000000040010043f0000056d010000410000145c000104300002000000000002000200000002001d0000051b0110019800000eb30000613d000100000001001d000000000010043f0000000301000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f000000010020019000000eb10000613d000000000101043b000000000101041a000000020010006c00000eb80000a13d0000000101000029000000000010043f0000000601000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f000000010020019000000eb10000613d000000000101043b0000000202000029000000000020043f000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f000000010020019000000eb10000613d000000000101043b000000000101041a000000000001042d00000000010000190000145c000104300000059001000041000000000010043f000000040000043f0000056d010000410000145c000104300000058b01000041000000000010043f0000000101000029000000040010043f0000000201000029000000240010043f0000058c010000410000145c000104300000000802000039000000000302041a000000000013004b00000ec80000a13d000000000020043f000005a40110009a0000000002000019000000000001042d0000058f01000041000000000010043f0000003201000039000000040010043f0000056d010000410000145c000104300000051b0110019800000edf0000613d000000000010043f0000000301000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f000000010020019000000ee40000613d000000000101043b000000000101041a000000000001042d0000059001000041000000000010043f000000040000043f0000056d010000410000145c0001043000000000010000190000145c000104300001000000000002000100000001001d000000000010043f0000000201000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f000000010020019000000ef90000613d000000000101043b000000000101041a0000051b0110019800000efb0000613d000000000001042d00000000010000190000145c00010430000005a101000041000000000010043f0000000101000029000000040010043f0000056d010000410000145c00010430000005710010009c00000f060000413d0000004003000039000005710210012a00000f0f0000013d000005730010009c0000000002010019000005720220212a00000000030000390000002003002039000005740020009c00000010033081bf0000057502208197000005740220812a000005760020009c00000008033080390000051c02208197000005760220812a000027100020008c00000004033080390000051802208197000027100220811a000000640020008c00000002033080390000ffff0220818f000000640220811a000000090020008c00000001033020390000059c063001970000005f026000390000059c07200197000000400200043d0000000004270019000000000074004b000000000700003900000001070040390000051c0040009c00000f470000213d000000010070019000000f470000c13d000000400040043f0000000104300039000000000442043600000020076000390000059c067001980000001f0570018f00000f370000613d000000000664001900000000070000310000000207700367000000007807043c0000000004840436000000000064004b00000f330000c13d000000000005004b00000000033200190000002103300039000000090010008c0000000a4110011a0000000304400210000000010330008a00000000050304330000057705500197000005780440021f0000057904400197000000000445019f000000000043043500000f3a0000213d0000000001020019000000000001042d0000058f01000041000000000010043f0000004101000039000000040010043f0000056d010000410000145c000104300000058101000041000000000010044300000000010004120000000400100443000000600100003900000024001004430000000001000414000005180010009c0000051801008041000000c00110021000000582011001c70000800502000039145a14550000040f000000010020019000000f620000613d000000000101043b0000051b011001970000000002000411000000000012004b00000f630000c13d000000000001042d000000000001042f0000058301000041000000000010043f00000537010000410000145c00010430000d000000000002000b01200010003d00000002020003670000000b03200360000000000403043b000000000300003100000000051300490000001f0550008a0000051d065001970000051d07400197000000000867013f000000000067004b00000000060000190000051d06002041000000000054004b00000000050000190000051d050040410000051d0080009c000000000605c019000000000006004b000012b00000613d0000000004140019000000000142034f000000000101043b0000051c0010009c000012b00000213d000000000513004900000020034000390000051d045001970000051d06300197000000000746013f000000000046004b00000000040000190000051d04004041000000000053004b00000000050000190000051d050020410000051d0070009c000000000405c019000000000004004b000012b00000c13d000000400010008c000012b00000413d000000000132034f0000002003300039000000000232034f000000000202043b000900000002001d000000000101043b000800000001001d000000000010043f0000000e01000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f0000000100200190000012b00000613d000000000101043b0000000902000029000000000020043f000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f0000000100200190000012b00000613d000000000101043b0000000201100039000000000101041a000000ff00100190000012b80000613d0000000b01000029000000600110008a0000000201100367000000000101043b000600000001001d0000051b0010009c000012b00000213d00000006010000290000051b01100197000a00000001001d000000000010043f0000001001000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f0000000100200190000012b00000613d000000000101043b0000000802000029000000000020043f000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f0000000100200190000012b00000613d000000000101043b0000000902000029000000000020043f000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f0000000100200190000012b00000613d000000000101043b000000000101041a000000ff00100190000012bf0000c13d0000000a01000029000000000010043f0000001001000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f0000000100200190000012b00000613d000000000101043b0000000802000029000000000020043f000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f0000000100200190000012b00000613d000000000101043b0000000902000029000000000020043f000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f0000000100200190000012b00000613d000000000101043b000000000201041a0000059b0220019700000001022001bf000000000021041b0000000b01000039000000000201041a000b00000002001d000000010220003a000012b20000613d000000000021041b000000400200043d000005a80020009c000013200000813d0000002001200039000500000001001d000000400010043f000400000002001d00000000000204350000000a0000006b000012d00000613d0000000b01000029000000000010043f0000000201000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f0000000100200190000012b00000613d000000000101043b000000000101041a0000051b00100198000012d20000c13d0000000b01000029000000000010043f0000000201000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f0000000100200190000012b00000613d000000000101043b000000000101041a0007051b0010019c0000106b0000613d0000000b01000029000000000010043f0000000401000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f0000000100200190000012b00000613d000000000101043b000000000201041a0000052602200197000000000021041b0000000701000029000000000010043f0000000301000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f0000000100200190000012b00000613d000000000101043b000000000201041a000000010220008a000000000021041b0000000a01000029000000000010043f0000000301000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f0000000100200190000012b00000613d000000000101043b000000000201041a0000000102200039000000000021041b0000000b01000029000000000010043f0000000201000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f0000000100200190000012b00000613d000000000101043b000000000201041a00000526022001970000000a06000029000000000262019f000000000021041b0000000001000414000005180010009c0000051801008041000000c00110021000000527011001c70000800d020000390000000403000039000005a20400004100000007050000290000000b07000029145a14500000040f0000000100200190000012b00000613d0000000701000029000000000001004b000011380000613d0000000a03000029000000000031004b000011560000613d000000000010043f0000000301000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f0000000100200190000012b00000613d000000000101043b000000000101041a000300000001001d0000000b01000029000000000010043f0000000701000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f0000000100200190000012b00000613d000000000101043b000000000201041a000000030020006c0000110c0000613d000200000002001d0000000701000029000000000010043f0000000601000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f0000000100200190000012b00000613d000000000101043b0000000302000029000000000020043f000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f0000000100200190000012b00000613d000000000101043b000000000101041a000100000001001d0000000701000029000000000010043f0000000601000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f0000000100200190000012b00000613d000000000101043b0000000202000029000000000020043f000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f0000000100200190000012b00000613d000000000101043b0000000102000029000000000021041b000000000020043f0000000701000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f0000000100200190000012b00000613d000000000101043b0000000202000029000000000021041b0000000b01000029000000000010043f0000000701000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f0000000100200190000012b00000613d000000000101043b000000000001041b0000000701000029000000000010043f0000000601000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f0000000100200190000012b00000613d000000000101043b0000000302000029000000000020043f000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f0000000100200190000012b00000613d000000000101043b0000000002000019000011530000013d0000000801000039000000000101041a000300000001001d0000000b01000029000000000010043f0000000901000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f0000000100200190000012b00000613d000000000101043b0000000302000029000000000021041b0000051c0020009c000013200000213d00000001012000390000000803000039000000000013041b000000000030043f000005a40120009a0000000b020000290000000a03000029000000000021041b0000000701000029000000000031004b000011980000613d000000000030043f0000000301000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f0000000100200190000012b00000613d000000000101043b000000000101041a000300000001001d000000000001004b000012b20000613d0000000a01000029000000000010043f0000000601000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f0000000100200190000012b00000613d0000000302000029000000010220008a000000000101043b000300000002001d000000000020043f000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f0000000100200190000012b00000613d000000000101043b0000000b02000029000000000021041b000000000020043f0000000701000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f0000000100200190000012b00000613d000000000101043b0000000302000029000000000021041b0000000701000029000000000001004b000012e60000c13d000005aa010000410000000000100443000000060100002900000004001004430000000001000414000005180010009c0000051801008041000000c001100210000005ab011001c70000800202000039145a14550000040f0000000100200190000012eb0000613d000000400c00043d000000000101043b000000000001004b000011d30000613d0000006401c00039000000800b0000390000000000b104350000004401c000390000000b020000290000000000210435000005ac0100004100000000001c04350000000401c00039000000000200041100000000002104350000002401c000390000000000010435000000040100002900000000010104330000008402c000390000000000120435000000200a00008a0000000005a1016f0000001f0410018f000000a403c000390000000502000029000000000032004b000011d50000813d000000000005004b000011cf0000613d00000000074200190000000006430019000000200660008a000000200770008a0000000008560019000000000957001900000000090904330000000000980435000000200550008c000011c90000c13d000000000004004b000011eb0000613d0000000006030019000011e10000013d00000000030c0019000012420000013d0000000006530019000000000005004b000011de0000613d0000000007020019000000000803001900000000790704340000000008980436000000000068004b000011da0000c13d000000000004004b000011eb0000613d00000000025200190000000304400210000000000506043300000000054501cf000000000545022f00000000070204330000010004400089000000000747022f00000000044701cf000000000454019f00000000004604350000000003310019000000000003043500000000030004140000000a02000029000000040020008c000011f80000c13d00000000050004150000000d0550008a00000005055002100000000104000031000000200040008c00000020040080390000122d0000013d00060000000b001d0000001f011000390000000001a1016f000000a401100039000005180010009c000005180100804100000060011002100000051800c0009c000005180400004100000000040c40190000004004400210000000000141019f000005180030009c0000051803008041000000c003300210000000000131019f00070000000c001d145a14500000040f000000070c00002900000060031002700000051803300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c00190000121a0000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b000012160000c13d000000000006004b000012270000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000100000003001f00000000050004150000000c0550008a00000005055002100000000100200190000012ec0000613d0000001f01400039000000600110018f0000000003c10019000000000013004b000000000100003900000001010040390000051c0030009c000013200000213d0000000100100190000013200000c13d000000400030043f000000200040008c000012b00000413d00000000010c04330000059500100198000012b00000c13d0000000502500270000000000201001f000005ae01100197000005ac0010009c0000131a0000c13d000005700030009c000013200000213d0000006001300039000000400010043f00000040023000390000000101000039000600000002001d0000000000120435000000080100002900000000021304360000000901000029000500000002001d00000000001204350000000b01000029000000000010043f0000000f01000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039000700000003001d145a14550000040f00000007030000290000000100200190000012b00000613d0000000002030433000000000101043b000000000021041b000000050200002900000000020204330000000103100039000000000023041b0000000201100039000000000201041a0000059b0220019700000006030000290000000003030433000000000003004b000000010220c1bf000000000021041b0000000a01000029000000000010043f0000001101000039000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f0000000100200190000012b00000613d000000000101043b0000000802000029000000000020043f000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f0000000100200190000012b00000613d000000000101043b0000000902000029000000000020043f000000200010043f0000000001000414000005180010009c0000051801008041000000c0011002100000052b011001c70000801002000039145a14550000040f0000000100200190000012b00000613d000000000101043b0000000b03000029000000000031041b000000400100043d0000004002100039000000000032043500000020021000390000000903000029000000000032043500000008020000290000000000210435000005180010009c000005180100804100000040011002100000000002000414000005180020009c0000051802008041000000c002200210000000000112019f000005af011001c70000800d020000390000000203000039000005b0040000410000000a05000029145a14500000040f0000000100200190000012b00000613d000000000001042d00000000010000190000145c000104300000058f01000041000000000010043f0000001101000039000000040010043f0000056d010000410000145c00010430000000400100043d0000004402100039000005b103000041000000000032043500000024021000390000001003000039000012c50000013d000000400100043d0000004402100039000005a70300004100000000003204350000002402100039000000150300003900000000003204350000057e020000410000000000210435000000040210003900000020030000390000000000320435000005180010009c000005180100804100000040011002100000057f011001c70000145c00010430000005a601000041000012e70000013d000000400100043d00000064021000390000059f03000041000000000032043500000044021000390000059203000041000000000032043500000024021000390000002c0300003900000000003204350000057e020000410000000000210435000000040210003900000020030000390000000000320435000005180010009c00000518010080410000004001100210000005a0011001c70000145c00010430000005a901000041000000000010043f000000040000043f0000056d010000410000145c00010430000000000001042f000000000003004b000012f00000c13d0000006002000039000013170000013d0000001f0230003900000519022001970000003f02200039000005ad04200197000000400200043d0000000004420019000000000024004b000000000500003900000001050040390000051c0040009c000013200000213d0000000100500190000013200000c13d000000400040043f0000001f0430018f00000000063204360000051a05300198000600000006001d00000000035600190000130a0000613d000000000601034f0000000607000029000000006806043c0000000007870436000000000037004b000013060000c13d000000000004004b000013170000613d000000000151034f0000000304400210000000000503043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f00000000001304350000000001020433000000000001004b000013260000c13d000005a601000041000000000010043f0000000a01000029000000040010043f0000056d010000410000145c000104300000058f01000041000000000010043f0000004101000039000000040010043f0000056d010000410000145c000104300000000602000029000005180020009c00000518020080410000004002200210000005180010009c00000518010080410000006001100210000000000121019f0000145c000104300006000000000002000300000004001d000200000003001d000100000001001d000005aa010000410000000000100443000400000002001d00000004002004430000000001000414000005180010009c0000051801008041000000c001100210000005ab011001c70000800202000039145a14550000040f0000000100200190000013e10000613d000000000101043b000000000001004b000013de0000613d000000400d00043d0000006401d00039000000800c0000390000000000c104350000004401d000390000000202000029000000000021043500000001010000290000051b011001970000002402d000390000000000120435000005ac0100004100000000001d04350000000401d00039000000000200041100000000002104350000008402d0003900000003010000290000000041010434000000000012043500000004020000290000051b02200197000000200b00008a0000000006b1016f0000001f0510018f000000a403d00039000000000034004b0000136f0000813d000000000006004b0000136b0000613d00000000085400190000000007530019000000200770008a000000200880008a0000000009670019000000000a680019000000000a0a04330000000000a90435000000200660008c000013650000c13d000000000005004b000013850000613d00000000070300190000137b0000013d0000000007630019000000000006004b000013780000613d00000000080400190000000009030019000000008a0804340000000009a90436000000000079004b000013740000c13d000000000005004b000013850000613d00000000046400190000000305500210000000000607043300000000065601cf000000000656022f00000000040404330000010005500089000000000454022f00000000045401cf000000000464019f0000000000470435000000000331001900000000000304350000000003000414000000040020008c000013920000c13d0000000005000415000000060550008a00000005055002100000000103000031000000200030008c00000020040000390000000004034019000013c90000013d00020000000c001d0000001f011000390000000001b1016f000000a401100039000005180010009c000005180100804100000060011002100000051800d0009c000005180400004100000000040d40190000004004400210000000000141019f000005180030009c0000051803008041000000c003300210000000000131019f000400000002001d00030000000d001d145a14500000040f000000030d00002900000060031002700000051803300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057d0019000013b50000613d000000000801034f00000000090d0019000000008a08043c0000000009a90436000000000059004b000013b10000c13d000000000006004b000013c20000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000100000003001f0000000005000415000000050550008a000000050550021000000001002001900000000402000029000013e20000613d0000001f01400039000000600410018f0000000001d40019000000000041004b000000000400003900000001040040390000051c0010009c000014160000213d0000000100400190000014160000c13d000000400010043f0000001f0030008c000013df0000a13d00000000010d04330000059500100198000013df0000c13d0000000503500270000000000301001f000005ae01100197000005ac0010009c000014110000c13d000000000001042d00000000010000190000145c00010430000000000001042f000000000003004b000013e60000c13d00000060020000390000140d0000013d0000001f0230003900000519022001970000003f02200039000005ad04200197000000400200043d0000000004420019000000000024004b000000000500003900000001050040390000051c0040009c000014160000213d0000000100500190000014160000c13d000000400040043f0000001f0430018f00000000063204360000051a05300198000200000006001d0000000003560019000014000000613d000000000601034f0000000207000029000000006806043c0000000007870436000000000037004b000013fc0000c13d000000000004004b0000140d0000613d000000000151034f0000000304400210000000000503043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f00000000001304350000000001020433000000000001004b00000004020000290000141c0000c13d000005a601000041000000000010043f000000040020043f0000056d010000410000145c000104300000058f01000041000000000010043f0000004101000039000000040010043f0000056d010000410000145c000104300000000202000029000005180020009c00000518020080410000004002200210000005180010009c00000518010080410000006001100210000000000121019f0000145c00010430000000000001042f000005180010009c000005180100804100000060011002100000000002000414000005180020009c0000051802008041000000c002200210000000000112019f00000527011001c70000801002000039145a14550000040f0000000100200190000014350000613d000000000101043b000000000001042d00000000010000190000145c0001043000000000050100190000000000200443000000040100003900000005024002700000000002020031000000000121043a0000002004400039000000000031004b0000143a0000413d000005180030009c000005180300804100000060013002100000000002000414000005180020009c0000051802008041000000c002200210000000000112019f000005b2011001c70000000002050019145a14550000040f00000001002001900000144f0000613d000000000101043b000000000001042d000000000001042f00001453002104210000000102000039000000000001042d0000000002000019000000000001042d00001458002104230000000102000039000000000001042d0000000002000019000000000001042d0000145a000004320000145b0001042e0000145c0001043000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffff00000000000000000000000000000000000000000000000000000001ffffffe000000000000000000000000000000000000000000000000000000000ffffffe0000000000000000000000000ffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000ffffffffffffffff8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffbf536f70686f6e20416368696576656d656e7420426164676573000000000000005341420000000000000000000000000000000000000000000000000000000000d6f21326ab749d5729fcba5677c79037b459436ab7bff709c9d06ce9f10c1a9d290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56302000000000000000000000000000000000000200000000000000000000000004ef1d2ad89edf8c4d91132028e8195cdf30bb4b5053d4f8cd260341d4805f30ab10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6ffffffffffffffffffffffff000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000008be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0284966fefa8e6efe2541488ebb0d5cc7a37fcc532c506816bdc596a17e52e14bd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb502000000000000000000000000000000000000400000000000000000000000004578706c6f726572000000000000000000000000000000000000000000000010427269646765720000000000000000000000000000000000000000000000000e4661726d6572000000000000000000000000000000000000000000000000000c477561726469616e00000000000000000000000000000000000000000000001053656e646572000000000000000000000000000000000000000000000000000c4e465420436f6c6c6563746f720000000000000000000000000000000000001a417373657420486f6c6465720000000000000000000000000000000000000018426164676520436f6c6c6563746f72000000000000000000000000000000001e4561726c79204269726400000000000000000000000000000000000000000014000000020000000000000000000000000000014000000100000000000000000083780ffe0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000001574f9f3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070a0823000000000000000000000000000000000000000000000000000000000b88d4fdd00000000000000000000000000000000000000000000000000000000e49617e000000000000000000000000000000000000000000000000000000000e985e9c400000000000000000000000000000000000000000000000000000000e985e9c500000000000000000000000000000000000000000000000000000000f2fde38b00000000000000000000000000000000000000000000000000000000faf8ef9800000000000000000000000000000000000000000000000000000000e49617e100000000000000000000000000000000000000000000000000000000e60c350500000000000000000000000000000000000000000000000000000000ce46e04500000000000000000000000000000000000000000000000000000000ce46e04600000000000000000000000000000000000000000000000000000000e257792e00000000000000000000000000000000000000000000000000000000b88d4fde00000000000000000000000000000000000000000000000000000000c87b56dd0000000000000000000000000000000000000000000000000000000091db0b7d00000000000000000000000000000000000000000000000000000000a22cb46400000000000000000000000000000000000000000000000000000000a22cb46500000000000000000000000000000000000000000000000000000000a69c5aab00000000000000000000000000000000000000000000000000000000aee24d440000000000000000000000000000000000000000000000000000000091db0b7e0000000000000000000000000000000000000000000000000000000095d89b410000000000000000000000000000000000000000000000000000000088e5b2d80000000000000000000000000000000000000000000000000000000088e5b2d9000000000000000000000000000000000000000000000000000000008da5cb5b0000000000000000000000000000000000000000000000000000000070a0823100000000000000000000000000000000000000000000000000000000715018a6000000000000000000000000000000000000000000000000000000002f745c58000000000000000000000000000000000000000000000000000000004f6ccce60000000000000000000000000000000000000000000000000000000055f804b20000000000000000000000000000000000000000000000000000000055f804b30000000000000000000000000000000000000000000000000000000056066f51000000000000000000000000000000000000000000000000000000006352211e000000000000000000000000000000000000000000000000000000004f6ccce70000000000000000000000000000000000000000000000000000000054fd4d5000000000000000000000000000000000000000000000000000000000389a105a00000000000000000000000000000000000000000000000000000000389a105b0000000000000000000000000000000000000000000000000000000042842e0e000000000000000000000000000000000000000000000000000000002f745c590000000000000000000000000000000000000000000000000000000037c245fe0000000000000000000000000000000000000000000000000000000018160ddc0000000000000000000000000000000000000000000000000000000023b872dc0000000000000000000000000000000000000000000000000000000023b872dd000000000000000000000000000000000000000000000000000000002aa7555e0000000000000000000000000000000000000000000000000000000018160ddd00000000000000000000000000000000000000000000000000000000194aa16500000000000000000000000000000000000000000000000000000000081812fb00000000000000000000000000000000000000000000000000000000081812fc00000000000000000000000000000000000000000000000000000000095ea7b30000000000000000000000000000000000000000000000000000000001ffc9a70000000000000000000000000000000000000000000000000000000006fdde030000000000000000000000000000000000000020000000000000000000000000118cdaa70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000240000000000000000000000001e4fbdf7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000800000000000000000000000000000000000000000000000000000000000000000ffffffffffffff9f0000000000184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000000000000000000000000000000000000000004ee2d6d415b85acef810000000000000000000000000000000000000000000004ee2d6d415b85acef80ffffffff000000000000000000000000000000000000000000000000002386f26fc1000000000000000000000000000000000000ffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000005f5e10000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff30313233343536373839616263646566000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000062616467652d747970652d0000000000000000000000000000000000000000002d6c6576656c2d000000000000000000000000000000000000000000000000002e6a736f6e000000000000000000000000000000000000000000000000000000546f6b656e20646f6573206e6f7420657869737400000000000000000000000008c379a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff7f310ab089e4439a4c15d089f94afb7896ff553aecb10793d0ab882de59d99a32e02000002000000000000000000000000000000440000000000000000000000004ca8886700000000000000000000000000000000000000000000000000000000947d5a84000000000000000000000000000000000000000000000000000000001101129400000000000000000000000000000000000000000000000000000000fdffffffffffffffffffffffffffffffffffffffffffff800000000000000000000000000000000000000000000000000000000000000000000000010000000002000000000000000000000000000000ffffffff0000008000000000000000006741b2fc379fad678116fe3d4d4b9a1a184ab53ba36b86ad0fa66340b1ab41ad2e00000000000000000000000000000000000000000000000000000000000000a57d13dc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004400000000000000000000000000000000000000000000000000000000000000600000008000000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe04e487b710000000000000000000000000000000000000000000000000000000089c62b64000000000000000000000000000000000000000000000000000000005ac2ef6bd64fa382235f85ff11ab6e916e564751e1cc43cc5fa95dab462839b1426164676520697320736f756c626f756e6420616e642063616e6e6f7420626520617070726f76656420666f72207472616e7366657200000000000000000000000000000000000000000000000000000000008400000080000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff780e9d62ffffffffffffffffffffffffffffffffffffffffffffffffffffffff80ac58cd00000000000000000000000000000000000000000000000000000000780e9d630000000000000000000000000000000000000000000000000000000001ffc9a7000000000000000000000000000000000000000000000000000000005b5e139f00000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff207472616e73666572726564000000000000000000000000000000000000000000000000000000000000000000000000000000840000000000000000000000007e27328900000000000000000000000000000000000000000000000000000000ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef00000000000000000000000000000000000000000000000100000000000000000c085601c9b05546c4de925af5cdebeab0dd5f5d4bea4dc57b37e961749c911d64283d7b0000000000000000000000000000000000000000000000000000000064a0ae9200000000000000000000000000000000000000000000000000000000426164676520616c726561647920636c61696d65640000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffe073c6ac6e000000000000000000000000000000000000000000000000000000001806aa1896bbf26568e884a7374b41e002500962caba6a15023a8d90e8508b830200000200000000000000000000000000000024000000000000000000000000150b7a020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ffffffe0ffffffff0000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000600000000000000000000000002829783e381f74160210e11f6812c2405c29bce79a9eeeee84eefdc8a5711eb74261646765206e6f742061637469766500000000000000000000000000000000020000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008a27798ee634870dbb02f1da0fb6b9b18d60ea83437471ba0b7f5f44557f9b06

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

000000000000000000000000299174d47c243b5381c6062abefbff915b601d85000000000000000000000000ef273702f027e5aff29e7553f5dbee8e6e248cab0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002768747470733a2f2f6170692e736f70686f6e2e78797a2f6261646765732f6d657461646174612f00000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : initialOwner (address): 0x299174d47c243B5381c6062aBEFbfF915B601D85
Arg [1] : easContractAddress (address): 0xEf273702f027E5aFF29E7553f5dbEe8e6e248CaB
Arg [2] : baseURI (string): https://api.sophon.xyz/badges/metadata/

-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 000000000000000000000000299174d47c243b5381c6062abefbff915b601d85
Arg [1] : 000000000000000000000000ef273702f027e5aff29e7553f5dbee8e6e248cab
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000027
Arg [4] : 68747470733a2f2f6170692e736f70686f6e2e78797a2f6261646765732f6d65
Arg [5] : 7461646174612f00000000000000000000000000000000000000000000000000


[ Download: CSV Export  ]
[ 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.