ETH Price: $1,921.67 (+1.25%)

Contract

0x4Ff7DB3e6D9F06212e20b0C66D11804D0F66b2Ce

Overview

ETH Balance

0 ETH

ETH Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To

There are no matching entries

Please try again later

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

Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
FrameMessageValidator

Compiler Version
v0.8.21+commit.d9974bed

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion
File 1 of 10 : FrameMessageValidator.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import {IKeyRegistry} from "farcaster/interfaces/IKeyRegistry.sol";

import {
    MessageDataCodec, MessageData, MessageCodec, Message, SignatureScheme, MessageType
} from "./protobufs/Message.sol";

import {Blake3} from "farcaster-solidity/libraries/Blake3.sol";
import {Ed25519} from "farcaster-solidity/libraries/Ed25519.sol";

contract FrameMessageValidator {
    error InvalidMessage();
    error InvalidMessageHash();
    error InvalidSignature();
    error InvalidKey();
    error InvalidMessageType();
    error InvalidSignatureScheme();
    error InvalidUrl();
    error InvalidButtonIndex();

    address constant keyRegistry = 0x00000000Fc1237824fb747aBDE0FF18990E59b7e;

    function validateMessage(bytes memory message) public view returns (Message memory) {
        // Decode message
        (bool msgValid,, Message memory decodedMessage) = MessageCodec.decode(0, message, uint64(message.length));

        // Message must be valid
        if (!msgValid) revert InvalidMessage();

        {
            // re-encode message data
            bytes memory messageData = MessageDataCodec.encode(decodedMessage.data);

            // Calculate Blake3 hash of FC message (first 20 bytes)
            bytes memory messageHash = Blake3.hash(messageData, 20);

            // Message hash must be valid
            if (keccak256(messageHash) != keccak256(decodedMessage.hash_)) revert InvalidMessageHash();
        }

        {
            bytes32 sig_r;
            bytes32 sig_s;
            bytes memory signature = decodedMessage.signature;

            assembly {
                sig_r := mload(add(signature, 32))
                sig_s := mload(add(signature, 64))
            }

            // Verify signature
            bool sigValid = Ed25519.verify(bytes32(decodedMessage.signer), sig_r, sig_s, decodedMessage.hash_);

            // Signature must be valid
            if (!sigValid) revert InvalidSignature();
        }

        // Public key must be valid for fid
        IKeyRegistry.KeyData memory data =
            IKeyRegistry(keyRegistry).keyDataOf(decodedMessage.data.fid, decodedMessage.signer);

        if (data.state != IKeyRegistry.KeyState.ADDED) revert InvalidKey();

        // Validate frame message (see: https://docs.farcaster.xyz/reference/frames/spec#frame-signature)

        // Frame messages must use ed25519 signature scheme
        if (decodedMessage.signature_scheme != SignatureScheme.SIGNATURE_SCHEME_ED25519) {
            revert InvalidSignatureScheme();
        }

        // Message must be a frame action
        if (decodedMessage.data.type_ != MessageType.MESSAGE_TYPE_FRAME_ACTION) revert InvalidMessageType();

        // Url length must be <= 256 bytes
        if (decodedMessage.data.frame_action_body.url.length > 256) revert InvalidUrl();

        // Button index must be between 1 and 4
        uint32 buttonIndex = decodedMessage.data.frame_action_body.button_index;
        if (buttonIndex < 1 || buttonIndex > 4) revert InvalidButtonIndex();

        return decodedMessage;
    }
}

File 2 of 10 : IKeyRegistry.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;

import {IMetadataValidator} from "./IMetadataValidator.sol";
import {IdRegistryLike} from "./IdRegistryLike.sol";

interface IKeyRegistry {
    /*//////////////////////////////////////////////////////////////
                                 ERRORS
    //////////////////////////////////////////////////////////////*/

    /// @dev Revert if a key violates KeyState transition rules.
    error InvalidState();

    /// @dev Revert if adding a key exceeds the maximum number of allowed keys per fid.
    error ExceedsMaximum();

    /// @dev Revert if a validator has not been registered for this keyType and metadataType.
    error ValidatorNotFound(uint32 keyType, uint8 metadataType);

    /// @dev Revert if metadata validation failed.
    error InvalidMetadata();

    /// @dev Revert if the admin sets a validator for keyType 0.
    error InvalidKeyType();

    /// @dev Revert if the admin sets a validator for metadataType 0.
    error InvalidMetadataType();

    /// @dev Revert if the caller does not have the authority to perform the action.
    error Unauthorized();

    /// @dev Revert if the owner sets maxKeysPerFid equal to or below its current value.
    error InvalidMaxKeys();

    /// @dev Revert when the gateway dependency is permanently frozen.
    error GatewayFrozen();

    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    /**
     * @dev Emit an event when an admin or fid adds a new key.
     *
     *      Hubs listen for this, validate that keyBytes is an EdDSA pub key and keyType == 1 and
     *      add keyBytes to its SignerStore. Messages signed by keyBytes with `fid` are now valid
     *      and accepted over gossip, sync and client apis. Hubs assume the invariants:
     *
     *      1. Add(fid, ..., key, keyBytes, ...) cannot emit if there is an earlier emit with
     *         Add(fid, ..., key, keyBytes, ...) and no AdminReset(fid, key, keyBytes) inbetween.
     *
     *      2. Add(fid, ..., key, keyBytes, ...) cannot emit if there is an earlier emit with
     *         Remove(fid, key, keyBytes).
     *
     *      3. For all Add(..., ..., key, keyBytes, ...), key = keccak(keyBytes)
     *
     * @param fid          The fid associated with the key.
     * @param keyType      The type of the key.
     * @param key          The key being registered. (indexed as hash)
     * @param keyBytes     The bytes of the key being registered.
     * @param metadataType The type of the metadata.
     * @param metadata     Metadata about the key.
     */
    event Add(
        uint256 indexed fid,
        uint32 indexed keyType,
        bytes indexed key,
        bytes keyBytes,
        uint8 metadataType,
        bytes metadata
    );

    /**
     * @dev Emit an event when an fid removes an added key.
     *
     *      Hubs listen for this, validate that keyType == 1 and keyBytes exists in its SignerStore.
     *      keyBytes is marked as removed, messages signed by keyBytes with `fid` are invalid,
     *      dropped immediately and no longer accepted. Hubs assume the invariants:
     *
     *      1. Remove(fid, key, keyBytes) cannot emit if there is no earlier emit with
     *         Add(fid, ..., key, keyBytes, ...)
     *
     *      2. Remove(fid, key, keyBytes) cannot emit if there is an earlier emit with
     *         Remove(fid, key, keyBytes)
     *
     *      3. For all Remove(..., key, keyBytes), key = keccak(keyBytes)
     *
     * @param fid       The fid associated with the key.
     * @param key       The key being registered. (indexed as hash)
     * @param keyBytes  The bytes of the key being registered.
     */
    event Remove(uint256 indexed fid, bytes indexed key, bytes keyBytes);

    /**
     * @dev Emit an event when an admin resets an added key.
     *
     *      Hubs listen for this, validate that keyType == 1 and that keyBytes exists in its SignerStore.
     *      keyBytes is no longer tracked, messages signed by keyBytes with `fid` are invalid, dropped
     *      immediately and not accepted. Hubs assume the following invariants:
     *
     *      1. AdminReset(fid, key, keyBytes) cannot emit unless the most recent event for the fid
     *         was Add(fid, ..., key, keyBytes, ...).
     *
     *      2. For all AdminReset(..., key, keyBytes), key = keccak(keyBytes).
     *
     *      3. AdminReset() cannot emit after Migrated().
     *
     * @param fid       The fid associated with the key.
     * @param key       The key being reset. (indexed as hash)
     * @param keyBytes  The bytes of the key being registered.
     */
    event AdminReset(uint256 indexed fid, bytes indexed key, bytes keyBytes);

    /**
     * @dev Emit an event when the admin sets a metadata validator contract for a given
     *      keyType and metadataType.
     *
     * @param keyType      The numeric keyType associated with this validator.
     * @param metadataType The metadataType associated with this validator.
     * @param oldValidator The previous validator contract address.
     * @param newValidator The new validator contract address.
     */
    event SetValidator(uint32 keyType, uint8 metadataType, address oldValidator, address newValidator);

    /**
     * @dev Emit an event when the admin sets a new IdRegistry contract address.
     *
     * @param oldIdRegistry The previous IdRegistry address.
     * @param newIdRegistry The new IdRegistry address.
     */
    event SetIdRegistry(address oldIdRegistry, address newIdRegistry);

    /**
     * @dev Emit an event when the admin sets a new KeyGateway address.
     *
     * @param oldKeyGateway The previous KeyGateway address.
     * @param newKeyGateway The new KeyGateway address.
     */
    event SetKeyGateway(address oldKeyGateway, address newKeyGateway);

    /**
     * @dev Emit an event when the admin sets a new maximum keys per fid.
     *
     * @param oldMax The previous maximum.
     * @param newMax The new maximum.
     */
    event SetMaxKeysPerFid(uint256 oldMax, uint256 newMax);

    /**
     * @dev Emit an event when the contract owner permanently freezes the KeyGateway address.
     *
     * @param keyGateway The permanent KeyGateway address.
     */
    event FreezeKeyGateway(address keyGateway);

    /*//////////////////////////////////////////////////////////////
                                 STRUCTS
    //////////////////////////////////////////////////////////////*/

    /**
     *  @notice State enumeration for a key in the registry. During migration, an admin can change
     *          the state of any fids key from NULL to ADDED or ADDED to NULL. After migration, an
     *          fid can change the state of a key from NULL to ADDED or ADDED to REMOVED only.
     *
     *          - NULL: The key is not in the registry.
     *          - ADDED: The key has been added to the registry.
     *          - REMOVED: The key was added to the registry but is now removed.
     */
    enum KeyState {
        NULL,
        ADDED,
        REMOVED
    }

    /**
     *  @notice Data about a key.
     *
     *  @param state   The current state of the key.
     *  @param keyType Numeric ID representing the manner in which the key should be used.
     */
    struct KeyData {
        KeyState state;
        uint32 keyType;
    }

    /**
     * @dev Struct argument for bulk add function, representing an FID
     *      and its associated keys.
     *
     * @param fid  Fid associated with provided keys to add.
     * @param keys Array of BulkAddKey structs, including key and metadata.
     */
    struct BulkAddData {
        uint256 fid;
        BulkAddKey[] keys;
    }

    /**
     * @dev Struct argument for bulk add function, representing a key
     *      and its associated metadata.
     *
     * @param key  Bytes of the signer key.
     * @param keys Metadata metadata of the signer key.
     */
    struct BulkAddKey {
        bytes key;
        bytes metadata;
    }

    /**
     * @dev Struct argument for bulk reset function, representing an FID
     *      and its associated keys.
     *
     * @param fid  Fid associated with provided keys to reset.
     * @param keys Array of keys to reset.
     */
    struct BulkResetData {
        uint256 fid;
        bytes[] keys;
    }

    /*//////////////////////////////////////////////////////////////
                              CONSTANTS
    //////////////////////////////////////////////////////////////*/

    /**
     * @notice Contract version specified in the Farcaster protocol version scheme.
     */
    function VERSION() external view returns (string memory);

    /**
     * @notice EIP-712 typehash for Remove signatures.
     */
    function REMOVE_TYPEHASH() external view returns (bytes32);

    /*//////////////////////////////////////////////////////////////
                                STORAGE
    //////////////////////////////////////////////////////////////*/

    /**
     * @notice The IdRegistry contract.
     */
    function idRegistry() external view returns (IdRegistryLike);

    /**
     * @notice The KeyGateway address.
     */
    function keyGateway() external view returns (address);

    /**
     * @notice Whether the KeyGateway address is permanently frozen.
     */
    function gatewayFrozen() external view returns (bool);

    /**
     * @notice Maximum number of keys per fid.
     */
    function maxKeysPerFid() external view returns (uint256);

    /*//////////////////////////////////////////////////////////////
                                  VIEWS
    //////////////////////////////////////////////////////////////*/

    /**
     * @notice Return number of active keys for a given fid.
     *
     * @param fid the fid associated with the keys.
     *
     * @return uint256 total number of active keys associated with the fid.
     */
    function totalKeys(uint256 fid, KeyState state) external view returns (uint256);

    /**
     * @notice Return key at the given index in the fid's key set. Can be
     *         called to enumerate all active keys for a given fid.
     *
     * @param fid   the fid associated with the key.
     * @param index index of the key in the fid's key set. Must be a value
     *              less than totalKeys(fid). Note that because keys are
     *              stored in an underlying enumerable set, the ordering of
     *              keys is not guaranteed to be stable.
     *
     * @return bytes Bytes of the key.
     */
    function keyAt(uint256 fid, KeyState state, uint256 index) external view returns (bytes memory);

    /**
     * @notice Return an array of all active keys for a given fid.
     * @dev    WARNING: This function will copy the entire key set to memory,
     *         which can be quite expensive. This is intended to be called
     *         offchain with eth_call, not onchain.
     *
     * @param fid the fid associated with the keys.
     *
     * @return bytes[] Array of all keys.
     */
    function keysOf(uint256 fid, KeyState state) external view returns (bytes[] memory);

    /**
     * @notice Return an array of all active keys for a given fid,
     *         paged by index and batch size.
     *
     * @param fid       The fid associated with the keys.
     * @param startIdx  Start index of lookup.
     * @param batchSize Number of items to return.
     *
     * @return page    Array of keys.
     * @return nextIdx Next index in the set of all keys.
     */
    function keysOf(
        uint256 fid,
        KeyState state,
        uint256 startIdx,
        uint256 batchSize
    ) external view returns (bytes[] memory page, uint256 nextIdx);

    /**
     * @notice Retrieve state and type data for a given key.
     *
     * @param fid   The fid associated with the key.
     * @param key   Bytes of the key.
     *
     * @return KeyData struct that contains the state and keyType.
     */
    function keyDataOf(uint256 fid, bytes calldata key) external view returns (KeyData memory);

    /*//////////////////////////////////////////////////////////////
                              REMOVE KEYS
    //////////////////////////////////////////////////////////////*/

    /**
     * @notice Remove a key associated with the caller's fid, setting the key state to REMOVED.
     *         The key must be in the ADDED state.
     *
     * @param key   Bytes of the key to remove.
     */
    function remove(bytes calldata key) external;

    /**
     * @notice Remove a key on behalf of another fid owner, setting the key state to REMOVED.
     *         caller must supply a valid EIP-712 Remove signature from the fid owner.
     *
     * @param fidOwner The fid owner address.
     * @param key      Bytes of the key to remove.
     * @param deadline Deadline after which the signature expires.
     * @param sig      EIP-712 Remove signature generated by fid owner.
     */
    function removeFor(address fidOwner, bytes calldata key, uint256 deadline, bytes calldata sig) external;

    /*//////////////////////////////////////////////////////////////
                         PERMISSIONED ACTIONS
    //////////////////////////////////////////////////////////////*/

    /**
     * @notice Add a key associated with fidOwner's fid, setting the key state to ADDED.
     *         Can only be called by the keyGateway address.
     *
     * @param keyType      The key's numeric keyType.
     * @param key          Bytes of the key to add.
     * @param metadataType Metadata type ID.
     * @param metadata     Metadata about the key, which is not stored and only emitted in an event.
     */
    function add(
        address fidOwner,
        uint32 keyType,
        bytes calldata key,
        uint8 metadataType,
        bytes calldata metadata
    ) external;

    /**
     * @notice Add multiple keys as part of the initial migration. Only callable by the contract owner.
     *
     * @param items An array of BulkAddData structs including fid and array of BulkAddKey structs.
     */
    function bulkAddKeysForMigration(BulkAddData[] calldata items) external;

    /**
     * @notice Reset multiple keys as part of the initial migration. Only callable by the contract owner.
     *         Reset is not the same as removal: this function sets the key state back to NULL,
     *         rather than REMOVED. This allows the owner to correct any errors in the initial migration until
     *         the grace period expires.
     *
     * @param items   A list of BulkResetData structs including an fid and array of keys.
     */
    function bulkResetKeysForMigration(BulkResetData[] calldata items) external;

    /**
     * @notice Set a metadata validator contract for the given keyType and metadataType. Only callable by owner.
     *
     * @param keyType      The numeric key type ID associated with this validator.
     * @param metadataType The numeric metadata type ID associated with this validator.
     * @param validator    Contract implementing IMetadataValidator.
     */
    function setValidator(uint32 keyType, uint8 metadataType, IMetadataValidator validator) external;

    /**
     * @notice Set the IdRegistry contract address. Only callable by owner.
     *
     * @param _idRegistry The new IdRegistry address.
     */
    function setIdRegistry(address _idRegistry) external;

    /**
     * @notice Set the KeyGateway address allowed to add keys. Only callable by owner.
     *
     * @param _keyGateway The new KeyGateway address.
     */
    function setKeyGateway(address _keyGateway) external;

    /**
     * @notice Permanently freeze the KeyGateway address. Only callable by owner.
     */
    function freezeKeyGateway() external;

    /**
     * @notice Set the maximum number of keys allowed per fid. Only callable by owner.
     *
     * @param _maxKeysPerFid The new max keys per fid.
     */
    function setMaxKeysPerFid(uint256 _maxKeysPerFid) external;
}

File 3 of 10 : Message.sol
// File automatically generated by protoc-gen-sol v0.2.0
//
// modified by @jaydenwindle
// see: https://github.com/wilsoncusack/frame-verifier/blob/ed8bdb7c0117911be45ea2773080d21c67737385/src/Encoder.sol
// see: https://github.com/pavlovdog/farcaster-solidity/blob/e5272a57589c75f17394eba17d527246976154f4/contracts/protobufs/message.proto.sol
//
// SPDX-License-Identifier: CC0
pragma solidity >=0.6.0 <8.0.0;
pragma experimental ABIEncoderV2;

import "@lazyledger/protobuf3-solidity-lib/contracts/ProtobufLib.sol";

enum HashScheme {
    HASH_SCHEME_NONE,
    HASH_SCHEME_BLAKE3
}

enum SignatureScheme {
    SIGNATURE_SCHEME_NONE,
    SIGNATURE_SCHEME_ED25519,
    SIGNATURE_SCHEME_EIP712
}

enum MessageType {
    MESSAGE_TYPE_NONE,
    MESSAGE_TYPE_CAST_ADD,
    MESSAGE_TYPE_CAST_REMOVE,
    MESSAGE_TYPE_REACTION_ADD,
    MESSAGE_TYPE_REACTION_REMOVE,
    MESSAGE_TYPE_LINK_ADD,
    MESSAGE_TYPE_LINK_REMOVE,
    MESSAGE_TYPE_VERIFICATION_ADD_ETH_ADDRESS,
    MESSAGE_TYPE_VERIFICATION_REMOVE,
    DEPRECATED_MESSAGE_TYPE_SIGNER_ADD,
    DEPRECATED_MESSAGE_TYPE_SIGNER_REMOVE,
    MESSAGE_TYPE_USER_DATA_ADD,
    MESSAGE_TYPE_USERNAME_PROOF,
    MESSAGE_TYPE_FRAME_ACTION
}

enum FarcasterNetwork {
    FARCASTER_NETWORK_NONE,
    FARCASTER_NETWORK_MAINNET,
    FARCASTER_NETWORK_TESTNET,
    FARCASTER_NETWORK_DEVNET
}

enum UserDataType {
    USER_DATA_TYPE_NONE,
    USER_DATA_TYPE_PFP,
    USER_DATA_TYPE_DISPLAY,
    USER_DATA_TYPE_BIO,
    EMPTY,
    USER_DATA_TYPE_URL,
    USER_DATA_TYPE_USERNAME
}

enum ReactionType {
    REACTION_TYPE_NONE,
    REACTION_TYPE_LIKE,
    REACTION_TYPE_RECAST
}

struct Message {
    MessageData data;
    bytes hash_;
    HashScheme hash_scheme;
    bytes signature;
    SignatureScheme signature_scheme;
    bytes signer;
    bytes data_bytes;
}

library MessageCodec {
    function decode(uint64 initial_pos, bytes memory buf, uint64 len)
        internal
        pure
        returns (bool, uint64, Message memory)
    {
        // Message instance
        Message memory instance;
        // Previous field number
        uint64 previous_field_number = 0;
        // Current position in the buffer
        uint64 pos = initial_pos;

        // Sanity checks
        if (pos + len < pos) {
            return (false, pos, instance);
        }

        while (pos - initial_pos < len) {
            // Decode the key (field number and wire type)
            bool success;
            uint64 field_number;
            ProtobufLib.WireType wire_type;
            (success, pos, field_number, wire_type) = ProtobufLib.decode_key(pos, buf);
            if (!success) {
                return (false, pos, instance);
            }

            // Check that the field number is within bounds
            if (field_number > 7) {
                return (false, pos, instance);
            }

            // Check that the field number of monotonically increasing
            if (field_number <= previous_field_number) {
                return (false, pos, instance);
            }

            // Check that the wire type is correct
            success = check_key(field_number, wire_type);
            if (!success) {
                return (false, pos, instance);
            }

            // Actually decode the field
            (success, pos) = decode_field(pos, buf, len, field_number, instance);
            if (!success) {
                return (false, pos, instance);
            }

            previous_field_number = field_number;
        }

        // Decoding must have consumed len bytes
        if (pos != initial_pos + len) {
            return (false, pos, instance);
        }

        return (true, pos, instance);
    }

    function check_key(uint64 field_number, ProtobufLib.WireType wire_type) internal pure returns (bool) {
        if (field_number == 1) {
            return wire_type == ProtobufLib.WireType.LengthDelimited;
        }

        if (field_number == 2) {
            return wire_type == ProtobufLib.WireType.LengthDelimited;
        }

        if (field_number == 3) {
            return wire_type == ProtobufLib.WireType.Varint;
        }

        if (field_number == 4) {
            return wire_type == ProtobufLib.WireType.LengthDelimited;
        }

        if (field_number == 5) {
            return wire_type == ProtobufLib.WireType.Varint;
        }

        if (field_number == 6) {
            return wire_type == ProtobufLib.WireType.LengthDelimited;
        }

        if (field_number == 7) {
            return wire_type == ProtobufLib.WireType.LengthDelimited;
        }

        return false;
    }

    function decode_field(
        uint64 initial_pos,
        bytes memory buf,
        uint64, // len
        uint64 field_number,
        Message memory instance
    ) internal pure returns (bool, uint64) {
        uint64 pos = initial_pos;

        if (field_number == 1) {
            bool success;
            (success, pos) = decode_1(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        if (field_number == 2) {
            bool success;
            (success, pos) = decode_2(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        if (field_number == 3) {
            bool success;
            (success, pos) = decode_3(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        if (field_number == 4) {
            bool success;
            (success, pos) = decode_4(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        if (field_number == 5) {
            bool success;
            (success, pos) = decode_5(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        if (field_number == 6) {
            bool success;
            (success, pos) = decode_6(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        if (field_number == 7) {
            bool success;
            (success, pos) = decode_7(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        return (false, pos);
    }

    // Message.data
    function decode_1(uint64 pos, bytes memory buf, Message memory instance) internal pure returns (bool, uint64) {
        bool success;

        uint64 len;
        (success, pos, len) = ProtobufLib.decode_embedded_message(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (len == 0) {
            return (false, pos);
        }

        MessageData memory nestedInstance;
        (success, pos, nestedInstance) = MessageDataCodec.decode(pos, buf, len);
        if (!success) {
            return (false, pos);
        }

        instance.data = nestedInstance;

        return (true, pos);
    }

    // Message.hash_
    function decode_2(uint64 pos, bytes memory buf, Message memory instance) internal pure returns (bool, uint64) {
        bool success;

        uint64 len;
        (success, pos, len) = ProtobufLib.decode_bytes(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (len == 0) {
            return (false, pos);
        }

        instance.hash_ = new bytes(len);
        for (uint64 i = 0; i < len; i++) {
            instance.hash_[i] = buf[pos + i];
        }

        pos = pos + len;

        return (true, pos);
    }

    // Message.hash_scheme
    function decode_3(uint64 pos, bytes memory buf, Message memory instance) internal pure returns (bool, uint64) {
        bool success;

        int32 v;
        (success, pos, v) = ProtobufLib.decode_enum(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (v == 0) {
            return (false, pos);
        }

        // Check that value is within enum range
        if (v < 0 || v > 1) {
            return (false, pos);
        }

        instance.hash_scheme = HashScheme(v);

        return (true, pos);
    }

    // Message.signature
    function decode_4(uint64 pos, bytes memory buf, Message memory instance) internal pure returns (bool, uint64) {
        bool success;

        uint64 len;
        (success, pos, len) = ProtobufLib.decode_bytes(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (len == 0) {
            return (false, pos);
        }

        instance.signature = new bytes(len);
        for (uint64 i = 0; i < len; i++) {
            instance.signature[i] = buf[pos + i];
        }

        pos = pos + len;

        return (true, pos);
    }

    // Message.signature_scheme
    function decode_5(uint64 pos, bytes memory buf, Message memory instance) internal pure returns (bool, uint64) {
        bool success;

        int32 v;
        (success, pos, v) = ProtobufLib.decode_enum(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (v == 0) {
            return (false, pos);
        }

        // Check that value is within enum range
        if (v < 0 || v > 2) {
            return (false, pos);
        }

        instance.signature_scheme = SignatureScheme(v);

        return (true, pos);
    }

    // Message.signer
    function decode_6(uint64 pos, bytes memory buf, Message memory instance) internal pure returns (bool, uint64) {
        bool success;

        uint64 len;
        (success, pos, len) = ProtobufLib.decode_bytes(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (len == 0) {
            return (false, pos);
        }

        instance.signer = new bytes(len);
        for (uint64 i = 0; i < len; i++) {
            instance.signer[i] = buf[pos + i];
        }

        pos = pos + len;

        return (true, pos);
    }

    // Message.data_bytes
    function decode_7(uint64 pos, bytes memory buf, Message memory instance) internal pure returns (bool, uint64) {
        bool success;

        uint64 len;
        (success, pos, len) = ProtobufLib.decode_bytes(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (len == 0) {
            return (false, pos);
        }

        instance.data_bytes = new bytes(len);
        for (uint64 i = 0; i < len; i++) {
            instance.data_bytes[i] = buf[pos + i];
        }

        pos = pos + len;

        return (true, pos);
    }
}

struct MessageData {
    MessageType type_;
    uint64 fid;
    uint32 timestamp;
    FarcasterNetwork network;
    CastAddBody cast_add_body;
    bool empty_cast_remove_body;
    ReactionBody reaction_body;
    bool empty;
    VerificationAddEthAddressBody verification_add_eth_address_body;
    bool empty_verification_remove_body;
    bool deprecated_signer_add_body;
    bool user_data_body;
    bool deprecated_signer_remove_body;
    LinkBody link_body;
    bool empty_username_proof_body;
    FrameActionBody frame_action_body;
}

library MessageDataCodec {
    function encode(MessageData memory instance) internal pure returns (bytes memory) {
        // Omit encoding fields if default value
        bytes memory type__Key =
            uint64(instance.type_) != 0 ? ProtobufLib.encode_key(1, uint64(ProtobufLib.WireType.Varint)) : new bytes(0);
        bytes memory type_ =
            uint64(instance.type_) != 0 ? ProtobufLib.encode_int32(int32(uint32(instance.type_))) : new bytes(0);
        bytes memory fid__Key =
            uint64(instance.fid) != 0 ? ProtobufLib.encode_key(2, uint64(ProtobufLib.WireType.Varint)) : new bytes(0);
        bytes memory fid = uint64(instance.fid) != 0 ? ProtobufLib.encode_uint64(instance.fid) : new bytes(0);
        bytes memory timestamp__Key = uint64(instance.timestamp) != 0
            ? ProtobufLib.encode_key(3, uint64(ProtobufLib.WireType.Varint))
            : new bytes(0);
        bytes memory timestamp =
            uint64(instance.timestamp) != 0 ? ProtobufLib.encode_uint32(instance.timestamp) : new bytes(0);
        bytes memory network__Key = uint64(instance.network) != 0
            ? ProtobufLib.encode_key(4, uint64(ProtobufLib.WireType.Varint))
            : new bytes(0);
        bytes memory network =
            uint64(instance.network) != 0 ? ProtobufLib.encode_int32(int32(uint32(instance.network))) : new bytes(0);

        // Encode frame_action_body
        FrameActionBodyCodec.FrameActionBody__Encoded__Nested memory frame_action_body =
            FrameActionBodyCodec.encodeNested(16, instance.frame_action_body);
        bytes memory frame_action_body__Encoded =
            abi.encodePacked(frame_action_body.key, frame_action_body.length, frame_action_body.nestedInstance);

        // Use abi.encodePacked for efficient concatenation
        return abi.encodePacked(
            type__Key,
            type_,
            fid__Key,
            fid,
            timestamp__Key,
            timestamp,
            network__Key,
            network,
            frame_action_body__Encoded
        );
    }

    function decode(uint64 initial_pos, bytes memory buf, uint64 len)
        internal
        pure
        returns (bool, uint64, MessageData memory)
    {
        // Message instance
        MessageData memory instance;
        // Previous field number
        uint64 previous_field_number = 0;
        // Current position in the buffer
        uint64 pos = initial_pos;

        // Sanity checks
        if (pos + len < pos) {
            return (false, pos, instance);
        }

        while (pos - initial_pos < len) {
            // Decode the key (field number and wire type)
            bool success;
            uint64 field_number;
            ProtobufLib.WireType wire_type;
            (success, pos, field_number, wire_type) = ProtobufLib.decode_key(pos, buf);
            if (!success) {
                return (false, pos, instance);
            }

            // Check that the field number is within bounds
            if (field_number > 16) {
                return (false, pos, instance);
            }

            // Check that the field number of monotonically increasing
            if (field_number <= previous_field_number) {
                return (false, pos, instance);
            }

            // Check that the wire type is correct
            success = check_key(field_number, wire_type);
            if (!success) {
                return (false, pos, instance);
            }

            // Actually decode the field
            (success, pos) = decode_field(pos, buf, len, field_number, instance);
            if (!success) {
                return (false, pos, instance);
            }

            previous_field_number = field_number;
        }

        // Decoding must have consumed len bytes
        if (pos != initial_pos + len) {
            return (false, pos, instance);
        }

        return (true, pos, instance);
    }

    function check_key(uint64 field_number, ProtobufLib.WireType wire_type) internal pure returns (bool) {
        if (field_number == 1) {
            return wire_type == ProtobufLib.WireType.Varint;
        }

        if (field_number == 2) {
            return wire_type == ProtobufLib.WireType.Varint;
        }

        if (field_number == 3) {
            return wire_type == ProtobufLib.WireType.Varint;
        }

        if (field_number == 4) {
            return wire_type == ProtobufLib.WireType.Varint;
        }

        if (field_number == 5) {
            return wire_type == ProtobufLib.WireType.LengthDelimited;
        }

        if (field_number == 6) {
            return wire_type == ProtobufLib.WireType.Varint;
        }

        if (field_number == 7) {
            return wire_type == ProtobufLib.WireType.LengthDelimited;
        }

        if (field_number == 8) {
            return wire_type == ProtobufLib.WireType.Varint;
        }

        if (field_number == 9) {
            return wire_type == ProtobufLib.WireType.LengthDelimited;
        }

        if (field_number == 10) {
            return wire_type == ProtobufLib.WireType.Varint;
        }

        if (field_number == 11) {
            return wire_type == ProtobufLib.WireType.Varint;
        }

        if (field_number == 12) {
            return wire_type == ProtobufLib.WireType.Varint;
        }

        if (field_number == 13) {
            return wire_type == ProtobufLib.WireType.Varint;
        }

        if (field_number == 14) {
            return wire_type == ProtobufLib.WireType.LengthDelimited;
        }

        if (field_number == 15) {
            return wire_type == ProtobufLib.WireType.Varint;
        }

        if (field_number == 16) {
            return wire_type == ProtobufLib.WireType.LengthDelimited;
        }

        return false;
    }

    function decode_field(
        uint64 initial_pos,
        bytes memory buf,
        uint64, // len
        uint64 field_number,
        MessageData memory instance
    ) internal pure returns (bool, uint64) {
        uint64 pos = initial_pos;

        if (field_number == 1) {
            bool success;
            (success, pos) = decode_1(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        if (field_number == 2) {
            bool success;
            (success, pos) = decode_2(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        if (field_number == 3) {
            bool success;
            (success, pos) = decode_3(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        if (field_number == 4) {
            bool success;
            (success, pos) = decode_4(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        if (field_number == 5) {
            bool success;
            (success, pos) = decode_5(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        if (field_number == 6) {
            bool success;
            (success, pos) = decode_6(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        if (field_number == 7) {
            bool success;
            (success, pos) = decode_7(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        if (field_number == 8) {
            bool success;
            (success, pos) = decode_8(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        if (field_number == 9) {
            bool success;
            (success, pos) = decode_9(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        if (field_number == 10) {
            bool success;
            (success, pos) = decode_10(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        if (field_number == 11) {
            bool success;
            (success, pos) = decode_11(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        if (field_number == 12) {
            bool success;
            (success, pos) = decode_12(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        if (field_number == 13) {
            bool success;
            (success, pos) = decode_13(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        if (field_number == 14) {
            bool success;
            (success, pos) = decode_14(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        if (field_number == 15) {
            bool success;
            (success, pos) = decode_15(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        if (field_number == 16) {
            bool success;
            (success, pos) = decode_16(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        return (false, pos);
    }

    // MessageData.type_
    function decode_1(uint64 pos, bytes memory buf, MessageData memory instance) internal pure returns (bool, uint64) {
        bool success;

        int32 v;
        (success, pos, v) = ProtobufLib.decode_enum(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (v == 0) {
            return (false, pos);
        }

        // Check that value is within enum range
        if (v < 0 || v > 13) {
            return (false, pos);
        }

        instance.type_ = MessageType(v);

        return (true, pos);
    }

    // MessageData.fid
    function decode_2(uint64 pos, bytes memory buf, MessageData memory instance) internal pure returns (bool, uint64) {
        bool success;

        uint64 v;
        (success, pos, v) = ProtobufLib.decode_uint64(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (v == 0) {
            return (false, pos);
        }

        instance.fid = v;

        return (true, pos);
    }

    // MessageData.timestamp
    function decode_3(uint64 pos, bytes memory buf, MessageData memory instance) internal pure returns (bool, uint64) {
        bool success;

        uint32 v;
        (success, pos, v) = ProtobufLib.decode_uint32(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (v == 0) {
            return (false, pos);
        }

        instance.timestamp = v;

        return (true, pos);
    }

    // MessageData.network
    function decode_4(uint64 pos, bytes memory buf, MessageData memory instance) internal pure returns (bool, uint64) {
        bool success;

        int32 v;
        (success, pos, v) = ProtobufLib.decode_enum(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (v == 0) {
            return (false, pos);
        }

        // Check that value is within enum range
        if (v < 0 || v > 3) {
            return (false, pos);
        }

        instance.network = FarcasterNetwork(v);

        return (true, pos);
    }

    // MessageData.cast_add_body
    function decode_5(uint64 pos, bytes memory buf, MessageData memory instance) internal pure returns (bool, uint64) {
        bool success;

        uint64 len;
        (success, pos, len) = ProtobufLib.decode_embedded_message(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (len == 0) {
            return (false, pos);
        }

        CastAddBody memory nestedInstance;
        (success, pos, nestedInstance) = CastAddBodyCodec.decode(pos, buf, len);
        if (!success) {
            return (false, pos);
        }

        instance.cast_add_body = nestedInstance;

        return (true, pos);
    }

    // MessageData.empty_cast_remove_body
    function decode_6(uint64 pos, bytes memory buf, MessageData memory instance) internal pure returns (bool, uint64) {
        bool success;

        bool v;
        (success, pos, v) = ProtobufLib.decode_bool(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (v == false) {
            return (false, pos);
        }

        instance.empty_cast_remove_body = v;

        return (true, pos);
    }

    // MessageData.reaction_body
    function decode_7(uint64 pos, bytes memory buf, MessageData memory instance) internal pure returns (bool, uint64) {
        bool success;

        uint64 len;
        (success, pos, len) = ProtobufLib.decode_embedded_message(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (len == 0) {
            return (false, pos);
        }

        ReactionBody memory nestedInstance;
        (success, pos, nestedInstance) = ReactionBodyCodec.decode(pos, buf, len);
        if (!success) {
            return (false, pos);
        }

        instance.reaction_body = nestedInstance;

        return (true, pos);
    }

    // MessageData.empty
    function decode_8(uint64 pos, bytes memory buf, MessageData memory instance) internal pure returns (bool, uint64) {
        bool success;

        bool v;
        (success, pos, v) = ProtobufLib.decode_bool(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (v == false) {
            return (false, pos);
        }

        instance.empty = v;

        return (true, pos);
    }

    // MessageData.verification_add_eth_address_body
    function decode_9(uint64 pos, bytes memory buf, MessageData memory instance) internal pure returns (bool, uint64) {
        bool success;

        uint64 len;
        (success, pos, len) = ProtobufLib.decode_embedded_message(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (len == 0) {
            return (false, pos);
        }

        VerificationAddEthAddressBody memory nestedInstance;
        (success, pos, nestedInstance) = VerificationAddEthAddressBodyCodec.decode(pos, buf, len);
        if (!success) {
            return (false, pos);
        }

        instance.verification_add_eth_address_body = nestedInstance;

        return (true, pos);
    }

    // MessageData.empty_verification_remove_body
    function decode_10(uint64 pos, bytes memory buf, MessageData memory instance)
        internal
        pure
        returns (bool, uint64)
    {
        bool success;

        bool v;
        (success, pos, v) = ProtobufLib.decode_bool(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (v == false) {
            return (false, pos);
        }

        instance.empty_verification_remove_body = v;

        return (true, pos);
    }

    // MessageData.deprecated_signer_add_body
    function decode_11(uint64 pos, bytes memory buf, MessageData memory instance)
        internal
        pure
        returns (bool, uint64)
    {
        bool success;

        bool v;
        (success, pos, v) = ProtobufLib.decode_bool(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (v == false) {
            return (false, pos);
        }

        instance.deprecated_signer_add_body = v;

        return (true, pos);
    }

    // MessageData.user_data_body
    function decode_12(uint64 pos, bytes memory buf, MessageData memory instance)
        internal
        pure
        returns (bool, uint64)
    {
        bool success;

        bool v;
        (success, pos, v) = ProtobufLib.decode_bool(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (v == false) {
            return (false, pos);
        }

        instance.user_data_body = v;

        return (true, pos);
    }

    // MessageData.deprecated_signer_remove_body
    function decode_13(uint64 pos, bytes memory buf, MessageData memory instance)
        internal
        pure
        returns (bool, uint64)
    {
        bool success;

        bool v;
        (success, pos, v) = ProtobufLib.decode_bool(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (v == false) {
            return (false, pos);
        }

        instance.deprecated_signer_remove_body = v;

        return (true, pos);
    }

    // MessageData.link_body
    function decode_14(uint64 pos, bytes memory buf, MessageData memory instance)
        internal
        pure
        returns (bool, uint64)
    {
        bool success;

        uint64 len;
        (success, pos, len) = ProtobufLib.decode_embedded_message(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (len == 0) {
            return (false, pos);
        }

        LinkBody memory nestedInstance;
        (success, pos, nestedInstance) = LinkBodyCodec.decode(pos, buf, len);
        if (!success) {
            return (false, pos);
        }

        instance.link_body = nestedInstance;

        return (true, pos);
    }

    // MessageData.empty_username_proof_body
    function decode_15(uint64 pos, bytes memory buf, MessageData memory instance)
        internal
        pure
        returns (bool, uint64)
    {
        bool success;

        bool v;
        (success, pos, v) = ProtobufLib.decode_bool(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (v == false) {
            return (false, pos);
        }

        instance.empty_username_proof_body = v;

        return (true, pos);
    }

    // MessageData.frame_action_body
    function decode_16(uint64 pos, bytes memory buf, MessageData memory instance)
        internal
        pure
        returns (bool, uint64)
    {
        bool success;

        uint64 len;
        (success, pos, len) = ProtobufLib.decode_embedded_message(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (len == 0) {
            return (false, pos);
        }

        FrameActionBody memory nestedInstance;
        (success, pos, nestedInstance) = FrameActionBodyCodec.decode(pos, buf, len);
        if (!success) {
            return (false, pos);
        }

        instance.frame_action_body = nestedInstance;

        return (true, pos);
    }
}

struct UserDataBody {
    UserDataType type_;
    string value;
}

library UserDataBodyCodec {
    function decode(uint64 initial_pos, bytes memory buf, uint64 len)
        internal
        pure
        returns (bool, uint64, UserDataBody memory)
    {
        // Message instance
        UserDataBody memory instance;
        // Previous field number
        uint64 previous_field_number = 0;
        // Current position in the buffer
        uint64 pos = initial_pos;

        // Sanity checks
        if (pos + len < pos) {
            return (false, pos, instance);
        }

        while (pos - initial_pos < len) {
            // Decode the key (field number and wire type)
            bool success;
            uint64 field_number;
            ProtobufLib.WireType wire_type;
            (success, pos, field_number, wire_type) = ProtobufLib.decode_key(pos, buf);
            if (!success) {
                return (false, pos, instance);
            }

            // Check that the field number is within bounds
            if (field_number > 2) {
                return (false, pos, instance);
            }

            // Check that the field number of monotonically increasing
            if (field_number <= previous_field_number) {
                return (false, pos, instance);
            }

            // Check that the wire type is correct
            success = check_key(field_number, wire_type);
            if (!success) {
                return (false, pos, instance);
            }

            // Actually decode the field
            (success, pos) = decode_field(pos, buf, len, field_number, instance);
            if (!success) {
                return (false, pos, instance);
            }

            previous_field_number = field_number;
        }

        // Decoding must have consumed len bytes
        if (pos != initial_pos + len) {
            return (false, pos, instance);
        }

        return (true, pos, instance);
    }

    function check_key(uint64 field_number, ProtobufLib.WireType wire_type) internal pure returns (bool) {
        if (field_number == 1) {
            return wire_type == ProtobufLib.WireType.Varint;
        }

        if (field_number == 2) {
            return wire_type == ProtobufLib.WireType.LengthDelimited;
        }

        return false;
    }

    function decode_field(
        uint64 initial_pos,
        bytes memory buf,
        uint64, // len
        uint64 field_number,
        UserDataBody memory instance
    ) internal pure returns (bool, uint64) {
        uint64 pos = initial_pos;

        if (field_number == 1) {
            bool success;
            (success, pos) = decode_1(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        if (field_number == 2) {
            bool success;
            (success, pos) = decode_2(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        return (false, pos);
    }

    // UserDataBody.type_
    function decode_1(uint64 pos, bytes memory buf, UserDataBody memory instance)
        internal
        pure
        returns (bool, uint64)
    {
        bool success;

        int32 v;
        (success, pos, v) = ProtobufLib.decode_enum(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (v == 0) {
            return (false, pos);
        }

        // Check that value is within enum range
        if (v < 0 || v > 6) {
            return (false, pos);
        }

        instance.type_ = UserDataType(v);

        return (true, pos);
    }

    // UserDataBody.value
    function decode_2(uint64 pos, bytes memory buf, UserDataBody memory instance)
        internal
        pure
        returns (bool, uint64)
    {
        bool success;

        string memory v;
        (success, pos, v) = ProtobufLib.decode_string(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (bytes(v).length == 0) {
            return (false, pos);
        }

        instance.value = v;

        return (true, pos);
    }
}

struct Embed {
    string url;
    CastId cast_id;
}

library EmbedCodec {
    function decode(uint64 initial_pos, bytes memory buf, uint64 len)
        internal
        pure
        returns (bool, uint64, Embed memory)
    {
        // Message instance
        Embed memory instance;
        // Previous field number
        uint64 previous_field_number = 0;
        // Current position in the buffer
        uint64 pos = initial_pos;

        // Sanity checks
        if (pos + len < pos) {
            return (false, pos, instance);
        }

        while (pos - initial_pos < len) {
            // Decode the key (field number and wire type)
            bool success;
            uint64 field_number;
            ProtobufLib.WireType wire_type;
            (success, pos, field_number, wire_type) = ProtobufLib.decode_key(pos, buf);
            if (!success) {
                return (false, pos, instance);
            }

            // Check that the field number is within bounds
            if (field_number > 2) {
                return (false, pos, instance);
            }

            // Check that the field number of monotonically increasing
            if (field_number <= previous_field_number) {
                return (false, pos, instance);
            }

            // Check that the wire type is correct
            success = check_key(field_number, wire_type);
            if (!success) {
                return (false, pos, instance);
            }

            // Actually decode the field
            (success, pos) = decode_field(pos, buf, len, field_number, instance);
            if (!success) {
                return (false, pos, instance);
            }

            previous_field_number = field_number;
        }

        // Decoding must have consumed len bytes
        if (pos != initial_pos + len) {
            return (false, pos, instance);
        }

        return (true, pos, instance);
    }

    function check_key(uint64 field_number, ProtobufLib.WireType wire_type) internal pure returns (bool) {
        if (field_number == 1) {
            return wire_type == ProtobufLib.WireType.LengthDelimited;
        }

        if (field_number == 2) {
            return wire_type == ProtobufLib.WireType.LengthDelimited;
        }

        return false;
    }

    function decode_field(
        uint64 initial_pos,
        bytes memory buf,
        uint64, // len
        uint64 field_number,
        Embed memory instance
    ) internal pure returns (bool, uint64) {
        uint64 pos = initial_pos;

        if (field_number == 1) {
            bool success;
            (success, pos) = decode_1(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        if (field_number == 2) {
            bool success;
            (success, pos) = decode_2(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        return (false, pos);
    }

    // Embed.url
    function decode_1(uint64 pos, bytes memory buf, Embed memory instance) internal pure returns (bool, uint64) {
        bool success;

        string memory v;
        (success, pos, v) = ProtobufLib.decode_string(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (bytes(v).length == 0) {
            return (false, pos);
        }

        instance.url = v;

        return (true, pos);
    }

    // Embed.cast_id
    function decode_2(uint64 pos, bytes memory buf, Embed memory instance) internal pure returns (bool, uint64) {
        bool success;

        uint64 len;
        (success, pos, len) = ProtobufLib.decode_embedded_message(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (len == 0) {
            return (false, pos);
        }

        CastId memory nestedInstance;
        (success, pos, nestedInstance) = CastIdCodec.decode(pos, buf, len);
        if (!success) {
            return (false, pos);
        }

        instance.cast_id = nestedInstance;

        return (true, pos);
    }
}

struct CastAddBody {
    string embeds_deprecated;
    uint64[] mentions;
    CastId parent_cast_id;
    string text;
    uint32[] mentions_positions;
    Embed[] embeds;
    string parent_url;
}

library CastAddBodyCodec {
    function decode(uint64 initial_pos, bytes memory buf, uint64 len)
        internal
        pure
        returns (bool, uint64, CastAddBody memory)
    {
        // Message instance
        CastAddBody memory instance;
        // Previous field number
        uint64 previous_field_number = 0;
        // Current position in the buffer
        uint64 pos = initial_pos;

        // Sanity checks
        if (pos + len < pos) {
            return (false, pos, instance);
        }

        while (pos - initial_pos < len) {
            // Decode the key (field number and wire type)
            bool success;
            uint64 field_number;
            ProtobufLib.WireType wire_type;
            (success, pos, field_number, wire_type) = ProtobufLib.decode_key(pos, buf);
            if (!success) {
                return (false, pos, instance);
            }

            // Check that the field number is within bounds
            if (field_number > 7) {
                return (false, pos, instance);
            }

            // Check that the field number of monotonically increasing
            if (field_number <= previous_field_number) {
                return (false, pos, instance);
            }

            // Check that the wire type is correct
            success = check_key(field_number, wire_type);
            if (!success) {
                return (false, pos, instance);
            }

            // Actually decode the field
            (success, pos) = decode_field(pos, buf, len, field_number, instance);
            if (!success) {
                return (false, pos, instance);
            }

            previous_field_number = field_number;
        }

        // Decoding must have consumed len bytes
        if (pos != initial_pos + len) {
            return (false, pos, instance);
        }

        return (true, pos, instance);
    }

    function check_key(uint64 field_number, ProtobufLib.WireType wire_type) internal pure returns (bool) {
        if (field_number == 1) {
            return wire_type == ProtobufLib.WireType.LengthDelimited;
        }

        if (field_number == 2) {
            return wire_type == ProtobufLib.WireType.LengthDelimited;
        }

        if (field_number == 3) {
            return wire_type == ProtobufLib.WireType.LengthDelimited;
        }

        if (field_number == 4) {
            return wire_type == ProtobufLib.WireType.LengthDelimited;
        }

        if (field_number == 5) {
            return wire_type == ProtobufLib.WireType.LengthDelimited;
        }

        if (field_number == 6) {
            return wire_type == ProtobufLib.WireType.LengthDelimited;
        }

        if (field_number == 7) {
            return wire_type == ProtobufLib.WireType.LengthDelimited;
        }

        return false;
    }

    function decode_field(
        uint64 initial_pos,
        bytes memory buf,
        uint64, // len
        uint64 field_number,
        CastAddBody memory instance
    ) internal pure returns (bool, uint64) {
        uint64 pos = initial_pos;

        if (field_number == 1) {
            bool success;
            (success, pos) = decode_1(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        if (field_number == 2) {
            bool success;
            (success, pos) = decode_2(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        if (field_number == 3) {
            bool success;
            (success, pos) = decode_3(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        if (field_number == 4) {
            bool success;
            (success, pos) = decode_4(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        if (field_number == 5) {
            bool success;
            (success, pos) = decode_5(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        if (field_number == 6) {
            bool success;
            (success, pos) = decode_6(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        if (field_number == 7) {
            bool success;
            (success, pos) = decode_7(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        return (false, pos);
    }

    // CastAddBody.embeds_deprecated
    function decode_1(uint64 pos, bytes memory buf, CastAddBody memory instance) internal pure returns (bool, uint64) {
        bool success;

        string memory v;
        (success, pos, v) = ProtobufLib.decode_string(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (bytes(v).length == 0) {
            return (false, pos);
        }

        instance.embeds_deprecated = v;

        return (true, pos);
    }

    // CastAddBody.mentions
    function decode_2(uint64 pos, bytes memory buf, CastAddBody memory instance) internal pure returns (bool, uint64) {
        bool success;

        uint64 len;
        (success, pos, len) = ProtobufLib.decode_length_delimited(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Empty packed array must be omitted
        if (len == 0) {
            return (false, pos);
        }

        uint64 initial_pos = pos;

        // Sanity checks
        if (pos + len < pos) {
            return (false, pos);
        }

        // Do one pass to count the number of elements
        uint64 cnt = 0;
        while (pos - initial_pos < len) {
            uint64 v;
            (success, pos, v) = ProtobufLib.decode_uint64(pos, buf);
            if (!success) {
                return (false, pos);
            }
            cnt += 1;
        }

        // Allocated memory
        instance.mentions = new uint64[](cnt);

        // Now actually parse the elements
        pos = initial_pos;
        for (uint64 i = 0; i < cnt; i++) {
            uint64 v;
            (success, pos, v) = ProtobufLib.decode_uint64(pos, buf);
            if (!success) {
                return (false, pos);
            }

            instance.mentions[i] = v;
        }

        // Decoding must have consumed len bytes
        if (pos != initial_pos + len) {
            return (false, pos);
        }

        return (true, pos);
    }

    // CastAddBody.parent_cast_id
    function decode_3(uint64 pos, bytes memory buf, CastAddBody memory instance) internal pure returns (bool, uint64) {
        bool success;

        uint64 len;
        (success, pos, len) = ProtobufLib.decode_embedded_message(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (len == 0) {
            return (false, pos);
        }

        CastId memory nestedInstance;
        (success, pos, nestedInstance) = CastIdCodec.decode(pos, buf, len);
        if (!success) {
            return (false, pos);
        }

        instance.parent_cast_id = nestedInstance;

        return (true, pos);
    }

    // CastAddBody.text
    function decode_4(uint64 pos, bytes memory buf, CastAddBody memory instance) internal pure returns (bool, uint64) {
        bool success;

        string memory v;
        (success, pos, v) = ProtobufLib.decode_string(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (bytes(v).length == 0) {
            return (false, pos);
        }

        instance.text = v;

        return (true, pos);
    }

    // CastAddBody.mentions_positions
    function decode_5(uint64 pos, bytes memory buf, CastAddBody memory instance) internal pure returns (bool, uint64) {
        bool success;

        uint64 len;
        (success, pos, len) = ProtobufLib.decode_length_delimited(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Empty packed array must be omitted
        if (len == 0) {
            return (false, pos);
        }

        uint64 initial_pos = pos;

        // Sanity checks
        if (pos + len < pos) {
            return (false, pos);
        }

        // Do one pass to count the number of elements
        uint64 cnt = 0;
        while (pos - initial_pos < len) {
            uint32 v;
            (success, pos, v) = ProtobufLib.decode_uint32(pos, buf);
            if (!success) {
                return (false, pos);
            }
            cnt += 1;
        }

        // Allocated memory
        instance.mentions_positions = new uint32[](cnt);

        // Now actually parse the elements
        pos = initial_pos;
        for (uint64 i = 0; i < cnt; i++) {
            uint32 v;
            (success, pos, v) = ProtobufLib.decode_uint32(pos, buf);
            if (!success) {
                return (false, pos);
            }

            instance.mentions_positions[i] = v;
        }

        // Decoding must have consumed len bytes
        if (pos != initial_pos + len) {
            return (false, pos);
        }

        return (true, pos);
    }

    // CastAddBody.embeds
    function decode_6(uint64 pos, bytes memory buf, CastAddBody memory instance) internal pure returns (bool, uint64) {
        bool success;

        uint64 initial_pos = pos;

        // Do one pass to count the number of elements
        uint64 cnt = 0;
        while (pos < buf.length) {
            uint64 len;
            (success, pos, len) = ProtobufLib.decode_embedded_message(pos, buf);
            if (!success) {
                return (false, pos);
            }

            // Sanity checks
            if (pos + len < pos) {
                return (false, pos);
            }

            pos += len;
            cnt += 1;

            if (pos >= buf.length) {
                break;
            }

            // Decode next key
            uint64 field_number;
            ProtobufLib.WireType wire_type;
            (success, pos, field_number, wire_type) = ProtobufLib.decode_key(pos, buf);
            if (!success) {
                return (false, pos);
            }

            // Check if the field number is different
            if (field_number != 6) {
                break;
            }
        }

        // Allocated memory
        instance.embeds = new Embed[](cnt);

        // Now actually parse the elements
        pos = initial_pos;
        for (uint64 i = 0; i < cnt; i++) {
            uint64 len;
            (success, pos, len) = ProtobufLib.decode_embedded_message(pos, buf);
            if (!success) {
                return (false, pos);
            }

            initial_pos = pos;

            Embed memory nestedInstance;
            (success, pos, nestedInstance) = EmbedCodec.decode(pos, buf, len);
            if (!success) {
                return (false, pos);
            }

            instance.embeds[i] = nestedInstance;

            // Skip over next key, reuse len
            if (i < cnt - 1) {
                (success, pos, len) = ProtobufLib.decode_uint64(pos, buf);
                if (!success) {
                    return (false, pos);
                }
            }
        }

        return (true, pos);
    }

    // CastAddBody.parent_url
    function decode_7(uint64 pos, bytes memory buf, CastAddBody memory instance) internal pure returns (bool, uint64) {
        bool success;

        string memory v;
        (success, pos, v) = ProtobufLib.decode_string(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (bytes(v).length == 0) {
            return (false, pos);
        }

        instance.parent_url = v;

        return (true, pos);
    }
}

struct CastRemoveBody {
    bytes target_hash;
}

library CastRemoveBodyCodec {
    function decode(uint64 initial_pos, bytes memory buf, uint64 len)
        internal
        pure
        returns (bool, uint64, CastRemoveBody memory)
    {
        // Message instance
        CastRemoveBody memory instance;
        // Previous field number
        uint64 previous_field_number = 0;
        // Current position in the buffer
        uint64 pos = initial_pos;

        // Sanity checks
        if (pos + len < pos) {
            return (false, pos, instance);
        }

        while (pos - initial_pos < len) {
            // Decode the key (field number and wire type)
            bool success;
            uint64 field_number;
            ProtobufLib.WireType wire_type;
            (success, pos, field_number, wire_type) = ProtobufLib.decode_key(pos, buf);
            if (!success) {
                return (false, pos, instance);
            }

            // Check that the field number is within bounds
            if (field_number > 1) {
                return (false, pos, instance);
            }

            // Check that the field number of monotonically increasing
            if (field_number <= previous_field_number) {
                return (false, pos, instance);
            }

            // Check that the wire type is correct
            success = check_key(field_number, wire_type);
            if (!success) {
                return (false, pos, instance);
            }

            // Actually decode the field
            (success, pos) = decode_field(pos, buf, len, field_number, instance);
            if (!success) {
                return (false, pos, instance);
            }

            previous_field_number = field_number;
        }

        // Decoding must have consumed len bytes
        if (pos != initial_pos + len) {
            return (false, pos, instance);
        }

        return (true, pos, instance);
    }

    function check_key(uint64 field_number, ProtobufLib.WireType wire_type) internal pure returns (bool) {
        if (field_number == 1) {
            return wire_type == ProtobufLib.WireType.LengthDelimited;
        }

        return false;
    }

    function decode_field(
        uint64 initial_pos,
        bytes memory buf,
        uint64, // len
        uint64 field_number,
        CastRemoveBody memory instance
    ) internal pure returns (bool, uint64) {
        uint64 pos = initial_pos;

        if (field_number == 1) {
            bool success;
            (success, pos) = decode_1(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        return (false, pos);
    }

    // CastRemoveBody.target_hash
    function decode_1(uint64 pos, bytes memory buf, CastRemoveBody memory instance)
        internal
        pure
        returns (bool, uint64)
    {
        bool success;

        uint64 len;
        (success, pos, len) = ProtobufLib.decode_bytes(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (len == 0) {
            return (false, pos);
        }

        instance.target_hash = new bytes(len);
        for (uint64 i = 0; i < len; i++) {
            instance.target_hash[i] = buf[pos + i];
        }

        pos = pos + len;

        return (true, pos);
    }
}

struct CastId {
    uint64 fid;
    bytes hash_;
}

library CastIdCodec {
    // Holds encoded version of nested message
    struct CastId__Encoded__Nested {
        bytes key;
        bytes length;
        bytes nestedInstance;
    }

    function encode(CastId memory instance) internal pure returns (bytes memory) {
        bytes memory fid__Key =
            uint64(instance.fid) != 0 ? ProtobufLib.encode_key(1, uint64(ProtobufLib.WireType.Varint)) : new bytes(0);
        bytes memory fid = uint64(instance.fid) != 0 ? ProtobufLib.encode_uint64(instance.fid) : new bytes(0);
        bytes memory hash__Key = instance.hash_.length > 0
            ? ProtobufLib.encode_key(2, uint64(ProtobufLib.WireType.LengthDelimited))
            : new bytes(0);
        bytes memory hash__Length =
            instance.hash_.length > 0 ? ProtobufLib.encode_uint64(uint64(instance.hash_.length)) : new bytes(0);
        bytes memory hash = instance.hash_.length > 0 ? bytes(instance.hash_) : new bytes(0);

        return abi.encodePacked(fid__Key, fid, hash__Key, hash__Length, hash);
    }

    // Encode a nested CastId, wrapped in key and length if non-default
    function encodeNested(uint64 field_number, CastId memory instance)
        internal
        pure
        returns (CastId__Encoded__Nested memory)
    {
        bytes memory nestedInstance = encode(instance);
        uint64 len = uint64(nestedInstance.length);
        bytes memory key = len > 0 ? ProtobufLib.encode_key(field_number, 2) : new bytes(0);
        bytes memory length = len > 0 ? ProtobufLib.encode_uint64(len) : new bytes(0);

        return CastId__Encoded__Nested(key, length, nestedInstance);
    }

    function decode(uint64 initial_pos, bytes memory buf, uint64 len)
        internal
        pure
        returns (bool, uint64, CastId memory)
    {
        // Message instance
        CastId memory instance;
        // Previous field number
        uint64 previous_field_number = 0;
        // Current position in the buffer
        uint64 pos = initial_pos;

        // Sanity checks
        if (pos + len < pos) {
            return (false, pos, instance);
        }

        while (pos - initial_pos < len) {
            // Decode the key (field number and wire type)
            bool success;
            uint64 field_number;
            ProtobufLib.WireType wire_type;
            (success, pos, field_number, wire_type) = ProtobufLib.decode_key(pos, buf);
            if (!success) {
                return (false, pos, instance);
            }

            // Check that the field number is within bounds
            if (field_number > 2) {
                return (false, pos, instance);
            }

            // Check that the field number of monotonically increasing
            if (field_number <= previous_field_number) {
                return (false, pos, instance);
            }

            // Check that the wire type is correct
            success = check_key(field_number, wire_type);
            if (!success) {
                return (false, pos, instance);
            }

            // Actually decode the field
            (success, pos) = decode_field(pos, buf, len, field_number, instance);
            if (!success) {
                return (false, pos, instance);
            }

            previous_field_number = field_number;
        }

        // Decoding must have consumed len bytes
        if (pos != initial_pos + len) {
            return (false, pos, instance);
        }

        return (true, pos, instance);
    }

    function check_key(uint64 field_number, ProtobufLib.WireType wire_type) internal pure returns (bool) {
        if (field_number == 1) {
            return wire_type == ProtobufLib.WireType.Varint;
        }

        if (field_number == 2) {
            return wire_type == ProtobufLib.WireType.LengthDelimited;
        }

        return false;
    }

    function decode_field(
        uint64 initial_pos,
        bytes memory buf,
        uint64, // len
        uint64 field_number,
        CastId memory instance
    ) internal pure returns (bool, uint64) {
        uint64 pos = initial_pos;

        if (field_number == 1) {
            bool success;
            (success, pos) = decode_1(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        if (field_number == 2) {
            bool success;
            (success, pos) = decode_2(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        return (false, pos);
    }

    // CastId.fid
    function decode_1(uint64 pos, bytes memory buf, CastId memory instance) internal pure returns (bool, uint64) {
        bool success;

        uint64 v;
        (success, pos, v) = ProtobufLib.decode_uint64(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (v == 0) {
            return (false, pos);
        }

        instance.fid = v;

        return (true, pos);
    }

    // CastId.hash_
    function decode_2(uint64 pos, bytes memory buf, CastId memory instance) internal pure returns (bool, uint64) {
        bool success;

        uint64 len;
        (success, pos, len) = ProtobufLib.decode_bytes(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (len == 0) {
            return (false, pos);
        }

        instance.hash_ = new bytes(len);
        for (uint64 i = 0; i < len; i++) {
            instance.hash_[i] = buf[pos + i];
        }

        pos = pos + len;

        return (true, pos);
    }
}

struct ReactionBody {
    ReactionType type_;
    CastId target_cast_id;
    string target_url;
}

library ReactionBodyCodec {
    function decode(uint64 initial_pos, bytes memory buf, uint64 len)
        internal
        pure
        returns (bool, uint64, ReactionBody memory)
    {
        // Message instance
        ReactionBody memory instance;
        // Previous field number
        uint64 previous_field_number = 0;
        // Current position in the buffer
        uint64 pos = initial_pos;

        // Sanity checks
        if (pos + len < pos) {
            return (false, pos, instance);
        }

        while (pos - initial_pos < len) {
            // Decode the key (field number and wire type)
            bool success;
            uint64 field_number;
            ProtobufLib.WireType wire_type;
            (success, pos, field_number, wire_type) = ProtobufLib.decode_key(pos, buf);
            if (!success) {
                return (false, pos, instance);
            }

            // Check that the field number is within bounds
            if (field_number > 3) {
                return (false, pos, instance);
            }

            // Check that the field number of monotonically increasing
            if (field_number <= previous_field_number) {
                return (false, pos, instance);
            }

            // Check that the wire type is correct
            success = check_key(field_number, wire_type);
            if (!success) {
                return (false, pos, instance);
            }

            // Actually decode the field
            (success, pos) = decode_field(pos, buf, len, field_number, instance);
            if (!success) {
                return (false, pos, instance);
            }

            previous_field_number = field_number;
        }

        // Decoding must have consumed len bytes
        if (pos != initial_pos + len) {
            return (false, pos, instance);
        }

        return (true, pos, instance);
    }

    function check_key(uint64 field_number, ProtobufLib.WireType wire_type) internal pure returns (bool) {
        if (field_number == 1) {
            return wire_type == ProtobufLib.WireType.Varint;
        }

        if (field_number == 2) {
            return wire_type == ProtobufLib.WireType.LengthDelimited;
        }

        if (field_number == 3) {
            return wire_type == ProtobufLib.WireType.LengthDelimited;
        }

        return false;
    }

    function decode_field(
        uint64 initial_pos,
        bytes memory buf,
        uint64, // len
        uint64 field_number,
        ReactionBody memory instance
    ) internal pure returns (bool, uint64) {
        uint64 pos = initial_pos;

        if (field_number == 1) {
            bool success;
            (success, pos) = decode_1(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        if (field_number == 2) {
            bool success;
            (success, pos) = decode_2(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        if (field_number == 3) {
            bool success;
            (success, pos) = decode_3(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        return (false, pos);
    }

    // ReactionBody.type_
    function decode_1(uint64 pos, bytes memory buf, ReactionBody memory instance)
        internal
        pure
        returns (bool, uint64)
    {
        bool success;

        int32 v;
        (success, pos, v) = ProtobufLib.decode_enum(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (v == 0) {
            return (false, pos);
        }

        // Check that value is within enum range
        if (v < 0 || v > 2) {
            return (false, pos);
        }

        instance.type_ = ReactionType(v);

        return (true, pos);
    }

    // ReactionBody.target_cast_id
    function decode_2(uint64 pos, bytes memory buf, ReactionBody memory instance)
        internal
        pure
        returns (bool, uint64)
    {
        bool success;

        uint64 len;
        (success, pos, len) = ProtobufLib.decode_embedded_message(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (len == 0) {
            return (false, pos);
        }

        CastId memory nestedInstance;
        (success, pos, nestedInstance) = CastIdCodec.decode(pos, buf, len);
        if (!success) {
            return (false, pos);
        }

        instance.target_cast_id = nestedInstance;

        return (true, pos);
    }

    // ReactionBody.target_url
    function decode_3(uint64 pos, bytes memory buf, ReactionBody memory instance)
        internal
        pure
        returns (bool, uint64)
    {
        bool success;

        string memory v;
        (success, pos, v) = ProtobufLib.decode_string(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (bytes(v).length == 0) {
            return (false, pos);
        }

        instance.target_url = v;

        return (true, pos);
    }
}

struct VerificationAddEthAddressBody {
    bytes address_;
    bytes eth_signature;
    bytes block_hash;
    uint32 verification_type;
    uint32 chain_id;
}

library VerificationAddEthAddressBodyCodec {
    function decode(uint64 initial_pos, bytes memory buf, uint64 len)
        internal
        pure
        returns (bool, uint64, VerificationAddEthAddressBody memory)
    {
        // Message instance
        VerificationAddEthAddressBody memory instance;
        // Previous field number
        uint64 previous_field_number = 0;
        // Current position in the buffer
        uint64 pos = initial_pos;

        // Sanity checks
        if (pos + len < pos) {
            return (false, pos, instance);
        }

        while (pos - initial_pos < len) {
            // Decode the key (field number and wire type)
            bool success;
            uint64 field_number;
            ProtobufLib.WireType wire_type;
            (success, pos, field_number, wire_type) = ProtobufLib.decode_key(pos, buf);
            if (!success) {
                return (false, pos, instance);
            }

            // Check that the field number is within bounds
            if (field_number > 5) {
                return (false, pos, instance);
            }

            // Check that the field number of monotonically increasing
            if (field_number <= previous_field_number) {
                return (false, pos, instance);
            }

            // Check that the wire type is correct
            success = check_key(field_number, wire_type);
            if (!success) {
                return (false, pos, instance);
            }

            // Actually decode the field
            (success, pos) = decode_field(pos, buf, len, field_number, instance);
            if (!success) {
                return (false, pos, instance);
            }

            previous_field_number = field_number;
        }

        // Decoding must have consumed len bytes
        if (pos != initial_pos + len) {
            return (false, pos, instance);
        }

        return (true, pos, instance);
    }

    function check_key(uint64 field_number, ProtobufLib.WireType wire_type) internal pure returns (bool) {
        if (field_number == 1) {
            return wire_type == ProtobufLib.WireType.LengthDelimited;
        }

        if (field_number == 2) {
            return wire_type == ProtobufLib.WireType.LengthDelimited;
        }

        if (field_number == 3) {
            return wire_type == ProtobufLib.WireType.LengthDelimited;
        }

        if (field_number == 4) {
            return wire_type == ProtobufLib.WireType.Varint;
        }

        if (field_number == 5) {
            return wire_type == ProtobufLib.WireType.Varint;
        }

        return false;
    }

    function decode_field(
        uint64 initial_pos,
        bytes memory buf,
        uint64, // len
        uint64 field_number,
        VerificationAddEthAddressBody memory instance
    ) internal pure returns (bool, uint64) {
        uint64 pos = initial_pos;

        if (field_number == 1) {
            bool success;
            (success, pos) = decode_1(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        if (field_number == 2) {
            bool success;
            (success, pos) = decode_2(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        if (field_number == 3) {
            bool success;
            (success, pos) = decode_3(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        if (field_number == 4) {
            bool success;
            (success, pos) = decode_4(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        if (field_number == 5) {
            bool success;
            (success, pos) = decode_5(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        return (false, pos);
    }

    // VerificationAddEthAddressBody.address_
    function decode_1(uint64 pos, bytes memory buf, VerificationAddEthAddressBody memory instance)
        internal
        pure
        returns (bool, uint64)
    {
        bool success;

        uint64 len;
        (success, pos, len) = ProtobufLib.decode_bytes(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (len == 0) {
            return (false, pos);
        }

        instance.address_ = new bytes(len);
        for (uint64 i = 0; i < len; i++) {
            instance.address_[i] = buf[pos + i];
        }

        pos = pos + len;

        return (true, pos);
    }

    // VerificationAddEthAddressBody.eth_signature
    function decode_2(uint64 pos, bytes memory buf, VerificationAddEthAddressBody memory instance)
        internal
        pure
        returns (bool, uint64)
    {
        bool success;

        uint64 len;
        (success, pos, len) = ProtobufLib.decode_bytes(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (len == 0) {
            return (false, pos);
        }

        instance.eth_signature = new bytes(len);
        for (uint64 i = 0; i < len; i++) {
            instance.eth_signature[i] = buf[pos + i];
        }

        pos = pos + len;

        return (true, pos);
    }

    // VerificationAddEthAddressBody.block_hash
    function decode_3(uint64 pos, bytes memory buf, VerificationAddEthAddressBody memory instance)
        internal
        pure
        returns (bool, uint64)
    {
        bool success;

        uint64 len;
        (success, pos, len) = ProtobufLib.decode_bytes(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (len == 0) {
            return (false, pos);
        }

        instance.block_hash = new bytes(len);
        for (uint64 i = 0; i < len; i++) {
            instance.block_hash[i] = buf[pos + i];
        }

        pos = pos + len;

        return (true, pos);
    }

    // VerificationAddEthAddressBody.verification_type
    function decode_4(uint64 pos, bytes memory buf, VerificationAddEthAddressBody memory instance)
        internal
        pure
        returns (bool, uint64)
    {
        bool success;

        uint32 v;
        (success, pos, v) = ProtobufLib.decode_uint32(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (v == 0) {
            return (false, pos);
        }

        instance.verification_type = v;

        return (true, pos);
    }

    // VerificationAddEthAddressBody.chain_id
    function decode_5(uint64 pos, bytes memory buf, VerificationAddEthAddressBody memory instance)
        internal
        pure
        returns (bool, uint64)
    {
        bool success;

        uint32 v;
        (success, pos, v) = ProtobufLib.decode_uint32(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (v == 0) {
            return (false, pos);
        }

        instance.chain_id = v;

        return (true, pos);
    }
}

struct VerificationRemoveBody {
    bytes address_;
}

library VerificationRemoveBodyCodec {
    function decode(uint64 initial_pos, bytes memory buf, uint64 len)
        internal
        pure
        returns (bool, uint64, VerificationRemoveBody memory)
    {
        // Message instance
        VerificationRemoveBody memory instance;
        // Previous field number
        uint64 previous_field_number = 0;
        // Current position in the buffer
        uint64 pos = initial_pos;

        // Sanity checks
        if (pos + len < pos) {
            return (false, pos, instance);
        }

        while (pos - initial_pos < len) {
            // Decode the key (field number and wire type)
            bool success;
            uint64 field_number;
            ProtobufLib.WireType wire_type;
            (success, pos, field_number, wire_type) = ProtobufLib.decode_key(pos, buf);
            if (!success) {
                return (false, pos, instance);
            }

            // Check that the field number is within bounds
            if (field_number > 1) {
                return (false, pos, instance);
            }

            // Check that the field number of monotonically increasing
            if (field_number <= previous_field_number) {
                return (false, pos, instance);
            }

            // Check that the wire type is correct
            success = check_key(field_number, wire_type);
            if (!success) {
                return (false, pos, instance);
            }

            // Actually decode the field
            (success, pos) = decode_field(pos, buf, len, field_number, instance);
            if (!success) {
                return (false, pos, instance);
            }

            previous_field_number = field_number;
        }

        // Decoding must have consumed len bytes
        if (pos != initial_pos + len) {
            return (false, pos, instance);
        }

        return (true, pos, instance);
    }

    function check_key(uint64 field_number, ProtobufLib.WireType wire_type) internal pure returns (bool) {
        if (field_number == 1) {
            return wire_type == ProtobufLib.WireType.LengthDelimited;
        }

        return false;
    }

    function decode_field(
        uint64 initial_pos,
        bytes memory buf,
        uint64, // len
        uint64 field_number,
        VerificationRemoveBody memory instance
    ) internal pure returns (bool, uint64) {
        uint64 pos = initial_pos;

        if (field_number == 1) {
            bool success;
            (success, pos) = decode_1(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        return (false, pos);
    }

    // VerificationRemoveBody.address_
    function decode_1(uint64 pos, bytes memory buf, VerificationRemoveBody memory instance)
        internal
        pure
        returns (bool, uint64)
    {
        bool success;

        uint64 len;
        (success, pos, len) = ProtobufLib.decode_bytes(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (len == 0) {
            return (false, pos);
        }

        instance.address_ = new bytes(len);
        for (uint64 i = 0; i < len; i++) {
            instance.address_[i] = buf[pos + i];
        }

        pos = pos + len;

        return (true, pos);
    }
}

struct LinkBody {
    string type_;
    uint32 displayTimestamp;
    uint64 target_fid;
}

library LinkBodyCodec {
    function decode(uint64 initial_pos, bytes memory buf, uint64 len)
        internal
        pure
        returns (bool, uint64, LinkBody memory)
    {
        // Message instance
        LinkBody memory instance;
        // Previous field number
        uint64 previous_field_number = 0;
        // Current position in the buffer
        uint64 pos = initial_pos;

        // Sanity checks
        if (pos + len < pos) {
            return (false, pos, instance);
        }

        while (pos - initial_pos < len) {
            // Decode the key (field number and wire type)
            bool success;
            uint64 field_number;
            ProtobufLib.WireType wire_type;
            (success, pos, field_number, wire_type) = ProtobufLib.decode_key(pos, buf);
            if (!success) {
                return (false, pos, instance);
            }

            // Check that the field number is within bounds
            if (field_number > 3) {
                return (false, pos, instance);
            }

            // Check that the field number of monotonically increasing
            if (field_number <= previous_field_number) {
                return (false, pos, instance);
            }

            // Check that the wire type is correct
            success = check_key(field_number, wire_type);
            if (!success) {
                return (false, pos, instance);
            }

            // Actually decode the field
            (success, pos) = decode_field(pos, buf, len, field_number, instance);
            if (!success) {
                return (false, pos, instance);
            }

            previous_field_number = field_number;
        }

        // Decoding must have consumed len bytes
        if (pos != initial_pos + len) {
            return (false, pos, instance);
        }

        return (true, pos, instance);
    }

    function check_key(uint64 field_number, ProtobufLib.WireType wire_type) internal pure returns (bool) {
        if (field_number == 1) {
            return wire_type == ProtobufLib.WireType.LengthDelimited;
        }

        if (field_number == 2) {
            return wire_type == ProtobufLib.WireType.Varint;
        }

        if (field_number == 3) {
            return wire_type == ProtobufLib.WireType.Varint;
        }

        return false;
    }

    function decode_field(
        uint64 initial_pos,
        bytes memory buf,
        uint64, // len
        uint64 field_number,
        LinkBody memory instance
    ) internal pure returns (bool, uint64) {
        uint64 pos = initial_pos;

        if (field_number == 1) {
            bool success;
            (success, pos) = decode_1(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        if (field_number == 2) {
            bool success;
            (success, pos) = decode_2(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        if (field_number == 3) {
            bool success;
            (success, pos) = decode_3(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        return (false, pos);
    }

    // LinkBody.type_
    function decode_1(uint64 pos, bytes memory buf, LinkBody memory instance) internal pure returns (bool, uint64) {
        bool success;

        string memory v;
        (success, pos, v) = ProtobufLib.decode_string(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (bytes(v).length == 0) {
            return (false, pos);
        }

        instance.type_ = v;

        return (true, pos);
    }

    // LinkBody.displayTimestamp
    function decode_2(uint64 pos, bytes memory buf, LinkBody memory instance) internal pure returns (bool, uint64) {
        bool success;

        uint32 v;
        (success, pos, v) = ProtobufLib.decode_uint32(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (v == 0) {
            return (false, pos);
        }

        instance.displayTimestamp = v;

        return (true, pos);
    }

    // LinkBody.target_fid
    function decode_3(uint64 pos, bytes memory buf, LinkBody memory instance) internal pure returns (bool, uint64) {
        bool success;

        uint64 v;
        (success, pos, v) = ProtobufLib.decode_uint64(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (v == 0) {
            return (false, pos);
        }

        instance.target_fid = v;

        return (true, pos);
    }
}

struct FrameActionBody {
    bytes url;
    uint32 button_index;
    CastId cast_id;
}

library FrameActionBodyCodec {
    // Holds encoded version of nested message
    struct FrameActionBody__Encoded__Nested {
        bytes key;
        bytes length;
        bytes nestedInstance;
    }

    function encode(FrameActionBody memory instance) internal pure returns (bytes memory) {
        bytes memory url__Key = instance.url.length > 0
            ? ProtobufLib.encode_key(1, uint64(ProtobufLib.WireType.LengthDelimited))
            : new bytes(0);
        bytes memory url__Length =
            instance.url.length > 0 ? ProtobufLib.encode_uint64(uint64(instance.url.length)) : new bytes(0);
        bytes memory url = instance.url.length > 0 ? bytes(instance.url) : new bytes(0);
        bytes memory button_index__Key = uint64(instance.button_index) != 0
            ? ProtobufLib.encode_key(2, uint64(ProtobufLib.WireType.Varint))
            : new bytes(0);
        bytes memory button_index =
            uint64(instance.button_index) != 0 ? ProtobufLib.encode_uint32(instance.button_index) : new bytes(0);
        CastIdCodec.CastId__Encoded__Nested memory cast_id = CastIdCodec.encodeNested(3, instance.cast_id);
        bytes memory cast_id__Encoded = abi.encodePacked(cast_id.key, cast_id.length, cast_id.nestedInstance);

        return abi.encodePacked(url__Key, url__Length, url, button_index__Key, button_index, cast_id__Encoded);
    }

    // Encode a nested FrameActionBody, wrapped in key and length if non-default
    function encodeNested(uint64 field_number, FrameActionBody memory instance)
        internal
        pure
        returns (FrameActionBody__Encoded__Nested memory)
    {
        bytes memory nestedInstance = encode(instance);
        uint64 len = uint64(nestedInstance.length);
        bytes memory key = len > 0 ? ProtobufLib.encode_key(field_number, 2) : new bytes(0);
        bytes memory length = len > 0 ? ProtobufLib.encode_uint64(len) : new bytes(0);

        return FrameActionBody__Encoded__Nested(key, length, nestedInstance);
    }

    function decode(uint64 initial_pos, bytes memory buf, uint64 len)
        internal
        pure
        returns (bool, uint64, FrameActionBody memory)
    {
        // Message instance
        FrameActionBody memory instance;
        // Previous field number
        uint64 previous_field_number = 0;
        // Current position in the buffer
        uint64 pos = initial_pos;

        // Sanity checks
        if (pos + len < pos) {
            return (false, pos, instance);
        }

        while (pos - initial_pos < len) {
            // Decode the key (field number and wire type)
            bool success;
            uint64 field_number;
            ProtobufLib.WireType wire_type;
            (success, pos, field_number, wire_type) = ProtobufLib.decode_key(pos, buf);
            if (!success) {
                return (false, pos, instance);
            }

            // Check that the field number is within bounds
            if (field_number > 3) {
                return (false, pos, instance);
            }

            // Check that the field number of monotonically increasing
            if (field_number <= previous_field_number) {
                return (false, pos, instance);
            }

            // Check that the wire type is correct
            success = check_key(field_number, wire_type);
            if (!success) {
                return (false, pos, instance);
            }

            // Actually decode the field
            (success, pos) = decode_field(pos, buf, len, field_number, instance);
            if (!success) {
                return (false, pos, instance);
            }

            previous_field_number = field_number;
        }

        // Decoding must have consumed len bytes
        if (pos != initial_pos + len) {
            return (false, pos, instance);
        }

        return (true, pos, instance);
    }

    function check_key(uint64 field_number, ProtobufLib.WireType wire_type) internal pure returns (bool) {
        if (field_number == 1) {
            return wire_type == ProtobufLib.WireType.LengthDelimited;
        }

        if (field_number == 2) {
            return wire_type == ProtobufLib.WireType.Varint;
        }

        if (field_number == 3) {
            return wire_type == ProtobufLib.WireType.LengthDelimited;
        }

        return false;
    }

    function decode_field(
        uint64 initial_pos,
        bytes memory buf,
        uint64, // len
        uint64 field_number,
        FrameActionBody memory instance
    ) internal pure returns (bool, uint64) {
        uint64 pos = initial_pos;

        if (field_number == 1) {
            bool success;
            (success, pos) = decode_1(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        if (field_number == 2) {
            bool success;
            (success, pos) = decode_2(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        if (field_number == 3) {
            bool success;
            (success, pos) = decode_3(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        return (false, pos);
    }

    // FrameActionBody.url
    function decode_1(uint64 pos, bytes memory buf, FrameActionBody memory instance)
        internal
        pure
        returns (bool, uint64)
    {
        bool success;

        uint64 len;
        (success, pos, len) = ProtobufLib.decode_bytes(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (len == 0) {
            return (false, pos);
        }

        instance.url = new bytes(len);
        for (uint64 i = 0; i < len; i++) {
            instance.url[i] = buf[pos + i];
        }

        pos = pos + len;

        return (true, pos);
    }

    // FrameActionBody.button_index
    function decode_2(uint64 pos, bytes memory buf, FrameActionBody memory instance)
        internal
        pure
        returns (bool, uint64)
    {
        bool success;

        uint32 v;
        (success, pos, v) = ProtobufLib.decode_uint32(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (v == 0) {
            return (false, pos);
        }

        instance.button_index = v;

        return (true, pos);
    }

    // FrameActionBody.cast_id
    function decode_3(uint64 pos, bytes memory buf, FrameActionBody memory instance)
        internal
        pure
        returns (bool, uint64)
    {
        bool success;

        uint64 len;
        (success, pos, len) = ProtobufLib.decode_embedded_message(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (len == 0) {
            return (false, pos);
        }

        CastId memory nestedInstance;
        (success, pos, nestedInstance) = CastIdCodec.decode(pos, buf, len);
        if (!success) {
            return (false, pos);
        }

        instance.cast_id = nestedInstance;

        return (true, pos);
    }
}

enum UserNameType {
    USERNAME_TYPE_NONE,
    USERNAME_TYPE_FNAME,
    USERNAME_TYPE_ENS_L1
}

struct UserNameProof {
    uint64 timestamp;
    bytes name;
    bytes owner;
    bytes signature;
    uint64 fid;
    UserNameType type_;
}

library UserNameProofCodec {
    function decode(uint64 initial_pos, bytes memory buf, uint64 len)
        internal
        pure
        returns (bool, uint64, UserNameProof memory)
    {
        // Message instance
        UserNameProof memory instance;
        // Previous field number
        uint64 previous_field_number = 0;
        // Current position in the buffer
        uint64 pos = initial_pos;

        // Sanity checks
        if (pos + len < pos) {
            return (false, pos, instance);
        }

        while (pos - initial_pos < len) {
            // Decode the key (field number and wire type)
            bool success;
            uint64 field_number;
            ProtobufLib.WireType wire_type;
            (success, pos, field_number, wire_type) = ProtobufLib.decode_key(pos, buf);
            if (!success) {
                return (false, pos, instance);
            }

            // Check that the field number is within bounds
            if (field_number > 6) {
                return (false, pos, instance);
            }

            // Check that the field number of monotonically increasing
            if (field_number <= previous_field_number) {
                return (false, pos, instance);
            }

            // Check that the wire type is correct
            success = check_key(field_number, wire_type);
            if (!success) {
                return (false, pos, instance);
            }

            // Actually decode the field
            (success, pos) = decode_field(pos, buf, len, field_number, instance);
            if (!success) {
                return (false, pos, instance);
            }

            previous_field_number = field_number;
        }

        // Decoding must have consumed len bytes
        if (pos != initial_pos + len) {
            return (false, pos, instance);
        }

        return (true, pos, instance);
    }

    function check_key(uint64 field_number, ProtobufLib.WireType wire_type) internal pure returns (bool) {
        if (field_number == 1) {
            return wire_type == ProtobufLib.WireType.Varint;
        }

        if (field_number == 2) {
            return wire_type == ProtobufLib.WireType.LengthDelimited;
        }

        if (field_number == 3) {
            return wire_type == ProtobufLib.WireType.LengthDelimited;
        }

        if (field_number == 4) {
            return wire_type == ProtobufLib.WireType.LengthDelimited;
        }

        if (field_number == 5) {
            return wire_type == ProtobufLib.WireType.Varint;
        }

        if (field_number == 6) {
            return wire_type == ProtobufLib.WireType.Varint;
        }

        return false;
    }

    function decode_field(
        uint64 initial_pos,
        bytes memory buf,
        uint64, // len
        uint64 field_number,
        UserNameProof memory instance
    ) internal pure returns (bool, uint64) {
        uint64 pos = initial_pos;

        if (field_number == 1) {
            bool success;
            (success, pos) = decode_1(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        if (field_number == 2) {
            bool success;
            (success, pos) = decode_2(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        if (field_number == 3) {
            bool success;
            (success, pos) = decode_3(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        if (field_number == 4) {
            bool success;
            (success, pos) = decode_4(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        if (field_number == 5) {
            bool success;
            (success, pos) = decode_5(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        if (field_number == 6) {
            bool success;
            (success, pos) = decode_6(pos, buf, instance);
            if (!success) {
                return (false, pos);
            }

            return (true, pos);
        }

        return (false, pos);
    }

    // UserNameProof.timestamp
    function decode_1(uint64 pos, bytes memory buf, UserNameProof memory instance)
        internal
        pure
        returns (bool, uint64)
    {
        bool success;

        uint64 v;
        (success, pos, v) = ProtobufLib.decode_uint64(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (v == 0) {
            return (false, pos);
        }

        instance.timestamp = v;

        return (true, pos);
    }

    // UserNameProof.name
    function decode_2(uint64 pos, bytes memory buf, UserNameProof memory instance)
        internal
        pure
        returns (bool, uint64)
    {
        bool success;

        uint64 len;
        (success, pos, len) = ProtobufLib.decode_bytes(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (len == 0) {
            return (false, pos);
        }

        instance.name = new bytes(len);
        for (uint64 i = 0; i < len; i++) {
            instance.name[i] = buf[pos + i];
        }

        pos = pos + len;

        return (true, pos);
    }

    // UserNameProof.owner
    function decode_3(uint64 pos, bytes memory buf, UserNameProof memory instance)
        internal
        pure
        returns (bool, uint64)
    {
        bool success;

        uint64 len;
        (success, pos, len) = ProtobufLib.decode_bytes(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (len == 0) {
            return (false, pos);
        }

        instance.owner = new bytes(len);
        for (uint64 i = 0; i < len; i++) {
            instance.owner[i] = buf[pos + i];
        }

        pos = pos + len;

        return (true, pos);
    }

    // UserNameProof.signature
    function decode_4(uint64 pos, bytes memory buf, UserNameProof memory instance)
        internal
        pure
        returns (bool, uint64)
    {
        bool success;

        uint64 len;
        (success, pos, len) = ProtobufLib.decode_bytes(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (len == 0) {
            return (false, pos);
        }

        instance.signature = new bytes(len);
        for (uint64 i = 0; i < len; i++) {
            instance.signature[i] = buf[pos + i];
        }

        pos = pos + len;

        return (true, pos);
    }

    // UserNameProof.fid
    function decode_5(uint64 pos, bytes memory buf, UserNameProof memory instance)
        internal
        pure
        returns (bool, uint64)
    {
        bool success;

        uint64 v;
        (success, pos, v) = ProtobufLib.decode_uint64(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (v == 0) {
            return (false, pos);
        }

        instance.fid = v;

        return (true, pos);
    }

    // UserNameProof.type_
    function decode_6(uint64 pos, bytes memory buf, UserNameProof memory instance)
        internal
        pure
        returns (bool, uint64)
    {
        bool success;

        int32 v;
        (success, pos, v) = ProtobufLib.decode_enum(pos, buf);
        if (!success) {
            return (false, pos);
        }

        // Default value must be omitted
        if (v == 0) {
            return (false, pos);
        }

        // Check that value is within enum range
        if (v < 0 || v > 2) {
            return (false, pos);
        }

        instance.type_ = UserNameType(v);

        return (true, pos);
    }
}

File 4 of 10 : Blake3.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.9;

library Blake3 {
    uint256 constant BLOCK_LEN = 64;
    uint32 constant OUT_LEN = 32;
    uint32 constant CHUNK_LEN = 1024;

    // Flag constants
    uint32 constant CHUNK_START = 1 << 0;
    uint32 constant CHUNK_END = 1 << 1;
    uint32 constant PARENT = 1 << 2;
    uint32 constant ROOT = 1 << 3;
    uint32 constant KEYED_HASH = 1 << 4;
    uint32 constant DERIVE_KEY_CONTEXT = 1 << 5;
    uint32 constant DERIVE_KEY_MATERIAL = 1 << 6;

    // Product of a ChunkState before deriving chain value
    struct Output {
        uint32[8] input_chaining_value;
        uint32[16] block_words;
        uint64 counter;
        uint256 block_len;
        uint32 flags;
    }

    struct ChunkState {
        uint32[8] chaining_value;
        uint64 chunk_counter;
        // Has a max size of BLOCK_LEN
        bytes block_bytes;
        uint256 block_len;
        uint256 blocks_compressed;
        uint32 flags;
    }

    // An incremental hasher that can accept any number of writes.
    struct Hasher {
        ChunkState chunk_state;
        uint32[8] key_words;
        uint32[8][54] cv_stack; // Space for 54 subtree chaining values:
        uint8 cv_stack_len;     // 2^54 * CHUNK_LEN = 2^64
        uint32 flags;
    }

    // INTERNAL FUNCTIONS

    // This should remain constant but solidity doesn't support declaring it
    // uint8[16] MSG_PERMUTATION = [2, 6, 3, 10, 7, 0, 4, 13, 1, 11, 12, 5, 9, 14, 15, 8];
    // uint32[8] IV = [
    //     0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19
    // ];
    function _MSG_PERMUTATION() internal pure returns (uint8[16] memory) {
        return [2, 6, 3, 10, 7, 0, 4, 13, 1, 11, 12, 5, 9, 14, 15, 8];
    }

    function _IV() internal pure returns (uint32[8] memory) {
        return [0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19];
    }

    // Mixing function G
    function _g(
        uint32[16] memory state,
        uint32 a,
        uint32 b,
        uint32 c,
        uint32 d,
        uint32 mx,
        uint32 my
    ) internal pure {
        unchecked {
            state[a] = state[a] + state[b] + mx;
            state[d] = _rotr(state[d] ^ state[a], 16);
            state[c] = state[c] + state[d];
            state[b] = _rotr(state[b] ^ state[c], 12);
            state[a] = state[a] + state[b] + my;
            state[d] = _rotr(state[d] ^ state[a], 8);
            state[c] = state[c] + state[d];
            state[b] = _rotr(state[b] ^ state[c], 7);
        }
    }

    function _round(uint32[16] memory state, uint32[16] memory m) internal pure {
        // Mix the columns.
        _g(state, 0, 4, 8, 12, m[0], m[1]);
        _g(state, 1, 5, 9, 13, m[2], m[3]);
        _g(state, 2, 6, 10, 14, m[4], m[5]);
        _g(state, 3, 7, 11, 15, m[6], m[7]);

        // Mix the diagonals.
        _g(state, 0, 5, 10, 15, m[8], m[9]);
        _g(state, 1, 6, 11, 12, m[10], m[11]);
        _g(state, 2, 7, 8, 13, m[12], m[13]);
        _g(state, 3, 4, 9, 14, m[14], m[15]);
    }

    function _permute(uint32[16] memory m) internal pure {
        uint8[16] memory MSG_PERMUTATION = _MSG_PERMUTATION();
        uint32[16] memory permuted;

        for (uint256 i = 0; i < 16; ++i) {
            permuted[i] = m[MSG_PERMUTATION[i]];
        }

        for (uint256 i = 0; i < 16; ++i) {
            m[i] = permuted[i];
        }
    }

    function _compress(
        uint32[8] memory chaining_value,
        uint32[16] memory block_words_ref,
        uint64 counter,
        uint256 block_len,
        uint32 flags
    ) internal pure returns (uint32[16] memory) {
        uint32[8] memory IV = _IV();
        uint32[16] memory block_words;
        for (uint256 i = 0; i < 16; ++i) {
            block_words[i] = block_words_ref[i];
        }

        uint32[16] memory state = [
            chaining_value[0],
            chaining_value[1],
            chaining_value[2],
            chaining_value[3],
            chaining_value[4],
            chaining_value[5],
            chaining_value[6],
            chaining_value[7],
            IV[0],
            IV[1],
            IV[2],
            IV[3],
            uint32(counter),
            uint32(counter >> 32),
            ///////////////////////////////
            uint32(block_len),
            flags
        ];


        _round(state, block_words); // round 1
        _permute(block_words);
        _round(state, block_words); // round 2
        _permute(block_words);
        _round(state, block_words); // round 3
        _permute(block_words);
        _round(state, block_words); // round 4
        _permute(block_words);
        _round(state, block_words); // round 5
        _permute(block_words);
        _round(state, block_words); // round 6
        _permute(block_words);
        _round(state, block_words); // round 7

        for (uint256 i = 0; i < 8; ++i) {
            state[i] ^= state[i + 8];
            state[i + 8] ^= chaining_value[i];
        }

        return state;
    }

    function _rotr(uint32 x, uint8 n) internal pure returns (uint32) {
        bytes4 b = bytes4(x);
        return uint32((b >> n) | (b << (32 - n)));
    }

    function _chaining_value(Output memory o) internal pure returns (uint32[8] memory) {
        uint32[16] memory compression_output = _compress(
            o.input_chaining_value,
            o.block_words,
            o.counter,
            o.block_len,
            o.flags
        );

        return _first_8_words(compression_output);
    }

    function _root_output_bytes(
        Output memory self,
        bytes memory out_slice
    ) internal pure {
        //uint32 output_block_counter = 0;
        // Take 64-byte chunks at a time from out_slice
        //for (uint32 i = 0; i < out_slice.length; i += 2 * OUT_LEN) {
        uint32[16] memory words = _compress(
            self.input_chaining_value,
            self.block_words,
            0,
            //output_block_counter,
            self.block_len,
            self.flags | ROOT
        );

        // Load compressed words into out_slice (4 bytes at a time)
        // The output length might not be a multiple of 4.
        //for (uint32 j = 0; j < words.length && out_slice.length > j*4; j++) {
        //for (uint32 j = 0; j < words.length; j++) {
        for (uint32 j = 0; j < 8; j++) {
            // Load word at j into out_slice as little endian
            _load_uint32_to_le_bytes(words[j], out_slice, j*4);
        }

            //output_block_counter += 1;
        //}
    }

    function _load_uint32_to_le_bytes(
        uint32 n,
        bytes memory buf,
        uint32 offset
    ) internal pure {
        for (uint256 i = 0; i < 4; ++i) {
            buf[offset+i] = bytes1(uint8(n / (2 ** (i*8))));
        }
    }

    function _uint32_to_le_bytes(uint32 n) internal pure returns (bytes4) {
        bytes4 buf;
        for (uint256 i = 0; i < 4; ++i) {
            assembly {
                let cc := add(buf, 0x20)
                let buf_idx := add(cc, sub(3, i))
                let n_idx := add(n, i)
                mstore8(buf_idx, n_idx)
            }
        }

        return buf;
    }


    function _le_bytes_get_uint32(bytes memory _bytes, uint256 _start) internal pure returns (uint32) {
        require(_bytes.length >= _start + 4, "le_bytes_get_uint32_outOfBounds");
        uint32 tempUint;

        for (uint256 i = 0; i < 4; ++i) {
            //tempUint += uint32(uint8(_bytes[i]) * (2 ** (8*i)));
            tempUint += uint32(bytes4(_bytes[3-i+_start]) >> (8 * i));
        }
        /*
        assembly {
            // TODO why is this 0x4 in the bytes library???
            //tempUint := mload(add(add(_bytes, 0x4), _start))

            // Load 32 bytes from array (u256)
            tempUint := mload(add(add(_bytes, 0x20), _start))
            // Keep just the first 4 bytes (u32)
            //tempUint := xor(tempUint, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000)
            tempUint := xor(tempUint, 0x00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff)
        }
        */

        return tempUint;
    }

    function _words_from_little_endian_bytes8(
        bytes memory data_bytes,
        uint32[8] memory words
    ) internal pure {
        require(data_bytes.length <= 4*8,
                "Data bytes is too long to convert to 8 4-byte words");

        for (uint256 i = 0; i < data_bytes.length/4; ++i) {
            words[i] = _le_bytes_get_uint32(data_bytes, i*4);
        }
    }

    function _words_from_little_endian_bytes(
        bytes memory data_bytes,
        uint32[16] memory words
    ) internal pure {
        require(data_bytes.length <= 64 && data_bytes.length%4 == 0,
                "Data bytes is too long to convert to 16 4-byte words");

        for (uint256 i = 0; i < data_bytes.length/4; ++i) {
            words[i] = _le_bytes_get_uint32(data_bytes, i*4);
        }
    }


    // TODO I wish this didn't require a copy to convert array sizes
    function _first_8_words(uint32[16] memory words) internal pure returns (uint32[8] memory) {
        // TODO there must be a way to do this without copying
        // How to take a slice of a memory array?
        uint32[8] memory first_8;
        for (uint256 i = 0; i < 8; ++i) {
            first_8[i] = words[i];
        }

        return first_8;
    }


    //
    // Chunk state functions
    //

    function _new_chunkstate(
        uint32[8] memory key_words,
        uint64 chunk_counter,
        uint32 flags
    ) internal pure returns (ChunkState memory) {
        bytes memory block_bytes = new bytes(BLOCK_LEN);
        return ChunkState({
            chaining_value: key_words,
            chunk_counter: chunk_counter,
            block_bytes: block_bytes,
            block_len: 0,
            blocks_compressed: 0,
            flags: flags
        });
    }

    function _len(ChunkState memory chunk) internal pure returns (uint256) {
        return BLOCK_LEN * chunk.blocks_compressed + chunk.block_len;
    }

    function _start_flag(ChunkState memory chunk) internal pure returns (uint32) {
        if (chunk.blocks_compressed == 0) {
            return CHUNK_START;
        } else {
            return 0;
        }
    }

    // Returns a new input offset
    function _update_chunkstate(
        ChunkState memory chunk,
        bytes memory input
    ) internal pure {//returns (uint32) {
        uint256 input_offset = 0;
        while (input_offset < input.length) {
            // If the block buffer is full, compress it and clear it. More
            // input is coming, so this compression is not CHUNK_END.
            if (chunk.block_len == BLOCK_LEN) {
                uint32[16] memory block_words;
                _words_from_little_endian_bytes(chunk.block_bytes, block_words);
                chunk.chaining_value = _first_8_words(_compress(
                    chunk.chaining_value,
                    block_words,
                    chunk.chunk_counter,
                    BLOCK_LEN,
                    chunk.flags | _start_flag(chunk)
                ));
                chunk.blocks_compressed += 1;
                // TODO probably cheaper to zero-out byte array than to reallocate
                chunk.block_bytes = new bytes(BLOCK_LEN);
                chunk.block_len = 0;
            }

            // Take enough to fill a block [min(want, input.length)]
            uint256 want = BLOCK_LEN - chunk.block_len;
            uint256 take = _min(want, input.length - input_offset);

            // Copy bytes from input to chunk block
            //chunk.block_bytes[self.block_len as usize..][..take].copy_from_slice(&input[..take]);
            for (uint256 i = 0; i < take; ++i) {
                // TODO recheck this logic
                chunk.block_bytes[i+chunk.block_len] = input[input_offset+i];
            }
            /*
            bytes memory block_ref = chunk.block_bytes;
            uint32 blen = chunk.block_len;
            assembly {
                let block_addr := add(add(block_ref, 0x20), blen)
                let input_addr := add(add(input.offset, 0x20), input_offset)
                memorycopy(block_addr, input_addr, take)
            }
            */

            chunk.block_len += take;
            input_offset += take;
        }
    }

    function _min(uint256 x, uint256 y) internal pure returns (uint256) {
        if (x < y) {
            return x;
        } else {
            return y;
        }
    }

    function _output(ChunkState memory chunk) internal pure returns (Output memory) {
        uint32[16] memory block_words;
        _words_from_little_endian_bytes(chunk.block_bytes, block_words);

        return Output({
            input_chaining_value: chunk.chaining_value,
            block_words: block_words,
            counter: chunk.chunk_counter,
            block_len: chunk.block_len,
            flags: chunk.flags | _start_flag(chunk) | CHUNK_END
        });
    }

    //
    // Parent functions
    //

    function _parent_output(
        uint32[8] memory left_child_cv,
        uint32[8] memory right_child_cv,
        uint32[8] memory key_words,
        uint32 flags
    ) internal pure returns (Output memory) {
        uint32[16] memory block_words;

        for (uint256 i = 0; i < 8; ++i) {
            block_words[i] = left_child_cv[i];
        }

        for (uint256 i = 8; i < 16; ++i) {
            block_words[i] = right_child_cv[i - 8];
        }

        return Output({
            input_chaining_value: key_words,
            block_words: block_words,
            counter: 0,           // Always 0 for parent nodes.
            block_len: BLOCK_LEN, // Always BLOCK_LEN (64) for parent nodes.
            flags: PARENT | flags
        });
    }

    function _parent_cv(
        uint32[8] memory left_child_cv,
        uint32[8] memory right_child_cv,
        uint32[8] memory key_words,
        uint32 flags
    ) internal pure returns (uint32[8] memory) {
        return _chaining_value(_parent_output(left_child_cv, right_child_cv, key_words, flags));
    }


    //
    // Hasher functions
    //

    function _new_hasher_internal(
        uint32[8] memory key_words, uint32 flags
    ) internal pure returns (Hasher memory) {
        uint32[8][54] memory cv_stack;
        return Hasher({
            chunk_state: _new_chunkstate(key_words, 0, flags),
            key_words: key_words,
            cv_stack: cv_stack,
            cv_stack_len: 0,
            flags: flags
        });
    }

    /// Construct a new `Hasher` for the regular hash function.
    function new_hasher() internal pure returns (Hasher memory) {
        uint32[8] memory IV = _IV();
        return _new_hasher_internal(IV, 0);
    }

    /// Construct a new `Hasher` for the keyed hash function.
    function new_keyed(bytes memory key) internal pure returns (Hasher memory) {
        uint32[8] memory key_words;
        bytes memory key_mem = key;
        _words_from_little_endian_bytes8(key_mem, key_words);
        return _new_hasher_internal(key_words, KEYED_HASH);
    }

    // Construct a new `Hasher` for the key derivation function. The context
    // string should be hardcoded, globally unique, and application-specific
    function new_derive_key(bytes memory context) internal pure returns (Hasher memory) {
        uint32[8] memory IV = _IV();
        Hasher memory context_hasher = _new_hasher_internal(IV, DERIVE_KEY_CONTEXT);
        update_hasher(context_hasher, context);

        bytes memory context_key = new bytes(256);
        _finalize_internal(context_hasher, context_key);

        uint32[8] memory context_key_words;
        _words_from_little_endian_bytes8(context_key, context_key_words);

        return _new_hasher_internal(context_key_words, DERIVE_KEY_MATERIAL);
    }

    function _push_stack(Hasher memory self, uint32[8] memory cv) internal pure {
        self.cv_stack[self.cv_stack_len] = cv;
        self.cv_stack_len += 1;
    }

    function _pop_stack(Hasher memory self) internal pure returns (uint32[8] memory) {
        self.cv_stack_len -= 1;
        return self.cv_stack[self.cv_stack_len];
    }

    function _add_chunk_chaining_value(
        Hasher memory self,
        uint32[8] memory new_cv,
        uint64 total_chunks
    ) internal pure {
        while (total_chunks & 1 == 0) {
            new_cv = _parent_cv(_pop_stack(self), new_cv, self.key_words, self.flags);
            total_chunks >>= 1;
        }

        _push_stack(self, new_cv);
    }

    function _slice(
        bytes memory data,
        uint256 start,
        uint256 end
    ) internal pure returns (bytes memory) {
        uint256 dataSliceLength = end - start;
        bytes memory dataSlice = new bytes(dataSliceLength);

        for (uint256 i = 0; i < dataSliceLength; ++i) {
            dataSlice[i] = data[start + i];
        }

        return dataSlice;
    }

    // Add input to the hash state. This can be called any number of times.
    function update_hasher(
        Hasher memory self, bytes memory input
    ) internal pure returns (Hasher memory) {
        uint256 input_offset = 0;

        while (input_offset < input.length) {
            // If the current chunk is complete, finalize it and reset the
            // chunk state. More input is coming, so this chunk is not ROOT.
                if (_len(self.chunk_state) == CHUNK_LEN) {
                uint32[8] memory chunk_cv = _chaining_value(_output(self.chunk_state));
                uint64 total_chunks = self.chunk_state.chunk_counter + 1;

                _add_chunk_chaining_value(self, chunk_cv, total_chunks);

                self.chunk_state = _new_chunkstate(self.key_words, total_chunks, self.flags);
            }

            // Compress input bytes into the current chunk state.
            uint256 want = CHUNK_LEN - _len(self.chunk_state);
            uint256 take = _min(want, uint32(input.length - input_offset));

            // Update chunk state
            bytes memory input_slice = _slice(input, input_offset, take + input_offset);
            _update_chunkstate(self.chunk_state, input_slice);

            input_offset += take;
        }

        return self;
    }

    function finalize(Hasher memory self) internal pure returns (bytes memory) {
        bytes memory output = new bytes(32);

        _finalize_internal(self, output);

        return output;
    }

    function _finalize_internal(
        Hasher memory self, bytes memory out_slice
    ) internal pure {
        // Starting with the Output from the current chunk, compute all the
        // parent chaining values along the right edge of the tree, until we
        // have the root Output.
        Output memory output = _output(self.chunk_state);
        uint32 parent_nodes_remaining = self.cv_stack_len;

        while (parent_nodes_remaining > 0) {
            parent_nodes_remaining -= 1;

            output = _parent_output(
                self.cv_stack[parent_nodes_remaining],
                _chaining_value(output),
                self.key_words,
                self.flags
            );
        }
        _root_output_bytes(output, out_slice);
    }

    function sliceBytes(bytes memory message, uint64 length) internal pure returns (bytes memory) {
        require(length <= message.length, "Length exceeds message length");
        
        // Overwrite the length field of the bytes to crop the message
        assembly {
            mstore(message, length)
        }
        
        return message;
    }

    function hash(
        bytes memory message,
        uint32 length
    ) external pure returns (bytes memory) {
        Hasher memory hasher = new_hasher();
        update_hasher(hasher, message);

        return sliceBytes(finalize(hasher), length);
    }
}

File 5 of 10 : Ed25519.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.9;

import "./Sha512.sol";
import "./Ed25519_pow.sol";

library Ed25519 {
    function verify(
        bytes32 k,
        bytes32 r,
        bytes32 s,
        bytes memory m
    ) external pure returns (bool) {
        unchecked {
            uint256 hh;
            // Step 1: compute SHA-512(R, A, M)
            {
                bytes memory rs = new bytes(k.length + r.length + m.length);
                for (uint256 i = 0; i < r.length; i++) {
                    rs[i] = r[i];
                }
                for (uint256 i = 0; i < k.length; i++) {
                    rs[i + 32] = k[i];
                }
                    for (uint256 i = 0; i < m.length; i++) {
                    rs[i + 64] = m[i];
                }
                uint64[8] memory result = Sha512.hash(rs);

                uint256 h0 = uint256(result[0]) | uint256(result[1]) << 64 | uint256(result[2]) << 128 | uint256(result[3]) << 192;

                h0 =
                    ((h0 & 0xff00ff_00ff00ff_00ff00ff_00ff00ff_00ff00ff_00ff00ff_00ff00ff_00ff00ff) << 8) |
                    ((h0 & 0xff00ff00_ff00ff00_ff00ff00_ff00ff00_ff00ff00_ff00ff00_ff00ff00_ff00ff00) >> 8);
                h0 =
                    ((h0 & 0xffff_0000ffff_0000ffff_0000ffff_0000ffff_0000ffff_0000ffff_0000ffff) << 16) |
                    ((h0 & 0xffff0000_ffff0000_ffff0000_ffff0000_ffff0000_ffff0000_ffff0000_ffff0000) >> 16);
                h0 =
                    ((h0 & 0xffffffff_00000000_ffffffff_00000000_ffffffff_00000000_ffffffff) << 32) |
                    ((h0 & 0xffffffff_00000000_ffffffff_00000000_ffffffff_00000000_ffffffff_00000000) >> 32);

                uint256 h1 = uint256(result[4]) | uint256(result[5]) << 64 | uint256(result[6]) << 128 | uint256(result[7]) << 192;

                h1 =
                    ((h1 & 0xff00ff_00ff00ff_00ff00ff_00ff00ff_00ff00ff_00ff00ff_00ff00ff_00ff00ff) << 8) |
                    ((h1 & 0xff00ff00_ff00ff00_ff00ff00_ff00ff00_ff00ff00_ff00ff00_ff00ff00_ff00ff00) >> 8);
                h1 =
                    ((h1 & 0xffff_0000ffff_0000ffff_0000ffff_0000ffff_0000ffff_0000ffff_0000ffff) << 16) |
                    ((h1 & 0xffff0000_ffff0000_ffff0000_ffff0000_ffff0000_ffff0000_ffff0000_ffff0000) >> 16);
                h1 =
                    ((h1 & 0xffffffff_00000000_ffffffff_00000000_ffffffff_00000000_ffffffff) << 32) |
                    ((h1 & 0xffffffff_00000000_ffffffff_00000000_ffffffff_00000000_ffffffff_00000000) >> 32);
                hh = addmod(
                    h0,
                    mulmod(
                        h1,
                        0xfffffff_ffffffff_ffffffff_fffffffe_c6ef5bf4_737dcf70_d6ec3174_8d98951d,
                        0x10000000_00000000_00000000_00000000_14def9de_a2f79cd6_5812631a_5cf5d3ed
                    ),
                    0x10000000_00000000_00000000_00000000_14def9de_a2f79cd6_5812631a_5cf5d3ed
                );
            }
            // Step 2: unpack k
            k = bytes32(
                ((uint256(k) & 0xff00ff_00ff00ff_00ff00ff_00ff00ff_00ff00ff_00ff00ff_00ff00ff_00ff00ff) << 8) |
                    ((uint256(k) & 0xff00ff00_ff00ff00_ff00ff00_ff00ff00_ff00ff00_ff00ff00_ff00ff00_ff00ff00) >> 8)
            );
            k = bytes32(
                ((uint256(k) & 0xffff_0000ffff_0000ffff_0000ffff_0000ffff_0000ffff_0000ffff_0000ffff) << 16) |
                    ((uint256(k) & 0xffff0000_ffff0000_ffff0000_ffff0000_ffff0000_ffff0000_ffff0000_ffff0000) >> 16)
            );
            k = bytes32(
                ((uint256(k) & 0xffffffff_00000000_ffffffff_00000000_ffffffff_00000000_ffffffff) << 32) |
                    ((uint256(k) & 0xffffffff_00000000_ffffffff_00000000_ffffffff_00000000_ffffffff_00000000) >> 32)
            );
            k = bytes32(
                ((uint256(k) & 0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff) << 64) |
                    ((uint256(k) & 0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff_00000000_00000000) >> 64)
            );
            k = bytes32((uint256(k) << 128) | (uint256(k) >> 128));
            uint256 ky = uint256(k) & 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff;
            uint256 kx;
            {
                uint256 ky2 = mulmod(ky, ky, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
                uint256 u =
                    addmod(
                        ky2,
                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffec,
                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed
                    );
                uint256 v =
                    mulmod(
                        ky2,
                        0x52036cee_2b6ffe73_8cc74079_7779e898_00700a4d_4141d8ab_75eb4dca_135978a3,
                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed
                    ) + 1;
                uint256 t = mulmod(u, v, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
                (kx, ) = Ed25519_pow.pow22501(t);
                kx = mulmod(kx, kx, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
                kx = mulmod(
                    u,
                    mulmod(
                        mulmod(kx, kx, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed),
                        t,
                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed
                    ),
                    0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed
                );
                t = mulmod(
                    mulmod(kx, kx, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed),
                    v,
                    0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed
                );
                if (t != u) {
                    if (t != 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed - u) {
                        return false;
                    }
                    kx = mulmod(
                        kx,
                        0x2b832480_4fc1df0b_2b4d0099_3dfbd7a7_2f431806_ad2fe478_c4ee1b27_4a0ea0b0,
                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed
                    );
                }
            }
            if ((kx & 1) != uint256(k) >> 255) {
                kx = 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed - kx;
            }
            // Verify s
            s = bytes32(
                ((uint256(s) & 0xff00ff_00ff00ff_00ff00ff_00ff00ff_00ff00ff_00ff00ff_00ff00ff_00ff00ff) << 8) |
                    ((uint256(s) & 0xff00ff00_ff00ff00_ff00ff00_ff00ff00_ff00ff00_ff00ff00_ff00ff00_ff00ff00) >> 8)
            );
            s = bytes32(
                ((uint256(s) & 0xffff_0000ffff_0000ffff_0000ffff_0000ffff_0000ffff_0000ffff_0000ffff) << 16) |
                    ((uint256(s) & 0xffff0000_ffff0000_ffff0000_ffff0000_ffff0000_ffff0000_ffff0000_ffff0000) >> 16)
            );
            s = bytes32(
                ((uint256(s) & 0xffffffff_00000000_ffffffff_00000000_ffffffff_00000000_ffffffff) << 32) |
                    ((uint256(s) & 0xffffffff_00000000_ffffffff_00000000_ffffffff_00000000_ffffffff_00000000) >> 32)
            );
            s = bytes32(
                ((uint256(s) & 0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff) << 64) |
                    ((uint256(s) & 0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff_00000000_00000000) >> 64)
            );
            s = bytes32((uint256(s) << 128) | (uint256(s) >> 128));
            if (uint256(s) >= 0x10000000_00000000_00000000_00000000_14def9de_a2f79cd6_5812631a_5cf5d3ed) {
                return false;
            }
            uint256 vx;
            uint256 vu;
            uint256 vy;
            uint256 vv;
            // Step 3: compute multiples of k
            uint256[8][3][2] memory tables;
            {
                uint256 ks = ky + kx;
                uint256 kd = ky + 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed - kx;
                uint256 k2dt =
                    mulmod(
                        mulmod(kx, ky, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed),
                        0x2406d9dc_56dffce7_198e80f2_eef3d130_00e0149a_8283b156_ebd69b94_26b2f159,
                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed
                    );
                uint256 kky = ky;
                uint256 kkx = kx;
                uint256 kku = 1;
                uint256 kkv = 1;
                {
                    uint256 xx =
                        mulmod(kkx, kkv, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
                    uint256 yy =
                        mulmod(kky, kku, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
                    uint256 zz =
                        mulmod(kku, kkv, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
                    uint256 xx2 =
                        mulmod(xx, xx, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
                    uint256 yy2 =
                        mulmod(yy, yy, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
                    uint256 xxyy =
                        mulmod(xx, yy, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
                    uint256 zz2 =
                        mulmod(zz, zz, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
                    kkx = xxyy + xxyy;
                    kku = yy2 - xx2 + 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed;
                    kky = xx2 + yy2;
                    kkv = addmod(
                        zz2 + zz2,
                        0xffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffda - kku,
                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed
                    );
                }
                {
                    uint256 xx =
                        mulmod(kkx, kkv, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
                    uint256 yy =
                        mulmod(kky, kku, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
                    uint256 zz =
                        mulmod(kku, kkv, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
                    uint256 xx2 =
                        mulmod(xx, xx, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
                    uint256 yy2 =
                        mulmod(yy, yy, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
                    uint256 xxyy =
                        mulmod(xx, yy, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
                    uint256 zz2 =
                        mulmod(zz, zz, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
                    kkx = xxyy + xxyy;
                    kku = yy2 - xx2 + 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed;
                    kky = xx2 + yy2;
                    kkv = addmod(
                        zz2 + zz2,
                        0xffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffda - kku,
                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed
                    );
                }
                {
                    uint256 xx =
                        mulmod(kkx, kkv, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
                    uint256 yy =
                        mulmod(kky, kku, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
                    uint256 zz =
                        mulmod(kku, kkv, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
                    uint256 xx2 =
                        mulmod(xx, xx, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
                    uint256 yy2 =
                        mulmod(yy, yy, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
                    uint256 xxyy =
                        mulmod(xx, yy, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
                    uint256 zz2 =
                        mulmod(zz, zz, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
                    kkx = xxyy + xxyy;
                    kku = yy2 - xx2 + 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed;
                    kky = xx2 + yy2;
                    kkv = addmod(
                        zz2 + zz2,
                        0xffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffda - kku,
                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed
                    );
                }
                uint256 cprod = 1;
                uint256[8][3][2] memory tables_ = tables;
                for (uint256 i = 0; ; i++) {
                    uint256 cs;
                    uint256 cd;
                    uint256 ct;
                    uint256 c2z;
                    {
                        uint256 cx =
                            mulmod(kkx, kkv, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
                        uint256 cy =
                            mulmod(kky, kku, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
                        uint256 cz =
                            mulmod(kku, kkv, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
                        ct = mulmod(
                            kkx,
                            kky,
                            0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed
                        );
                        cs = cy + cx;
                        cd = cy - cx + 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed;
                        c2z = cz + cz;
                    }
                    tables_[1][0][i] = cs;
                    tables_[1][1][i] = cd;
                    tables_[1][2][i] = mulmod(
                        ct,
                        0x2406d9dc_56dffce7_198e80f2_eef3d130_00e0149a_8283b156_ebd69b94_26b2f159,
                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed
                    );
                    tables_[0][0][i] = c2z;
                    tables_[0][1][i] = cprod;
                    cprod = mulmod(
                        cprod,
                        c2z,
                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed
                    );
                    if (i == 7) {
                        break;
                    }
                    uint256 ab =
                        mulmod(cs, ks, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
                    uint256 aa =
                        mulmod(cd, kd, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
                    uint256 ac =
                        mulmod(ct, k2dt, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
                    kkx = ab - aa + 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed;
                    kku = addmod(c2z, ac, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
                    kky = ab + aa;
                    kkv = addmod(
                        c2z,
                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed - ac,
                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed
                    );
                }
                uint256 t;
                (cprod, t) = Ed25519_pow.pow22501(cprod);
                cprod = mulmod(cprod, cprod, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
                cprod = mulmod(cprod, cprod, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
                cprod = mulmod(cprod, cprod, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
                cprod = mulmod(cprod, cprod, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
                cprod = mulmod(cprod, cprod, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
                cprod = mulmod(cprod, t, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
                for (uint256 i = 7; ; i--) {
                    uint256 cinv =
                        mulmod(
                            cprod,
                            tables_[0][1][i],
                            0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed
                        );
                    tables_[1][0][i] = mulmod(
                        tables_[1][0][i],
                        cinv,
                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed
                    );
                    tables_[1][1][i] = mulmod(
                        tables_[1][1][i],
                        cinv,
                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed
                    );
                    tables_[1][2][i] = mulmod(
                        tables_[1][2][i],
                        cinv,
                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed
                    );
                    if (i == 0) {
                        break;
                    }
                    cprod = mulmod(
                        cprod,
                        tables_[0][0][i],
                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed
                    );
                }
                tables_[0] = [
                    [
                        0x43e7ce9d_19ea5d32_9385a44c_321ea161_67c996e3_7dc6070c_97de49e3_7ac61db9,
                        0x40cff344_25d8ec30_a3bb74ba_58cd5854_fa1e3818_6ad0d31e_bc8ae251_ceb2c97e,
                        0x459bd270_46e8dd45_aea7008d_b87a5a8f_79067792_53d64523_58951859_9fdfbf4b,
                        0x69fdd1e2_8c23cc38_94d0c8ff_90e76f6d_5b6e4c2e_620136d0_4dd83c4a_51581ab9,
                        0x54dceb34_13ce5cfa_11196dfc_960b6eda_f4b380c6_d4d23784_19cc0279_ba49c5f3,
                        0x4e24184d_d71a3d77_eef3729f_7f8cf7c1_7224cf40_aa7b9548_b9942f3c_5084ceed,
                        0x5a0e5aab_20262674_ae117576_1cbf5e88_9b52a55f_d7ac5027_c228cebd_c8d2360a,
                        0x26239334_073e9b38_c6285955_6d451c3d_cc8d30e8_4b361174_f488eadd_e2cf17d9
                    ],
                    [
                        0x227e97c9_4c7c0933_d2e0c21a_3447c504_fe9ccf82_e8a05f59_ce881c82_eba0489f,
                        0x226a3e0e_cc4afec6_fd0d2884_13014a9d_bddecf06_c1a2f0bb_702ba77c_613d8209,
                        0x34d7efc8_51d45c5e_71efeb0f_235b7946_91de6228_877569b3_a8d52bf0_58b8a4a0,
                        0x3c1f5fb3_ca7166fc_e1471c9b_752b6d28_c56301ad_7b65e845_1b2c8c55_26726e12,
                        0x6102416c_f02f02ff_5be75275_f55f28db_89b2a9d2_456b860c_e22fc0e5_031f7cc5,
                        0x40adf677_f1bfdae0_57f0fd17_9c126179_18ddaa28_91a6530f_b1a4294f_a8665490,
                        0x61936f3c_41560904_6187b8ba_a978cbc9_b4789336_3ae5a3cc_7d909f36_35ae7f48,
                        0x562a9662_b6ec47f9_e979d473_c02b51e4_42336823_8c58ddb5_2f0e5c6a_180e6410
                    ],
                    [
                        0x3788bdb4_4f8632d4_2d0dbee5_eea1acc6_136cf411_e655624f_55e48902_c3bd5534,
                        0x6190cf2c_2a7b5ad7_69d594a8_2844f23b_4167fa7c_8ac30e51_aa6cfbeb_dcd4b945,
                        0x65f77870_96be9204_123a71f3_ac88a87b_e1513217_737d6a1e_2f3a13a4_3d7e3a9a,
                        0x23af32d_bfa67975_536479a7_a7ce74a0_2142147f_ac048018_7f1f1334_9cda1f2d,
                        0x64fc44b7_fc6841bd_db0ced8b_8b0fe675_9137ef87_ee966512_15fc1dbc_d25c64dc,
                        0x1434aa37_48b701d5_b69df3d7_d340c1fe_3f6b9c1e_fc617484_caadb47e_382f4475,
                        0x457a6da8_c962ef35_f2b21742_3e5844e9_d2353452_7e8ea429_0d24e3dd_f21720c6,
                        0x63b9540c_eb60ccb5_1e4d989d_956e053c_f2511837_efb79089_d2ff4028_4202c53d
                    ]
                ];
            }
            // Step 4: compute s*G - h*A
            {
                uint256 ss = uint256(s) << 3;
                uint256 hhh = hh + 0x80000000_00000000_00000000_00000000_a6f7cef5_17bce6b2_c09318d2_e7ae9f60;
                uint256 vvx = 0;
                uint256 vvu = 1;
                uint256 vvy = 1;
                uint256 vvv = 1;
                for (uint256 i = 252; ; i--) {
                    uint256 bit = 8 << i;
                    if ((ss & bit) != 0) {
                        uint256 ws;
                        uint256 wd;
                        uint256 wz;
                        uint256 wt;
                        {
                            uint256 wx =
                                mulmod(
                                    vvx,
                                    vvv,
                                    0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed
                                );
                            uint256 wy =
                                mulmod(
                                    vvy,
                                    vvu,
                                    0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed
                                );
                            ws = wy + wx;
                            wd = wy - wx + 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed;
                            wz = mulmod(
                                vvu,
                                vvv,
                                0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed
                            );
                            wt = mulmod(
                                vvx,
                                vvy,
                                0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed
                            );
                        }
                        uint256 j = (ss >> i) & 7;
                        ss &= ~(7 << i);
                        uint256[8][3][2] memory tables_ = tables;
                        uint256 aa =
                            mulmod(
                                wd,
                                tables_[0][1][j],
                                0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed
                            );
                        uint256 ab =
                            mulmod(
                                ws,
                                tables_[0][0][j],
                                0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed
                            );
                        uint256 ac =
                            mulmod(
                                wt,
                                tables_[0][2][j],
                                0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed
                            );
                        vvx = ab - aa + 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed;
                        vvu = wz + ac;
                        vvy = ab + aa;
                        vvv = wz - ac + 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed;
                    }
                    if ((hhh & bit) != 0) {
                        uint256 ws;
                        uint256 wd;
                        uint256 wz;
                        uint256 wt;
                        {
                            uint256 wx =
                                mulmod(
                                    vvx,
                                    vvv,
                                    0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed
                                );
                            uint256 wy =
                                mulmod(
                                    vvy,
                                    vvu,
                                    0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed
                                );
                            ws = wy + wx;
                            wd = wy - wx + 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed;
                            wz = mulmod(
                                vvu,
                                vvv,
                                0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed
                            );
                            wt = mulmod(
                                vvx,
                                vvy,
                                0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed
                            );
                        }
                        uint256 j = (hhh >> i) & 7;
                        hhh &= ~(7 << i);
                        uint256[8][3][2] memory tables_ = tables;
                        uint256 aa =
                            mulmod(
                                wd,
                                tables_[1][0][j],
                                0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed
                            );
                        uint256 ab =
                            mulmod(
                                ws,
                                tables_[1][1][j],
                                0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed
                            );
                        uint256 ac =
                            mulmod(
                                wt,
                                tables_[1][2][j],
                                0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed
                            );
                        vvx = ab - aa + 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed;
                        vvu = wz - ac + 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed;
                        vvy = ab + aa;
                        vvv = wz + ac;
                    }
                    if (i == 0) {
                        uint256 ws;
                        uint256 wd;
                        uint256 wz;
                        uint256 wt;
                        {
                            uint256 wx =
                                mulmod(
                                    vvx,
                                    vvv,
                                    0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed
                                );
                            uint256 wy =
                                mulmod(
                                    vvy,
                                    vvu,
                                    0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed
                                );
                            ws = wy + wx;
                            wd = wy - wx + 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed;
                            wz = mulmod(
                                vvu,
                                vvv,
                                0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed
                            );
                            wt = mulmod(
                                vvx,
                                vvy,
                                0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed
                            );
                        }
                        uint256 j = hhh & 7;
                        uint256[8][3][2] memory tables_ = tables;
                        uint256 aa =
                            mulmod(
                                wd,
                                tables_[1][0][j],
                                0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed
                            );
                        uint256 ab =
                            mulmod(
                                ws,
                                tables_[1][1][j],
                                0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed
                            );
                        uint256 ac =
                            mulmod(
                                wt,
                                tables_[1][2][j],
                                0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed
                            );
                        vvx = ab - aa + 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed;
                        vvu = wz - ac + 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed;
                        vvy = ab + aa;
                        vvv = wz + ac;
                        break;
                    }
                    {
                        uint256 xx =
                            mulmod(vvx, vvv, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
                        uint256 yy =
                            mulmod(vvy, vvu, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
                        uint256 zz =
                            mulmod(vvu, vvv, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
                        uint256 xx2 =
                            mulmod(xx, xx, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
                        uint256 yy2 =
                            mulmod(yy, yy, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
                        uint256 xxyy =
                            mulmod(xx, yy, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
                        uint256 zz2 =
                            mulmod(zz, zz, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
                        vvx = xxyy + xxyy;
                        vvu = yy2 - xx2 + 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed;
                        vvy = xx2 + yy2;
                        vvv = addmod(
                            zz2 + zz2,
                            0xffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffda - vvu,
                            0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed
                        );
                    }
                }
                vx = vvx;
                vu = vvu;
                vy = vvy;
                vv = vvv;
            }
            // Step 5: compare the points
            (uint256 vi, uint256 vj) =
                Ed25519_pow.pow22501(mulmod(vu, vv, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed));
            vi = mulmod(vi, vi, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
            vi = mulmod(vi, vi, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
            vi = mulmod(vi, vi, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
            vi = mulmod(vi, vi, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
            vi = mulmod(vi, vi, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
            vi = mulmod(vi, vj, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
            vx = mulmod(
                vx,
                mulmod(vi, vv, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed),
                0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed
            );
            vy = mulmod(
                vy,
                mulmod(vi, vu, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed),
                0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed
            );
            bytes32 vr = bytes32(vy | (vx << 255));
            vr = bytes32(
                ((uint256(vr) & 0xff00ff_00ff00ff_00ff00ff_00ff00ff_00ff00ff_00ff00ff_00ff00ff_00ff00ff) << 8) |
                    ((uint256(vr) & 0xff00ff00_ff00ff00_ff00ff00_ff00ff00_ff00ff00_ff00ff00_ff00ff00_ff00ff00) >> 8)
            );
            vr = bytes32(
                ((uint256(vr) & 0xffff_0000ffff_0000ffff_0000ffff_0000ffff_0000ffff_0000ffff_0000ffff) << 16) |
                    ((uint256(vr) & 0xffff0000_ffff0000_ffff0000_ffff0000_ffff0000_ffff0000_ffff0000_ffff0000) >> 16)
            );
            vr = bytes32(
                ((uint256(vr) & 0xffffffff_00000000_ffffffff_00000000_ffffffff_00000000_ffffffff) << 32) |
                    ((uint256(vr) & 0xffffffff_00000000_ffffffff_00000000_ffffffff_00000000_ffffffff_00000000) >> 32)
            );
            vr = bytes32(
                ((uint256(vr) & 0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff) << 64) |
                    ((uint256(vr) & 0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff_00000000_00000000) >> 64)
            );
            vr = bytes32((uint256(vr) << 128) | (uint256(vr) >> 128));

            return vr == r;
        }
    }
}

File 6 of 10 : IMetadataValidator.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.21;

interface IMetadataValidator {
    /**
     * @notice Validate metadata associated with a key.
     *
     * @param userFid      The fid associated with the key.
     * @param key          Bytes of the key.
     * @param metadata     Metadata about the key.
     *
     * @return bool Whether the provided key and metadata are valid.
     */
    function validate(uint256 userFid, bytes memory key, bytes memory metadata) external returns (bool);
}

File 7 of 10 : IdRegistryLike.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;

/**
 * @dev Minimal interface for IdRegistry, used by the KeyRegistry.
 */
interface IdRegistryLike {
    /*//////////////////////////////////////////////////////////////
                                 STORAGE
    //////////////////////////////////////////////////////////////*/

    /**
     * @notice Maps each address to an fid, or zero if it does not own an fid.
     */
    function idOf(address fidOwner) external view returns (uint256);

    /*//////////////////////////////////////////////////////////////
                                 VIEWS
    //////////////////////////////////////////////////////////////*/

    /**
     * @notice Verify that a signature was produced by the custody address that owns an fid.
     *
     * @param custodyAddress   The address to check the signature of.
     * @param fid              The fid to check the signature of.
     * @param digest           The digest that was signed.
     * @param sig              The signature to check.
     *
     * @return isValid Whether provided signature is valid.
     */
    function verifyFidSignature(
        address custodyAddress,
        uint256 fid,
        bytes32 digest,
        bytes calldata sig
    ) external view returns (bool isValid);
}

File 8 of 10 : ProtobufLib.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity >=0.8.4 <0.9.0;

library ProtobufLib {
    /// @notice Protobuf wire types.
    enum WireType {
        Varint,
        Bits64,
        LengthDelimited,
        StartGroup,
        EndGroup,
        Bits32,
        WIRE_TYPE_MAX
    }

    /// @dev Maximum number of bytes for a varint.
    /// @dev 64 bits, in groups of base-128 (7 bits).
    uint64 internal constant MAX_VARINT_BYTES = 10;

    ////////////////////////////////////
    // Decoding
    ////////////////////////////////////

    /// @notice Decode key.
    /// @dev https://developers.google.com/protocol-buffers/docs/encoding#structure
    /// @param p Position
    /// @param buf Buffer
    /// @return Success
    /// @return New position
    /// @return Field number
    /// @return Wire type
    function decode_key(uint64 p, bytes memory buf)
        internal
        pure
        returns (
            bool,
            uint64,
            uint64,
            WireType
        )
    {
        // The key is a varint with encoding
        // (field_number << 3) | wire_type
        (bool success, uint64 pos, uint64 key) = decode_varint(p, buf);
        if (!success) {
            return (false, pos, 0, WireType.WIRE_TYPE_MAX);
        }

        uint64 field_number = key >> 3;
        uint64 wire_type_val = key & 0x07;
        // Check that wire type is bounded
        if (wire_type_val >= uint64(WireType.WIRE_TYPE_MAX)) {
            return (false, pos, 0, WireType.WIRE_TYPE_MAX);
        }
        WireType wire_type = WireType(wire_type_val);

        // Start and end group types are deprecated, so forbid them
        if (wire_type == WireType.StartGroup || wire_type == WireType.EndGroup) {
            return (false, pos, 0, WireType.WIRE_TYPE_MAX);
        }

        return (true, pos, field_number, wire_type);
    }

    /// @notice Decode varint.
    /// @dev https://developers.google.com/protocol-buffers/docs/encoding#varints
    /// @param p Position
    /// @param buf Buffer
    /// @return Success
    /// @return New position
    /// @return Decoded int
    function decode_varint(uint64 p, bytes memory buf)
        internal
        pure
        returns (
            bool,
            uint64,
            uint64
        )
    {
        uint64 val;
        uint64 i;

        for (i = 0; i < MAX_VARINT_BYTES; i++) {
            // Check that index is within bounds
            if (i + p >= buf.length) {
                return (false, p, 0);
            }

            // Get byte at offset
            uint8 b = uint8(buf[p + i]);

            // Highest bit is used to indicate if there are more bytes to come
            // Mask to get 7-bit value: 0111 1111
            uint8 v = b & 0x7F;

            // Groups of 7 bits are ordered least significant first
            val |= uint64(v) << uint64(i * 7);

            // Mask to get keep going bit: 1000 0000
            if (b & 0x80 == 0) {
                // [STRICT]
                // Check for trailing zeroes if more than one byte is used
                // (the value 0 still uses one byte)
                if (i > 0 && v == 0) {
                    return (false, p, 0);
                }

                break;
            }
        }

        // Check that at most MAX_VARINT_BYTES are used
        if (i >= MAX_VARINT_BYTES) {
            return (false, p, 0);
        }

        // [STRICT]
        // If all 10 bytes are used, the last byte (most significant 7 bits)
        // must be at most 0000 0001, since 7*9 = 63
        if (i == MAX_VARINT_BYTES - 1) {
            if (uint8(buf[p + i]) > 1) {
                return (false, p, 0);
            }
        }

        return (true, p + i + 1, val);
    }

    /// @notice Decode varint int32.
    /// @param p Position
    /// @param buf Buffer
    /// @return Success
    /// @return New position
    /// @return Decoded int
    function decode_int32(uint64 p, bytes memory buf)
        internal
        pure
        returns (
            bool,
            uint64,
            int32
        )
    {
        (bool success, uint64 pos, uint64 val) = decode_varint(p, buf);
        if (!success) {
            return (false, pos, 0);
        }

        // [STRICT]
        // Highest 4 bytes must be 0 if positive
        if (val >> 63 == 0) {
            if (val & 0xFFFFFFFF00000000 != 0) {
                return (false, pos, 0);
            }
        }

        return (true, pos, int32(uint32(val)));
    }

    /// @notice Decode varint int64.
    /// @param p Position
    /// @param buf Buffer
    /// @return Success
    /// @return New position
    /// @return Decoded int
    function decode_int64(uint64 p, bytes memory buf)
        internal
        pure
        returns (
            bool,
            uint64,
            int64
        )
    {
        (bool success, uint64 pos, uint64 val) = decode_varint(p, buf);
        if (!success) {
            return (false, pos, 0);
        }

        return (true, pos, int64(val));
    }

    /// @notice Decode varint uint32.
    /// @param p Position
    /// @param buf Buffer
    /// @return Success
    /// @return New position
    /// @return Decoded int
    function decode_uint32(uint64 p, bytes memory buf)
        internal
        pure
        returns (
            bool,
            uint64,
            uint32
        )
    {
        (bool success, uint64 pos, uint64 val) = decode_varint(p, buf);
        if (!success) {
            return (false, pos, 0);
        }

        // [STRICT]
        // Highest 4 bytes must be 0
        if (val & 0xFFFFFFFF00000000 != 0) {
            return (false, pos, 0);
        }

        return (true, pos, uint32(val));
    }

    /// @notice Decode varint uint64.
    /// @param p Position
    /// @param buf Buffer
    /// @return Success
    /// @return New position
    /// @return Decoded int
    function decode_uint64(uint64 p, bytes memory buf)
        internal
        pure
        returns (
            bool,
            uint64,
            uint64
        )
    {
        (bool success, uint64 pos, uint64 val) = decode_varint(p, buf);
        if (!success) {
            return (false, pos, 0);
        }

        return (true, pos, val);
    }

    /// @notice Decode varint sint32.
    /// @param p Position
    /// @param buf Buffer
    /// @return Success
    /// @return New position
    /// @return Decoded int
    function decode_sint32(uint64 p, bytes memory buf)
        internal
        pure
        returns (
            bool,
            uint64,
            int32
        )
    {
        (bool success, uint64 pos, uint64 val) = decode_varint(p, buf);
        if (!success) {
            return (false, pos, 0);
        }

        // [STRICT]
        // Highest 4 bytes must be 0
        if (val & 0xFFFFFFFF00000000 != 0) {
            return (false, pos, 0);
        }

        // https://stackoverflow.com/questions/2210923/zig-zag-decoding/2211086#2211086
        uint64 zigzag_val;
        unchecked {
            zigzag_val = (val >> 1) - (~(val & 1) + 1);
        }

        return (true, pos, int32(uint32(zigzag_val)));
    }

    /// @notice Decode varint sint64.
    /// @param p Position
    /// @param buf Buffer
    /// @return Success
    /// @return New position
    /// @return Decoded int
    function decode_sint64(uint64 p, bytes memory buf)
        internal
        pure
        returns (
            bool,
            uint64,
            int64
        )
    {
        (bool success, uint64 pos, uint64 val) = decode_varint(p, buf);
        if (!success) {
            return (false, pos, 0);
        }

        // https://stackoverflow.com/questions/2210923/zig-zag-decoding/2211086#2211086
        uint64 zigzag_val;
        unchecked {
            zigzag_val = (val >> 1) - (~(val & 1) + 1);
        }

        return (true, pos, int64(zigzag_val));
    }

    /// @notice Decode Boolean.
    /// @param p Position
    /// @param buf Buffer
    /// @return Success
    /// @return New position
    /// @return Decoded bool
    function decode_bool(uint64 p, bytes memory buf)
        internal
        pure
        returns (
            bool,
            uint64,
            bool
        )
    {
        (bool success, uint64 pos, uint64 val) = decode_varint(p, buf);
        if (!success) {
            return (false, pos, false);
        }

        // [STRICT]
        // Value must be 0 or 1
        if (val > 1) {
            return (false, pos, false);
        }

        if (val == 0) {
            return (true, pos, false);
        }

        return (true, pos, true);
    }

    /// @notice Decode enumeration.
    /// @param p Position
    /// @param buf Buffer
    /// @return Success
    /// @return New position
    /// @return Decoded enum as raw int
    function decode_enum(uint64 p, bytes memory buf)
        internal
        pure
        returns (
            bool,
            uint64,
            int32
        )
    {
        return decode_int32(p, buf);
    }

    /// @notice Decode fixed 64-bit int.
    /// @param p Position
    /// @param buf Buffer
    /// @return Success
    /// @return New position
    /// @return Decoded int
    function decode_bits64(uint64 p, bytes memory buf)
        internal
        pure
        returns (
            bool,
            uint64,
            uint64
        )
    {
        uint64 val;

        // Check that index is within bounds
        if (8 + p > buf.length) {
            return (false, p, 0);
        }

        for (uint64 i = 0; i < 8; i++) {
            uint8 b = uint8(buf[p + i]);

            // Little endian
            val |= uint64(b) << uint64(i * 8);
        }

        return (true, p + 8, val);
    }

    /// @notice Decode fixed uint64.
    /// @param p Position
    /// @param buf Buffer
    /// @return Success
    /// @return New position
    /// @return Decoded int
    function decode_fixed64(uint64 p, bytes memory buf)
        internal
        pure
        returns (
            bool,
            uint64,
            uint64
        )
    {
        (bool success, uint64 pos, uint64 val) = decode_bits64(p, buf);
        if (!success) {
            return (false, pos, 0);
        }

        return (true, pos, val);
    }

    /// @notice Decode fixed int64.
    /// @param p Position
    /// @param buf Buffer
    /// @return Success
    /// @return New position
    /// @return Decoded int
    function decode_sfixed64(uint64 p, bytes memory buf)
        internal
        pure
        returns (
            bool,
            uint64,
            int64
        )
    {
        (bool success, uint64 pos, uint64 val) = decode_bits64(p, buf);
        if (!success) {
            return (false, pos, 0);
        }

        return (true, pos, int64(val));
    }

    /// @notice Decode fixed 32-bit int.
    /// @param p Position
    /// @param buf Buffer
    /// @return Success
    /// @return New position
    /// @return Decoded int
    function decode_bits32(uint64 p, bytes memory buf)
        internal
        pure
        returns (
            bool,
            uint64,
            uint32
        )
    {
        uint32 val;

        // Check that index is within bounds
        if (4 + p > buf.length) {
            return (false, p, 0);
        }

        for (uint64 i = 0; i < 4; i++) {
            uint8 b = uint8(buf[p + i]);

            // Little endian
            val |= uint32(b) << uint32(i * 8);
        }

        return (true, p + 4, val);
    }

    /// @notice Decode fixed uint32.
    /// @param p Position
    /// @param buf Buffer
    /// @return Success
    /// @return New position
    /// @return Decoded int
    function decode_fixed32(uint64 p, bytes memory buf)
        internal
        pure
        returns (
            bool,
            uint64,
            uint32
        )
    {
        (bool success, uint64 pos, uint32 val) = decode_bits32(p, buf);
        if (!success) {
            return (false, pos, 0);
        }

        return (true, pos, val);
    }

    /// @notice Decode fixed int32.
    /// @param p Position
    /// @param buf Buffer
    /// @return Success
    /// @return New position
    /// @return Decoded int
    function decode_sfixed32(uint64 p, bytes memory buf)
        internal
        pure
        returns (
            bool,
            uint64,
            int32
        )
    {
        (bool success, uint64 pos, uint32 val) = decode_bits32(p, buf);
        if (!success) {
            return (false, pos, 0);
        }

        return (true, pos, int32(val));
    }

    /// @notice Decode length-delimited field.
    /// @param p Position
    /// @param buf Buffer
    /// @return Success
    /// @return New position (after size)
    /// @return Size in bytes
    function decode_length_delimited(uint64 p, bytes memory buf)
        internal
        pure
        returns (
            bool,
            uint64,
            uint64
        )
    {
        // Length-delimited fields begin with a varint of the number of bytes that follow
        (bool success, uint64 pos, uint64 size) = decode_varint(p, buf);
        if (!success) {
            return (false, pos, 0);
        }

        // Check for overflow
        unchecked {
            if (pos + size < pos) {
                return (false, pos, 0);
            }
        }

        // Check that index is within bounds
        if (size + pos > buf.length) {
            return (false, pos, 0);
        }

        return (true, pos, size);
    }

    /// @notice Decode string.
    /// @param p Position
    /// @param buf Buffer
    /// @return Success
    /// @return New position
    /// @return Size in bytes
    function decode_string(uint64 p, bytes memory buf)
        internal
        pure
        returns (
            bool,
            uint64,
            string memory
        )
    {
        (bool success, uint64 pos, uint64 size) = decode_length_delimited(p, buf);
        if (!success) {
            return (false, pos, "");
        }

        bytes memory field = new bytes(size);
        for (uint64 i = 0; i < size; i++) {
            field[i] = buf[pos + i];
        }

        return (true, pos + size, string(field));
    }

    /// @notice Decode bytes array.
    /// @param p Position
    /// @param buf Buffer
    /// @return Success
    /// @return New position (after size)
    /// @return Size in bytes
    function decode_bytes(uint64 p, bytes memory buf)
        internal
        pure
        returns (
            bool,
            uint64,
            uint64
        )
    {
        return decode_length_delimited(p, buf);
    }

    /// @notice Decode embedded message.
    /// @param p Position
    /// @param buf Buffer
    /// @return Success
    /// @return New position (after size)
    /// @return Size in bytes
    function decode_embedded_message(uint64 p, bytes memory buf)
        internal
        pure
        returns (
            bool,
            uint64,
            uint64
        )
    {
        return decode_length_delimited(p, buf);
    }

    /// @notice Decode packed repeated field.
    /// @param p Position
    /// @param buf Buffer
    /// @return Success
    /// @return New position (after size)
    /// @return Size in bytes
    function decode_packed_repeated(uint64 p, bytes memory buf)
        internal
        pure
        returns (
            bool,
            uint64,
            uint64
        )
    {
        return decode_length_delimited(p, buf);
    }

    ////////////////////////////////////
    // Encoding
    ////////////////////////////////////

    /// @notice Encode key.
    /// @dev https://developers.google.com/protocol-buffers/docs/encoding#structure
    /// @param field_number Field number
    /// @param wire_type Wire type
    /// @return Marshaled bytes
    function encode_key(uint64 field_number, uint64 wire_type) internal pure returns (bytes memory) {
        uint64 key = (field_number << 3) | wire_type;

        bytes memory buf = encode_varint(key);

        return buf;
    }

    /// @notice Encode varint.
    /// @dev https://developers.google.com/protocol-buffers/docs/encoding#varints
    /// @param n Number
    /// @return Marshaled bytes
    function encode_varint(uint64 n) internal pure returns (bytes memory) {
        // Count the number of groups of 7 bits
        // We need this pre-processing step since Solidity doesn't allow dynamic memory resizing
        uint64 tmp = n;
        uint64 num_bytes = 1;
        while (tmp > 0x7F) {
            tmp = tmp >> 7;
            num_bytes += 1;
        }

        bytes memory buf = new bytes(num_bytes);

        tmp = n;
        for (uint64 i = 0; i < num_bytes; i++) {
            // Set the first bit in the byte for each group of 7 bits
            buf[i] = bytes1(0x80 | uint8(tmp & 0x7F));
            tmp = tmp >> 7;
        }
        // Unset the first bit of the last byte
        buf[num_bytes - 1] &= 0x7F;

        return buf;
    }

    /// @notice Encode varint int32.
    /// @param n Number
    /// @return Marshaled bytes
    function encode_int32(int32 n) internal pure returns (bytes memory) {
        return encode_varint(uint64(int64(n)));
    }

    /// @notice Decode varint int64.
    /// @param n Number
    /// @return Marshaled bytes
    function encode_int64(int64 n) internal pure returns (bytes memory) {
        return encode_varint(uint64(n));
    }

    /// @notice Encode varint uint32.
    /// @param n Number
    /// @return Marshaled bytes
    function encode_uint32(uint32 n) internal pure returns (bytes memory) {
        return encode_varint(n);
    }

    /// @notice Encode varint uint64.
    /// @param n Number
    /// @return Marshaled bytes
    function encode_uint64(uint64 n) internal pure returns (bytes memory) {
        return encode_varint(n);
    }

    /// @notice Encode varint sint32.
    /// @param n Number
    /// @return Marshaled bytes
    function encode_sint32(int32 n) internal pure returns (bytes memory) {
        // https://developers.google.com/protocol-buffers/docs/encoding#signed_integers
        uint32 mask = 0;
        if (n < 0) {
            unchecked {
                mask -= 1;
            }
        }
        uint32 zigzag_val = (uint32(n) << 1) ^ mask;

        return encode_varint(zigzag_val);
    }

    /// @notice Encode varint sint64.
    /// @param n Number
    /// @return Marshaled bytes
    function encode_sint64(int64 n) internal pure returns (bytes memory) {
        // https://developers.google.com/protocol-buffers/docs/encoding#signed_integers
        uint64 mask = 0;
        if (n < 0) {
            unchecked {
                mask -= 1;
            }
        }
        uint64 zigzag_val = (uint64(n) << 1) ^ mask;

        return encode_varint(zigzag_val);
    }

    /// @notice Encode Boolean.
    /// @param b Boolean
    /// @return Marshaled bytes
    function encode_bool(bool b) internal pure returns (bytes memory) {
        uint64 n = b ? 1 : 0;

        return encode_varint(n);
    }

    /// @notice Encode enumeration.
    /// @param n Number
    /// @return Marshaled bytes
    function encode_enum(int32 n) internal pure returns (bytes memory) {
        return encode_int32(n);
    }

    /// @notice Encode fixed 64-bit int.
    /// @param n Number
    /// @return Marshaled bytes
    function encode_bits64(uint64 n) internal pure returns (bytes memory) {
        bytes memory buf = new bytes(8);

        uint64 tmp = n;
        for (uint64 i = 0; i < 8; i++) {
            // Little endian
            buf[i] = bytes1(uint8(tmp & 0xFF));
            tmp = tmp >> 8;
        }

        return buf;
    }

    /// @notice Encode fixed uint64.
    /// @param n Number
    /// @return Marshaled bytes
    function encode_fixed64(uint64 n) internal pure returns (bytes memory) {
        return encode_bits64(n);
    }

    /// @notice Encode fixed int64.
    /// @param n Number
    /// @return Marshaled bytes
    function encode_sfixed64(int64 n) internal pure returns (bytes memory) {
        return encode_bits64(uint64(n));
    }

    /// @notice Decode fixed 32-bit int.
    /// @param n Number
    /// @return Marshaled bytes
    function encode_bits32(uint32 n) internal pure returns (bytes memory) {
        bytes memory buf = new bytes(4);

        uint64 tmp = n;
        for (uint64 i = 0; i < 4; i++) {
            // Little endian
            buf[i] = bytes1(uint8(tmp & 0xFF));
            tmp = tmp >> 8;
        }

        return buf;
    }

    /// @notice Encode fixed uint32.
    /// @param n Number
    /// @return Marshaled bytes
    function encode_fixed32(uint32 n) internal pure returns (bytes memory) {
        return encode_bits32(n);
    }

    /// @notice Encode fixed int32.
    /// @param n Number
    /// @return Marshaled bytes
    function encode_sfixed32(int32 n) internal pure returns (bytes memory) {
        return encode_bits32(uint32(n));
    }

    /// @notice Encode length-delimited field.
    /// @param b Bytes
    /// @return Marshaled bytes
    function encode_length_delimited(bytes memory b) internal pure returns (bytes memory) {
        // Length-delimited fields begin with a varint of the number of bytes that follow
        bytes memory length_buf = encode_uint64(uint64(b.length));
        bytes memory buf = new bytes(b.length + length_buf.length);

        for (uint64 i = 0; i < length_buf.length; i++) {
            buf[i] = length_buf[i];
        }

        for (uint64 i = 0; i < b.length; i++) {
            buf[i + length_buf.length] = b[i];
        }

        return buf;
    }

    /// @notice Encode string.
    /// @param s String
    /// @return Marshaled bytes
    function encode_string(string memory s) internal pure returns (bytes memory) {
        return encode_length_delimited(bytes(s));
    }

    /// @notice Encode bytes array.
    /// @param b Bytes
    /// @return Marshaled bytes
    function encode_bytes(bytes memory b) internal pure returns (bytes memory) {
        return encode_length_delimited(b);
    }

    /// @notice Encode embedded message.
    /// @param m Message
    /// @return Marshaled bytes
    function encode_embedded_message(bytes memory m) internal pure returns (bytes memory) {
        return encode_length_delimited(m);
    }

    /// @notice Encode packed repeated field.
    /// @param b Bytes
    /// @return Marshaled bytes
    function encode_packed_repeated(bytes memory b) internal pure returns (bytes memory) {
        return encode_length_delimited(b);
    }
}

File 9 of 10 : Sha512.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.9;

// Reference: https://csrc.nist.gov/csrc/media/publications/fips/180/2/archive/2002-08-01/documents/fips180-2.pdf

library Sha512 {
    // @notice: The message, M, shall be padded before hash computation begins.
    //          The purpose of this padding is to ensure that the padded message is a multiple of 1024 bits.
    // @param message input raw message bytes
    // @return padded message bytes
    function preprocess(bytes memory message)
        internal
        pure
        returns (bytes memory)
    {
        uint256 padding = 128 - (message.length % 128);
        if (message.length % 128 >= 112) {
            padding = 256 - (message.length % 128);
        }
        bytes memory result = new bytes(message.length + padding);

        for (uint256 i = 0; i < message.length; i++) {
            result[i] = message[i];
        }
        result[message.length] = 0x80;

        uint128 bitSize = uint128(message.length * 8);
        bytes memory bitlength = abi.encodePacked(bitSize);
        for (uint256 index = 0; index < bitlength.length; index++) {
            result[result.length - 1 - index] = bitlength[
                bitlength.length - 1 - index
            ];
        }
        return result;
    }

    function bytesToBytes8(bytes memory b, uint256 offset)
        internal
        pure
        returns (bytes8)
    {
        bytes8 out;
        for (uint256 i = 0; i < 8; i++) {
            out |= bytes8(b[offset + i] & 0xFF) >> (i * 8);
        }
        return out;
    }

    function cutBlock(bytes memory data, uint256 blockIndex)
        internal
        pure
        returns (uint64[16] memory)
    {
        uint64[16] memory result;
        for (uint8 r = 0; r < result.length; r++) {
            result[r] = uint64(bytesToBytes8(data, blockIndex * 128 + r * 8));
        }
        return result;
    }

    // This section defines the functions that are used by sha-512.
    // https://csrc.nist.gov/csrc/media/publications/fips/180/2/archive/2002-08-01/documents/fips180-2.pdf#page=15

    // @notice: Thus, ROTR(x, n) is equivalent to a circular shift (rotation) of x by n positions to the right.
    // @param x input num
    // @param n num of positions to circular shift
    // @return uint64
    function ROTR(uint64 x, uint256 n) internal pure returns (uint64) {
        return (x << (64 - n)) + (x >> n);
    }

    // @notice: The right shift operation SHR n(x), where x is a w-bit word and n is an integer with 0 <= n < w, is defined by SHR(x, n) = x >> n.
    // @param x input num
    // @param n num of positions to shift
    // @return uint64
    function SHR(uint64 x, uint256 n) internal pure returns (uint64) {
        return uint64(x >> n);
    }

    // @notice: Ch(x, y, z) = (x ^ y) ⊕ (﹁ x ^ z)
    // @param x x
    // @param y y
    // @param z z
    // @return uint64
    function Ch(
        uint64 x,
        uint64 y,
        uint64 z
    ) internal pure returns (uint64) {
        return (x & y) ^ ((x ^ 0xffffffffffffffff) & z);
    }

    // @notice: Maj(x, y, z) = (x ^ y) ⊕ (x ^ z) ⊕ (y ^ z)
    // @param x x
    // @param y y
    // @param z z
    // @return uint64
    function Maj(
        uint64 x,
        uint64 y,
        uint64 z
    ) internal pure returns (uint64) {
        return (x & y) ^ (x & z) ^ (y & z);
    }

    // @notice: sigma0(x) = ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39)
    // @param x x
    // @return uint64
    function sigma0(uint64 x) internal pure returns (uint64) {
        return ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39);
    }

    // @notice: sigma1(x) = ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41)
    // @param x x
    // @return uint64
    function sigma1(uint64 x) internal pure returns (uint64) {
        return ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41);
    }

    // @notice: gamma0(x) = OTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7)
    // @param x x
    // @return uint64
    function gamma0(uint64 x) internal pure returns (uint64) {
        return ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7);
    }

    // @notice: gamma1(x) = ROTR(x, 19) ^ ROTR(x, 61) ^ SHR(x, 6)
    // @param x x
    // @return uint64
    function gamma1(uint64 x) internal pure returns (uint64) {
        return ROTR(x, 19) ^ ROTR(x, 61) ^ SHR(x, 6);
    }

    struct FuncVar {
        uint64 a;
        uint64 b;
        uint64 c;
        uint64 d;
        uint64 e;
        uint64 f;
        uint64 g;
        uint64 h;
    }

    // @notice Calculate the SHA512 of input data.
    // @param data input data bytes
    // @return 512 bits hash result
    function hash(bytes memory data) external pure returns (uint64[8] memory) {
        uint64[8] memory H = [
            0x6a09e667f3bcc908,
            0xbb67ae8584caa73b,
            0x3c6ef372fe94f82b,
            0xa54ff53a5f1d36f1,
            0x510e527fade682d1,
            0x9b05688c2b3e6c1f,
            0x1f83d9abfb41bd6b,
            0x5be0cd19137e2179
        ];

        unchecked {
            uint64 T1;
            uint64 T2;

            uint64[80] memory W;
            FuncVar memory fvar;

            uint64[80] memory K = [
                0x428a2f98d728ae22,
                0x7137449123ef65cd,
                0xb5c0fbcfec4d3b2f,
                0xe9b5dba58189dbbc,
                0x3956c25bf348b538,
                0x59f111f1b605d019,
                0x923f82a4af194f9b,
                0xab1c5ed5da6d8118,
                0xd807aa98a3030242,
                0x12835b0145706fbe,
                0x243185be4ee4b28c,
                0x550c7dc3d5ffb4e2,
                0x72be5d74f27b896f,
                0x80deb1fe3b1696b1,
                0x9bdc06a725c71235,
                0xc19bf174cf692694,
                0xe49b69c19ef14ad2,
                0xefbe4786384f25e3,
                0x0fc19dc68b8cd5b5,
                0x240ca1cc77ac9c65,
                0x2de92c6f592b0275,
                0x4a7484aa6ea6e483,
                0x5cb0a9dcbd41fbd4,
                0x76f988da831153b5,
                0x983e5152ee66dfab,
                0xa831c66d2db43210,
                0xb00327c898fb213f,
                0xbf597fc7beef0ee4,
                0xc6e00bf33da88fc2,
                0xd5a79147930aa725,
                0x06ca6351e003826f,
                0x142929670a0e6e70,
                0x27b70a8546d22ffc,
                0x2e1b21385c26c926,
                0x4d2c6dfc5ac42aed,
                0x53380d139d95b3df,
                0x650a73548baf63de,
                0x766a0abb3c77b2a8,
                0x81c2c92e47edaee6,
                0x92722c851482353b,
                0xa2bfe8a14cf10364,
                0xa81a664bbc423001,
                0xc24b8b70d0f89791,
                0xc76c51a30654be30,
                0xd192e819d6ef5218,
                0xd69906245565a910,
                0xf40e35855771202a,
                0x106aa07032bbd1b8,
                0x19a4c116b8d2d0c8,
                0x1e376c085141ab53,
                0x2748774cdf8eeb99,
                0x34b0bcb5e19b48a8,
                0x391c0cb3c5c95a63,
                0x4ed8aa4ae3418acb,
                0x5b9cca4f7763e373,
                0x682e6ff3d6b2b8a3,
                0x748f82ee5defb2fc,
                0x78a5636f43172f60,
                0x84c87814a1f0ab72,
                0x8cc702081a6439ec,
                0x90befffa23631e28,
                0xa4506cebde82bde9,
                0xbef9a3f7b2c67915,
                0xc67178f2e372532b,
                0xca273eceea26619c,
                0xd186b8c721c0c207,
                0xeada7dd6cde0eb1e,
                0xf57d4f7fee6ed178,
                0x06f067aa72176fba,
                0x0a637dc5a2c898a6,
                0x113f9804bef90dae,
                0x1b710b35131c471b,
                0x28db77f523047d84,
                0x32caab7b40c72493,
                0x3c9ebe0a15c9bebc,
                0x431d67c49c100d4c,
                0x4cc5d4becb3e42b6,
                0x597f299cfc657e2a,
                0x5fcb6fab3ad6faec,
                0x6c44198c4a475817
            ];

            bytes memory blocks = preprocess(data);

            for (uint256 j = 0; j < blocks.length / 128; j++) {
                uint64[16] memory M = cutBlock(blocks, j);

                fvar.a = H[0];
                fvar.b = H[1];
                fvar.c = H[2];
                fvar.d = H[3];
                fvar.e = H[4];
                fvar.f = H[5];
                fvar.g = H[6];
                fvar.h = H[7];

                for (uint256 i = 0; i < 80; i++) {
                    if (i < 16) {
                        W[i] = M[i];
                    } else {
                        W[i] =
                            gamma1(W[i - 2]) +
                            W[i - 7] +
                            gamma0(W[i - 15]) +
                            W[i - 16];
                    }

                    T1 =
                        fvar.h +
                        sigma1(fvar.e) +
                        Ch(fvar.e, fvar.f, fvar.g) +
                        K[i] +
                        W[i];
                    T2 = sigma0(fvar.a) + Maj(fvar.a, fvar.b, fvar.c);

                    fvar.h = fvar.g;
                    fvar.g = fvar.f;
                    fvar.f = fvar.e;
                    fvar.e = fvar.d + T1;
                    fvar.d = fvar.c;
                    fvar.c = fvar.b;
                    fvar.b = fvar.a;
                    fvar.a = T1 + T2;
                }

                H[0] = H[0] + fvar.a;
                H[1] = H[1] + fvar.b;
                H[2] = H[2] + fvar.c;
                H[3] = H[3] + fvar.d;
                H[4] = H[4] + fvar.e;
                H[5] = H[5] + fvar.f;
                H[6] = H[6] + fvar.g;
                H[7] = H[7] + fvar.h;
            }           
        }

        return H;
    }
}

File 10 of 10 : Ed25519_pow.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.9;


library Ed25519_pow {
      // Computes (v^(2^250-1), v^11) mod p
    function pow22501(uint256 v) external pure returns (uint256 p22501, uint256 p11) {
        p11 = mulmod(v, v, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        p22501 = mulmod(p11, p11, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        p22501 = mulmod(
            mulmod(p22501, p22501, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed),
            v,
            0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed
        );
        p11 = mulmod(p22501, p11, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        p22501 = mulmod(
            mulmod(p11, p11, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed),
            p22501,
            0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed
        );
        uint256 a = mulmod(p22501, p22501, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        p22501 = mulmod(p22501, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(p22501, p22501, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(p22501, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        uint256 b = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        p22501 = mulmod(p22501, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(p22501, p22501, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(p22501, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
        p22501 = mulmod(p22501, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);
    }
}

Settings
{
  "remappings": [
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "forge-std/=lib/forge-std/src/",
    "frame-verifier/=lib/frame-verifier/src/",
    "solady/=lib/solady/src/",
    "wormhole/=lib/wormhole/ethereum/contracts/",
    "erc6551/=lib/erc6551/src/",
    "farcaster/=lib/farcaster/src/",
    "account-abstraction/=lib/account-abstraction/contracts/",
    "farcaster-solidity/=lib/farcaster-solidity/contracts/",
    "@openzeppelin/=lib/erc6551/lib/openzeppelin-contracts/",
    "chainlink-brownie-contracts/=lib/farcaster/lib/chainlink-brownie-contracts/",
    "chainlink/=lib/farcaster/lib/chainlink-brownie-contracts/contracts/src/",
    "erc4626-tests/=lib/farcaster/lib/openzeppelin-latest/lib/erc4626-tests/",
    "halmos-cheatcodes/=lib/farcaster/lib/halmos-cheatcodes/src/",
    "openzeppelin-contracts/=lib/farcaster/lib/openzeppelin-contracts/",
    "openzeppelin-latest/=lib/farcaster/lib/openzeppelin-latest/",
    "openzeppelin/=lib/farcaster/lib/openzeppelin-contracts/",
    "solmate/=lib/farcaster/lib/solmate/",
    "@lazyledger/protobuf3-solidity-lib/=lib/protobuf3-solidity-lib/",
    "protobuf3-solidity-lib/=lib/protobuf3-solidity-lib/contracts/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "paris",
  "libraries": {
    "lib/farcaster-solidity/contracts/libraries/Blake3.sol": {
      "Blake3": "0x33937f3b8a9107e409931b70478ae716cb51aee8"
    },
    "lib/farcaster-solidity/contracts/libraries/Ed25519.sol": {
      "Ed25519": "0xfa7321696663ea6b9c8d4d3c892c1176e2587a39"
    },
    "lib/farcaster-solidity/contracts/libraries/Ed25519_pow.sol": {
      "Ed25519_pow": "0xb4e22f10318492b7bbd160d736f708c1f23df021"
    },
    "lib/farcaster-solidity/contracts/libraries/Sha512.sol": {
      "Sha512": "0x3c25e1bf271cc1d1ddc10c55c836c4ec727c20aa"
    }
  }
}

Contract Security Audit

Contract ABI

API
[{"inputs":[],"name":"InvalidButtonIndex","type":"error"},{"inputs":[],"name":"InvalidKey","type":"error"},{"inputs":[],"name":"InvalidMessage","type":"error"},{"inputs":[],"name":"InvalidMessageHash","type":"error"},{"inputs":[],"name":"InvalidMessageType","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"InvalidSignatureScheme","type":"error"},{"inputs":[],"name":"InvalidUrl","type":"error"},{"inputs":[{"internalType":"bytes","name":"message","type":"bytes"}],"name":"validateMessage","outputs":[{"components":[{"components":[{"internalType":"enum MessageType","name":"type_","type":"uint8"},{"internalType":"uint64","name":"fid","type":"uint64"},{"internalType":"uint32","name":"timestamp","type":"uint32"},{"internalType":"enum FarcasterNetwork","name":"network","type":"uint8"},{"components":[{"internalType":"string","name":"embeds_deprecated","type":"string"},{"internalType":"uint64[]","name":"mentions","type":"uint64[]"},{"components":[{"internalType":"uint64","name":"fid","type":"uint64"},{"internalType":"bytes","name":"hash_","type":"bytes"}],"internalType":"struct CastId","name":"parent_cast_id","type":"tuple"},{"internalType":"string","name":"text","type":"string"},{"internalType":"uint32[]","name":"mentions_positions","type":"uint32[]"},{"components":[{"internalType":"string","name":"url","type":"string"},{"components":[{"internalType":"uint64","name":"fid","type":"uint64"},{"internalType":"bytes","name":"hash_","type":"bytes"}],"internalType":"struct CastId","name":"cast_id","type":"tuple"}],"internalType":"struct Embed[]","name":"embeds","type":"tuple[]"},{"internalType":"string","name":"parent_url","type":"string"}],"internalType":"struct CastAddBody","name":"cast_add_body","type":"tuple"},{"internalType":"bool","name":"empty_cast_remove_body","type":"bool"},{"components":[{"internalType":"enum ReactionType","name":"type_","type":"uint8"},{"components":[{"internalType":"uint64","name":"fid","type":"uint64"},{"internalType":"bytes","name":"hash_","type":"bytes"}],"internalType":"struct CastId","name":"target_cast_id","type":"tuple"},{"internalType":"string","name":"target_url","type":"string"}],"internalType":"struct ReactionBody","name":"reaction_body","type":"tuple"},{"internalType":"bool","name":"empty","type":"bool"},{"components":[{"internalType":"bytes","name":"address_","type":"bytes"},{"internalType":"bytes","name":"eth_signature","type":"bytes"},{"internalType":"bytes","name":"block_hash","type":"bytes"},{"internalType":"uint32","name":"verification_type","type":"uint32"},{"internalType":"uint32","name":"chain_id","type":"uint32"}],"internalType":"struct VerificationAddEthAddressBody","name":"verification_add_eth_address_body","type":"tuple"},{"internalType":"bool","name":"empty_verification_remove_body","type":"bool"},{"internalType":"bool","name":"deprecated_signer_add_body","type":"bool"},{"internalType":"bool","name":"user_data_body","type":"bool"},{"internalType":"bool","name":"deprecated_signer_remove_body","type":"bool"},{"components":[{"internalType":"string","name":"type_","type":"string"},{"internalType":"uint32","name":"displayTimestamp","type":"uint32"},{"internalType":"uint64","name":"target_fid","type":"uint64"}],"internalType":"struct LinkBody","name":"link_body","type":"tuple"},{"internalType":"bool","name":"empty_username_proof_body","type":"bool"},{"components":[{"internalType":"bytes","name":"url","type":"bytes"},{"internalType":"uint32","name":"button_index","type":"uint32"},{"components":[{"internalType":"uint64","name":"fid","type":"uint64"},{"internalType":"bytes","name":"hash_","type":"bytes"}],"internalType":"struct CastId","name":"cast_id","type":"tuple"}],"internalType":"struct FrameActionBody","name":"frame_action_body","type":"tuple"}],"internalType":"struct MessageData","name":"data","type":"tuple"},{"internalType":"bytes","name":"hash_","type":"bytes"},{"internalType":"enum HashScheme","name":"hash_scheme","type":"uint8"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"enum SignatureScheme","name":"signature_scheme","type":"uint8"},{"internalType":"bytes","name":"signer","type":"bytes"},{"internalType":"bytes","name":"data_bytes","type":"bytes"}],"internalType":"struct Message","name":"","type":"tuple"}],"stateMutability":"view","type":"function"}]

608060405234801561001057600080fd5b50615529806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063277e661d14610030575b600080fd5b61004361003e366004614a1b565b610059565b6040516100509190614e5f565b60405180910390f35b61006161478a565b60008061007160008586516103c0565b92505091508161009457604051636eca2e4b60e01b815260040160405180910390fd5b60006100a38260000151610551565b905060007333937f3b8a9107e409931b70478ae716cb51aee863227bb04d8360146040518363ffffffff1660e01b81526004016100e19291906150a0565b600060405180830381865af41580156100fe573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261012691908101906150c8565b905082602001518051906020012081805190602001201461015a57604051638b56642d60e01b815260040160405180910390fd5b505060608101516020810151604082015160a08401519192909160009073fa7321696663ea6b9c8d4d3c892c1176e2587a3990632bf6eda89061019c90615135565b868689602001516040518563ffffffff1660e01b81526004016101c2949392919061515c565b602060405180830381865af41580156101df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610203919061518b565b90508061022357604051638baa579f60e01b815260040160405180910390fd5b505082516020015160a084015160405163561a662d60e11b8152600094506ffc1237824fb747abde0ff18990e59b7e935063ac34cc5a926102689290916004016151b4565b6040805180830381865afa158015610284573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102a891906151d6565b90506001815160028111156102bf576102bf614a9a565b146102dd57604051630eda9c3d60e31b815260040160405180910390fd5b6001826080015160028111156102f5576102f5614a9a565b1461031357604051632171ecf960e01b815260040160405180910390fd5b600d825151600d81111561032957610329614a9a565b1461034757604051635b60892f60e01b815260040160405180910390fd5b81516101e00151515161010010156103725760405163e7bc872f60e01b815260040160405180910390fd5b81516101e0015160200151600163ffffffff82161080610398575060048163ffffffff16115b156103b657604051639a759aa960e01b815260040160405180910390fd5b5090949350505050565b6000806103cb61478a565b6103d361478a565b6000876001600160401b0381166103ea8883615257565b6001600160401b03161015610409576000955093509091506105489050565b6001600160401b03871661041d8a8361527e565b6001600160401b0316101561050b57600080600061043b848c61080f565b91965091945090925090508261045f57506000975091955092935061054892505050565b6007826001600160401b0316111561048557506000975091955092935061054892505050565b846001600160401b0316826001600160401b0316116104b257506000975091955092935061054892505050565b6104bc8282610901565b9250826104d757506000975091955092935061054892505050565b6104e4848c8c858a6109cb565b945092508261050157506000975091955092935061054892505050565b5092506104099050565b610515878a615257565b6001600160401b0316816001600160401b03161461053d576000955093509091506105489050565b600195509350909150505b93509350939050565b606060008260000151600d81111561056b5761056b614a9a565b6001600160401b031660000361058f5760408051600081526020810190915261059b565b61059b60016000610ad3565b905060008360000151600d8111156105b5576105b5614a9a565b6001600160401b03166000036105d9576040805160008152602081019091526105f5565b83516105f590600d8111156105f0576105f0614a9a565b610afb565b9050600084602001516001600160401b03166000036106225760408051600081526020810190915261062e565b61062e60026000610ad3565b9050600085602001516001600160401b031660000361065b57604080516000815260208101909152610668565b6106688660200151610b09565b90506000866040015163ffffffff166001600160401b031660000361069b576040805160008152602081019091526106a7565b6106a760036000610ad3565b90506000876040015163ffffffff166001600160401b03166000036106da576040805160008152602081019091526106e7565b6106e78860400151610b14565b905060008860600151600381111561070157610701614a9a565b6001600160401b031660000361072557604080516000815260208101909152610731565b61073160046000610ad3565b905060008960600151600381111561074b5761074b614a9a565b6001600160401b031660000361076f57604080516000815260208101909152610788565b6107888a6060015160038111156105f0576105f0614a9a565b9050600061079c60108c6101e00151610b25565b805160208083015160408085015190519495506000946107bd94930161529e565b60405160208183030381529060405290508989898989898989886040516020016107ef999897969594939291906152e1565b6040516020818303038152906040529a5050505050505050505050919050565b60008060008060008060006108248989610bdd565b925092509250826108445750600095509350849250600691506108f89050565b600381901c671fffffffffffffff1660078216600681106108785760008460006006985098509850985050505050506108f8565b6000816001600160401b0316600681111561089557610895614a9a565b905060038160068111156108ab576108ab614a9a565b14806108c8575060048160068111156108c6576108c6614a9a565b145b156108e7576000856000600699509950995099505050505050506108f8565b600199509397509095509193505050505b92959194509250565b6000826001600160401b03166001036109315760025b82600681111561092957610929614a9a565b1490506109c5565b826001600160401b0316600203610949576002610917565b826001600160401b0316600303610961576000610917565b826001600160401b0316600403610979576002610917565b826001600160401b0316600503610991576000610917565b826001600160401b03166006036109a9576002610917565b826001600160401b03166007036109c1576002610917565b5060005b92915050565b600080866001600160401b038516600103610a0e5760006109ed828987610d88565b9250905080610a025750600092509050610ac9565b50600192509050610ac9565b846001600160401b0316600203610a2c5760006109ed828987610e15565b846001600160401b0316600303610a4a5760006109ed828987610f5e565b846001600160401b0316600403610a685760006109ed828987611017565b846001600160401b0316600503610a865760006109ed828987611146565b846001600160401b0316600603610aa45760006109ed8289876111f0565b846001600160401b0316600703610ac25760006109ed82898761131f565b6000925090505b9550959350505050565b60606807fffffffffffffff8600384901b1682176000610af28261144e565b95945050505050565b60606109c58260030b61144e565b60606109c58261144e565b60606109c58263ffffffff1661144e565b610b4960405180606001604052806060815260200160608152602001606081525090565b6000610b54836115a8565b805190915060006001600160401b038216610b7d57604080516000815260208101909152610b88565b610b88866002610ad3565b9050600080836001600160401b031611610bb057604080516000815260208101909152610bb9565b610bb983610b09565b60408051606081018252938452602084019190915282019390935295945050505050565b60008060008060005b600a6001600160401b0382161015610cd3578551610c048883615257565b6001600160401b031610610c245760008760009450945094505050610d81565b600086610c31838a615257565b6001600160401b031681518110610c4a57610c4a6153a2565b016020015160f81c9050607f8116610c638360076153b8565b60ff82166001600160401b03919091161b939093179260808216600003610cbe576000836001600160401b0316118015610c9e575060ff8116155b15610cb757600089600096509650965050505050610d81565b5050610cd3565b50508080610ccb906153e3565b915050610be6565b600a6001600160401b03821610610cf65760008760009450945094505050610d81565b610d026001600a61527e565b6001600160401b0316816001600160401b031603610d6057600186610d27838a615257565b6001600160401b031681518110610d4057610d406153a2565b016020015160f81c1115610d605760008760009450945094505050610d81565b6001610d6c8289615257565b610d77906001615257565b8394509450945050505b9250925092565b600080600080610d98878761172b565b909850909250905081610db357600087935093505050610e0d565b806001600160401b0316600003610dd257600087935093505050610e0d565b610dda6147cd565b610de5888884611747565b909950909350905082610e015760008894509450505050610e0d565b85525060019250859150505b935093915050565b600080600080610e25878761172b565b909850909250905081610e4057600087935093505050610e0d565b806001600160401b0316600003610e5f57600087935093505050610e0d565b806001600160401b03166001600160401b03811115610e8057610e806149ae565b6040519080825280601f01601f191660200182016040528015610eaa576020820181803683370190505b50602086015260005b816001600160401b0316816001600160401b03161015610f445786610ed8828a615257565b6001600160401b031681518110610ef157610ef16153a2565b602001015160f81c60f81b8660200151826001600160401b031681518110610f1b57610f1b6153a2565b60200101906001600160f81b031916908160001a90535080610f3c816153e3565b915050610eb3565b50610f4f8188615257565b60019890975095505050505050565b600080600080610f6e8787611892565b909850909250905081610f8957600087935093505050610e0d565b8060030b600003610fa257600087935093505050610e0d565b60008160030b1280610fb7575060018160030b135b15610fca57600087935093505050610e0d565b8060030b6001811115610fdf57610fdf614a9a565b85604001906001811115610ff557610ff5614a9a565b9081600181111561100857611008614a9a565b90525060019795505050505050565b600080600080611027878761172b565b90985090925090508161104257600087935093505050610e0d565b806001600160401b031660000361106157600087935093505050610e0d565b806001600160401b03166001600160401b03811115611082576110826149ae565b6040519080825280601f01601f1916602001820160405280156110ac576020820181803683370190505b50606086015260005b816001600160401b0316816001600160401b03161015610f4457866110da828a615257565b6001600160401b0316815181106110f3576110f36153a2565b602001015160f81c60f81b8660600151826001600160401b03168151811061111d5761111d6153a2565b60200101906001600160f81b031916908160001a9053508061113e816153e3565b9150506110b5565b6000806000806111568787611892565b90985090925090508161117157600087935093505050610e0d565b8060030b60000361118a57600087935093505050610e0d565b60008160030b128061119f575060028160030b135b156111b257600087935093505050610e0d565b8060030b60028111156111c7576111c7614a9a565b856080019060028111156111dd576111dd614a9a565b9081600281111561100857611008614a9a565b600080600080611200878761172b565b90985090925090508161121b57600087935093505050610e0d565b806001600160401b031660000361123a57600087935093505050610e0d565b806001600160401b03166001600160401b0381111561125b5761125b6149ae565b6040519080825280601f01601f191660200182016040528015611285576020820181803683370190505b5060a086015260005b816001600160401b0316816001600160401b03161015610f4457866112b3828a615257565b6001600160401b0316815181106112cc576112cc6153a2565b602001015160f81c60f81b8660a00151826001600160401b0316815181106112f6576112f66153a2565b60200101906001600160f81b031916908160001a90535080611317816153e3565b91505061128e565b60008060008061132f878761172b565b90985090925090508161134a57600087935093505050610e0d565b806001600160401b031660000361136957600087935093505050610e0d565b806001600160401b03166001600160401b0381111561138a5761138a6149ae565b6040519080825280601f01601f1916602001820160405280156113b4576020820181803683370190505b5060c086015260005b816001600160401b0316816001600160401b03161015610f4457866113e2828a615257565b6001600160401b0316815181106113fb576113fb6153a2565b602001015160f81c60f81b8660c00151826001600160401b031681518110611425576114256153a2565b60200101906001600160f81b031916908160001a90535080611446816153e3565b9150506113bd565b60608160015b607f826001600160401b0316111561148a576007826001600160401b0316901c91506001816114839190615257565b9050611454565b6000816001600160401b03166001600160401b038111156114ad576114ad6149ae565b6040519080825280601f01601f1916602001820160405280156114d7576020820181803683370190505b50905084925060005b826001600160401b0316816001600160401b031610156115595783607f1660801760f81b82826001600160401b03168151811061151f5761151f6153a2565b60200101906001600160f81b031916908160001a9053506007846001600160401b0316901c93508080611551906153e3565b9150506114e0565b50607f60f81b8161156b60018561527e565b6001600160401b031681518110611584576115846153a2565b0160200180519091166001600160f81b03191690600082901a905350949350505050565b6060600080836000015151116115cc576040805160008152602081019091526115d8565b6115d860016002610ad3565b9050600080846000015151116115fc57604080516000815260208101909152611608565b83515161160890610b09565b90506000808560000151511161162c5760408051600081526020810190915261162f565b84515b90506000856020015163ffffffff166001600160401b03166000036116625760408051600081526020810190915261166e565b61166e60026000610ad3565b90506000866020015163ffffffff166001600160401b03166000036116a1576040805160008152602081019091526116ae565b6116ae8760200151610b14565b905060006116c1600389604001516118a1565b805160208083015160408085015190519495506000946116e294930161529e565b604051602081830303815290604052905086868686868560405160200161170e96959493929190615409565b604051602081830303815290604052975050505050505050919050565b600080600061173a85856118d0565b9250925092509250925092565b6000806117526147cd565b61175a6147cd565b6000876001600160401b0381166117718883615257565b6001600160401b03161015611790576000955093509091506105489050565b6001600160401b0387166117a48a8361527e565b6001600160401b0316101561050b5760008060006117c2848c61080f565b9196509194509092509050826117e657506000975091955092935061054892505050565b6010826001600160401b0316111561180c57506000975091955092935061054892505050565b846001600160401b0316826001600160401b03161161183957506000975091955092935061054892505050565b6118438282611967565b92508261185e57506000975091955092935061054892505050565b61186b848c8c858a611ae9565b945092508261188857506000975091955092935061054892505050565b5092506117909050565b600080600061173a8585611ccd565b6118c560405180606001604052806060815260200160608152602001606081525090565b6000610b5483611d2c565b6000806000806000806118e38888610bdd565b925092509250826118ff5750600094509250839150610d819050565b816001600160401b03168183016001600160401b0316101561192c5750600094509250839150610d819050565b86516119388383615257565b6001600160401b031611156119585750600094509250839150610d819050565b60019891975095509350505050565b6000826001600160401b0316600103611981576000610917565b826001600160401b0316600203611999576000610917565b826001600160401b03166003036119b1576000610917565b826001600160401b03166004036119c9576000610917565b826001600160401b03166005036119e1576002610917565b826001600160401b03166006036119f9576000610917565b826001600160401b0316600703611a11576002610917565b826001600160401b0316600803611a29576000610917565b826001600160401b0316600903611a41576002610917565b826001600160401b0316600a03611a59576000610917565b826001600160401b0316600b03611a71576000610917565b826001600160401b0316600c03611a89576000610917565b826001600160401b0316600d03611aa1576000610917565b826001600160401b0316600e03611ab9576002610917565b826001600160401b0316600f03611ad1576000610917565b826001600160401b03166010036109c1576002610917565b600080866001600160401b038516600103611b0b5760006109ed828987611e5e565b846001600160401b0316600203611b295760006109ed828987611f05565b846001600160401b0316600303611b475760006109ed828987611f6c565b846001600160401b0316600403611b655760006109ed828987611fcd565b846001600160401b0316600503611b835760006109ed828987612077565b846001600160401b0316600603611ba15760006109ed828987612105565b846001600160401b0316600703611bbf5760006109ed82898761215e565b846001600160401b0316600803611bdd5760006109ed8289876121ec565b846001600160401b0316600903611bfb5760006109ed828987612245565b846001600160401b0316600a03611c195760006109ed8289876122d4565b846001600160401b0316600b03611c375760006109ed82898761232e565b846001600160401b0316600c03611c555760006109ed828987612388565b846001600160401b0316600d03611c735760006109ed8289876123e2565b846001600160401b0316600e03611c915760006109ed82898761243c565b846001600160401b0316600f03611caf5760006109ed8289876124e0565b846001600160401b0316601003610ac25760006109ed82898761253a565b600080600080600080611ce08888610bdd565b92509250925082611cfc5750600094509250839150610d819050565b6001603f82901c166000036119585767ffffffff000000008116156119585750600094509250839150610d819050565b6060600082600001516001600160401b0316600003611d5957604080516000815260208101909152611d65565b611d6560016000610ad3565b9050600083600001516001600160401b0316600003611d9257604080516000815260208101909152611d9d565b8351611d9d90610b09565b905060008085602001515111611dc157604080516000815260208101909152611dcc565b611dcc600280610ad3565b905060008086602001515111611df057604080516000815260208101909152611dfe565b611dfe866020015151610b09565b905060008087602001515111611e2257604080516000815260208101909152611e28565b86602001515b90508484848484604051602001611e43959493929190615488565b60405160208183030381529060405295505050505050919050565b600080600080611e6e8787611892565b909850909250905081611e8957600087935093505050610e0d565b8060030b600003611ea257600087935093505050610e0d565b60008160030b1280611eb75750600d8160030b135b15611eca57600087935093505050610e0d565b8060030b600d811115611edf57611edf614a9a565b8590600d811115611ef257611ef2614a9a565b9081600d81111561100857611008614a9a565b600080600080611f1587876125c9565b909850909250905081611f3057600087935093505050610e0d565b806001600160401b0316600003611f4f57600087935093505050610e0d565b6001600160401b0316602094909401939093525060019492505050565b600080600080611f7c87876125f8565b909850909250905081611f9757600087935093505050610e0d565b8063ffffffff16600003611fb357600087935093505050610e0d565b63ffffffff16604094909401939093525060019492505050565b600080600080611fdd8787611892565b909850909250905081611ff857600087935093505050610e0d565b8060030b60000361201157600087935093505050610e0d565b60008160030b1280612026575060038160030b135b1561203957600087935093505050610e0d565b8060030b600381111561204e5761204e614a9a565b8560600190600381111561206457612064614a9a565b9081600381111561100857611008614a9a565b600080600080612087878761172b565b9098509092509050816120a257600087935093505050610e0d565b806001600160401b03166000036120c157600087935093505050610e0d565b6120c9614883565b6120d4888884612648565b9099509093509050826120f05760008894509450505050610e0d565b60809590950194909452506001959350505050565b6000806000806121158787612793565b90985090925090508161213057600087935093505050610e0d565b80151560000361214857600087935093505050610e0d565b151560a094909401939093525060019492505050565b60008060008061216e878761172b565b90985090925090508161218957600087935093505050610e0d565b806001600160401b03166000036121a857600087935093505050610e0d565b6121b06148d9565b6121bb888884612819565b9099509093509050826121d75760008894509450505050610e0d565b60c09590950194909452506001959350505050565b6000806000806121fc8787612793565b90985090925090508161221757600087935093505050610e0d565b80151560000361222f57600087935093505050610e0d565b151560e094909401939093525060019492505050565b600080600080612255878761172b565b90985090925090508161227057600087935093505050610e0d565b806001600160401b031660000361228f57600087935093505050610e0d565b612297614914565b6122a2888884612964565b9099509093509050826122be5760008894509450505050610e0d565b6101009590950194909452506001959350505050565b6000806000806122e48787612793565b9098509092509050816122ff57600087935093505050610e0d565b80151560000361231757600087935093505050610e0d565b151561012094909401939093525060019492505050565b60008060008061233e8787612793565b90985090925090508161235957600087935093505050610e0d565b80151560000361237157600087935093505050610e0d565b151561014094909401939093525060019492505050565b6000806000806123988787612793565b9098509092509050816123b357600087935093505050610e0d565b8015156000036123cb57600087935093505050610e0d565b151561016094909401939093525060019492505050565b6000806000806123f28787612793565b90985090925090508161240d57600087935093505050610e0d565b80151560000361242557600087935093505050610e0d565b151561018094909401939093525060019492505050565b60008060008061244c878761172b565b90985090925090508161246757600087935093505050610e0d565b806001600160401b031660000361248657600087935093505050610e0d565b60408051606080820183528152600060208201819052918101919091526124ae888884612aaf565b9099509093509050826124ca5760008894509450505050610e0d565b6101a09590950194909452506001959350505050565b6000806000806124f08787612793565b90985090925090508161250b57600087935093505050610e0d565b80151560000361252357600087935093505050610e0d565b15156101c094909401939093525060019492505050565b60008060008061254a878761172b565b90985090925090508161256557600087935093505050610e0d565b806001600160401b031660000361258457600087935093505050610e0d565b61258c61494f565b612597888884612c1c565b9099509093509050826125b35760008894509450505050610e0d565b6101e09590950194909452506001959350505050565b6000806000806000806125dc8888610bdd565b925092509250826119585750600094509250839150610d819050565b60008060008060008061260b8888610bdd565b925092509250826126275750600094509250839150610d819050565b67ffffffff000000008116156119585750600094509250839150610d819050565b600080612653614883565b61265b614883565b6000876001600160401b0381166126728883615257565b6001600160401b03161015612691576000955093509091506105489050565b6001600160401b0387166126a58a8361527e565b6001600160401b0316101561050b5760008060006126c3848c61080f565b9196509194509092509050826126e757506000975091955092935061054892505050565b6007826001600160401b0316111561270d57506000975091955092935061054892505050565b846001600160401b0316826001600160401b03161161273a57506000975091955092935061054892505050565b6127448282612d67565b92508261275f57506000975091955092935061054892505050565b61276c848c8c858a612de1565b945092508261278957506000975091955092935061054892505050565b5092506126919050565b6000806000806000806127a68888610bdd565b925092509250826127c25750600094509250839150610d819050565b6001816001600160401b031611156127e55750600094509250839150610d819050565b806001600160401b0316600003612808575060019450925060009150610d819050565b506001979096508795509350505050565b6000806128246148d9565b61282c6148d9565b6000876001600160401b0381166128438883615257565b6001600160401b03161015612862576000955093509091506105489050565b6001600160401b0387166128768a8361527e565b6001600160401b0316101561050b576000806000612894848c61080f565b9196509194509092509050826128b857506000975091955092935061054892505050565b6003826001600160401b031611156128de57506000975091955092935061054892505050565b846001600160401b0316826001600160401b03161161290b57506000975091955092935061054892505050565b6129158282612eb7565b92508261293057506000975091955092935061054892505050565b61293d848c8c858a612f01565b945092508261295a57506000975091955092935061054892505050565b5092506128629050565b60008061296f614914565b612977614914565b6000876001600160401b03811661298e8883615257565b6001600160401b031610156129ad576000955093509091506105489050565b6001600160401b0387166129c18a8361527e565b6001600160401b0316101561050b5760008060006129df848c61080f565b919650919450909250905082612a0357506000975091955092935061054892505050565b6005826001600160401b03161115612a2957506000975091955092935061054892505050565b846001600160401b0316826001600160401b031611612a5657506000975091955092935061054892505050565b612a608282612f5f565b925082612a7b57506000975091955092935061054892505050565b612a88848c8c858a612fd9565b9450925082612aa557506000975091955092935061054892505050565b5092506129ad9050565b60408051606080820183528082526000602080840182905283850182905284518084018652928352820181905292810183905282919082876001600160401b038116612afb8883615257565b6001600160401b03161015612b1a576000955093509091506105489050565b6001600160401b038716612b2e8a8361527e565b6001600160401b0316101561050b576000806000612b4c848c61080f565b919650919450909250905082612b7057506000975091955092935061054892505050565b6003826001600160401b03161115612b9657506000975091955092935061054892505050565b846001600160401b0316826001600160401b031611612bc357506000975091955092935061054892505050565b612bcd8282613073565b925082612be857506000975091955092935061054892505050565b612bf5848c8c858a6130bd565b9450925082612c1257506000975091955092935061054892505050565b509250612b1a9050565b600080612c2761494f565b612c2f61494f565b6000876001600160401b038116612c468883615257565b6001600160401b03161015612c65576000955093509091506105489050565b6001600160401b038716612c798a8361527e565b6001600160401b0316101561050b576000806000612c97848c61080f565b919650919450909250905082612cbb57506000975091955092935061054892505050565b6003826001600160401b03161115612ce157506000975091955092935061054892505050565b846001600160401b0316826001600160401b031611612d0e57506000975091955092935061054892505050565b612d18828261311b565b925082612d3357506000975091955092935061054892505050565b612d40848c8c858a61314d565b9450925082612d5d57506000975091955092935061054892505050565b509250612c659050565b6000826001600160401b0316600103612d81576002610917565b826001600160401b0316600203612d99576002610917565b826001600160401b0316600303612db1576002610917565b826001600160401b0316600403612dc9576002610917565b826001600160401b0316600503610991576002610917565b600080866001600160401b038516600103612e035760006109ed8289876131ab565b846001600160401b0316600203612e215760006109ed8289876131fb565b846001600160401b0316600303612e3f5760006109ed828987613404565b846001600160401b0316600403612e5d5760006109ed82898761349f565b846001600160401b0316600503612e7b5760006109ed8289876134f6565b846001600160401b0316600603612e995760006109ed8289876136bb565b846001600160401b0316600703610ac25760006109ed82898761391e565b6000826001600160401b0316600103612ed1576000610917565b826001600160401b0316600203612ee9576002610917565b826001600160401b03166003036109c1576002610917565b600080866001600160401b038516600103612f235760006109ed828987613975565b846001600160401b0316600203612f415760006109ed828987613a09565b846001600160401b0316600303610ac25760006109ed828987613aa4565b6000826001600160401b0316600103612f79576002610917565b826001600160401b0316600203612f91576002610917565b826001600160401b0316600303612fa9576002610917565b826001600160401b0316600403612fc1576000610917565b826001600160401b03166005036109c1576000610917565b600080866001600160401b038516600103612ffb5760006109ed828987613afb565b846001600160401b03166002036130195760006109ed828987613c27565b846001600160401b03166003036130375760006109ed828987613d56565b846001600160401b03166004036130555760006109ed828987613e85565b846001600160401b0316600503610ac25760006109ed828987613ee6565b6000826001600160401b031660010361308d576002610917565b826001600160401b03166002036130a5576000610917565b826001600160401b03166003036109c1576000610917565b600080866001600160401b0385166001036130df5760006109ed8289876131ab565b846001600160401b03166002036130fd5760006109ed828987613f47565b846001600160401b0316600303610ac25760006109ed828987613fa8565b6000826001600160401b0316600103613135576002610917565b826001600160401b0316600203612ee9576000610917565b600080866001600160401b03851660010361316f5760006109ed82898761400f565b846001600160401b031660020361318d5760006109ed828987613f47565b846001600160401b0316600303610ac25760006109ed828987613404565b600080600060606131bc878761413b565b9098509092509050816131d757600087935093505050610e0d565b80516000036131ee57600087935093505050610e0d565b9093525060019492505050565b60008060008061320b87876118d0565b90985090925090508161322657600087935093505050610e0d565b806001600160401b031660000361324557600087935093505050610e0d565b866001600160401b03811661325a8383615257565b6001600160401b031610156132785760008894509450505050610e0d565b60005b6001600160401b03831661328f838b61527e565b6001600160401b031610156132db5760006132aa8a8a6125c9565b909b509095509050846132c85760008a965096505050505050610e0d565b6132d3600183615257565b91505061327b565b806001600160401b03166001600160401b038111156132fc576132fc6149ae565b604051908082528060200260200182016040528015613325578160200160208202803683370190505b506020880152909750879060005b816001600160401b0316816001600160401b031610156133c35760006133598b8b6125c9565b909c509096509050856133785760008b97509750505050505050610e0d565b808960200151836001600160401b031681518110613398576133986153a2565b6001600160401b039092166020928302919091019091015250806133bb816153e3565b915050613333565b506133ce8383615257565b6001600160401b0316896001600160401b0316146133f6576000899550955050505050610e0d565b506001989650505050505050565b600080600080613414878761172b565b90985090925090508161342f57600087935093505050610e0d565b806001600160401b031660000361344e57600087935093505050610e0d565b60408051808201909152600081526060602082015261346e888884614279565b90995090935090508261348a5760008894509450505050610e0d565b60409590950194909452506001959350505050565b600080600060606134b0878761413b565b9098509092509050816134cb57600087935093505050610e0d565b80516000036134e257600087935093505050610e0d565b606094909401939093525060019492505050565b60008060008061350687876118d0565b90985090925090508161352157600087935093505050610e0d565b806001600160401b031660000361354057600087935093505050610e0d565b866001600160401b0381166135558383615257565b6001600160401b031610156135735760008894509450505050610e0d565b60005b6001600160401b03831661358a838b61527e565b6001600160401b031610156135d65760006135a58a8a6125f8565b909b509095509050846135c35760008a965096505050505050610e0d565b6135ce600183615257565b915050613576565b806001600160401b03166001600160401b038111156135f7576135f76149ae565b604051908082528060200260200182016040528015613620578160200160208202803683370190505b506080880152909750879060005b816001600160401b0316816001600160401b031610156133c35760006136548b8b6125f8565b909c509096509050856136735760008b97509750505050505050610e0d565b808960800151836001600160401b031681518110613693576136936153a2565b63ffffffff9092166020928302919091019091015250806136b3816153e3565b91505061362e565b6000808085815b8651886001600160401b031610156137b05760006136e0898961172b565b909a509094509050836136fd576000899550955050505050610e0d565b6001600160401b038916613711828b615257565b6001600160401b03161015613730576000899550955050505050610e0d565b61373a818a615257565b9850613747600183615257565b91508751896001600160401b03161061376057506137b0565b60008061376d8b8b61080f565b919d5091975090925090508561378f5760008b97509750505050505050610e0d565b816001600160401b03166006146137a8575050506137b0565b5050506136c2565b806001600160401b03166001600160401b038111156137d1576137d16149ae565b60405190808252806020026020018201604052801561380a57816020015b6137f7614981565b8152602001906001900390816137ef5790505b5060a0870152909650869060005b816001600160401b0316816001600160401b031610156133f657600061383e8a8a61172b565b909b5090955090508461385c5760008a965096505050505050610e0d565b899350613867614981565b6138728b8b846143e4565b909c509096509050856138915760008b97509750505050505050610e0d565b808960a00151846001600160401b0316815181106138b1576138b16153a2565b60209081029190910101526138c760018561527e565b6001600160401b0316836001600160401b03161015613909576138ea8b8b6125c9565b909c509096509150856139095760008b97509750505050505050610e0d565b50508080613916906153e3565b915050613818565b6000806000606061392f878761413b565b90985090925090508161394a57600087935093505050610e0d565b805160000361396157600087935093505050610e0d565b60c094909401939093525060019492505050565b6000806000806139858787611892565b9098509092509050816139a057600087935093505050610e0d565b8060030b6000036139b957600087935093505050610e0d565b60008160030b12806139ce575060028160030b135b156139e157600087935093505050610e0d565b8060030b60028111156139f6576139f6614a9a565b859060028111156111dd576111dd614a9a565b600080600080613a19878761172b565b909850909250905081613a3457600087935093505050610e0d565b806001600160401b0316600003613a5357600087935093505050610e0d565b604080518082019091526000815260606020820152613a73888884614279565b909950909350905082613a8f5760008894509450505050610e0d565b60209590950194909452506001959350505050565b60008060006060613ab5878761413b565b909850909250905081613ad057600087935093505050610e0d565b8051600003613ae757600087935093505050610e0d565b604094909401939093525060019492505050565b600080600080613b0b878761172b565b909850909250905081613b2657600087935093505050610e0d565b806001600160401b0316600003613b4557600087935093505050610e0d565b806001600160401b03166001600160401b03811115613b6657613b666149ae565b6040519080825280601f01601f191660200182016040528015613b90576020820181803683370190505b50855260005b816001600160401b0316816001600160401b03161015610f445786613bbb828a615257565b6001600160401b031681518110613bd457613bd46153a2565b602001015160f81c60f81b8660000151826001600160401b031681518110613bfe57613bfe6153a2565b60200101906001600160f81b031916908160001a90535080613c1f816153e3565b915050613b96565b600080600080613c37878761172b565b909850909250905081613c5257600087935093505050610e0d565b806001600160401b0316600003613c7157600087935093505050610e0d565b806001600160401b03166001600160401b03811115613c9257613c926149ae565b6040519080825280601f01601f191660200182016040528015613cbc576020820181803683370190505b50602086015260005b816001600160401b0316816001600160401b03161015610f445786613cea828a615257565b6001600160401b031681518110613d0357613d036153a2565b602001015160f81c60f81b8660200151826001600160401b031681518110613d2d57613d2d6153a2565b60200101906001600160f81b031916908160001a90535080613d4e816153e3565b915050613cc5565b600080600080613d66878761172b565b909850909250905081613d8157600087935093505050610e0d565b806001600160401b0316600003613da057600087935093505050610e0d565b806001600160401b03166001600160401b03811115613dc157613dc16149ae565b6040519080825280601f01601f191660200182016040528015613deb576020820181803683370190505b50604086015260005b816001600160401b0316816001600160401b03161015610f445786613e19828a615257565b6001600160401b031681518110613e3257613e326153a2565b602001015160f81c60f81b8660400151826001600160401b031681518110613e5c57613e5c6153a2565b60200101906001600160f81b031916908160001a90535080613e7d816153e3565b915050613df4565b600080600080613e9587876125f8565b909850909250905081613eb057600087935093505050610e0d565b8063ffffffff16600003613ecc57600087935093505050610e0d565b63ffffffff16606094909401939093525060019492505050565b600080600080613ef687876125f8565b909850909250905081613f1157600087935093505050610e0d565b8063ffffffff16600003613f2d57600087935093505050610e0d565b63ffffffff16608094909401939093525060019492505050565b600080600080613f5787876125f8565b909850909250905081613f7257600087935093505050610e0d565b8063ffffffff16600003613f8e57600087935093505050610e0d565b63ffffffff16602094909401939093525060019492505050565b600080600080613fb887876125c9565b909850909250905081613fd357600087935093505050610e0d565b806001600160401b0316600003613ff257600087935093505050610e0d565b6001600160401b0316604094909401939093525060019492505050565b60008060008061401f878761172b565b90985090925090508161403a57600087935093505050610e0d565b806001600160401b031660000361405957600087935093505050610e0d565b806001600160401b03166001600160401b0381111561407a5761407a6149ae565b6040519080825280601f01601f1916602001820160405280156140a4576020820181803683370190505b50855260005b816001600160401b0316816001600160401b03161015610f4457866140cf828a615257565b6001600160401b0316815181106140e8576140e86153a2565b602001015160f81c60f81b8660000151826001600160401b031681518110614112576141126153a2565b60200101906001600160f81b031916908160001a90535080614133816153e3565b9150506140aa565b6000806060600080600061414f88886118d0565b9250925092508261417b5760008260405180602001604052806000815250955095509550505050610d81565b6000816001600160401b03166001600160401b0381111561419e5761419e6149ae565b6040519080825280601f01601f1916602001820160405280156141c8576020820181803683370190505b50905060005b826001600160401b0316816001600160401b0316101561425b57886141f38286615257565b6001600160401b03168151811061420c5761420c6153a2565b602001015160f81c60f81b82826001600160401b031681518110614232576142326153a2565b60200101906001600160f81b031916908160001a90535080614253816153e3565b9150506141ce565b5060016142688385615257565b909750955093505050509250925092565b60008061429760408051808201909152600081526060602082015290565b6040805180820190915260008152606060208201526000876001600160401b0381166142c38883615257565b6001600160401b031610156142e2576000955093509091506105489050565b6001600160401b0387166142f68a8361527e565b6001600160401b0316101561050b576000806000614314848c61080f565b91965091945090925090508261433857506000975091955092935061054892505050565b6002826001600160401b0316111561435e57506000975091955092935061054892505050565b846001600160401b0316826001600160401b03161161438b57506000975091955092935061054892505050565b614395828261452f565b9250826143b057506000975091955092935061054892505050565b6143bd848c8c858a614561565b94509250826143da57506000975091955092935061054892505050565b5092506142e29050565b6000806143ef614981565b6143f7614981565b6000876001600160401b03811661440e8883615257565b6001600160401b0316101561442d576000955093509091506105489050565b6001600160401b0387166144418a8361527e565b6001600160401b0316101561050b57600080600061445f848c61080f565b91965091945090925090508261448357506000975091955092935061054892505050565b6002826001600160401b031611156144a957506000975091955092935061054892505050565b846001600160401b0316826001600160401b0316116144d657506000975091955092935061054892505050565b6144e082826145a1565b9250826144fb57506000975091955092935061054892505050565b614508848c8c858a6145bb565b945092508261452557506000975091955092935061054892505050565b50925061442d9050565b6000826001600160401b0316600103614549576000610917565b826001600160401b03166002036109c1576002610917565b600080866001600160401b0385166001036145835760006109ed8289876145fb565b846001600160401b0316600203610ac25760006109ed82898761465b565b6000826001600160401b0316600103614549576002610917565b600080866001600160401b0385166001036145dd5760006109ed8289876131ab565b846001600160401b0316600203610ac25760006109ed828987613a09565b60008060008061460b87876125c9565b90985090925090508161462657600087935093505050610e0d565b806001600160401b031660000361464557600087935093505050610e0d565b6001600160401b03169093525060019492505050565b60008060008061466b878761172b565b90985090925090508161468657600087935093505050610e0d565b806001600160401b03166000036146a557600087935093505050610e0d565b806001600160401b03166001600160401b038111156146c6576146c66149ae565b6040519080825280601f01601f1916602001820160405280156146f0576020820181803683370190505b50602086015260005b816001600160401b0316816001600160401b03161015610f44578661471e828a615257565b6001600160401b031681518110614737576147376153a2565b602001015160f81c60f81b8660200151826001600160401b031681518110614761576147616153a2565b60200101906001600160f81b031916908160001a90535080614782816153e3565b9150506146f9565b6040518060e0016040528061479d6147cd565b81526060602082015260400160008152606060208201526040016000815260200160608152602001606081525090565b60408051610200810182526000808252602082018190529181018290526060810191909152608081016147fe614883565b8152600060208201526040016148126148d9565b815260006020820152604001614826614914565b81526000602082018190526040820181905260608201819052608082015260a00161486a604080516060808201835281526000602082018190529181019190915290565b81526000602082015260400161487e61494f565b905290565b6040518060e0016040528060608152602001606081526020016148b760408051808201909152600081526060602082015290565b8152602001606081526020016060815260200160608152602001606081525090565b6040805160608101909152806000815260200161490760408051808201909152600081526060602082015290565b8152602001606081525090565b6040518060a00160405280606081526020016060815260200160608152602001600063ffffffff168152602001600063ffffffff1681525090565b604080516060808201835281526000602082015290810161487e60408051808201909152600081526060602082015290565b60405180604001604052806060815260200161487e60408051808201909152600081526060602082015290565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156149ec576149ec6149ae565b604052919050565b60006001600160401b03821115614a0d57614a0d6149ae565b50601f01601f191660200190565b600060208284031215614a2d57600080fd5b81356001600160401b03811115614a4357600080fd5b8201601f81018413614a5457600080fd5b8035614a67614a62826149f4565b6149c4565b818152856020838501011115614a7c57600080fd5b81602084016020830137600091810160200191909152949350505050565b634e487b7160e01b600052602160045260246000fd5b600e8110614ac057614ac0614a9a565b9052565b60048110614ac057614ac0614a9a565b60005b83811015614aef578181015183820152602001614ad7565b50506000910152565b60008151808452614b10816020860160208601614ad4565b601f01601f19169290920160200192915050565b600081518084526020808501945080840160005b83811015614b5d5781516001600160401b031687529582019590820190600101614b38565b509495945050505050565b6001600160401b0381511682526000602082015160406020850152614b906040850182614af8565b949350505050565b600081518084526020808501945080840160005b83811015614b5d57815163ffffffff1687529582019590820190600101614bac565b600081518084526020808501808196508360051b8101915082860160005b85811015614c3c578284038952815160408151818752614c0e82880182614af8565b91505086820151915085810387870152614c288183614b68565b9a87019a9550505090840190600101614bec565b5091979650505050505050565b6000815160e08452614c5e60e0850182614af8565b905060208301518482036020860152614c778282614b24565b91505060408301518482036040860152614c918282614b68565b91505060608301518482036060860152614cab8282614af8565b91505060808301518482036080860152614cc58282614b98565b91505060a083015184820360a0860152614cdf8282614bce565b91505060c083015184820360c0860152610af28282614af8565b60038110614d0957614d09614a9a565b50565b60008151614d1981614cf9565b80845250602082015160606020850152614d366060850182614b68565b905060408301518482036040860152610af28282614af8565b6000815160a08452614d6460a0850182614af8565b905060208301518482036020860152614d7d8282614af8565b91505060408301518482036040860152614d978282614af8565b915050606083015163ffffffff808216606087015280608086015116608087015250508091505092915050565b6000815160608452614dd96060850182614af8565b905063ffffffff60208401511660208501526001600160401b0360408401511660408501528091505092915050565b6000815160608452614e1d6060850182614af8565b905063ffffffff602084015116602085015260408301518482036040860152610af28282614b68565b60028110614ac057614ac0614a9a565b614ac081614cf9565b602081526000825160e06020840152614e7d61010084018251614ab0565b6020810151610120614e99818601836001600160401b03169052565b60408301519150610140614eb48187018463ffffffff169052565b60608401519250610160614eca81880185614ac4565b6080850151935061020061018081818a0152614eea6103008a0187614c49565b955060a08701516101a0614f01818c018315159052565b60c0890151915060ff196101c0818d8b0301818e0152614f218a85614d0c565b995060e08b015193506101e0614f3a818f018615159052565b6101008c01519450828e8c0301878f0152614f558b86614d4f565b998c0151999a50614f6b6102208f018b15159052565b888c01519950614f806102408f018b15159052565b878c01519950614f956102608f018b15159052565b858c01519950614faa6102808f018b15159052565b838c01519950828e8c03016102a08f0152614fc58b8b614dc4565b9a50818c01519950614fdc6102c08f018b15159052565b808c01519b505050808c8a03016102e08d015250505050505050506150018183614e08565b9150506020840151601f19808584030160408601526150208383614af8565b9250604086015191506150366060860183614e46565b60608601519150808584030160808601526150518383614af8565b92506080860151915061506760a0860183614e56565b60a08601519150808584030160c08601526150828383614af8565b925060c08601519150808584030160e086015250610af28282614af8565b6040815260006150b36040830185614af8565b905063ffffffff831660208301529392505050565b6000602082840312156150da57600080fd5b81516001600160401b038111156150f057600080fd5b8201601f8101841361510157600080fd5b805161510f614a62826149f4565b81815285602083850101111561512457600080fd5b610af2826020830160208601614ad4565b80516020808301519190811015615156576000198160200360031b1b821691505b50919050565b8481528360208201528260408201526080606082015260006151816080830184614af8565b9695505050505050565b60006020828403121561519d57600080fd5b815180151581146151ad57600080fd5b9392505050565b6001600160401b0383168152604060208201526000614b906040830184614af8565b6000604082840312156151e857600080fd5b604051604081018181106001600160401b038211171561520a5761520a6149ae565b60405282516003811061521c57600080fd5b8152602083015163ffffffff8116811461523557600080fd5b60208201529392505050565b634e487b7160e01b600052601160045260246000fd5b6001600160401b0381811683821601908082111561527757615277615241565b5092915050565b6001600160401b0382811682821603908082111561527757615277615241565b600084516152b0818460208901614ad4565b8451908301906152c4818360208901614ad4565b84519101906152d7818360208801614ad4565b0195945050505050565b60008a516152f3818460208f01614ad4565b8a516153058183860160208f01614ad4565b8a51918401019061531a818360208e01614ad4565b895161532c8183850160208e01614ad4565b8951929091010190615342818360208c01614ad4565b87516153548183850160208c01614ad4565b875192909101019061536a818360208a01614ad4565b855161537c8183850160208a01614ad4565b8551929091010190615392818360208801614ad4565b019b9a5050505050505050505050565b634e487b7160e01b600052603260045260246000fd5b6001600160401b038181168382160280821691908281146153db576153db615241565b505092915050565b60006001600160401b038083168181036153ff576153ff615241565b6001019392505050565b60008751602061541c8285838d01614ad4565b88519184019161542f8184848d01614ad4565b88519201916154418184848c01614ad4565b87519201916154538184848b01614ad4565b86519201916154658184848a01614ad4565b85519201916154778184848901614ad4565b919091019998505050505050505050565b6000865161549a818460208b01614ad4565b8651908301906154ae818360208b01614ad4565b86519101906154c1818360208a01614ad4565b85519101906154d4818360208901614ad4565b84519101906154e7818360208801614ad4565b0197965050505050505056fea26469706673582212204cb1bddfd4e08baedc3556521923f5dd4dff2d8852ddacbeb2aa1d8298f468e164736f6c63430008150033

Deployed Bytecode

0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063277e661d14610030575b600080fd5b61004361003e366004614a1b565b610059565b6040516100509190614e5f565b60405180910390f35b61006161478a565b60008061007160008586516103c0565b92505091508161009457604051636eca2e4b60e01b815260040160405180910390fd5b60006100a38260000151610551565b905060007333937f3b8a9107e409931b70478ae716cb51aee863227bb04d8360146040518363ffffffff1660e01b81526004016100e19291906150a0565b600060405180830381865af41580156100fe573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261012691908101906150c8565b905082602001518051906020012081805190602001201461015a57604051638b56642d60e01b815260040160405180910390fd5b505060608101516020810151604082015160a08401519192909160009073fa7321696663ea6b9c8d4d3c892c1176e2587a3990632bf6eda89061019c90615135565b868689602001516040518563ffffffff1660e01b81526004016101c2949392919061515c565b602060405180830381865af41580156101df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610203919061518b565b90508061022357604051638baa579f60e01b815260040160405180910390fd5b505082516020015160a084015160405163561a662d60e11b8152600094506ffc1237824fb747abde0ff18990e59b7e935063ac34cc5a926102689290916004016151b4565b6040805180830381865afa158015610284573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102a891906151d6565b90506001815160028111156102bf576102bf614a9a565b146102dd57604051630eda9c3d60e31b815260040160405180910390fd5b6001826080015160028111156102f5576102f5614a9a565b1461031357604051632171ecf960e01b815260040160405180910390fd5b600d825151600d81111561032957610329614a9a565b1461034757604051635b60892f60e01b815260040160405180910390fd5b81516101e00151515161010010156103725760405163e7bc872f60e01b815260040160405180910390fd5b81516101e0015160200151600163ffffffff82161080610398575060048163ffffffff16115b156103b657604051639a759aa960e01b815260040160405180910390fd5b5090949350505050565b6000806103cb61478a565b6103d361478a565b6000876001600160401b0381166103ea8883615257565b6001600160401b03161015610409576000955093509091506105489050565b6001600160401b03871661041d8a8361527e565b6001600160401b0316101561050b57600080600061043b848c61080f565b91965091945090925090508261045f57506000975091955092935061054892505050565b6007826001600160401b0316111561048557506000975091955092935061054892505050565b846001600160401b0316826001600160401b0316116104b257506000975091955092935061054892505050565b6104bc8282610901565b9250826104d757506000975091955092935061054892505050565b6104e4848c8c858a6109cb565b945092508261050157506000975091955092935061054892505050565b5092506104099050565b610515878a615257565b6001600160401b0316816001600160401b03161461053d576000955093509091506105489050565b600195509350909150505b93509350939050565b606060008260000151600d81111561056b5761056b614a9a565b6001600160401b031660000361058f5760408051600081526020810190915261059b565b61059b60016000610ad3565b905060008360000151600d8111156105b5576105b5614a9a565b6001600160401b03166000036105d9576040805160008152602081019091526105f5565b83516105f590600d8111156105f0576105f0614a9a565b610afb565b9050600084602001516001600160401b03166000036106225760408051600081526020810190915261062e565b61062e60026000610ad3565b9050600085602001516001600160401b031660000361065b57604080516000815260208101909152610668565b6106688660200151610b09565b90506000866040015163ffffffff166001600160401b031660000361069b576040805160008152602081019091526106a7565b6106a760036000610ad3565b90506000876040015163ffffffff166001600160401b03166000036106da576040805160008152602081019091526106e7565b6106e78860400151610b14565b905060008860600151600381111561070157610701614a9a565b6001600160401b031660000361072557604080516000815260208101909152610731565b61073160046000610ad3565b905060008960600151600381111561074b5761074b614a9a565b6001600160401b031660000361076f57604080516000815260208101909152610788565b6107888a6060015160038111156105f0576105f0614a9a565b9050600061079c60108c6101e00151610b25565b805160208083015160408085015190519495506000946107bd94930161529e565b60405160208183030381529060405290508989898989898989886040516020016107ef999897969594939291906152e1565b6040516020818303038152906040529a5050505050505050505050919050565b60008060008060008060006108248989610bdd565b925092509250826108445750600095509350849250600691506108f89050565b600381901c671fffffffffffffff1660078216600681106108785760008460006006985098509850985050505050506108f8565b6000816001600160401b0316600681111561089557610895614a9a565b905060038160068111156108ab576108ab614a9a565b14806108c8575060048160068111156108c6576108c6614a9a565b145b156108e7576000856000600699509950995099505050505050506108f8565b600199509397509095509193505050505b92959194509250565b6000826001600160401b03166001036109315760025b82600681111561092957610929614a9a565b1490506109c5565b826001600160401b0316600203610949576002610917565b826001600160401b0316600303610961576000610917565b826001600160401b0316600403610979576002610917565b826001600160401b0316600503610991576000610917565b826001600160401b03166006036109a9576002610917565b826001600160401b03166007036109c1576002610917565b5060005b92915050565b600080866001600160401b038516600103610a0e5760006109ed828987610d88565b9250905080610a025750600092509050610ac9565b50600192509050610ac9565b846001600160401b0316600203610a2c5760006109ed828987610e15565b846001600160401b0316600303610a4a5760006109ed828987610f5e565b846001600160401b0316600403610a685760006109ed828987611017565b846001600160401b0316600503610a865760006109ed828987611146565b846001600160401b0316600603610aa45760006109ed8289876111f0565b846001600160401b0316600703610ac25760006109ed82898761131f565b6000925090505b9550959350505050565b60606807fffffffffffffff8600384901b1682176000610af28261144e565b95945050505050565b60606109c58260030b61144e565b60606109c58261144e565b60606109c58263ffffffff1661144e565b610b4960405180606001604052806060815260200160608152602001606081525090565b6000610b54836115a8565b805190915060006001600160401b038216610b7d57604080516000815260208101909152610b88565b610b88866002610ad3565b9050600080836001600160401b031611610bb057604080516000815260208101909152610bb9565b610bb983610b09565b60408051606081018252938452602084019190915282019390935295945050505050565b60008060008060005b600a6001600160401b0382161015610cd3578551610c048883615257565b6001600160401b031610610c245760008760009450945094505050610d81565b600086610c31838a615257565b6001600160401b031681518110610c4a57610c4a6153a2565b016020015160f81c9050607f8116610c638360076153b8565b60ff82166001600160401b03919091161b939093179260808216600003610cbe576000836001600160401b0316118015610c9e575060ff8116155b15610cb757600089600096509650965050505050610d81565b5050610cd3565b50508080610ccb906153e3565b915050610be6565b600a6001600160401b03821610610cf65760008760009450945094505050610d81565b610d026001600a61527e565b6001600160401b0316816001600160401b031603610d6057600186610d27838a615257565b6001600160401b031681518110610d4057610d406153a2565b016020015160f81c1115610d605760008760009450945094505050610d81565b6001610d6c8289615257565b610d77906001615257565b8394509450945050505b9250925092565b600080600080610d98878761172b565b909850909250905081610db357600087935093505050610e0d565b806001600160401b0316600003610dd257600087935093505050610e0d565b610dda6147cd565b610de5888884611747565b909950909350905082610e015760008894509450505050610e0d565b85525060019250859150505b935093915050565b600080600080610e25878761172b565b909850909250905081610e4057600087935093505050610e0d565b806001600160401b0316600003610e5f57600087935093505050610e0d565b806001600160401b03166001600160401b03811115610e8057610e806149ae565b6040519080825280601f01601f191660200182016040528015610eaa576020820181803683370190505b50602086015260005b816001600160401b0316816001600160401b03161015610f445786610ed8828a615257565b6001600160401b031681518110610ef157610ef16153a2565b602001015160f81c60f81b8660200151826001600160401b031681518110610f1b57610f1b6153a2565b60200101906001600160f81b031916908160001a90535080610f3c816153e3565b915050610eb3565b50610f4f8188615257565b60019890975095505050505050565b600080600080610f6e8787611892565b909850909250905081610f8957600087935093505050610e0d565b8060030b600003610fa257600087935093505050610e0d565b60008160030b1280610fb7575060018160030b135b15610fca57600087935093505050610e0d565b8060030b6001811115610fdf57610fdf614a9a565b85604001906001811115610ff557610ff5614a9a565b9081600181111561100857611008614a9a565b90525060019795505050505050565b600080600080611027878761172b565b90985090925090508161104257600087935093505050610e0d565b806001600160401b031660000361106157600087935093505050610e0d565b806001600160401b03166001600160401b03811115611082576110826149ae565b6040519080825280601f01601f1916602001820160405280156110ac576020820181803683370190505b50606086015260005b816001600160401b0316816001600160401b03161015610f4457866110da828a615257565b6001600160401b0316815181106110f3576110f36153a2565b602001015160f81c60f81b8660600151826001600160401b03168151811061111d5761111d6153a2565b60200101906001600160f81b031916908160001a9053508061113e816153e3565b9150506110b5565b6000806000806111568787611892565b90985090925090508161117157600087935093505050610e0d565b8060030b60000361118a57600087935093505050610e0d565b60008160030b128061119f575060028160030b135b156111b257600087935093505050610e0d565b8060030b60028111156111c7576111c7614a9a565b856080019060028111156111dd576111dd614a9a565b9081600281111561100857611008614a9a565b600080600080611200878761172b565b90985090925090508161121b57600087935093505050610e0d565b806001600160401b031660000361123a57600087935093505050610e0d565b806001600160401b03166001600160401b0381111561125b5761125b6149ae565b6040519080825280601f01601f191660200182016040528015611285576020820181803683370190505b5060a086015260005b816001600160401b0316816001600160401b03161015610f4457866112b3828a615257565b6001600160401b0316815181106112cc576112cc6153a2565b602001015160f81c60f81b8660a00151826001600160401b0316815181106112f6576112f66153a2565b60200101906001600160f81b031916908160001a90535080611317816153e3565b91505061128e565b60008060008061132f878761172b565b90985090925090508161134a57600087935093505050610e0d565b806001600160401b031660000361136957600087935093505050610e0d565b806001600160401b03166001600160401b0381111561138a5761138a6149ae565b6040519080825280601f01601f1916602001820160405280156113b4576020820181803683370190505b5060c086015260005b816001600160401b0316816001600160401b03161015610f4457866113e2828a615257565b6001600160401b0316815181106113fb576113fb6153a2565b602001015160f81c60f81b8660c00151826001600160401b031681518110611425576114256153a2565b60200101906001600160f81b031916908160001a90535080611446816153e3565b9150506113bd565b60608160015b607f826001600160401b0316111561148a576007826001600160401b0316901c91506001816114839190615257565b9050611454565b6000816001600160401b03166001600160401b038111156114ad576114ad6149ae565b6040519080825280601f01601f1916602001820160405280156114d7576020820181803683370190505b50905084925060005b826001600160401b0316816001600160401b031610156115595783607f1660801760f81b82826001600160401b03168151811061151f5761151f6153a2565b60200101906001600160f81b031916908160001a9053506007846001600160401b0316901c93508080611551906153e3565b9150506114e0565b50607f60f81b8161156b60018561527e565b6001600160401b031681518110611584576115846153a2565b0160200180519091166001600160f81b03191690600082901a905350949350505050565b6060600080836000015151116115cc576040805160008152602081019091526115d8565b6115d860016002610ad3565b9050600080846000015151116115fc57604080516000815260208101909152611608565b83515161160890610b09565b90506000808560000151511161162c5760408051600081526020810190915261162f565b84515b90506000856020015163ffffffff166001600160401b03166000036116625760408051600081526020810190915261166e565b61166e60026000610ad3565b90506000866020015163ffffffff166001600160401b03166000036116a1576040805160008152602081019091526116ae565b6116ae8760200151610b14565b905060006116c1600389604001516118a1565b805160208083015160408085015190519495506000946116e294930161529e565b604051602081830303815290604052905086868686868560405160200161170e96959493929190615409565b604051602081830303815290604052975050505050505050919050565b600080600061173a85856118d0565b9250925092509250925092565b6000806117526147cd565b61175a6147cd565b6000876001600160401b0381166117718883615257565b6001600160401b03161015611790576000955093509091506105489050565b6001600160401b0387166117a48a8361527e565b6001600160401b0316101561050b5760008060006117c2848c61080f565b9196509194509092509050826117e657506000975091955092935061054892505050565b6010826001600160401b0316111561180c57506000975091955092935061054892505050565b846001600160401b0316826001600160401b03161161183957506000975091955092935061054892505050565b6118438282611967565b92508261185e57506000975091955092935061054892505050565b61186b848c8c858a611ae9565b945092508261188857506000975091955092935061054892505050565b5092506117909050565b600080600061173a8585611ccd565b6118c560405180606001604052806060815260200160608152602001606081525090565b6000610b5483611d2c565b6000806000806000806118e38888610bdd565b925092509250826118ff5750600094509250839150610d819050565b816001600160401b03168183016001600160401b0316101561192c5750600094509250839150610d819050565b86516119388383615257565b6001600160401b031611156119585750600094509250839150610d819050565b60019891975095509350505050565b6000826001600160401b0316600103611981576000610917565b826001600160401b0316600203611999576000610917565b826001600160401b03166003036119b1576000610917565b826001600160401b03166004036119c9576000610917565b826001600160401b03166005036119e1576002610917565b826001600160401b03166006036119f9576000610917565b826001600160401b0316600703611a11576002610917565b826001600160401b0316600803611a29576000610917565b826001600160401b0316600903611a41576002610917565b826001600160401b0316600a03611a59576000610917565b826001600160401b0316600b03611a71576000610917565b826001600160401b0316600c03611a89576000610917565b826001600160401b0316600d03611aa1576000610917565b826001600160401b0316600e03611ab9576002610917565b826001600160401b0316600f03611ad1576000610917565b826001600160401b03166010036109c1576002610917565b600080866001600160401b038516600103611b0b5760006109ed828987611e5e565b846001600160401b0316600203611b295760006109ed828987611f05565b846001600160401b0316600303611b475760006109ed828987611f6c565b846001600160401b0316600403611b655760006109ed828987611fcd565b846001600160401b0316600503611b835760006109ed828987612077565b846001600160401b0316600603611ba15760006109ed828987612105565b846001600160401b0316600703611bbf5760006109ed82898761215e565b846001600160401b0316600803611bdd5760006109ed8289876121ec565b846001600160401b0316600903611bfb5760006109ed828987612245565b846001600160401b0316600a03611c195760006109ed8289876122d4565b846001600160401b0316600b03611c375760006109ed82898761232e565b846001600160401b0316600c03611c555760006109ed828987612388565b846001600160401b0316600d03611c735760006109ed8289876123e2565b846001600160401b0316600e03611c915760006109ed82898761243c565b846001600160401b0316600f03611caf5760006109ed8289876124e0565b846001600160401b0316601003610ac25760006109ed82898761253a565b600080600080600080611ce08888610bdd565b92509250925082611cfc5750600094509250839150610d819050565b6001603f82901c166000036119585767ffffffff000000008116156119585750600094509250839150610d819050565b6060600082600001516001600160401b0316600003611d5957604080516000815260208101909152611d65565b611d6560016000610ad3565b9050600083600001516001600160401b0316600003611d9257604080516000815260208101909152611d9d565b8351611d9d90610b09565b905060008085602001515111611dc157604080516000815260208101909152611dcc565b611dcc600280610ad3565b905060008086602001515111611df057604080516000815260208101909152611dfe565b611dfe866020015151610b09565b905060008087602001515111611e2257604080516000815260208101909152611e28565b86602001515b90508484848484604051602001611e43959493929190615488565b60405160208183030381529060405295505050505050919050565b600080600080611e6e8787611892565b909850909250905081611e8957600087935093505050610e0d565b8060030b600003611ea257600087935093505050610e0d565b60008160030b1280611eb75750600d8160030b135b15611eca57600087935093505050610e0d565b8060030b600d811115611edf57611edf614a9a565b8590600d811115611ef257611ef2614a9a565b9081600d81111561100857611008614a9a565b600080600080611f1587876125c9565b909850909250905081611f3057600087935093505050610e0d565b806001600160401b0316600003611f4f57600087935093505050610e0d565b6001600160401b0316602094909401939093525060019492505050565b600080600080611f7c87876125f8565b909850909250905081611f9757600087935093505050610e0d565b8063ffffffff16600003611fb357600087935093505050610e0d565b63ffffffff16604094909401939093525060019492505050565b600080600080611fdd8787611892565b909850909250905081611ff857600087935093505050610e0d565b8060030b60000361201157600087935093505050610e0d565b60008160030b1280612026575060038160030b135b1561203957600087935093505050610e0d565b8060030b600381111561204e5761204e614a9a565b8560600190600381111561206457612064614a9a565b9081600381111561100857611008614a9a565b600080600080612087878761172b565b9098509092509050816120a257600087935093505050610e0d565b806001600160401b03166000036120c157600087935093505050610e0d565b6120c9614883565b6120d4888884612648565b9099509093509050826120f05760008894509450505050610e0d565b60809590950194909452506001959350505050565b6000806000806121158787612793565b90985090925090508161213057600087935093505050610e0d565b80151560000361214857600087935093505050610e0d565b151560a094909401939093525060019492505050565b60008060008061216e878761172b565b90985090925090508161218957600087935093505050610e0d565b806001600160401b03166000036121a857600087935093505050610e0d565b6121b06148d9565b6121bb888884612819565b9099509093509050826121d75760008894509450505050610e0d565b60c09590950194909452506001959350505050565b6000806000806121fc8787612793565b90985090925090508161221757600087935093505050610e0d565b80151560000361222f57600087935093505050610e0d565b151560e094909401939093525060019492505050565b600080600080612255878761172b565b90985090925090508161227057600087935093505050610e0d565b806001600160401b031660000361228f57600087935093505050610e0d565b612297614914565b6122a2888884612964565b9099509093509050826122be5760008894509450505050610e0d565b6101009590950194909452506001959350505050565b6000806000806122e48787612793565b9098509092509050816122ff57600087935093505050610e0d565b80151560000361231757600087935093505050610e0d565b151561012094909401939093525060019492505050565b60008060008061233e8787612793565b90985090925090508161235957600087935093505050610e0d565b80151560000361237157600087935093505050610e0d565b151561014094909401939093525060019492505050565b6000806000806123988787612793565b9098509092509050816123b357600087935093505050610e0d565b8015156000036123cb57600087935093505050610e0d565b151561016094909401939093525060019492505050565b6000806000806123f28787612793565b90985090925090508161240d57600087935093505050610e0d565b80151560000361242557600087935093505050610e0d565b151561018094909401939093525060019492505050565b60008060008061244c878761172b565b90985090925090508161246757600087935093505050610e0d565b806001600160401b031660000361248657600087935093505050610e0d565b60408051606080820183528152600060208201819052918101919091526124ae888884612aaf565b9099509093509050826124ca5760008894509450505050610e0d565b6101a09590950194909452506001959350505050565b6000806000806124f08787612793565b90985090925090508161250b57600087935093505050610e0d565b80151560000361252357600087935093505050610e0d565b15156101c094909401939093525060019492505050565b60008060008061254a878761172b565b90985090925090508161256557600087935093505050610e0d565b806001600160401b031660000361258457600087935093505050610e0d565b61258c61494f565b612597888884612c1c565b9099509093509050826125b35760008894509450505050610e0d565b6101e09590950194909452506001959350505050565b6000806000806000806125dc8888610bdd565b925092509250826119585750600094509250839150610d819050565b60008060008060008061260b8888610bdd565b925092509250826126275750600094509250839150610d819050565b67ffffffff000000008116156119585750600094509250839150610d819050565b600080612653614883565b61265b614883565b6000876001600160401b0381166126728883615257565b6001600160401b03161015612691576000955093509091506105489050565b6001600160401b0387166126a58a8361527e565b6001600160401b0316101561050b5760008060006126c3848c61080f565b9196509194509092509050826126e757506000975091955092935061054892505050565b6007826001600160401b0316111561270d57506000975091955092935061054892505050565b846001600160401b0316826001600160401b03161161273a57506000975091955092935061054892505050565b6127448282612d67565b92508261275f57506000975091955092935061054892505050565b61276c848c8c858a612de1565b945092508261278957506000975091955092935061054892505050565b5092506126919050565b6000806000806000806127a68888610bdd565b925092509250826127c25750600094509250839150610d819050565b6001816001600160401b031611156127e55750600094509250839150610d819050565b806001600160401b0316600003612808575060019450925060009150610d819050565b506001979096508795509350505050565b6000806128246148d9565b61282c6148d9565b6000876001600160401b0381166128438883615257565b6001600160401b03161015612862576000955093509091506105489050565b6001600160401b0387166128768a8361527e565b6001600160401b0316101561050b576000806000612894848c61080f565b9196509194509092509050826128b857506000975091955092935061054892505050565b6003826001600160401b031611156128de57506000975091955092935061054892505050565b846001600160401b0316826001600160401b03161161290b57506000975091955092935061054892505050565b6129158282612eb7565b92508261293057506000975091955092935061054892505050565b61293d848c8c858a612f01565b945092508261295a57506000975091955092935061054892505050565b5092506128629050565b60008061296f614914565b612977614914565b6000876001600160401b03811661298e8883615257565b6001600160401b031610156129ad576000955093509091506105489050565b6001600160401b0387166129c18a8361527e565b6001600160401b0316101561050b5760008060006129df848c61080f565b919650919450909250905082612a0357506000975091955092935061054892505050565b6005826001600160401b03161115612a2957506000975091955092935061054892505050565b846001600160401b0316826001600160401b031611612a5657506000975091955092935061054892505050565b612a608282612f5f565b925082612a7b57506000975091955092935061054892505050565b612a88848c8c858a612fd9565b9450925082612aa557506000975091955092935061054892505050565b5092506129ad9050565b60408051606080820183528082526000602080840182905283850182905284518084018652928352820181905292810183905282919082876001600160401b038116612afb8883615257565b6001600160401b03161015612b1a576000955093509091506105489050565b6001600160401b038716612b2e8a8361527e565b6001600160401b0316101561050b576000806000612b4c848c61080f565b919650919450909250905082612b7057506000975091955092935061054892505050565b6003826001600160401b03161115612b9657506000975091955092935061054892505050565b846001600160401b0316826001600160401b031611612bc357506000975091955092935061054892505050565b612bcd8282613073565b925082612be857506000975091955092935061054892505050565b612bf5848c8c858a6130bd565b9450925082612c1257506000975091955092935061054892505050565b509250612b1a9050565b600080612c2761494f565b612c2f61494f565b6000876001600160401b038116612c468883615257565b6001600160401b03161015612c65576000955093509091506105489050565b6001600160401b038716612c798a8361527e565b6001600160401b0316101561050b576000806000612c97848c61080f565b919650919450909250905082612cbb57506000975091955092935061054892505050565b6003826001600160401b03161115612ce157506000975091955092935061054892505050565b846001600160401b0316826001600160401b031611612d0e57506000975091955092935061054892505050565b612d18828261311b565b925082612d3357506000975091955092935061054892505050565b612d40848c8c858a61314d565b9450925082612d5d57506000975091955092935061054892505050565b509250612c659050565b6000826001600160401b0316600103612d81576002610917565b826001600160401b0316600203612d99576002610917565b826001600160401b0316600303612db1576002610917565b826001600160401b0316600403612dc9576002610917565b826001600160401b0316600503610991576002610917565b600080866001600160401b038516600103612e035760006109ed8289876131ab565b846001600160401b0316600203612e215760006109ed8289876131fb565b846001600160401b0316600303612e3f5760006109ed828987613404565b846001600160401b0316600403612e5d5760006109ed82898761349f565b846001600160401b0316600503612e7b5760006109ed8289876134f6565b846001600160401b0316600603612e995760006109ed8289876136bb565b846001600160401b0316600703610ac25760006109ed82898761391e565b6000826001600160401b0316600103612ed1576000610917565b826001600160401b0316600203612ee9576002610917565b826001600160401b03166003036109c1576002610917565b600080866001600160401b038516600103612f235760006109ed828987613975565b846001600160401b0316600203612f415760006109ed828987613a09565b846001600160401b0316600303610ac25760006109ed828987613aa4565b6000826001600160401b0316600103612f79576002610917565b826001600160401b0316600203612f91576002610917565b826001600160401b0316600303612fa9576002610917565b826001600160401b0316600403612fc1576000610917565b826001600160401b03166005036109c1576000610917565b600080866001600160401b038516600103612ffb5760006109ed828987613afb565b846001600160401b03166002036130195760006109ed828987613c27565b846001600160401b03166003036130375760006109ed828987613d56565b846001600160401b03166004036130555760006109ed828987613e85565b846001600160401b0316600503610ac25760006109ed828987613ee6565b6000826001600160401b031660010361308d576002610917565b826001600160401b03166002036130a5576000610917565b826001600160401b03166003036109c1576000610917565b600080866001600160401b0385166001036130df5760006109ed8289876131ab565b846001600160401b03166002036130fd5760006109ed828987613f47565b846001600160401b0316600303610ac25760006109ed828987613fa8565b6000826001600160401b0316600103613135576002610917565b826001600160401b0316600203612ee9576000610917565b600080866001600160401b03851660010361316f5760006109ed82898761400f565b846001600160401b031660020361318d5760006109ed828987613f47565b846001600160401b0316600303610ac25760006109ed828987613404565b600080600060606131bc878761413b565b9098509092509050816131d757600087935093505050610e0d565b80516000036131ee57600087935093505050610e0d565b9093525060019492505050565b60008060008061320b87876118d0565b90985090925090508161322657600087935093505050610e0d565b806001600160401b031660000361324557600087935093505050610e0d565b866001600160401b03811661325a8383615257565b6001600160401b031610156132785760008894509450505050610e0d565b60005b6001600160401b03831661328f838b61527e565b6001600160401b031610156132db5760006132aa8a8a6125c9565b909b509095509050846132c85760008a965096505050505050610e0d565b6132d3600183615257565b91505061327b565b806001600160401b03166001600160401b038111156132fc576132fc6149ae565b604051908082528060200260200182016040528015613325578160200160208202803683370190505b506020880152909750879060005b816001600160401b0316816001600160401b031610156133c35760006133598b8b6125c9565b909c509096509050856133785760008b97509750505050505050610e0d565b808960200151836001600160401b031681518110613398576133986153a2565b6001600160401b039092166020928302919091019091015250806133bb816153e3565b915050613333565b506133ce8383615257565b6001600160401b0316896001600160401b0316146133f6576000899550955050505050610e0d565b506001989650505050505050565b600080600080613414878761172b565b90985090925090508161342f57600087935093505050610e0d565b806001600160401b031660000361344e57600087935093505050610e0d565b60408051808201909152600081526060602082015261346e888884614279565b90995090935090508261348a5760008894509450505050610e0d565b60409590950194909452506001959350505050565b600080600060606134b0878761413b565b9098509092509050816134cb57600087935093505050610e0d565b80516000036134e257600087935093505050610e0d565b606094909401939093525060019492505050565b60008060008061350687876118d0565b90985090925090508161352157600087935093505050610e0d565b806001600160401b031660000361354057600087935093505050610e0d565b866001600160401b0381166135558383615257565b6001600160401b031610156135735760008894509450505050610e0d565b60005b6001600160401b03831661358a838b61527e565b6001600160401b031610156135d65760006135a58a8a6125f8565b909b509095509050846135c35760008a965096505050505050610e0d565b6135ce600183615257565b915050613576565b806001600160401b03166001600160401b038111156135f7576135f76149ae565b604051908082528060200260200182016040528015613620578160200160208202803683370190505b506080880152909750879060005b816001600160401b0316816001600160401b031610156133c35760006136548b8b6125f8565b909c509096509050856136735760008b97509750505050505050610e0d565b808960800151836001600160401b031681518110613693576136936153a2565b63ffffffff9092166020928302919091019091015250806136b3816153e3565b91505061362e565b6000808085815b8651886001600160401b031610156137b05760006136e0898961172b565b909a509094509050836136fd576000899550955050505050610e0d565b6001600160401b038916613711828b615257565b6001600160401b03161015613730576000899550955050505050610e0d565b61373a818a615257565b9850613747600183615257565b91508751896001600160401b03161061376057506137b0565b60008061376d8b8b61080f565b919d5091975090925090508561378f5760008b97509750505050505050610e0d565b816001600160401b03166006146137a8575050506137b0565b5050506136c2565b806001600160401b03166001600160401b038111156137d1576137d16149ae565b60405190808252806020026020018201604052801561380a57816020015b6137f7614981565b8152602001906001900390816137ef5790505b5060a0870152909650869060005b816001600160401b0316816001600160401b031610156133f657600061383e8a8a61172b565b909b5090955090508461385c5760008a965096505050505050610e0d565b899350613867614981565b6138728b8b846143e4565b909c509096509050856138915760008b97509750505050505050610e0d565b808960a00151846001600160401b0316815181106138b1576138b16153a2565b60209081029190910101526138c760018561527e565b6001600160401b0316836001600160401b03161015613909576138ea8b8b6125c9565b909c509096509150856139095760008b97509750505050505050610e0d565b50508080613916906153e3565b915050613818565b6000806000606061392f878761413b565b90985090925090508161394a57600087935093505050610e0d565b805160000361396157600087935093505050610e0d565b60c094909401939093525060019492505050565b6000806000806139858787611892565b9098509092509050816139a057600087935093505050610e0d565b8060030b6000036139b957600087935093505050610e0d565b60008160030b12806139ce575060028160030b135b156139e157600087935093505050610e0d565b8060030b60028111156139f6576139f6614a9a565b859060028111156111dd576111dd614a9a565b600080600080613a19878761172b565b909850909250905081613a3457600087935093505050610e0d565b806001600160401b0316600003613a5357600087935093505050610e0d565b604080518082019091526000815260606020820152613a73888884614279565b909950909350905082613a8f5760008894509450505050610e0d565b60209590950194909452506001959350505050565b60008060006060613ab5878761413b565b909850909250905081613ad057600087935093505050610e0d565b8051600003613ae757600087935093505050610e0d565b604094909401939093525060019492505050565b600080600080613b0b878761172b565b909850909250905081613b2657600087935093505050610e0d565b806001600160401b0316600003613b4557600087935093505050610e0d565b806001600160401b03166001600160401b03811115613b6657613b666149ae565b6040519080825280601f01601f191660200182016040528015613b90576020820181803683370190505b50855260005b816001600160401b0316816001600160401b03161015610f445786613bbb828a615257565b6001600160401b031681518110613bd457613bd46153a2565b602001015160f81c60f81b8660000151826001600160401b031681518110613bfe57613bfe6153a2565b60200101906001600160f81b031916908160001a90535080613c1f816153e3565b915050613b96565b600080600080613c37878761172b565b909850909250905081613c5257600087935093505050610e0d565b806001600160401b0316600003613c7157600087935093505050610e0d565b806001600160401b03166001600160401b03811115613c9257613c926149ae565b6040519080825280601f01601f191660200182016040528015613cbc576020820181803683370190505b50602086015260005b816001600160401b0316816001600160401b03161015610f445786613cea828a615257565b6001600160401b031681518110613d0357613d036153a2565b602001015160f81c60f81b8660200151826001600160401b031681518110613d2d57613d2d6153a2565b60200101906001600160f81b031916908160001a90535080613d4e816153e3565b915050613cc5565b600080600080613d66878761172b565b909850909250905081613d8157600087935093505050610e0d565b806001600160401b0316600003613da057600087935093505050610e0d565b806001600160401b03166001600160401b03811115613dc157613dc16149ae565b6040519080825280601f01601f191660200182016040528015613deb576020820181803683370190505b50604086015260005b816001600160401b0316816001600160401b03161015610f445786613e19828a615257565b6001600160401b031681518110613e3257613e326153a2565b602001015160f81c60f81b8660400151826001600160401b031681518110613e5c57613e5c6153a2565b60200101906001600160f81b031916908160001a90535080613e7d816153e3565b915050613df4565b600080600080613e9587876125f8565b909850909250905081613eb057600087935093505050610e0d565b8063ffffffff16600003613ecc57600087935093505050610e0d565b63ffffffff16606094909401939093525060019492505050565b600080600080613ef687876125f8565b909850909250905081613f1157600087935093505050610e0d565b8063ffffffff16600003613f2d57600087935093505050610e0d565b63ffffffff16608094909401939093525060019492505050565b600080600080613f5787876125f8565b909850909250905081613f7257600087935093505050610e0d565b8063ffffffff16600003613f8e57600087935093505050610e0d565b63ffffffff16602094909401939093525060019492505050565b600080600080613fb887876125c9565b909850909250905081613fd357600087935093505050610e0d565b806001600160401b0316600003613ff257600087935093505050610e0d565b6001600160401b0316604094909401939093525060019492505050565b60008060008061401f878761172b565b90985090925090508161403a57600087935093505050610e0d565b806001600160401b031660000361405957600087935093505050610e0d565b806001600160401b03166001600160401b0381111561407a5761407a6149ae565b6040519080825280601f01601f1916602001820160405280156140a4576020820181803683370190505b50855260005b816001600160401b0316816001600160401b03161015610f4457866140cf828a615257565b6001600160401b0316815181106140e8576140e86153a2565b602001015160f81c60f81b8660000151826001600160401b031681518110614112576141126153a2565b60200101906001600160f81b031916908160001a90535080614133816153e3565b9150506140aa565b6000806060600080600061414f88886118d0565b9250925092508261417b5760008260405180602001604052806000815250955095509550505050610d81565b6000816001600160401b03166001600160401b0381111561419e5761419e6149ae565b6040519080825280601f01601f1916602001820160405280156141c8576020820181803683370190505b50905060005b826001600160401b0316816001600160401b0316101561425b57886141f38286615257565b6001600160401b03168151811061420c5761420c6153a2565b602001015160f81c60f81b82826001600160401b031681518110614232576142326153a2565b60200101906001600160f81b031916908160001a90535080614253816153e3565b9150506141ce565b5060016142688385615257565b909750955093505050509250925092565b60008061429760408051808201909152600081526060602082015290565b6040805180820190915260008152606060208201526000876001600160401b0381166142c38883615257565b6001600160401b031610156142e2576000955093509091506105489050565b6001600160401b0387166142f68a8361527e565b6001600160401b0316101561050b576000806000614314848c61080f565b91965091945090925090508261433857506000975091955092935061054892505050565b6002826001600160401b0316111561435e57506000975091955092935061054892505050565b846001600160401b0316826001600160401b03161161438b57506000975091955092935061054892505050565b614395828261452f565b9250826143b057506000975091955092935061054892505050565b6143bd848c8c858a614561565b94509250826143da57506000975091955092935061054892505050565b5092506142e29050565b6000806143ef614981565b6143f7614981565b6000876001600160401b03811661440e8883615257565b6001600160401b0316101561442d576000955093509091506105489050565b6001600160401b0387166144418a8361527e565b6001600160401b0316101561050b57600080600061445f848c61080f565b91965091945090925090508261448357506000975091955092935061054892505050565b6002826001600160401b031611156144a957506000975091955092935061054892505050565b846001600160401b0316826001600160401b0316116144d657506000975091955092935061054892505050565b6144e082826145a1565b9250826144fb57506000975091955092935061054892505050565b614508848c8c858a6145bb565b945092508261452557506000975091955092935061054892505050565b50925061442d9050565b6000826001600160401b0316600103614549576000610917565b826001600160401b03166002036109c1576002610917565b600080866001600160401b0385166001036145835760006109ed8289876145fb565b846001600160401b0316600203610ac25760006109ed82898761465b565b6000826001600160401b0316600103614549576002610917565b600080866001600160401b0385166001036145dd5760006109ed8289876131ab565b846001600160401b0316600203610ac25760006109ed828987613a09565b60008060008061460b87876125c9565b90985090925090508161462657600087935093505050610e0d565b806001600160401b031660000361464557600087935093505050610e0d565b6001600160401b03169093525060019492505050565b60008060008061466b878761172b565b90985090925090508161468657600087935093505050610e0d565b806001600160401b03166000036146a557600087935093505050610e0d565b806001600160401b03166001600160401b038111156146c6576146c66149ae565b6040519080825280601f01601f1916602001820160405280156146f0576020820181803683370190505b50602086015260005b816001600160401b0316816001600160401b03161015610f44578661471e828a615257565b6001600160401b031681518110614737576147376153a2565b602001015160f81c60f81b8660200151826001600160401b031681518110614761576147616153a2565b60200101906001600160f81b031916908160001a90535080614782816153e3565b9150506146f9565b6040518060e0016040528061479d6147cd565b81526060602082015260400160008152606060208201526040016000815260200160608152602001606081525090565b60408051610200810182526000808252602082018190529181018290526060810191909152608081016147fe614883565b8152600060208201526040016148126148d9565b815260006020820152604001614826614914565b81526000602082018190526040820181905260608201819052608082015260a00161486a604080516060808201835281526000602082018190529181019190915290565b81526000602082015260400161487e61494f565b905290565b6040518060e0016040528060608152602001606081526020016148b760408051808201909152600081526060602082015290565b8152602001606081526020016060815260200160608152602001606081525090565b6040805160608101909152806000815260200161490760408051808201909152600081526060602082015290565b8152602001606081525090565b6040518060a00160405280606081526020016060815260200160608152602001600063ffffffff168152602001600063ffffffff1681525090565b604080516060808201835281526000602082015290810161487e60408051808201909152600081526060602082015290565b60405180604001604052806060815260200161487e60408051808201909152600081526060602082015290565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156149ec576149ec6149ae565b604052919050565b60006001600160401b03821115614a0d57614a0d6149ae565b50601f01601f191660200190565b600060208284031215614a2d57600080fd5b81356001600160401b03811115614a4357600080fd5b8201601f81018413614a5457600080fd5b8035614a67614a62826149f4565b6149c4565b818152856020838501011115614a7c57600080fd5b81602084016020830137600091810160200191909152949350505050565b634e487b7160e01b600052602160045260246000fd5b600e8110614ac057614ac0614a9a565b9052565b60048110614ac057614ac0614a9a565b60005b83811015614aef578181015183820152602001614ad7565b50506000910152565b60008151808452614b10816020860160208601614ad4565b601f01601f19169290920160200192915050565b600081518084526020808501945080840160005b83811015614b5d5781516001600160401b031687529582019590820190600101614b38565b509495945050505050565b6001600160401b0381511682526000602082015160406020850152614b906040850182614af8565b949350505050565b600081518084526020808501945080840160005b83811015614b5d57815163ffffffff1687529582019590820190600101614bac565b600081518084526020808501808196508360051b8101915082860160005b85811015614c3c578284038952815160408151818752614c0e82880182614af8565b91505086820151915085810387870152614c288183614b68565b9a87019a9550505090840190600101614bec565b5091979650505050505050565b6000815160e08452614c5e60e0850182614af8565b905060208301518482036020860152614c778282614b24565b91505060408301518482036040860152614c918282614b68565b91505060608301518482036060860152614cab8282614af8565b91505060808301518482036080860152614cc58282614b98565b91505060a083015184820360a0860152614cdf8282614bce565b91505060c083015184820360c0860152610af28282614af8565b60038110614d0957614d09614a9a565b50565b60008151614d1981614cf9565b80845250602082015160606020850152614d366060850182614b68565b905060408301518482036040860152610af28282614af8565b6000815160a08452614d6460a0850182614af8565b905060208301518482036020860152614d7d8282614af8565b91505060408301518482036040860152614d978282614af8565b915050606083015163ffffffff808216606087015280608086015116608087015250508091505092915050565b6000815160608452614dd96060850182614af8565b905063ffffffff60208401511660208501526001600160401b0360408401511660408501528091505092915050565b6000815160608452614e1d6060850182614af8565b905063ffffffff602084015116602085015260408301518482036040860152610af28282614b68565b60028110614ac057614ac0614a9a565b614ac081614cf9565b602081526000825160e06020840152614e7d61010084018251614ab0565b6020810151610120614e99818601836001600160401b03169052565b60408301519150610140614eb48187018463ffffffff169052565b60608401519250610160614eca81880185614ac4565b6080850151935061020061018081818a0152614eea6103008a0187614c49565b955060a08701516101a0614f01818c018315159052565b60c0890151915060ff196101c0818d8b0301818e0152614f218a85614d0c565b995060e08b015193506101e0614f3a818f018615159052565b6101008c01519450828e8c0301878f0152614f558b86614d4f565b998c0151999a50614f6b6102208f018b15159052565b888c01519950614f806102408f018b15159052565b878c01519950614f956102608f018b15159052565b858c01519950614faa6102808f018b15159052565b838c01519950828e8c03016102a08f0152614fc58b8b614dc4565b9a50818c01519950614fdc6102c08f018b15159052565b808c01519b505050808c8a03016102e08d015250505050505050506150018183614e08565b9150506020840151601f19808584030160408601526150208383614af8565b9250604086015191506150366060860183614e46565b60608601519150808584030160808601526150518383614af8565b92506080860151915061506760a0860183614e56565b60a08601519150808584030160c08601526150828383614af8565b925060c08601519150808584030160e086015250610af28282614af8565b6040815260006150b36040830185614af8565b905063ffffffff831660208301529392505050565b6000602082840312156150da57600080fd5b81516001600160401b038111156150f057600080fd5b8201601f8101841361510157600080fd5b805161510f614a62826149f4565b81815285602083850101111561512457600080fd5b610af2826020830160208601614ad4565b80516020808301519190811015615156576000198160200360031b1b821691505b50919050565b8481528360208201528260408201526080606082015260006151816080830184614af8565b9695505050505050565b60006020828403121561519d57600080fd5b815180151581146151ad57600080fd5b9392505050565b6001600160401b0383168152604060208201526000614b906040830184614af8565b6000604082840312156151e857600080fd5b604051604081018181106001600160401b038211171561520a5761520a6149ae565b60405282516003811061521c57600080fd5b8152602083015163ffffffff8116811461523557600080fd5b60208201529392505050565b634e487b7160e01b600052601160045260246000fd5b6001600160401b0381811683821601908082111561527757615277615241565b5092915050565b6001600160401b0382811682821603908082111561527757615277615241565b600084516152b0818460208901614ad4565b8451908301906152c4818360208901614ad4565b84519101906152d7818360208801614ad4565b0195945050505050565b60008a516152f3818460208f01614ad4565b8a516153058183860160208f01614ad4565b8a51918401019061531a818360208e01614ad4565b895161532c8183850160208e01614ad4565b8951929091010190615342818360208c01614ad4565b87516153548183850160208c01614ad4565b875192909101019061536a818360208a01614ad4565b855161537c8183850160208a01614ad4565b8551929091010190615392818360208801614ad4565b019b9a5050505050505050505050565b634e487b7160e01b600052603260045260246000fd5b6001600160401b038181168382160280821691908281146153db576153db615241565b505092915050565b60006001600160401b038083168181036153ff576153ff615241565b6001019392505050565b60008751602061541c8285838d01614ad4565b88519184019161542f8184848d01614ad4565b88519201916154418184848c01614ad4565b87519201916154538184848b01614ad4565b86519201916154658184848a01614ad4565b85519201916154778184848901614ad4565b919091019998505050505050505050565b6000865161549a818460208b01614ad4565b8651908301906154ae818360208b01614ad4565b86519101906154c1818360208a01614ad4565b85519101906154d4818360208901614ad4565b84519101906154e7818360208801614ad4565b0197965050505050505056fea26469706673582212204cb1bddfd4e08baedc3556521923f5dd4dff2d8852ddacbeb2aa1d8298f468e164736f6c63430008150033

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.