{
  "language": "Solidity",
  "sources": {
    "@openzeppelin/contracts/interfaces/draft-IERC6093.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.5.0) (interfaces/draft-IERC6093.sol)\n\npragma solidity >=0.8.4;\n\n/**\n * @dev Standard ERC-20 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.\n */\ninterface IERC20Errors {\n    /**\n     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     * @param balance Current balance for the interacting account.\n     * @param needed Minimum amount required to perform a transfer.\n     */\n    error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);\n\n    /**\n     * @dev Indicates a failure with the token `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     */\n    error ERC20InvalidSender(address sender);\n\n    /**\n     * @dev Indicates a failure with the token `receiver`. Used in transfers.\n     * @param receiver Address to which tokens are being transferred.\n     */\n    error ERC20InvalidReceiver(address receiver);\n\n    /**\n     * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.\n     * @param spender Address that may be allowed to operate on tokens without being their owner.\n     * @param allowance Amount of tokens a `spender` is allowed to operate with.\n     * @param needed Minimum amount required to perform a transfer.\n     */\n    error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);\n\n    /**\n     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n     * @param approver Address initiating an approval operation.\n     */\n    error ERC20InvalidApprover(address approver);\n\n    /**\n     * @dev Indicates a failure with the `spender` to be approved. Used in approvals.\n     * @param spender Address that may be allowed to operate on tokens without being their owner.\n     */\n    error ERC20InvalidSpender(address spender);\n}\n\n/**\n * @dev Standard ERC-721 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.\n */\ninterface IERC721Errors {\n    /**\n     * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-721.\n     * Used in balance queries.\n     * @param owner Address of the current owner of a token.\n     */\n    error ERC721InvalidOwner(address owner);\n\n    /**\n     * @dev Indicates a `tokenId` whose `owner` is the zero address.\n     * @param tokenId Identifier number of a token.\n     */\n    error ERC721NonexistentToken(uint256 tokenId);\n\n    /**\n     * @dev Indicates an error related to the ownership over a particular token. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     * @param tokenId Identifier number of a token.\n     * @param owner Address of the current owner of a token.\n     */\n    error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);\n\n    /**\n     * @dev Indicates a failure with the token `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     */\n    error ERC721InvalidSender(address sender);\n\n    /**\n     * @dev Indicates a failure with the token `receiver`. Used in transfers.\n     * @param receiver Address to which tokens are being transferred.\n     */\n    error ERC721InvalidReceiver(address receiver);\n\n    /**\n     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     * @param tokenId Identifier number of a token.\n     */\n    error ERC721InsufficientApproval(address operator, uint256 tokenId);\n\n    /**\n     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n     * @param approver Address initiating an approval operation.\n     */\n    error ERC721InvalidApprover(address approver);\n\n    /**\n     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     */\n    error ERC721InvalidOperator(address operator);\n}\n\n/**\n * @dev Standard ERC-1155 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.\n */\ninterface IERC1155Errors {\n    /**\n     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     * @param balance Current balance for the interacting account.\n     * @param needed Minimum amount required to perform a transfer.\n     * @param tokenId Identifier number of a token.\n     */\n    error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);\n\n    /**\n     * @dev Indicates a failure with the token `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     */\n    error ERC1155InvalidSender(address sender);\n\n    /**\n     * @dev Indicates a failure with the token `receiver`. Used in transfers.\n     * @param receiver Address to which tokens are being transferred.\n     */\n    error ERC1155InvalidReceiver(address receiver);\n\n    /**\n     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     * @param owner Address of the current owner of a token.\n     */\n    error ERC1155MissingApprovalForAll(address operator, address owner);\n\n    /**\n     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n     * @param approver Address initiating an approval operation.\n     */\n    error ERC1155InvalidApprover(address approver);\n\n    /**\n     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     */\n    error ERC1155InvalidOperator(address operator);\n\n    /**\n     * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.\n     * Used in batch transfers.\n     * @param idsLength Length of the array of token identifiers\n     * @param valuesLength Length of the array of token amounts\n     */\n    error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);\n}\n"
    },
    "@openzeppelin/contracts/token/ERC20/ERC20.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.5.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"./IERC20.sol\";\nimport {IERC20Metadata} from \"./extensions/IERC20Metadata.sol\";\nimport {Context} from \"../../utils/Context.sol\";\nimport {IERC20Errors} from \"../../interfaces/draft-IERC6093.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * The default value of {decimals} is 18. To change this, you should override\n * this function so it returns a different value.\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC-20\n * applications.\n */\nabstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {\n    mapping(address account => uint256) private _balances;\n\n    mapping(address account => mapping(address spender => uint256)) private _allowances;\n\n    uint256 private _totalSupply;\n\n    string private _name;\n    string private _symbol;\n\n    /**\n     * @dev Sets the values for {name} and {symbol}.\n     *\n     * Both values are immutable: they can only be set once during construction.\n     */\n    constructor(string memory name_, string memory symbol_) {\n        _name = name_;\n        _symbol = symbol_;\n    }\n\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() public view virtual returns (string memory) {\n        return _name;\n    }\n\n    /**\n     * @dev Returns the symbol of the token, usually a shorter version of the\n     * name.\n     */\n    function symbol() public view virtual returns (string memory) {\n        return _symbol;\n    }\n\n    /**\n     * @dev Returns the number of decimals used to get its user representation.\n     * For example, if `decimals` equals `2`, a balance of `505` tokens should\n     * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n     *\n     * Tokens usually opt for a value of 18, imitating the relationship between\n     * Ether and Wei. This is the default value returned by this function, unless\n     * it's overridden.\n     *\n     * NOTE: This information is only used for _display_ purposes: it in\n     * no way affects any of the arithmetic of the contract, including\n     * {IERC20-balanceOf} and {IERC20-transfer}.\n     */\n    function decimals() public view virtual returns (uint8) {\n        return 18;\n    }\n\n    /// @inheritdoc IERC20\n    function totalSupply() public view virtual returns (uint256) {\n        return _totalSupply;\n    }\n\n    /// @inheritdoc IERC20\n    function balanceOf(address account) public view virtual returns (uint256) {\n        return _balances[account];\n    }\n\n    /**\n     * @dev See {IERC20-transfer}.\n     *\n     * Requirements:\n     *\n     * - `to` cannot be the zero address.\n     * - the caller must have a balance of at least `value`.\n     */\n    function transfer(address to, uint256 value) public virtual returns (bool) {\n        address owner = _msgSender();\n        _transfer(owner, to, value);\n        return true;\n    }\n\n    /// @inheritdoc IERC20\n    function allowance(address owner, address spender) public view virtual returns (uint256) {\n        return _allowances[owner][spender];\n    }\n\n    /**\n     * @dev See {IERC20-approve}.\n     *\n     * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on\n     * `transferFrom`. This is semantically equivalent to an infinite approval.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     */\n    function approve(address spender, uint256 value) public virtual returns (bool) {\n        address owner = _msgSender();\n        _approve(owner, spender, value);\n        return true;\n    }\n\n    /**\n     * @dev See {IERC20-transferFrom}.\n     *\n     * Skips emitting an {Approval} event indicating an allowance update. This is not\n     * required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve].\n     *\n     * NOTE: Does not update the allowance if the current allowance\n     * is the maximum `uint256`.\n     *\n     * Requirements:\n     *\n     * - `from` and `to` cannot be the zero address.\n     * - `from` must have a balance of at least `value`.\n     * - the caller must have allowance for ``from``'s tokens of at least\n     * `value`.\n     */\n    function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {\n        address spender = _msgSender();\n        _spendAllowance(from, spender, value);\n        _transfer(from, to, value);\n        return true;\n    }\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to`.\n     *\n     * This internal function is equivalent to {transfer}, and can be used to\n     * e.g. implement automatic token fees, slashing mechanisms, etc.\n     *\n     * Emits a {Transfer} event.\n     *\n     * NOTE: This function is not virtual, {_update} should be overridden instead.\n     */\n    function _transfer(address from, address to, uint256 value) internal {\n        if (from == address(0)) {\n            revert ERC20InvalidSender(address(0));\n        }\n        if (to == address(0)) {\n            revert ERC20InvalidReceiver(address(0));\n        }\n        _update(from, to, value);\n    }\n\n    /**\n     * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`\n     * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding\n     * this function.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _update(address from, address to, uint256 value) internal virtual {\n        if (from == address(0)) {\n            // Overflow check required: The rest of the code assumes that totalSupply never overflows\n            _totalSupply += value;\n        } else {\n            uint256 fromBalance = _balances[from];\n            if (fromBalance < value) {\n                revert ERC20InsufficientBalance(from, fromBalance, value);\n            }\n            unchecked {\n                // Overflow not possible: value <= fromBalance <= totalSupply.\n                _balances[from] = fromBalance - value;\n            }\n        }\n\n        if (to == address(0)) {\n            unchecked {\n                // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.\n                _totalSupply -= value;\n            }\n        } else {\n            unchecked {\n                // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.\n                _balances[to] += value;\n            }\n        }\n\n        emit Transfer(from, to, value);\n    }\n\n    /**\n     * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).\n     * Relies on the `_update` mechanism\n     *\n     * Emits a {Transfer} event with `from` set to the zero address.\n     *\n     * NOTE: This function is not virtual, {_update} should be overridden instead.\n     */\n    function _mint(address account, uint256 value) internal {\n        if (account == address(0)) {\n            revert ERC20InvalidReceiver(address(0));\n        }\n        _update(address(0), account, value);\n    }\n\n    /**\n     * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.\n     * Relies on the `_update` mechanism.\n     *\n     * Emits a {Transfer} event with `to` set to the zero address.\n     *\n     * NOTE: This function is not virtual, {_update} should be overridden instead\n     */\n    function _burn(address account, uint256 value) internal {\n        if (account == address(0)) {\n            revert ERC20InvalidSender(address(0));\n        }\n        _update(account, address(0), value);\n    }\n\n    /**\n     * @dev Sets `value` as the allowance of `spender` over the `owner`'s tokens.\n     *\n     * This internal function is equivalent to `approve`, and can be used to\n     * e.g. set automatic allowances for certain subsystems, etc.\n     *\n     * Emits an {Approval} event.\n     *\n     * Requirements:\n     *\n     * - `owner` cannot be the zero address.\n     * - `spender` cannot be the zero address.\n     *\n     * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.\n     */\n    function _approve(address owner, address spender, uint256 value) internal {\n        _approve(owner, spender, value, true);\n    }\n\n    /**\n     * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.\n     *\n     * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by\n     * `_spendAllowance` during the `transferFrom` operation sets the flag to false. This saves gas by not emitting any\n     * `Approval` event during `transferFrom` operations.\n     *\n     * Anyone who wishes to continue emitting `Approval` events on the `transferFrom` operation can force the flag to\n     * true using the following override:\n     *\n     * ```solidity\n     * function _approve(address owner, address spender, uint256 value, bool) internal virtual override {\n     *     super._approve(owner, spender, value, true);\n     * }\n     * ```\n     *\n     * Requirements are the same as {_approve}.\n     */\n    function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {\n        if (owner == address(0)) {\n            revert ERC20InvalidApprover(address(0));\n        }\n        if (spender == address(0)) {\n            revert ERC20InvalidSpender(address(0));\n        }\n        _allowances[owner][spender] = value;\n        if (emitEvent) {\n            emit Approval(owner, spender, value);\n        }\n    }\n\n    /**\n     * @dev Updates `owner`'s allowance for `spender` based on spent `value`.\n     *\n     * Does not update the allowance value in case of infinite allowance.\n     * Revert if not enough allowance is available.\n     *\n     * Does not emit an {Approval} event.\n     */\n    function _spendAllowance(address owner, address spender, uint256 value) internal virtual {\n        uint256 currentAllowance = allowance(owner, spender);\n        if (currentAllowance < type(uint256).max) {\n            if (currentAllowance < value) {\n                revert ERC20InsufficientAllowance(spender, currentAllowance, value);\n            }\n            unchecked {\n                _approve(owner, spender, currentAllowance - value, false);\n            }\n        }\n    }\n}\n"
    },
    "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity >=0.6.2;\n\nimport {IERC20} from \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC-20 standard.\n */\ninterface IERC20Metadata is IERC20 {\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @dev Returns the symbol of the token.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @dev Returns the decimals places of the token.\n     */\n    function decimals() external view returns (uint8);\n}\n"
    },
    "@openzeppelin/contracts/token/ERC20/IERC20.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/IERC20.sol)\n\npragma solidity >=0.4.16;\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the value of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the value of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 value) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n     * caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the\n     * allowance mechanism. `value` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n"
    },
    "@openzeppelin/contracts/utils/Context.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    function _contextSuffixLength() internal view virtual returns (uint256) {\n        return 0;\n    }\n}\n"
    },
    "@openzeppelin/contracts/utils/ReentrancyGuard.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.5.0) (utils/ReentrancyGuard.sol)\n\npragma solidity ^0.8.20;\n\nimport {StorageSlot} from \"./StorageSlot.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If EIP-1153 (transient storage) is available on the chain you're deploying at,\n * consider using {ReentrancyGuardTransient} instead.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n *\n * IMPORTANT: Deprecated. This storage-based reentrancy guard will be removed and replaced\n * by the {ReentrancyGuardTransient} variant in v6.0.\n *\n * @custom:stateless\n */\nabstract contract ReentrancyGuard {\n    using StorageSlot for bytes32;\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.ReentrancyGuard\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant REENTRANCY_GUARD_STORAGE =\n        0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00;\n\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant NOT_ENTERED = 1;\n    uint256 private constant ENTERED = 2;\n\n    /**\n     * @dev Unauthorized reentrant call.\n     */\n    error ReentrancyGuardReentrantCall();\n\n    constructor() {\n        _reentrancyGuardStorageSlot().getUint256Slot().value = NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    /**\n     * @dev A `view` only version of {nonReentrant}. Use to block view functions\n     * from being called, preventing reading from inconsistent contract state.\n     *\n     * CAUTION: This is a \"view\" modifier and does not change the reentrancy\n     * status. Use it only on view functions. For payable or non-payable functions,\n     * use the standard {nonReentrant} modifier instead.\n     */\n    modifier nonReentrantView() {\n        _nonReentrantBeforeView();\n        _;\n    }\n\n    function _nonReentrantBeforeView() private view {\n        if (_reentrancyGuardEntered()) {\n            revert ReentrancyGuardReentrantCall();\n        }\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be NOT_ENTERED\n        _nonReentrantBeforeView();\n\n        // Any calls to nonReentrant after this point will fail\n        _reentrancyGuardStorageSlot().getUint256Slot().value = ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _reentrancyGuardStorageSlot().getUint256Slot().value = NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _reentrancyGuardStorageSlot().getUint256Slot().value == ENTERED;\n    }\n\n    function _reentrancyGuardStorageSlot() internal pure virtual returns (bytes32) {\n        return REENTRANCY_GUARD_STORAGE;\n    }\n}\n"
    },
    "@openzeppelin/contracts/utils/StorageSlot.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC-1967 implementation slot:\n * ```solidity\n * contract ERC1967 {\n *     // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\n *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n *     function _getImplementation() internal view returns (address) {\n *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n *     }\n *\n *     function _setImplementation(address newImplementation) internal {\n *         require(newImplementation.code.length > 0);\n *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n *     }\n * }\n * ```\n *\n * TIP: Consider using this library along with {SlotDerivation}.\n */\nlibrary StorageSlot {\n    struct AddressSlot {\n        address value;\n    }\n\n    struct BooleanSlot {\n        bool value;\n    }\n\n    struct Bytes32Slot {\n        bytes32 value;\n    }\n\n    struct Uint256Slot {\n        uint256 value;\n    }\n\n    struct Int256Slot {\n        int256 value;\n    }\n\n    struct StringSlot {\n        string value;\n    }\n\n    struct BytesSlot {\n        bytes value;\n    }\n\n    /**\n     * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n     */\n    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `BooleanSlot` with member `value` located at `slot`.\n     */\n    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `Bytes32Slot` with member `value` located at `slot`.\n     */\n    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `Uint256Slot` with member `value` located at `slot`.\n     */\n    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `Int256Slot` with member `value` located at `slot`.\n     */\n    function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `StringSlot` with member `value` located at `slot`.\n     */\n    function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\n     */\n    function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := store.slot\n        }\n    }\n\n    /**\n     * @dev Returns a `BytesSlot` with member `value` located at `slot`.\n     */\n    function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\n     */\n    function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := store.slot\n        }\n    }\n}\n"
    },
    "contracts/fanbeimao/FanBeiMaoGenesisSale.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.24;\n\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {ReentrancyGuard} from \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\";\n\ninterface IAgentRegistry {\n    function handleOf(address account) external view returns (string memory);\n    function ownerOfHandle(string calldata handle) external view returns (address);\n}\n\ninterface IPancakeRouter02 {\n    function factory() external view returns (address);\n    function addLiquidityETH(\n        address token,\n        uint256 amountTokenDesired,\n        uint256 amountTokenMin,\n        uint256 amountETHMin,\n        address to,\n        uint256 deadline\n    ) external payable returns (uint256 amountToken, uint256 amountETH, uint256 liquidity);\n}\n\ninterface IPancakeFactory {\n    function getPair(address tokenA, address tokenB) external view returns (address pair);\n}\n\n/**\n * 翻倍猫 · 创世销售（Phase 1）\n *\n * 规则：\n *   - 10,000 份：免费 2,000 份（每个 .ai Agent ID 1 份，每份 100,000 枚）\n *     付费 8,000 份（每个 Agent ID 最多 10 份，每份 0.001 BNB，每份 1,000,000 枚）\n *   - 免费卖完后付费开启；免费没卖完，7 天后也自动开启付费\n *   - 付费资金：80% 开池 / 10% 前 10 邀请人 / 10% 国库\n *   - 第 10,000 份自动开 PancakeSwap：6.4 BNB + 6.4e9 枚，LP 打黑洞\n *   - 开售 30 天未满 10,000 份：付费份额可退款\n *   - 代币由本合约托管，开池后买家自行 claim；退款成功后不再发币\n *\n * 这个合约只负责创世销售；交易税、每周 Merkle 分红、开池后继续铸造属于 Phase 2。\n */\ncontract FanBeiMaoGenesisSale is ReentrancyGuard {\n    address public constant DEAD = 0x000000000000000000000000000000000000dEaD;\n\n    uint256 public constant PRICE = 0.001 ether;\n    uint256 public constant FREE_TOKENS = 100_000;\n    uint256 public constant PAID_TOKENS = 1_000_000;\n    uint256 public constant POOL_TOKENS = 6_400_000_000;\n    uint256 public constant MAX_PER_AGENT = 10;\n    uint256 public constant POOL_BPS = 8_000;\n    uint256 public constant INVITER_BPS = 1_000;\n    uint256 public constant TREASURY_BPS = 1_000;\n    uint256 public constant REFUND_PERIOD = 30 days;\n    uint256 public constant PAID_DELAY = 7 days;\n\n    IERC20 public immutable token;\n    address payable public immutable treasury;\n    address public immutable agentRegistry;\n    address public immutable router;\n    address public immutable wbnb;\n    uint256 public immutable startAt;\n    uint256 public immutable refundAt;\n    uint256 public immutable freeCap;\n    uint256 public immutable paidCap;\n\n    uint256 public freeSold;\n    uint256 public paidSold;\n    uint256 public totalPaid;\n    uint256 public totalOwed;\n    uint256 public treasuryOwed;\n    bool public poolSeeded;\n    bool public poolPending;\n\n    mapping(bytes32 => bool) public freeClaimedByKey;\n    mapping(bytes32 => uint256) public paidByKey;\n    mapping(address => uint256) public sharesOf;\n    mapping(address => uint256) public tokensOwed;\n    mapping(address => uint256) public paidBy;\n    mapping(address => bool) public refunded;\n    mapping(address => uint256) public invites;\n    address[10] public topInviters;\n    uint256[10] public topCounts;\n\n    event FreeClaimed(address indexed buyer, bytes32 indexed key, uint256 tokens);\n    event SharesBought(address indexed buyer, address indexed referrer, uint256 shares, uint256 paid, uint256 tokens);\n    event InviteCounted(address indexed referrer, address indexed buyer, uint256 count);\n    event PoolSeeded(address indexed pair, uint256 bnbAmount, uint256 tokenAmount, uint256 liquidity);\n    event PoolPending();\n    event InviterPaid(address indexed inviter, uint256 amount);\n    event TreasuryPaid(uint256 amount);\n    event TokensClaimed(address indexed buyer, uint256 amount);\n    event Refunded(address indexed buyer, uint256 amount);\n\n    constructor(\n        address token_,\n        address payable treasury_,\n        address agentRegistry_,\n        address router_,\n        address wbnb_,\n        uint256 startAt_,\n        uint256 freeCap_,\n        uint256 paidCap_\n    ) {\n        require(token_ != address(0), \"token=0\");\n        require(treasury_ != address(0), \"treasury=0\");\n        require(agentRegistry_ != address(0), \"registry=0\");\n        require(router_ != address(0), \"router=0\");\n        require(wbnb_ != address(0), \"wbnb=0\");\n        require(startAt_ > 0, \"start=0\");\n        require(freeCap_ > 0 && paidCap_ > 0, \"cap=0\");\n        require(freeCap_ + paidCap_ <= 10_000, \"cap>10k\");\n\n        token = IERC20(token_);\n        treasury = treasury_;\n        agentRegistry = agentRegistry_;\n        router = router_;\n        wbnb = wbnb_;\n        startAt = startAt_;\n        refundAt = startAt_ + REFUND_PERIOD;\n        freeCap = freeCap_;\n        paidCap = paidCap_;\n    }\n\n    /* ----------------------------- views ----------------------------- */\n\n    function totalShares() public view returns (uint256) {\n        return freeCap + paidCap;\n    }\n\n    function totalSold() public view returns (uint256) {\n        return freeSold + paidSold;\n    }\n\n    function isFreeOpen() public view returns (bool) {\n        return block.timestamp >= startAt && block.timestamp < refundAt && !poolSeeded && freeSold < freeCap;\n    }\n\n    function isPaidOpen() public view returns (bool) {\n        if (block.timestamp < startAt || block.timestamp >= refundAt || poolSeeded || paidSold >= paidCap) return false;\n        return freeSold >= freeCap || block.timestamp >= startAt + PAID_DELAY;\n    }\n\n    function agentKeyOf(address who) external view returns (bytes32) {\n        return _agentKey(who);\n    }\n\n    function topInvitersList() external view returns (address[10] memory, uint256[10] memory) {\n        return (topInviters, topCounts);\n    }\n\n    /* ----------------------------- agent id ----------------------------- */\n\n    function _agentKey(address who) internal view returns (bytes32) {\n        try IAgentRegistry(agentRegistry).handleOf(who) returns (string memory h) {\n            if (bytes(h).length == 0) return bytes32(0);\n            try IAgentRegistry(agentRegistry).ownerOfHandle(h) returns (address owner_) {\n                if (owner_ != who) return bytes32(0);\n                return keccak256(bytes(h));\n            } catch {\n                return bytes32(0);\n            }\n        } catch {\n            return bytes32(0);\n        }\n    }\n\n    /* ----------------------------- mint ----------------------------- */\n\n    function claimFree() external nonReentrant {\n        require(isFreeOpen(), \"free closed\");\n        bytes32 key = _agentKey(msg.sender);\n        require(key != bytes32(0), \"agent id required\");\n        require(!freeClaimedByKey[key], \"free claimed\");\n\n        freeClaimedByKey[key] = true;\n        freeSold += 1;\n        sharesOf[msg.sender] += 1;\n        tokensOwed[msg.sender] += FREE_TOKENS;\n        totalOwed += FREE_TOKENS;\n\n        emit FreeClaimed(msg.sender, key, FREE_TOKENS);\n    }\n\n    function buy(uint256 shares, address referrer) external payable nonReentrant {\n        require(isPaidOpen(), \"paid closed\");\n        require(shares > 0 && shares <= MAX_PER_AGENT, \"shares\");\n        require(paidSold + shares <= paidCap, \"sold out\");\n\n        bytes32 key = _agentKey(msg.sender);\n        require(key != bytes32(0), \"agent id required\");\n        require(paidByKey[key] + shares <= MAX_PER_AGENT, \"quota\");\n\n        uint256 cost = PRICE * shares;\n        require(msg.value == cost, \"bad value\");\n\n        paidByKey[key] += shares;\n        paidSold += shares;\n        sharesOf[msg.sender] += shares;\n        paidBy[msg.sender] += cost;\n        totalPaid += cost;\n\n        uint256 tokens = PAID_TOKENS * shares;\n        tokensOwed[msg.sender] += tokens;\n        totalOwed += tokens;\n\n        if (referrer != address(0) && referrer != msg.sender) {\n            invites[referrer] += 1;\n            _updateTop(referrer);\n            emit InviteCounted(referrer, msg.sender, invites[referrer]);\n        }\n\n        emit SharesBought(msg.sender, referrer, shares, cost, tokens);\n\n        if (freeSold + paidSold >= totalShares()) {\n            _openPool();\n        }\n    }\n\n    /* ----------------------------- top inviters ----------------------------- */\n\n    function _updateTop(address who) internal {\n        uint256 count = invites[who];\n        uint256 idx = type(uint256).max;\n\n        for (uint256 i = 0; i < 10; i++) {\n            if (topInviters[i] == who) {\n                idx = i;\n                break;\n            }\n        }\n\n        if (idx != type(uint256).max) {\n            topCounts[idx] = count;\n            while (idx > 0 && topCounts[idx] > topCounts[idx - 1]) {\n                address ta = topInviters[idx];\n                topInviters[idx] = topInviters[idx - 1];\n                topInviters[idx - 1] = ta;\n                uint256 tc = topCounts[idx];\n                topCounts[idx] = topCounts[idx - 1];\n                topCounts[idx - 1] = tc;\n                idx--;\n            }\n            return;\n        }\n\n        if (count <= topCounts[9]) return;\n\n        topInviters[9] = who;\n        topCounts[9] = count;\n        uint256 i = 9;\n        while (i > 0 && topCounts[i] > topCounts[i - 1]) {\n            address ta = topInviters[i];\n            topInviters[i] = topInviters[i - 1];\n            topInviters[i - 1] = ta;\n            uint256 tc = topCounts[i];\n            topCounts[i] = topCounts[i - 1];\n            topCounts[i - 1] = tc;\n            i--;\n        }\n    }\n\n    /* ----------------------------- pool ----------------------------- */\n\n    function openPool() external nonReentrant {\n        require(freeSold + paidSold >= totalShares(), \"not filled\");\n        require(!poolSeeded, \"seeded\");\n        _openPool();\n        require(poolSeeded, \"pool failed\");\n    }\n\n    function _openPool() internal {\n        if (poolSeeded) return;\n        if (freeSold + paidSold < totalShares()) return;\n        require(token.balanceOf(address(this)) >= POOL_TOKENS + totalOwed, \"token balance\");\n\n        uint256 poolBnb = (totalPaid * POOL_BPS) / 10_000;\n        uint256 inviterBnb = (totalPaid * INVITER_BPS) / 10_000;\n        uint256 treasuryBnb = totalPaid - poolBnb - inviterBnb;\n\n        require(token.approve(router, POOL_TOKENS), \"approve\");\n\n        try IPancakeRouter02(router).addLiquidityETH{value: poolBnb}(\n            address(token), POOL_TOKENS, 0, 0, DEAD, block.timestamp + 600\n        ) returns (uint256, uint256, uint256 liquidity) {\n            require(liquidity > 0, \"no lp\");\n            poolSeeded = true;\n            poolPending = false;\n\n            address pair = IPancakeFactory(IPancakeRouter02(router).factory()).getPair(address(token), wbnb);\n            emit PoolSeeded(pair, poolBnb, POOL_TOKENS, liquidity);\n\n            _payInviters(inviterBnb);\n            treasuryOwed += treasuryBnb;\n\n            uint256 bal = token.balanceOf(address(this));\n            if (bal > totalOwed) {\n                token.transfer(treasury, bal - totalOwed);\n            }\n        } catch {\n            poolPending = true;\n            emit PoolPending();\n        }\n    }\n\n    function _payInviters(uint256 amount) internal {\n        uint256 total;\n        for (uint256 i = 0; i < 10; i++) total += topCounts[i];\n\n        if (total == 0) {\n            treasuryOwed += amount;\n            return;\n        }\n\n        uint256 paid;\n        for (uint256 i = 0; i < 10; i++) {\n            uint256 count = topCounts[i];\n            if (count == 0) continue;\n            uint256 share = (amount * count) / total;\n            if (share == 0) continue;\n            (bool ok, ) = payable(topInviters[i]).call{value: share}(\"\");\n            if (ok) {\n                paid += share;\n                emit InviterPaid(topInviters[i], share);\n            }\n        }\n        if (amount > paid) treasuryOwed += amount - paid;\n    }\n\n    function withdrawTreasury() external nonReentrant {\n        require(msg.sender == treasury, \"treasury only\");\n        uint256 amount = treasuryOwed;\n        require(amount > 0, \"nothing\");\n        treasuryOwed = 0;\n        (bool ok, ) = treasury.call{value: amount}(\"\");\n        require(ok, \"treasury xfer\");\n        emit TreasuryPaid(amount);\n    }\n\n    /* ----------------------------- claims / refunds ----------------------------- */\n\n    function claimTokens() external nonReentrant {\n        require(poolSeeded, \"not open\");\n        uint256 amount = tokensOwed[msg.sender];\n        require(amount > 0, \"nothing\");\n        tokensOwed[msg.sender] = 0;\n        totalOwed -= amount;\n        require(token.transfer(msg.sender, amount), \"token xfer\");\n        emit TokensClaimed(msg.sender, amount);\n    }\n\n    function refund() external nonReentrant {\n        require(!poolSeeded, \"pool live\");\n        require(freeSold + paidSold < totalShares(), \"filled\");\n        require(block.timestamp >= refundAt, \"too early\");\n\n        uint256 amount = paidBy[msg.sender];\n        require(amount > 0 && !refunded[msg.sender], \"nothing\");\n\n        refunded[msg.sender] = true;\n        paidBy[msg.sender] = 0;\n\n        uint256 owed = tokensOwed[msg.sender];\n        if (owed > 0) {\n            tokensOwed[msg.sender] = 0;\n            totalOwed -= owed;\n        }\n\n        (bool ok, ) = msg.sender.call{value: amount}(\"\");\n        require(ok, \"refund xfer\");\n        emit Refunded(msg.sender, amount);\n    }\n}\n"
    },
    "contracts/fanbeimao/FanBeiMaoToken.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.24;\n\nimport {ERC20} from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\n/**\n * 翻倍猫 · Double Cat\n *\n * 固定总量 100,000,000,000（10^11），0 位小数。\n * name / symbol 都是中文「翻倍猫」，Solidity 必须用 unicode 字面量。\n * 部署时一次性铸给 Sale 合约；没有 owner、没有增发、没有交易税。\n */\ncontract FanBeiMaoToken is ERC20 {\n    uint256 public constant TOTAL_SUPPLY = 100_000_000_000;\n\n    constructor(address sale) ERC20(unicode\"翻倍猫\", unicode\"翻倍猫\") {\n        require(sale != address(0), \"sale=0\");\n        _mint(sale, TOTAL_SUPPLY);\n    }\n\n    /// 0 位小数：totalSupply / balanceOf 都是「枚数」本身\n    function decimals() public pure override returns (uint8) {\n        return 0;\n    }\n}\n"
    }
  },
  "settings": {
    "optimizer": {
      "enabled": true,
      "runs": 200
    },
    "evmVersion": "paris",
    "outputSelection": {
      "*": {
        "*": [
          "abi",
          "evm.bytecode",
          "evm.deployedBytecode",
          "evm.methodIdentifiers",
          "metadata"
        ],
        "": [
          "ast"
        ]
      }
    }
  }
}