ETH Price: $2,935.56 (-7.02%)
Gas: 8 Gwei

Token

Cheezburger (CHZB)
 

Overview

Max Total Supply

992,874,308 CHZB

Holders

394

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 18 Decimals)

Balance
66,889 CHZB

Value
$0.00
0xad26085c07e70c73230d548224264d3941bc1dc6
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information
# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
Cheezburger

Compiler Version
v0.8.22+commit.4fc1097e

Optimization Enabled:
Yes with 825 runs

Other Settings:
shanghai EvmVersion, None license

Contract Source Code (Solidity Multiple files format)

File 1 of 13: Cheezburger.sol
// SPDX-License-Identifier: UNLICENSED
//
//           ████████████████████
//         ██                    ██
//       ██    ██          ██      ██
//     ██      ████        ████      ██
//     ██            ████            ██
//     ██                            ██
//   ████████████████████████████████████
//   ██▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓██
//     ████████████████████████████████
//   ██░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██
//     ██░░██░░░░██████░░░░░░██░░░░████
//     ████  ████      ██████  ████  ██
//     ██                            ██
//       ████████████████████████████
//
// Cheezburger enables frictionless creation of tokens for a wide
// range of use cases, including DAOs, utility tokens, community projects,
// memecoins, and more. It presents three revolutionary concepts:
//
// - Social Tokens:          Enables permissionless, one-click launches for social profiles.
// - Liquidity-Less Tokens:  Auto-generated liquidity removes the need for initial capital.
// - Factory Model:          Enables free, fast, and gas-efficient deployments with configurable
//                           settings, such as wallet caps, decaying premiums, and highly
//                           customizable tokenomics for fair launches.
//
// Social and Liquidity-Less tokens will be available when the V3 pool is opened.
//
// ATTENTION: The only genuine deployer is chzb.eth.
// Beware of scammers and follow official channels for more information.
//
// Read more on Cheezburger: https://cheezburger.lol
//                           https://documentation.cheezburger.lol
//
pragma solidity ^0.8.22;

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

import {CheezburgerDeployerKit} from "./CheezburgerDeployerKit.sol";
import {ICheezburgerFactory} from "./ICheezburgerFactory.sol";

contract Cheezburger is CheezburgerDeployerKit {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    error TransferToZeroAddress(address from, address to);
    error TransferToToken(address to);
    error CannotReceiveEtherDirectly();
    error EmptyAddressNotAllowed();
    error SupplyAllocationExceeded();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                           EVENTS                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    event GlobalSettingsChanged();
    event SettingsChanged();
    event PairingAmountsChanged();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                          STORAGE                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    uint256 internal constant LIQUIDITY_FEE_WITHDRAWAL_ROLE = _ROLE_1;
    uint256 internal constant CREATION_FEE_WITHDRAWAL_ROLE = _ROLE_2;
    uint256 internal constant PAIRING_AMOUNT_SETTER_ROLE = _ROLE_3;
    uint256 internal constant SETTINGS_SETTER_ROLE = _ROLE_4;

    string private _name;
    string private _symbol;

    constructor(
        TokenCustomization memory _customization,
        address _factory,
        address _router
    ) {
        if (_factory == address(0) || _router == address(0)) {
            revert EmptyAddressNotAllowed();
        }

        _name = _customization.name;
        _symbol = _customization.symbol;
        _website = _customization.website;
        _social = _customization.social;

        _initializeOwner(msg.sender);
        _mint(msg.sender, _customization.supply * (10 ** decimals()));
        changeSettings(
            SocialSettings({
                pairingAmount: 0,
                leftSideSupply: 1_000_000, // 1 million supply for each social token
                openFeeWei: 0, // Zero fee at launch
                poolCreatorFeePercentage: 4, // 4% of the fees to pool creator at launch
                walletSettings: DynamicSettings({
                    duration: 14 days, // Max wallet duration 2 weeks for each Social token
                    percentStart: 300, // 3% starting wallet cap
                    percentEnd: 4900 // 49% ending wallet cap
                }),
                feeSettings: DynamicSettings({
                    duration: 1 days, // 1 day EAP duration for each Social token
                    percentStart: 500, // 5% starting fee
                    percentEnd: 200 // 2% ending fee
                })
            }),
            TokenSettings({pairingAmount: 0, openFeeWei: 0})
        );
        changeGlobalSettings(
            GlobalSettings({
                factory: ICheezburgerFactory(_factory),
                router: _router
            })
        );
        // Keep it disabled until launch
        // changePairingAmounts(totalSupply() / 33, totalSupply() / 33); // 3% mint for social and regular token launches
    }

    /// @dev Prevents direct Ether transfers to contract
    receive() external payable {
        revert CannotReceiveEtherDirectly();
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       ERC20 METADATA                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    function name() public view virtual override returns (string memory) {
        return _name;
    }

    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    function website() public view returns (string memory) {
        return _website;
    }

    function social() public view returns (string memory) {
        return _social;
    }

    /// @dev Returns the amount of tokens in existence minus liquidity pools burned tokens.
    /// The total supply with liquidity pools can be calculated with totalSupply() + outOfCirculationTokens.
    function totalSupply() public view override returns (uint256) {
        unchecked {
            return super.totalSupply() - outOfCirculationTokens;
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  PUBLIC UPDATE FUNCTIONS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Burns `amount` tokens from the caller.
    function burn(uint256 amount) external {
        _burn(msg.sender, amount);
    }

    /// @dev Burns `amount` tokens from `account`, deducting from the caller's allowance.
    function burnFrom(address account, uint256 amount) external {
        _spendAllowance(account, msg.sender, amount);
        _burn(account, amount);
    }

    /// @dev Allows to withdraw creation liquidity fees to a customized contract
    function withdrawFeesOf(
        uint256 _userId,
        address _to
    ) external onlyRoles(LIQUIDITY_FEE_WITHDRAWAL_ROLE) returns (uint256) {
        return _withdrawFeesOf(_userId, _to);
    }

    /// @dev Allows to withdraw creation fees to a customized contract
    function withdrawCreationFees()
        external
        onlyRoles(CREATION_FEE_WITHDRAWAL_ROLE)
    {
        return SafeTransferLib.forceSafeTransferAllETH(msg.sender);
    }

    /// @dev Allow to change global settings by the owner only
    function changeGlobalSettings(
        GlobalSettings memory _globalSettings
    ) public onlyOwner {
        globalSettings = _globalSettings;
        emit GlobalSettingsChanged();
    }

    /// @dev Allow to change settings by the owner only or an authorized address
    function changeSettings(
        SocialSettings memory _socialSettings,
        TokenSettings memory _tokenSettings
    ) public onlyOwnerOrRoles(SETTINGS_SETTER_ROLE) {
        // Pairing amounts cannot be changed here
        socialSettings.leftSideSupply = _socialSettings.leftSideSupply;
        socialSettings.openFeeWei = _socialSettings.openFeeWei;
        socialSettings.poolCreatorFeePercentage = _socialSettings
            .poolCreatorFeePercentage;
        socialSettings.walletSettings = _socialSettings.walletSettings;
        socialSettings.feeSettings = _socialSettings.feeSettings;
        tokenSettings.openFeeWei = _tokenSettings.openFeeWei;
        emit SettingsChanged();
    }

    /// @dev Allow to change pairing amounts for token and social settings by the owner only or an authorized address
    function changePairingAmounts(
        uint256 _socialPairingAmount,
        uint256 _tokenPairingAmount
    ) public onlyOwnerOrRoles(PAIRING_AMOUNT_SETTER_ROLE) {
        uint256 maxSupplyPerCreation = totalSupply() / 25; // Capped to 4% of the supply
        if (
            _socialPairingAmount > maxSupplyPerCreation ||
            _tokenPairingAmount > maxSupplyPerCreation
        ) {
            revert SupplyAllocationExceeded();
        }
        socialSettings.pairingAmount = _socialPairingAmount;
        tokenSettings.pairingAmount = _tokenPairingAmount;
        emit PairingAmountsChanged();
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     INTERNAL FUNCTIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual override {
        super._beforeTokenTransfer(from, to, amount);

        // Don't allow token transfers to the contract
        if (from != address(0) && to == address(this)) {
            revert TransferToToken(to);
        }
    }

    function _afterTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual override {
        super._afterTokenTransfer(from, to, amount);

        // Must use burn() to burn tokens
        if (to == address(0) && balanceOf(address(0)) > 0) {
            revert TransferToZeroAddress(from, to);
        }
    }
}

File 2 of 13: CheezburgerDeployerKit.sol
// SPDX-License-Identifier: UNLICENSED
//
//           ████████████████████
//         ██                    ██
//       ██    ██          ██      ██
//     ██      ████        ████      ██
//     ██            ████            ██
//     ██                            ██
//   ████████████████████████████████████
//   ██▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓██
//     ████████████████████████████████
//   ██░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██
//     ██░░██░░░░██████░░░░░░██░░░░████
//     ████  ████      ██████  ████  ██
//     ██                            ██
//       ████████████████████████████
//
pragma solidity ^0.8.22;

import {ERC20} from "./ERC20.sol";
import {LibString} from "./LibString.sol";
import {SafeTransferLib} from "./SafeTransferLib.sol";
import {OwnableRoles} from "./OwnableRoles.sol";

import {ReentrancyGuard} from "./ReentrancyGuard.sol";
import {ICheezburgerFactory} from "./ICheezburgerFactory.sol";
import {CheezburgerRegistry} from "./CheezburgerRegistry.sol";

abstract contract CheezburgerDeployerKit is
    ERC20,
    CheezburgerRegistry,
    ReentrancyGuard,
    OwnableRoles
{
    using LibString for uint256;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    error EmptyNumericUserId();
    error SocialNotOpened();
    error UserIdNotFound();
    error UserIdAlreadyExist(uint256 userId);
    error IncorrectPoolOpeningFee(uint256 value, uint256 expected);
    error SupplyOverflow();
    error CannotUseCHZBNamespace();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                          STRUCT                            */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    struct GlobalSettings {
        ICheezburgerFactory factory;
        address router;
    }

    struct SocialSettings {
        uint256 pairingAmount;
        uint256 leftSideSupply;
        uint256 openFeeWei;
        uint8 poolCreatorFeePercentage;
        DynamicSettings walletSettings;
        DynamicSettings feeSettings;
    }

    struct TokenSettings {
        uint256 pairingAmount;
        uint256 openFeeWei;
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                           EVENTS                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    event SocialTokenDeployed(
        uint256 indexed userId,
        address indexed token,
        uint256 indexed creationAmount,
        uint256 currentOutOfCirculationSupply
    );

    event SocialTokenFeeWithdrawal(
        address indexed pair,
        address indexed to,
        uint256 indexed amount
    );

    event LiquidityLessTokenDeployed(
        address indexed token,
        uint256 indexed creationAmount,
        uint256 currentOutOfCirculationSupply
    );

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                          STORAGE                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    string internal _website;
    string internal _social;
    uint256 public outOfCirculationTokens;

    uint256 internal constant NAMESPACE_ROLE = _ROLE_5;

    GlobalSettings public globalSettings;
    SocialSettings public socialSettings;
    TokenSettings public tokenSettings;

    mapping(uint256 => Token) public socialTokens;
    mapping(address => uint256) public socialIds;

    /// @dev Deploy a new social token using bootstrapped CHZB liquidity
    /// @param userId User ID for the social token
    /// @dev Can be deployed from another contract but for gas reasons we'll let it here
    function deploySocialTokenWithCHZB(
        uint256 userId
    ) external payable nonReentrant returns (address) {
        // Ensure userId is valid
        if (userId == 0) {
            revert EmptyNumericUserId();
        }

        // Ensure userId doesn't already exist
        if (socialTokens[userId].leftSide != address(0)) {
            revert UserIdAlreadyExist(userId);
        }

        // Half liquidity is burned
        // Half is kept in the contract as a custodial
        address[] memory feeAddresses = new address[](2);
        feeAddresses[0] = address(0);
        feeAddresses[1] = address(this);

        // 50/50 fees split
        uint8[] memory feePercentages = new uint8[](1);
        feePercentages[0] = 50;

        // Transform the user ID to string for name and symbol
        string memory userIdString = userId.toString();

        Token memory token = _deployWithCHZB(
            TokenCustomization({
                name: LibString.concat(userIdString, " (Social)"),
                symbol: LibString.concat("CHZB-X-", userIdString),
                website: _website,
                social: _social,
                supply: socialSettings.leftSideSupply
            }),
            LiquiditySettings({
                feeThresholdPercent: 2,
                feeAddresses: feeAddresses,
                feePercentages: feePercentages
            }),
            socialSettings.feeSettings,
            socialSettings.walletSettings,
            socialSettings.poolCreatorFeePercentage > 0
                ? ReferralSettings({
                    feeReceiver: msg.sender,
                    feePercentage: socialSettings.poolCreatorFeePercentage
                })
                : ReferralSettings({feeReceiver: address(0), feePercentage: 0}),
            socialSettings.pairingAmount,
            socialSettings.openFeeWei
        );

        // Register ID
        socialTokens[userId] = token;
        socialIds[token.leftSide] = userId;

        emit SocialTokenDeployed(
            userId,
            token.leftSide,
            socialSettings.pairingAmount,
            outOfCirculationTokens
        );

        return address(token.leftSide);
    }

    /// @dev Deploy a new customized token with bootstrapped CHZB liquidity
    function deployTokenWithCHZB(
        TokenCustomization memory _customization,
        LiquiditySettings memory _liquidity,
        DynamicSettings memory _fee,
        DynamicSettings memory _wallet,
        ReferralSettings memory _referral
    ) external payable nonReentrant returns (address) {
        if (
            LibString.startsWith(_customization.symbol, "CHZB-") &&
            !hasAnyRole(msg.sender, NAMESPACE_ROLE)
        ) {
            revert CannotUseCHZBNamespace();
        }

        Token memory token = _deployWithCHZB(
            _customization,
            _liquidity,
            _fee,
            _wallet,
            _referral,
            tokenSettings.pairingAmount,
            tokenSettings.openFeeWei
        );

        emit LiquidityLessTokenDeployed(
            token.leftSide,
            tokenSettings.pairingAmount,
            outOfCirculationTokens
        );

        return address(token.leftSide);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     INTERNAL FUNCTIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    function _deployWithCHZB(
        TokenCustomization memory _customization,
        LiquiditySettings memory _liquidity,
        DynamicSettings memory _fee,
        DynamicSettings memory _wallet,
        ReferralSettings memory _referral,
        uint256 _pairingAmount,
        uint256 _openingFee
    ) private returns (Token memory) {
        // Collect fee if any
        if (msg.value != _openingFee) {
            revert IncorrectPoolOpeningFee(msg.value, _openingFee);
        }

        // The tokens are used to pool with the token to give initial liquidity
        // This have no impact on price and they cannot be withdrawn as they are burned
        _mint(address(this), _pairingAmount);

        // Approve the Factory to use the created CHZB
        SafeTransferLib.safeApprove(
            address(this),
            address(globalSettings.factory),
            _pairingAmount
        );

        // Create the token
        address tokenAddress = globalSettings.factory.deployWithToken(
            _customization,
            globalSettings.router,
            address(this),
            _pairingAmount,
            _liquidity,
            _fee,
            _wallet,
            _referral
        );

        // Get token info
        Token memory token = getToken(globalSettings.factory, tokenAddress);

        // Burn liquidity
        SafeTransferLib.safeTransferAll(address(token.pair), address(0));

        // Update out of circulating supply data
        unchecked {
            if (totalSupply() > totalSupply() + _pairingAmount) {
                revert SupplyOverflow();
            }
            outOfCirculationTokens = outOfCirculationTokens + _pairingAmount;
        }

        return token;
    }

    /// @dev Allows to withdraw creation liquidity fees to a customized contract
    function _withdrawFeesOf(
        uint256 _userId,
        address _to
    ) internal returns (uint256) {
        address pair = address(socialTokens[_userId].pair);
        if (pair == address(0)) {
            revert UserIdNotFound();
        }
        uint256 amount = SafeTransferLib.safeTransferAll(pair, _to);
        emit SocialTokenFeeWithdrawal(pair, _to, amount);
        return amount;
    }
}

File 3 of 13: CheezburgerRegistry.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.22;

import {ICheezburgerFactory} from "./ICheezburgerFactory.sol";
import {ICheezburger} from "./ICheezburger.sol";
import {CheezburgerStructs} from "./CheezburgerStructs.sol";

abstract contract CheezburgerRegistry is CheezburgerStructs {
    /// @dev Convert a socialTokens entry back to Token
    function getSocialToken(
        ICheezburger _chzb,
        uint256 _id
    ) internal view returns (Token memory) {
        (
            address _uniswapFactory,
            address _uniswapRouter,
            address _uniswapPair,
            address _creator,
            address _leftSide,
            address _rightSide,
            LiquiditySettings memory _liquidity,
            DynamicSettings memory _fee,
            DynamicSettings memory _wallet,
            ReferralSettings memory _referral
        ) = _chzb.socialTokens(_id);

        return
            Token({
                factory: _uniswapFactory,
                router: _uniswapRouter,
                pair: _uniswapPair,
                creator: _creator,
                leftSide: _leftSide,
                rightSide: _rightSide,
                liquidity: _liquidity,
                fee: _fee,
                wallet: _wallet,
                referral: _referral
            });
    }

    /// @dev Convert a burgerRegistry entry back to Token
    function getToken(
        ICheezburgerFactory _factory,
        address _pairedToken
    ) internal view returns (Token memory) {
        (
            address _uniswapFactory,
            address _uniswapRouter,
            address _uniswapPair,
            address _creator,
            address _leftSide,
            address _rightSide,
            LiquiditySettings memory _liquidity,
            DynamicSettings memory _fee,
            DynamicSettings memory _wallet,
            ReferralSettings memory _referral
        ) = _factory.burgerRegistry(_pairedToken);

        return
            Token({
                factory: _uniswapFactory,
                router: _uniswapRouter,
                pair: _uniswapPair,
                creator: _creator,
                leftSide: _leftSide,
                rightSide: _rightSide,
                liquidity: _liquidity,
                fee: _fee,
                wallet: _wallet,
                referral: _referral
            });
    }
}

File 4 of 13: CheezburgerStructs.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.22;

interface CheezburgerStructs {
    /// @dev Settings and contracts for a token pair and its liquidity pool.
    struct Token {
        /// @dev The Uniswap factory contract
        address factory;
        /// @dev The Uniswap router contract
        address router;
        /// @dev The Uniswap pair contract
        address pair;
        /// @dev The token creator
        address creator;
        /// @dev The left side of the pair
        address leftSide;
        /// @dev The right side ERC20 token of the pair
        address rightSide;
        /// @dev Liquidity settings
        LiquiditySettings liquidity;
        /// @dev Dynamic fee settings
        DynamicSettings fee;
        /// @dev Dynamic wallet settings
        DynamicSettings wallet;
        /// @dev Referral settings
        ReferralSettings referral;
    }

    /// @dev Settings for customizing the token
    /// @param name The name of the token
    /// @param symbol The symbol for the token
    /// @param website The website associated with the token
    /// @param social A social media link associated with the token
    /// @param supply The max supply of the token
    struct TokenCustomization {
        string name;
        string symbol;
        string website;
        string social;
        uint256 supply;
    }

    /// @dev Settings for dynamic fees that change over time
    /// @param duration The duration over which the rate changes
    /// @param percentStart The starting percentage rate
    /// @param percentEnd The ending percentage rate
    struct DynamicSettings {
        uint256 duration;
        uint16 percentStart;
        uint16 percentEnd;
    }

    /// @dev Settings for liquidity pool fees distributed to addresses
    /// @param feeThresholdPercent The percentage threshold that triggers liquidity swaps
    /// @param feeAddresses The addresses receiving distributed fee amounts
    /// @param feePercentages The percentage fee amounts for each address
    struct LiquiditySettings {
        uint8 feeThresholdPercent;
        address[] feeAddresses;
        uint8[] feePercentages;
    }

    /// @dev Settings for referrals. Referrals get commissions from fees whenever people uses the factory to deploy their token.
    /// @param feeReceiver The addresses receiving commissions
    /// @param feePercentage The percentage fee
    struct ReferralSettings {
        address feeReceiver;
        uint8 feePercentage;
    }
}

File 5 of 13: ECDSA.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Gas optimized ECDSA wrapper.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/ECDSA.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/ECDSA.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/ECDSA.sol)
///
/// @dev Note:
/// - The recovery functions use the ecrecover precompile (0x1).
/// - As of Solady version 0.0.68, the `recover` variants will revert upon recovery failure.
///   This is for more safety by default.
///   Use the `tryRecover` variants if you need to get the zero address back
///   upon recovery failure instead.
/// - As of Solady version 0.0.134, all `bytes signature` variants accept both
///   regular 65-byte `(r, s, v)` and EIP-2098 `(r, vs)` short form signatures.
///   See: https://eips.ethereum.org/EIPS/eip-2098
///   This is for calldata efficiency on smart accounts prevalent on L2s.
///
/// WARNING! Do NOT use signatures as unique identifiers:
/// - Use a nonce in the digest to prevent replay attacks on the same contract.
/// - Use EIP-712 for the digest to prevent replay attacks across different chains and contracts.
///   EIP-712 also enables readable signing of typed data for better user safety.
/// This implementation does NOT check if a signature is non-malleable.
library ECDSA {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                        CUSTOM ERRORS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The signature is invalid.
    error InvalidSignature();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                    RECOVERY OPERATIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Recovers the signer's address from a message digest `hash`, and the `signature`.
    function recover(bytes32 hash, bytes memory signature) internal view returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := 1
            let m := mload(0x40) // Cache the free memory pointer.
            for {} 1 {} {
                mstore(0x00, hash)
                mstore(0x40, mload(add(signature, 0x20))) // `r`.
                if eq(mload(signature), 64) {
                    let vs := mload(add(signature, 0x40))
                    mstore(0x20, add(shr(255, vs), 27)) // `v`.
                    mstore(0x60, shr(1, shl(1, vs))) // `s`.
                    break
                }
                if eq(mload(signature), 65) {
                    mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`.
                    mstore(0x60, mload(add(signature, 0x40))) // `s`.
                    break
                }
                result := 0
                break
            }
            result :=
                mload(
                    staticcall(
                        gas(), // Amount of gas left for the transaction.
                        result, // Address of `ecrecover`.
                        0x00, // Start of input.
                        0x80, // Size of input.
                        0x01, // Start of output.
                        0x20 // Size of output.
                    )
                )
            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
            if iszero(returndatasize()) {
                mstore(0x00, 0x8baa579f) // `InvalidSignature()`.
                revert(0x1c, 0x04)
            }
            mstore(0x60, 0) // Restore the zero slot.
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Recovers the signer's address from a message digest `hash`, and the `signature`.
    function recoverCalldata(bytes32 hash, bytes calldata signature)
        internal
        view
        returns (address result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            result := 1
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x00, hash)
            for {} 1 {} {
                if eq(signature.length, 64) {
                    let vs := calldataload(add(signature.offset, 0x20))
                    mstore(0x20, add(shr(255, vs), 27)) // `v`.
                    mstore(0x40, calldataload(signature.offset)) // `r`.
                    mstore(0x60, shr(1, shl(1, vs))) // `s`.
                    break
                }
                if eq(signature.length, 65) {
                    mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`.
                    calldatacopy(0x40, signature.offset, 0x40) // Copy `r` and `s`.
                    break
                }
                result := 0
                break
            }
            result :=
                mload(
                    staticcall(
                        gas(), // Amount of gas left for the transaction.
                        result, // Address of `ecrecover`.
                        0x00, // Start of input.
                        0x80, // Size of input.
                        0x01, // Start of output.
                        0x20 // Size of output.
                    )
                )
            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
            if iszero(returndatasize()) {
                mstore(0x00, 0x8baa579f) // `InvalidSignature()`.
                revert(0x1c, 0x04)
            }
            mstore(0x60, 0) // Restore the zero slot.
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Recovers the signer's address from a message digest `hash`,
    /// and the EIP-2098 short form signature defined by `r` and `vs`.
    function recover(bytes32 hash, bytes32 r, bytes32 vs) internal view returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x00, hash)
            mstore(0x20, add(shr(255, vs), 27)) // `v`.
            mstore(0x40, r)
            mstore(0x60, shr(1, shl(1, vs))) // `s`.
            result :=
                mload(
                    staticcall(
                        gas(), // Amount of gas left for the transaction.
                        1, // Address of `ecrecover`.
                        0x00, // Start of input.
                        0x80, // Size of input.
                        0x01, // Start of output.
                        0x20 // Size of output.
                    )
                )
            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
            if iszero(returndatasize()) {
                mstore(0x00, 0x8baa579f) // `InvalidSignature()`.
                revert(0x1c, 0x04)
            }
            mstore(0x60, 0) // Restore the zero slot.
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Recovers the signer's address from a message digest `hash`,
    /// and the signature defined by `v`, `r`, `s`.
    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s)
        internal
        view
        returns (address result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x00, hash)
            mstore(0x20, and(v, 0xff))
            mstore(0x40, r)
            mstore(0x60, s)
            result :=
                mload(
                    staticcall(
                        gas(), // Amount of gas left for the transaction.
                        1, // Address of `ecrecover`.
                        0x00, // Start of input.
                        0x80, // Size of input.
                        0x01, // Start of output.
                        0x20 // Size of output.
                    )
                )
            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
            if iszero(returndatasize()) {
                mstore(0x00, 0x8baa579f) // `InvalidSignature()`.
                revert(0x1c, 0x04)
            }
            mstore(0x60, 0) // Restore the zero slot.
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   TRY-RECOVER OPERATIONS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    // WARNING!
    // These functions will NOT revert upon recovery failure.
    // Instead, they will return the zero address upon recovery failure.
    // It is critical that the returned address is NEVER compared against
    // a zero address (e.g. an uninitialized address variable).

    /// @dev Recovers the signer's address from a message digest `hash`, and the `signature`.
    function tryRecover(bytes32 hash, bytes memory signature)
        internal
        view
        returns (address result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            result := 1
            let m := mload(0x40) // Cache the free memory pointer.
            for {} 1 {} {
                mstore(0x00, hash)
                mstore(0x40, mload(add(signature, 0x20))) // `r`.
                if eq(mload(signature), 64) {
                    let vs := mload(add(signature, 0x40))
                    mstore(0x20, add(shr(255, vs), 27)) // `v`.
                    mstore(0x60, shr(1, shl(1, vs))) // `s`.
                    break
                }
                if eq(mload(signature), 65) {
                    mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`.
                    mstore(0x60, mload(add(signature, 0x40))) // `s`.
                    break
                }
                result := 0
                break
            }
            pop(
                staticcall(
                    gas(), // Amount of gas left for the transaction.
                    result, // Address of `ecrecover`.
                    0x00, // Start of input.
                    0x80, // Size of input.
                    0x40, // Start of output.
                    0x20 // Size of output.
                )
            )
            mstore(0x60, 0) // Restore the zero slot.
            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
            result := mload(xor(0x60, returndatasize()))
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Recovers the signer's address from a message digest `hash`, and the `signature`.
    function tryRecoverCalldata(bytes32 hash, bytes calldata signature)
        internal
        view
        returns (address result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            result := 1
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x00, hash)
            for {} 1 {} {
                if eq(signature.length, 64) {
                    let vs := calldataload(add(signature.offset, 0x20))
                    mstore(0x20, add(shr(255, vs), 27)) // `v`.
                    mstore(0x40, calldataload(signature.offset)) // `r`.
                    mstore(0x60, shr(1, shl(1, vs))) // `s`.
                    break
                }
                if eq(signature.length, 65) {
                    mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`.
                    calldatacopy(0x40, signature.offset, 0x40) // Copy `r` and `s`.
                    break
                }
                result := 0
                break
            }
            pop(
                staticcall(
                    gas(), // Amount of gas left for the transaction.
                    result, // Address of `ecrecover`.
                    0x00, // Start of input.
                    0x80, // Size of input.
                    0x40, // Start of output.
                    0x20 // Size of output.
                )
            )
            mstore(0x60, 0) // Restore the zero slot.
            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
            result := mload(xor(0x60, returndatasize()))
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Recovers the signer's address from a message digest `hash`,
    /// and the EIP-2098 short form signature defined by `r` and `vs`.
    function tryRecover(bytes32 hash, bytes32 r, bytes32 vs)
        internal
        view
        returns (address result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x00, hash)
            mstore(0x20, add(shr(255, vs), 27)) // `v`.
            mstore(0x40, r)
            mstore(0x60, shr(1, shl(1, vs))) // `s`.
            pop(
                staticcall(
                    gas(), // Amount of gas left for the transaction.
                    1, // Address of `ecrecover`.
                    0x00, // Start of input.
                    0x80, // Size of input.
                    0x40, // Start of output.
                    0x20 // Size of output.
                )
            )
            mstore(0x60, 0) // Restore the zero slot.
            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
            result := mload(xor(0x60, returndatasize()))
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Recovers the signer's address from a message digest `hash`,
    /// and the signature defined by `v`, `r`, `s`.
    function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s)
        internal
        view
        returns (address result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x00, hash)
            mstore(0x20, and(v, 0xff))
            mstore(0x40, r)
            mstore(0x60, s)
            pop(
                staticcall(
                    gas(), // Amount of gas left for the transaction.
                    1, // Address of `ecrecover`.
                    0x00, // Start of input.
                    0x80, // Size of input.
                    0x40, // Start of output.
                    0x20 // Size of output.
                )
            )
            mstore(0x60, 0) // Restore the zero slot.
            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
            result := mload(xor(0x60, returndatasize()))
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     HASHING OPERATIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns an Ethereum Signed Message, created from a `hash`.
    /// This produces a hash corresponding to the one signed with the
    /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign)
    /// JSON-RPC method as part of EIP-191.
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x20, hash) // Store into scratch space for keccak256.
            mstore(0x00, "\x00\x00\x00\x00\x19Ethereum Signed Message:\n32") // 28 bytes.
            result := keccak256(0x04, 0x3c) // `32 * 2 - (32 - 28) = 60 = 0x3c`.
        }
    }

    /// @dev Returns an Ethereum Signed Message, created from `s`.
    /// This produces a hash corresponding to the one signed with the
    /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign)
    /// JSON-RPC method as part of EIP-191.
    /// Note: Supports lengths of `s` up to 999999 bytes.
    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let sLength := mload(s)
            let o := 0x20
            mstore(o, "\x19Ethereum Signed Message:\n") // 26 bytes, zero-right-padded.
            mstore(0x00, 0x00)
            // Convert the `s.length` to ASCII decimal representation: `base10(s.length)`.
            for { let temp := sLength } 1 {} {
                o := sub(o, 1)
                mstore8(o, add(48, mod(temp, 10)))
                temp := div(temp, 10)
                if iszero(temp) { break }
            }
            let n := sub(0x3a, o) // Header length: `26 + 32 - o`.
            // Throw an out-of-offset error (consumes all gas) if the header exceeds 32 bytes.
            returndatacopy(returndatasize(), returndatasize(), gt(n, 0x20))
            mstore(s, or(mload(0x00), mload(n))) // Temporarily store the header.
            result := keccak256(add(s, sub(0x20, n)), add(n, sLength))
            mstore(s, sLength) // Restore the length.
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   EMPTY CALLDATA HELPERS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns an empty calldata bytes.
    function emptySignature() internal pure returns (bytes calldata signature) {
        /// @solidity memory-safe-assembly
        assembly {
            signature.length := 0
        }
    }
}

File 6 of 13: ERC20.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Simple ERC20 + EIP-2612 implementation.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/tokens/ERC20.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol)
///
/// @dev Note:
/// - The ERC20 standard allows minting and transferring to and from the zero address,
///   minting and transferring zero tokens, as well as self-approvals.
///   For performance, this implementation WILL NOT revert for such actions.
///   Please add any checks with overrides if desired.
/// - The `permit` function uses the ecrecover precompile (0x1).
///
/// If you are overriding:
/// - NEVER violate the ERC20 invariant:
///   the total sum of all balances must be equal to `totalSupply()`.
/// - Check that the overridden function is actually used in the function you want to
///   change the behavior of. Much of the code has been manually inlined for performance.
abstract contract ERC20 {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The total supply has overflowed.
    error TotalSupplyOverflow();

    /// @dev The allowance has overflowed.
    error AllowanceOverflow();

    /// @dev The allowance has underflowed.
    error AllowanceUnderflow();

    /// @dev Insufficient balance.
    error InsufficientBalance();

    /// @dev Insufficient allowance.
    error InsufficientAllowance();

    /// @dev The permit is invalid.
    error InvalidPermit();

    /// @dev The permit has expired.
    error PermitExpired();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                           EVENTS                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Emitted when `amount` tokens is transferred from `from` to `to`.
    event Transfer(address indexed from, address indexed to, uint256 amount);

    /// @dev Emitted when `amount` tokens is approved by `owner` to be used by `spender`.
    event Approval(address indexed owner, address indexed spender, uint256 amount);

    /// @dev `keccak256(bytes("Transfer(address,address,uint256)"))`.
    uint256 private constant _TRANSFER_EVENT_SIGNATURE =
        0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef;

    /// @dev `keccak256(bytes("Approval(address,address,uint256)"))`.
    uint256 private constant _APPROVAL_EVENT_SIGNATURE =
        0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                          STORAGE                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The storage slot for the total supply.
    uint256 private constant _TOTAL_SUPPLY_SLOT = 0x05345cdf77eb68f44c;

    /// @dev The balance slot of `owner` is given by:
    /// ```
    ///     mstore(0x0c, _BALANCE_SLOT_SEED)
    ///     mstore(0x00, owner)
    ///     let balanceSlot := keccak256(0x0c, 0x20)
    /// ```
    uint256 private constant _BALANCE_SLOT_SEED = 0x87a211a2;

    /// @dev The allowance slot of (`owner`, `spender`) is given by:
    /// ```
    ///     mstore(0x20, spender)
    ///     mstore(0x0c, _ALLOWANCE_SLOT_SEED)
    ///     mstore(0x00, owner)
    ///     let allowanceSlot := keccak256(0x0c, 0x34)
    /// ```
    uint256 private constant _ALLOWANCE_SLOT_SEED = 0x7f5e9f20;

    /// @dev The nonce slot of `owner` is given by:
    /// ```
    ///     mstore(0x0c, _NONCES_SLOT_SEED)
    ///     mstore(0x00, owner)
    ///     let nonceSlot := keccak256(0x0c, 0x20)
    /// ```
    uint256 private constant _NONCES_SLOT_SEED = 0x38377508;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         CONSTANTS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev `(_NONCES_SLOT_SEED << 16) | 0x1901`.
    uint256 private constant _NONCES_SLOT_SEED_WITH_SIGNATURE_PREFIX = 0x383775081901;

    /// @dev `keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")`.
    bytes32 private constant _DOMAIN_TYPEHASH =
        0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f;

    /// @dev `keccak256("1")`.
    bytes32 private constant _VERSION_HASH =
        0xc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6;

    /// @dev `keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)")`.
    bytes32 private constant _PERMIT_TYPEHASH =
        0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       ERC20 METADATA                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the name of the token.
    function name() public view virtual returns (string memory);

    /// @dev Returns the symbol of the token.
    function symbol() public view virtual returns (string memory);

    /// @dev Returns the decimals places of the token.
    function decimals() public view virtual returns (uint8) {
        return 18;
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                           ERC20                            */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the amount of tokens in existence.
    function totalSupply() public view virtual returns (uint256 result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := sload(_TOTAL_SUPPLY_SLOT)
        }
    }

    /// @dev Returns the amount of tokens owned by `owner`.
    function balanceOf(address owner) public view virtual returns (uint256 result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x0c, _BALANCE_SLOT_SEED)
            mstore(0x00, owner)
            result := sload(keccak256(0x0c, 0x20))
        }
    }

    /// @dev Returns the amount of tokens that `spender` can spend on behalf of `owner`.
    function allowance(address owner, address spender)
        public
        view
        virtual
        returns (uint256 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x20, spender)
            mstore(0x0c, _ALLOWANCE_SLOT_SEED)
            mstore(0x00, owner)
            result := sload(keccak256(0x0c, 0x34))
        }
    }

    /// @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
    ///
    /// Emits a {Approval} event.
    function approve(address spender, uint256 amount) public virtual returns (bool) {
        /// @solidity memory-safe-assembly
        assembly {
            // Compute the allowance slot and store the amount.
            mstore(0x20, spender)
            mstore(0x0c, _ALLOWANCE_SLOT_SEED)
            mstore(0x00, caller())
            sstore(keccak256(0x0c, 0x34), amount)
            // Emit the {Approval} event.
            mstore(0x00, amount)
            log3(0x00, 0x20, _APPROVAL_EVENT_SIGNATURE, caller(), shr(96, mload(0x2c)))
        }
        return true;
    }

    /// @dev Transfer `amount` tokens from the caller to `to`.
    ///
    /// Requirements:
    /// - `from` must at least have `amount`.
    ///
    /// Emits a {Transfer} event.
    function transfer(address to, uint256 amount) public virtual returns (bool) {
        _beforeTokenTransfer(msg.sender, to, amount);
        /// @solidity memory-safe-assembly
        assembly {
            // Compute the balance slot and load its value.
            mstore(0x0c, _BALANCE_SLOT_SEED)
            mstore(0x00, caller())
            let fromBalanceSlot := keccak256(0x0c, 0x20)
            let fromBalance := sload(fromBalanceSlot)
            // Revert if insufficient balance.
            if gt(amount, fromBalance) {
                mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`.
                revert(0x1c, 0x04)
            }
            // Subtract and store the updated balance.
            sstore(fromBalanceSlot, sub(fromBalance, amount))
            // Compute the balance slot of `to`.
            mstore(0x00, to)
            let toBalanceSlot := keccak256(0x0c, 0x20)
            // Add and store the updated balance of `to`.
            // Will not overflow because the sum of all user balances
            // cannot exceed the maximum uint256 value.
            sstore(toBalanceSlot, add(sload(toBalanceSlot), amount))
            // Emit the {Transfer} event.
            mstore(0x20, amount)
            log3(0x20, 0x20, _TRANSFER_EVENT_SIGNATURE, caller(), shr(96, mload(0x0c)))
        }
        _afterTokenTransfer(msg.sender, to, amount);
        return true;
    }

    /// @dev Transfers `amount` tokens from `from` to `to`.
    ///
    /// Note: Does not update the allowance if it is the maximum uint256 value.
    ///
    /// Requirements:
    /// - `from` must at least have `amount`.
    /// - The caller must have at least `amount` of allowance to transfer the tokens of `from`.
    ///
    /// Emits a {Transfer} event.
    function transferFrom(address from, address to, uint256 amount) public virtual returns (bool) {
        _beforeTokenTransfer(from, to, amount);
        /// @solidity memory-safe-assembly
        assembly {
            let from_ := shl(96, from)
            // Compute the allowance slot and load its value.
            mstore(0x20, caller())
            mstore(0x0c, or(from_, _ALLOWANCE_SLOT_SEED))
            let allowanceSlot := keccak256(0x0c, 0x34)
            let allowance_ := sload(allowanceSlot)
            // If the allowance is not the maximum uint256 value.
            if add(allowance_, 1) {
                // Revert if the amount to be transferred exceeds the allowance.
                if gt(amount, allowance_) {
                    mstore(0x00, 0x13be252b) // `InsufficientAllowance()`.
                    revert(0x1c, 0x04)
                }
                // Subtract and store the updated allowance.
                sstore(allowanceSlot, sub(allowance_, amount))
            }
            // Compute the balance slot and load its value.
            mstore(0x0c, or(from_, _BALANCE_SLOT_SEED))
            let fromBalanceSlot := keccak256(0x0c, 0x20)
            let fromBalance := sload(fromBalanceSlot)
            // Revert if insufficient balance.
            if gt(amount, fromBalance) {
                mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`.
                revert(0x1c, 0x04)
            }
            // Subtract and store the updated balance.
            sstore(fromBalanceSlot, sub(fromBalance, amount))
            // Compute the balance slot of `to`.
            mstore(0x00, to)
            let toBalanceSlot := keccak256(0x0c, 0x20)
            // Add and store the updated balance of `to`.
            // Will not overflow because the sum of all user balances
            // cannot exceed the maximum uint256 value.
            sstore(toBalanceSlot, add(sload(toBalanceSlot), amount))
            // Emit the {Transfer} event.
            mstore(0x20, amount)
            log3(0x20, 0x20, _TRANSFER_EVENT_SIGNATURE, shr(96, from_), shr(96, mload(0x0c)))
        }
        _afterTokenTransfer(from, to, amount);
        return true;
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                          EIP-2612                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev For more performance, override to return the constant value
    /// of `keccak256(bytes(name()))` if `name()` will never change.
    function _constantNameHash() internal view virtual returns (bytes32 result) {}

    /// @dev Returns the current nonce for `owner`.
    /// This value is used to compute the signature for EIP-2612 permit.
    function nonces(address owner) public view virtual returns (uint256 result) {
        /// @solidity memory-safe-assembly
        assembly {
            // Compute the nonce slot and load its value.
            mstore(0x0c, _NONCES_SLOT_SEED)
            mstore(0x00, owner)
            result := sload(keccak256(0x0c, 0x20))
        }
    }

    /// @dev Sets `value` as the allowance of `spender` over the tokens of `owner`,
    /// authorized by a signed approval by `owner`.
    ///
    /// Emits a {Approval} event.
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual {
        bytes32 nameHash = _constantNameHash();
        //  We simply calculate it on-the-fly to allow for cases where the `name` may change.
        if (nameHash == bytes32(0)) nameHash = keccak256(bytes(name()));
        /// @solidity memory-safe-assembly
        assembly {
            // Revert if the block timestamp is greater than `deadline`.
            if gt(timestamp(), deadline) {
                mstore(0x00, 0x1a15a3cc) // `PermitExpired()`.
                revert(0x1c, 0x04)
            }
            let m := mload(0x40) // Grab the free memory pointer.
            // Clean the upper 96 bits.
            owner := shr(96, shl(96, owner))
            spender := shr(96, shl(96, spender))
            // Compute the nonce slot and load its value.
            mstore(0x0e, _NONCES_SLOT_SEED_WITH_SIGNATURE_PREFIX)
            mstore(0x00, owner)
            let nonceSlot := keccak256(0x0c, 0x20)
            let nonceValue := sload(nonceSlot)
            // Prepare the domain separator.
            mstore(m, _DOMAIN_TYPEHASH)
            mstore(add(m, 0x20), nameHash)
            mstore(add(m, 0x40), _VERSION_HASH)
            mstore(add(m, 0x60), chainid())
            mstore(add(m, 0x80), address())
            mstore(0x2e, keccak256(m, 0xa0))
            // Prepare the struct hash.
            mstore(m, _PERMIT_TYPEHASH)
            mstore(add(m, 0x20), owner)
            mstore(add(m, 0x40), spender)
            mstore(add(m, 0x60), value)
            mstore(add(m, 0x80), nonceValue)
            mstore(add(m, 0xa0), deadline)
            mstore(0x4e, keccak256(m, 0xc0))
            // Prepare the ecrecover calldata.
            mstore(0x00, keccak256(0x2c, 0x42))
            mstore(0x20, and(0xff, v))
            mstore(0x40, r)
            mstore(0x60, s)
            let t := staticcall(gas(), 1, 0, 0x80, 0x20, 0x20)
            // If the ecrecover fails, the returndatasize will be 0x00,
            // `owner` will be checked if it equals the hash at 0x00,
            // which evaluates to false (i.e. 0), and we will revert.
            // If the ecrecover succeeds, the returndatasize will be 0x20,
            // `owner` will be compared against the returned address at 0x20.
            if iszero(eq(mload(returndatasize()), owner)) {
                mstore(0x00, 0xddafbaef) // `InvalidPermit()`.
                revert(0x1c, 0x04)
            }
            // Increment and store the updated nonce.
            sstore(nonceSlot, add(nonceValue, t)) // `t` is 1 if ecrecover succeeds.
            // Compute the allowance slot and store the value.
            // The `owner` is already at slot 0x20.
            mstore(0x40, or(shl(160, _ALLOWANCE_SLOT_SEED), spender))
            sstore(keccak256(0x2c, 0x34), value)
            // Emit the {Approval} event.
            log3(add(m, 0x60), 0x20, _APPROVAL_EVENT_SIGNATURE, owner, spender)
            mstore(0x40, m) // Restore the free memory pointer.
            mstore(0x60, 0) // Restore the zero pointer.
        }
    }

    /// @dev Returns the EIP-712 domain separator for the EIP-2612 permit.
    function DOMAIN_SEPARATOR() public view virtual returns (bytes32 result) {
        bytes32 nameHash = _constantNameHash();
        //  We simply calculate it on-the-fly to allow for cases where the `name` may change.
        if (nameHash == bytes32(0)) nameHash = keccak256(bytes(name()));
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Grab the free memory pointer.
            mstore(m, _DOMAIN_TYPEHASH)
            mstore(add(m, 0x20), nameHash)
            mstore(add(m, 0x40), _VERSION_HASH)
            mstore(add(m, 0x60), chainid())
            mstore(add(m, 0x80), address())
            result := keccak256(m, 0xa0)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  INTERNAL MINT FUNCTIONS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Mints `amount` tokens to `to`, increasing the total supply.
    ///
    /// Emits a {Transfer} event.
    function _mint(address to, uint256 amount) internal virtual {
        _beforeTokenTransfer(address(0), to, amount);
        /// @solidity memory-safe-assembly
        assembly {
            let totalSupplyBefore := sload(_TOTAL_SUPPLY_SLOT)
            let totalSupplyAfter := add(totalSupplyBefore, amount)
            // Revert if the total supply overflows.
            if lt(totalSupplyAfter, totalSupplyBefore) {
                mstore(0x00, 0xe5cfe957) // `TotalSupplyOverflow()`.
                revert(0x1c, 0x04)
            }
            // Store the updated total supply.
            sstore(_TOTAL_SUPPLY_SLOT, totalSupplyAfter)
            // Compute the balance slot and load its value.
            mstore(0x0c, _BALANCE_SLOT_SEED)
            mstore(0x00, to)
            let toBalanceSlot := keccak256(0x0c, 0x20)
            // Add and store the updated balance.
            sstore(toBalanceSlot, add(sload(toBalanceSlot), amount))
            // Emit the {Transfer} event.
            mstore(0x20, amount)
            log3(0x20, 0x20, _TRANSFER_EVENT_SIGNATURE, 0, shr(96, mload(0x0c)))
        }
        _afterTokenTransfer(address(0), to, amount);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  INTERNAL BURN FUNCTIONS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Burns `amount` tokens from `from`, reducing the total supply.
    ///
    /// Emits a {Transfer} event.
    function _burn(address from, uint256 amount) internal virtual {
        _beforeTokenTransfer(from, address(0), amount);
        /// @solidity memory-safe-assembly
        assembly {
            // Compute the balance slot and load its value.
            mstore(0x0c, _BALANCE_SLOT_SEED)
            mstore(0x00, from)
            let fromBalanceSlot := keccak256(0x0c, 0x20)
            let fromBalance := sload(fromBalanceSlot)
            // Revert if insufficient balance.
            if gt(amount, fromBalance) {
                mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`.
                revert(0x1c, 0x04)
            }
            // Subtract and store the updated balance.
            sstore(fromBalanceSlot, sub(fromBalance, amount))
            // Subtract and store the updated total supply.
            sstore(_TOTAL_SUPPLY_SLOT, sub(sload(_TOTAL_SUPPLY_SLOT), amount))
            // Emit the {Transfer} event.
            mstore(0x00, amount)
            log3(0x00, 0x20, _TRANSFER_EVENT_SIGNATURE, shr(96, shl(96, from)), 0)
        }
        _afterTokenTransfer(from, address(0), amount);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                INTERNAL TRANSFER FUNCTIONS                 */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Moves `amount` of tokens from `from` to `to`.
    function _transfer(address from, address to, uint256 amount) internal virtual {
        _beforeTokenTransfer(from, to, amount);
        /// @solidity memory-safe-assembly
        assembly {
            let from_ := shl(96, from)
            // Compute the balance slot and load its value.
            mstore(0x0c, or(from_, _BALANCE_SLOT_SEED))
            let fromBalanceSlot := keccak256(0x0c, 0x20)
            let fromBalance := sload(fromBalanceSlot)
            // Revert if insufficient balance.
            if gt(amount, fromBalance) {
                mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`.
                revert(0x1c, 0x04)
            }
            // Subtract and store the updated balance.
            sstore(fromBalanceSlot, sub(fromBalance, amount))
            // Compute the balance slot of `to`.
            mstore(0x00, to)
            let toBalanceSlot := keccak256(0x0c, 0x20)
            // Add and store the updated balance of `to`.
            // Will not overflow because the sum of all user balances
            // cannot exceed the maximum uint256 value.
            sstore(toBalanceSlot, add(sload(toBalanceSlot), amount))
            // Emit the {Transfer} event.
            mstore(0x20, amount)
            log3(0x20, 0x20, _TRANSFER_EVENT_SIGNATURE, shr(96, from_), shr(96, mload(0x0c)))
        }
        _afterTokenTransfer(from, to, amount);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                INTERNAL ALLOWANCE FUNCTIONS                */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Updates the allowance of `owner` for `spender` based on spent `amount`.
    function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {
        /// @solidity memory-safe-assembly
        assembly {
            // Compute the allowance slot and load its value.
            mstore(0x20, spender)
            mstore(0x0c, _ALLOWANCE_SLOT_SEED)
            mstore(0x00, owner)
            let allowanceSlot := keccak256(0x0c, 0x34)
            let allowance_ := sload(allowanceSlot)
            // If the allowance is not the maximum uint256 value.
            if add(allowance_, 1) {
                // Revert if the amount to be transferred exceeds the allowance.
                if gt(amount, allowance_) {
                    mstore(0x00, 0x13be252b) // `InsufficientAllowance()`.
                    revert(0x1c, 0x04)
                }
                // Subtract and store the updated allowance.
                sstore(allowanceSlot, sub(allowance_, amount))
            }
        }
    }

    /// @dev Sets `amount` as the allowance of `spender` over the tokens of `owner`.
    ///
    /// Emits a {Approval} event.
    function _approve(address owner, address spender, uint256 amount) internal virtual {
        /// @solidity memory-safe-assembly
        assembly {
            let owner_ := shl(96, owner)
            // Compute the allowance slot and store the amount.
            mstore(0x20, spender)
            mstore(0x0c, or(owner_, _ALLOWANCE_SLOT_SEED))
            sstore(keccak256(0x0c, 0x34), amount)
            // Emit the {Approval} event.
            mstore(0x00, amount)
            log3(0x00, 0x20, _APPROVAL_EVENT_SIGNATURE, shr(96, owner_), shr(96, mload(0x2c)))
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     HOOKS TO OVERRIDE                      */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Hook that is called before any transfer of tokens.
    /// This includes minting and burning.
    function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}

    /// @dev Hook that is called after any transfer of tokens.
    /// This includes minting and burning.
    function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}
}

File 7 of 13: ICheezburger.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.22;

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

interface ICheezburger is CheezburgerStructs {
    function socialTokens(
        uint256 id
    )
        external
        view
        returns (
            address,
            address,
            address,
            address,
            address,
            address,
            LiquiditySettings calldata,
            DynamicSettings calldata,
            DynamicSettings calldata,
            ReferralSettings calldata
        );

    function withdrawFeesOf(
        uint256 _userId,
        address _to
    ) external returns (uint256);
}

File 8 of 13: ICheezburgerFactory.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.22;

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

interface ICheezburgerFactory is CheezburgerStructs {
    function deployWithToken(
        TokenCustomization memory _customization,
        address _router,
        address _rightSide,
        uint256 _rightSideAmount,
        LiquiditySettings memory _liquidity,
        DynamicSettings memory _fee,
        DynamicSettings memory _wallet,
        ReferralSettings memory _referral
    ) external returns (address);

    function burgerRegistry(
        address token
    )
        external
        view
        returns (
            address,
            address,
            address,
            address,
            address,
            address,
            LiquiditySettings calldata,
            DynamicSettings calldata,
            DynamicSettings calldata,
            ReferralSettings calldata
        );
}

File 9 of 13: LibString.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Library for converting numbers into strings and other string operations.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibString.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/LibString.sol)
library LibString {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                        CUSTOM ERRORS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The `length` of the output is too small to contain all the hex digits.
    error HexLengthInsufficient();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         CONSTANTS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The constant returned when the `search` is not found in the string.
    uint256 internal constant NOT_FOUND = type(uint256).max;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     DECIMAL OPERATIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the base 10 decimal representation of `value`.
    function toString(uint256 value) internal pure returns (string memory str) {
        /// @solidity memory-safe-assembly
        assembly {
            // The maximum value of a uint256 contains 78 digits (1 byte per digit), but
            // we allocate 0xa0 bytes to keep the free memory pointer 32-byte word aligned.
            // We will need 1 word for the trailing zeros padding, 1 word for the length,
            // and 3 words for a maximum of 78 digits.
            str := add(mload(0x40), 0x80)
            // Update the free memory pointer to allocate.
            mstore(0x40, add(str, 0x20))
            // Zeroize the slot after the string.
            mstore(str, 0)

            // Cache the end of the memory to calculate the length later.
            let end := str

            let w := not(0) // Tsk.
            // We write the string from rightmost digit to leftmost digit.
            // The following is essentially a do-while loop that also handles the zero case.
            for { let temp := value } 1 {} {
                str := add(str, w) // `sub(str, 1)`.
                // Write the character to the pointer.
                // The ASCII index of the '0' character is 48.
                mstore8(str, add(48, mod(temp, 10)))
                // Keep dividing `temp` until zero.
                temp := div(temp, 10)
                if iszero(temp) { break }
            }

            let length := sub(end, str)
            // Move the pointer 32 bytes leftwards to make room for the length.
            str := sub(str, 0x20)
            // Store the length.
            mstore(str, length)
        }
    }

    /// @dev Returns the base 10 decimal representation of `value`.
    function toString(int256 value) internal pure returns (string memory str) {
        if (value >= 0) {
            return toString(uint256(value));
        }
        unchecked {
            str = toString(uint256(-value));
        }
        /// @solidity memory-safe-assembly
        assembly {
            // We still have some spare memory space on the left,
            // as we have allocated 3 words (96 bytes) for up to 78 digits.
            let length := mload(str) // Load the string length.
            mstore(str, 0x2d) // Store the '-' character.
            str := sub(str, 1) // Move back the string pointer by a byte.
            mstore(str, add(length, 1)) // Update the string length.
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   HEXADECIMAL OPERATIONS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the hexadecimal representation of `value`,
    /// left-padded to an input length of `length` bytes.
    /// The output is prefixed with "0x" encoded using 2 hexadecimal digits per byte,
    /// giving a total length of `length * 2 + 2` bytes.
    /// Reverts if `length` is too small for the output to contain all the digits.
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory str) {
        str = toHexStringNoPrefix(value, length);
        /// @solidity memory-safe-assembly
        assembly {
            let strLength := add(mload(str), 2) // Compute the length.
            mstore(str, 0x3078) // Write the "0x" prefix.
            str := sub(str, 2) // Move the pointer.
            mstore(str, strLength) // Write the length.
        }
    }

    /// @dev Returns the hexadecimal representation of `value`,
    /// left-padded to an input length of `length` bytes.
    /// The output is prefixed with "0x" encoded using 2 hexadecimal digits per byte,
    /// giving a total length of `length * 2` bytes.
    /// Reverts if `length` is too small for the output to contain all the digits.
    function toHexStringNoPrefix(uint256 value, uint256 length)
        internal
        pure
        returns (string memory str)
    {
        /// @solidity memory-safe-assembly
        assembly {
            // We need 0x20 bytes for the trailing zeros padding, `length * 2` bytes
            // for the digits, 0x02 bytes for the prefix, and 0x20 bytes for the length.
            // We add 0x20 to the total and round down to a multiple of 0x20.
            // (0x20 + 0x20 + 0x02 + 0x20) = 0x62.
            str := add(mload(0x40), and(add(shl(1, length), 0x42), not(0x1f)))
            // Allocate the memory.
            mstore(0x40, add(str, 0x20))
            // Zeroize the slot after the string.
            mstore(str, 0)

            // Cache the end to calculate the length later.
            let end := str
            // Store "0123456789abcdef" in scratch space.
            mstore(0x0f, 0x30313233343536373839616263646566)

            let start := sub(str, add(length, length))
            let w := not(1) // Tsk.
            let temp := value
            // We write the string from rightmost digit to leftmost digit.
            // The following is essentially a do-while loop that also handles the zero case.
            for {} 1 {} {
                str := add(str, w) // `sub(str, 2)`.
                mstore8(add(str, 1), mload(and(temp, 15)))
                mstore8(str, mload(and(shr(4, temp), 15)))
                temp := shr(8, temp)
                if iszero(xor(str, start)) { break }
            }

            if temp {
                // Store the function selector of `HexLengthInsufficient()`.
                mstore(0x00, 0x2194895a)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }

            // Compute the string's length.
            let strLength := sub(end, str)
            // Move the pointer and write the length.
            str := sub(str, 0x20)
            mstore(str, strLength)
        }
    }

    /// @dev Returns the hexadecimal representation of `value`.
    /// The output is prefixed with "0x" and encoded using 2 hexadecimal digits per byte.
    /// As address are 20 bytes long, the output will left-padded to have
    /// a length of `20 * 2 + 2` bytes.
    function toHexString(uint256 value) internal pure returns (string memory str) {
        str = toHexStringNoPrefix(value);
        /// @solidity memory-safe-assembly
        assembly {
            let strLength := add(mload(str), 2) // Compute the length.
            mstore(str, 0x3078) // Write the "0x" prefix.
            str := sub(str, 2) // Move the pointer.
            mstore(str, strLength) // Write the length.
        }
    }

    /// @dev Returns the hexadecimal representation of `value`.
    /// The output is prefixed with "0x".
    /// The output excludes leading "0" from the `toHexString` output.
    /// `0x00: "0x0", 0x01: "0x1", 0x12: "0x12", 0x123: "0x123"`.
    function toMinimalHexString(uint256 value) internal pure returns (string memory str) {
        str = toHexStringNoPrefix(value);
        /// @solidity memory-safe-assembly
        assembly {
            let o := eq(byte(0, mload(add(str, 0x20))), 0x30) // Whether leading zero is present.
            let strLength := add(mload(str), 2) // Compute the length.
            mstore(add(str, o), 0x3078) // Write the "0x" prefix, accounting for leading zero.
            str := sub(add(str, o), 2) // Move the pointer, accounting for leading zero.
            mstore(str, sub(strLength, o)) // Write the length, accounting for leading zero.
        }
    }

    /// @dev Returns the hexadecimal representation of `value`.
    /// The output excludes leading "0" from the `toHexStringNoPrefix` output.
    /// `0x00: "0", 0x01: "1", 0x12: "12", 0x123: "123"`.
    function toMinimalHexStringNoPrefix(uint256 value) internal pure returns (string memory str) {
        str = toHexStringNoPrefix(value);
        /// @solidity memory-safe-assembly
        assembly {
            let o := eq(byte(0, mload(add(str, 0x20))), 0x30) // Whether leading zero is present.
            let strLength := mload(str) // Get the length.
            str := add(str, o) // Move the pointer, accounting for leading zero.
            mstore(str, sub(strLength, o)) // Write the length, accounting for leading zero.
        }
    }

    /// @dev Returns the hexadecimal representation of `value`.
    /// The output is encoded using 2 hexadecimal digits per byte.
    /// As address are 20 bytes long, the output will left-padded to have
    /// a length of `20 * 2` bytes.
    function toHexStringNoPrefix(uint256 value) internal pure returns (string memory str) {
        /// @solidity memory-safe-assembly
        assembly {
            // We need 0x20 bytes for the trailing zeros padding, 0x20 bytes for the length,
            // 0x02 bytes for the prefix, and 0x40 bytes for the digits.
            // The next multiple of 0x20 above (0x20 + 0x20 + 0x02 + 0x40) is 0xa0.
            str := add(mload(0x40), 0x80)
            // Allocate the memory.
            mstore(0x40, add(str, 0x20))
            // Zeroize the slot after the string.
            mstore(str, 0)

            // Cache the end to calculate the length later.
            let end := str
            // Store "0123456789abcdef" in scratch space.
            mstore(0x0f, 0x30313233343536373839616263646566)

            let w := not(1) // Tsk.
            // We write the string from rightmost digit to leftmost digit.
            // The following is essentially a do-while loop that also handles the zero case.
            for { let temp := value } 1 {} {
                str := add(str, w) // `sub(str, 2)`.
                mstore8(add(str, 1), mload(and(temp, 15)))
                mstore8(str, mload(and(shr(4, temp), 15)))
                temp := shr(8, temp)
                if iszero(temp) { break }
            }

            // Compute the string's length.
            let strLength := sub(end, str)
            // Move the pointer and write the length.
            str := sub(str, 0x20)
            mstore(str, strLength)
        }
    }

    /// @dev Returns the hexadecimal representation of `value`.
    /// The output is prefixed with "0x", encoded using 2 hexadecimal digits per byte,
    /// and the alphabets are capitalized conditionally according to
    /// https://eips.ethereum.org/EIPS/eip-55
    function toHexStringChecksummed(address value) internal pure returns (string memory str) {
        str = toHexString(value);
        /// @solidity memory-safe-assembly
        assembly {
            let mask := shl(6, div(not(0), 255)) // `0b010000000100000000 ...`
            let o := add(str, 0x22)
            let hashed := and(keccak256(o, 40), mul(34, mask)) // `0b10001000 ... `
            let t := shl(240, 136) // `0b10001000 << 240`
            for { let i := 0 } 1 {} {
                mstore(add(i, i), mul(t, byte(i, hashed)))
                i := add(i, 1)
                if eq(i, 20) { break }
            }
            mstore(o, xor(mload(o), shr(1, and(mload(0x00), and(mload(o), mask)))))
            o := add(o, 0x20)
            mstore(o, xor(mload(o), shr(1, and(mload(0x20), and(mload(o), mask)))))
        }
    }

    /// @dev Returns the hexadecimal representation of `value`.
    /// The output is prefixed with "0x" and encoded using 2 hexadecimal digits per byte.
    function toHexString(address value) internal pure returns (string memory str) {
        str = toHexStringNoPrefix(value);
        /// @solidity memory-safe-assembly
        assembly {
            let strLength := add(mload(str), 2) // Compute the length.
            mstore(str, 0x3078) // Write the "0x" prefix.
            str := sub(str, 2) // Move the pointer.
            mstore(str, strLength) // Write the length.
        }
    }

    /// @dev Returns the hexadecimal representation of `value`.
    /// The output is encoded using 2 hexadecimal digits per byte.
    function toHexStringNoPrefix(address value) internal pure returns (string memory str) {
        /// @solidity memory-safe-assembly
        assembly {
            str := mload(0x40)

            // Allocate the memory.
            // We need 0x20 bytes for the trailing zeros padding, 0x20 bytes for the length,
            // 0x02 bytes for the prefix, and 0x28 bytes for the digits.
            // The next multiple of 0x20 above (0x20 + 0x20 + 0x02 + 0x28) is 0x80.
            mstore(0x40, add(str, 0x80))

            // Store "0123456789abcdef" in scratch space.
            mstore(0x0f, 0x30313233343536373839616263646566)

            str := add(str, 2)
            mstore(str, 40)

            let o := add(str, 0x20)
            mstore(add(o, 40), 0)

            value := shl(96, value)

            // We write the string from rightmost digit to leftmost digit.
            // The following is essentially a do-while loop that also handles the zero case.
            for { let i := 0 } 1 {} {
                let p := add(o, add(i, i))
                let temp := byte(i, value)
                mstore8(add(p, 1), mload(and(temp, 15)))
                mstore8(p, mload(shr(4, temp)))
                i := add(i, 1)
                if eq(i, 20) { break }
            }
        }
    }

    /// @dev Returns the hex encoded string from the raw bytes.
    /// The output is encoded using 2 hexadecimal digits per byte.
    function toHexString(bytes memory raw) internal pure returns (string memory str) {
        str = toHexStringNoPrefix(raw);
        /// @solidity memory-safe-assembly
        assembly {
            let strLength := add(mload(str), 2) // Compute the length.
            mstore(str, 0x3078) // Write the "0x" prefix.
            str := sub(str, 2) // Move the pointer.
            mstore(str, strLength) // Write the length.
        }
    }

    /// @dev Returns the hex encoded string from the raw bytes.
    /// The output is encoded using 2 hexadecimal digits per byte.
    function toHexStringNoPrefix(bytes memory raw) internal pure returns (string memory str) {
        /// @solidity memory-safe-assembly
        assembly {
            let length := mload(raw)
            str := add(mload(0x40), 2) // Skip 2 bytes for the optional prefix.
            mstore(str, add(length, length)) // Store the length of the output.

            // Store "0123456789abcdef" in scratch space.
            mstore(0x0f, 0x30313233343536373839616263646566)

            let o := add(str, 0x20)
            let end := add(raw, length)

            for {} iszero(eq(raw, end)) {} {
                raw := add(raw, 1)
                mstore8(add(o, 1), mload(and(mload(raw), 15)))
                mstore8(o, mload(and(shr(4, mload(raw)), 15)))
                o := add(o, 2)
            }
            mstore(o, 0) // Zeroize the slot after the string.
            mstore(0x40, add(o, 0x20)) // Allocate the memory.
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   RUNE STRING OPERATIONS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the number of UTF characters in the string.
    function runeCount(string memory s) internal pure returns (uint256 result) {
        /// @solidity memory-safe-assembly
        assembly {
            if mload(s) {
                mstore(0x00, div(not(0), 255))
                mstore(0x20, 0x0202020202020202020202020202020202020202020202020303030304040506)
                let o := add(s, 0x20)
                let end := add(o, mload(s))
                for { result := 1 } 1 { result := add(result, 1) } {
                    o := add(o, byte(0, mload(shr(250, mload(o)))))
                    if iszero(lt(o, end)) { break }
                }
            }
        }
    }

    /// @dev Returns if this string is a 7-bit ASCII string.
    /// (i.e. all characters codes are in [0..127])
    function is7BitASCII(string memory s) internal pure returns (bool result) {
        /// @solidity memory-safe-assembly
        assembly {
            let mask := shl(7, div(not(0), 255))
            result := 1
            let n := mload(s)
            if n {
                let o := add(s, 0x20)
                let end := add(o, n)
                let last := mload(end)
                mstore(end, 0)
                for {} 1 {} {
                    if and(mask, mload(o)) {
                        result := 0
                        break
                    }
                    o := add(o, 0x20)
                    if iszero(lt(o, end)) { break }
                }
                mstore(end, last)
            }
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   BYTE STRING OPERATIONS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    // For performance and bytecode compactness, all indices of the following operations
    // are byte (ASCII) offsets, not UTF character offsets.

    /// @dev Returns `subject` all occurrences of `search` replaced with `replacement`.
    function replace(string memory subject, string memory search, string memory replacement)
        internal
        pure
        returns (string memory result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let subjectLength := mload(subject)
            let searchLength := mload(search)
            let replacementLength := mload(replacement)

            subject := add(subject, 0x20)
            search := add(search, 0x20)
            replacement := add(replacement, 0x20)
            result := add(mload(0x40), 0x20)

            let subjectEnd := add(subject, subjectLength)
            if iszero(gt(searchLength, subjectLength)) {
                let subjectSearchEnd := add(sub(subjectEnd, searchLength), 1)
                let h := 0
                if iszero(lt(searchLength, 0x20)) { h := keccak256(search, searchLength) }
                let m := shl(3, sub(0x20, and(searchLength, 0x1f)))
                let s := mload(search)
                for {} 1 {} {
                    let t := mload(subject)
                    // Whether the first `searchLength % 32` bytes of
                    // `subject` and `search` matches.
                    if iszero(shr(m, xor(t, s))) {
                        if h {
                            if iszero(eq(keccak256(subject, searchLength), h)) {
                                mstore(result, t)
                                result := add(result, 1)
                                subject := add(subject, 1)
                                if iszero(lt(subject, subjectSearchEnd)) { break }
                                continue
                            }
                        }
                        // Copy the `replacement` one word at a time.
                        for { let o := 0 } 1 {} {
                            mstore(add(result, o), mload(add(replacement, o)))
                            o := add(o, 0x20)
                            if iszero(lt(o, replacementLength)) { break }
                        }
                        result := add(result, replacementLength)
                        subject := add(subject, searchLength)
                        if searchLength {
                            if iszero(lt(subject, subjectSearchEnd)) { break }
                            continue
                        }
                    }
                    mstore(result, t)
                    result := add(result, 1)
                    subject := add(subject, 1)
                    if iszero(lt(subject, subjectSearchEnd)) { break }
                }
            }

            let resultRemainder := result
            result := add(mload(0x40), 0x20)
            let k := add(sub(resultRemainder, result), sub(subjectEnd, subject))
            // Copy the rest of the string one word at a time.
            for {} lt(subject, subjectEnd) {} {
                mstore(resultRemainder, mload(subject))
                resultRemainder := add(resultRemainder, 0x20)
                subject := add(subject, 0x20)
            }
            result := sub(result, 0x20)
            let last := add(add(result, 0x20), k) // Zeroize the slot after the string.
            mstore(last, 0)
            mstore(0x40, add(last, 0x20)) // Allocate the memory.
            mstore(result, k) // Store the length.
        }
    }

    /// @dev Returns the byte index of the first location of `search` in `subject`,
    /// searching from left to right, starting from `from`.
    /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found.
    function indexOf(string memory subject, string memory search, uint256 from)
        internal
        pure
        returns (uint256 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            for { let subjectLength := mload(subject) } 1 {} {
                if iszero(mload(search)) {
                    if iszero(gt(from, subjectLength)) {
                        result := from
                        break
                    }
                    result := subjectLength
                    break
                }
                let searchLength := mload(search)
                let subjectStart := add(subject, 0x20)

                result := not(0) // Initialize to `NOT_FOUND`.

                subject := add(subjectStart, from)
                let end := add(sub(add(subjectStart, subjectLength), searchLength), 1)

                let m := shl(3, sub(0x20, and(searchLength, 0x1f)))
                let s := mload(add(search, 0x20))

                if iszero(and(lt(subject, end), lt(from, subjectLength))) { break }

                if iszero(lt(searchLength, 0x20)) {
                    for { let h := keccak256(add(search, 0x20), searchLength) } 1 {} {
                        if iszero(shr(m, xor(mload(subject), s))) {
                            if eq(keccak256(subject, searchLength), h) {
                                result := sub(subject, subjectStart)
                                break
                            }
                        }
                        subject := add(subject, 1)
                        if iszero(lt(subject, end)) { break }
                    }
                    break
                }
                for {} 1 {} {
                    if iszero(shr(m, xor(mload(subject), s))) {
                        result := sub(subject, subjectStart)
                        break
                    }
                    subject := add(subject, 1)
                    if iszero(lt(subject, end)) { break }
                }
                break
            }
        }
    }

    /// @dev Returns the byte index of the first location of `search` in `subject`,
    /// searching from left to right.
    /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found.
    function indexOf(string memory subject, string memory search)
        internal
        pure
        returns (uint256 result)
    {
        result = indexOf(subject, search, 0);
    }

    /// @dev Returns the byte index of the first location of `search` in `subject`,
    /// searching from right to left, starting from `from`.
    /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found.
    function lastIndexOf(string memory subject, string memory search, uint256 from)
        internal
        pure
        returns (uint256 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            for {} 1 {} {
                result := not(0) // Initialize to `NOT_FOUND`.
                let searchLength := mload(search)
                if gt(searchLength, mload(subject)) { break }
                let w := result

                let fromMax := sub(mload(subject), searchLength)
                if iszero(gt(fromMax, from)) { from := fromMax }

                let end := add(add(subject, 0x20), w)
                subject := add(add(subject, 0x20), from)
                if iszero(gt(subject, end)) { break }
                // As this function is not too often used,
                // we shall simply use keccak256 for smaller bytecode size.
                for { let h := keccak256(add(search, 0x20), searchLength) } 1 {} {
                    if eq(keccak256(subject, searchLength), h) {
                        result := sub(subject, add(end, 1))
                        break
                    }
                    subject := add(subject, w) // `sub(subject, 1)`.
                    if iszero(gt(subject, end)) { break }
                }
                break
            }
        }
    }

    /// @dev Returns the byte index of the first location of `search` in `subject`,
    /// searching from right to left.
    /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found.
    function lastIndexOf(string memory subject, string memory search)
        internal
        pure
        returns (uint256 result)
    {
        result = lastIndexOf(subject, search, uint256(int256(-1)));
    }

    /// @dev Returns whether `subject` starts with `search`.
    function startsWith(string memory subject, string memory search)
        internal
        pure
        returns (bool result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let searchLength := mload(search)
            // Just using keccak256 directly is actually cheaper.
            // forgefmt: disable-next-item
            result := and(
                iszero(gt(searchLength, mload(subject))),
                eq(
                    keccak256(add(subject, 0x20), searchLength),
                    keccak256(add(search, 0x20), searchLength)
                )
            )
        }
    }

    /// @dev Returns whether `subject` ends with `search`.
    function endsWith(string memory subject, string memory search)
        internal
        pure
        returns (bool result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let searchLength := mload(search)
            let subjectLength := mload(subject)
            // Whether `search` is not longer than `subject`.
            let withinRange := iszero(gt(searchLength, subjectLength))
            // Just using keccak256 directly is actually cheaper.
            // forgefmt: disable-next-item
            result := and(
                withinRange,
                eq(
                    keccak256(
                        // `subject + 0x20 + max(subjectLength - searchLength, 0)`.
                        add(add(subject, 0x20), mul(withinRange, sub(subjectLength, searchLength))),
                        searchLength
                    ),
                    keccak256(add(search, 0x20), searchLength)
                )
            )
        }
    }

    /// @dev Returns `subject` repeated `times`.
    function repeat(string memory subject, uint256 times)
        internal
        pure
        returns (string memory result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let subjectLength := mload(subject)
            if iszero(or(iszero(times), iszero(subjectLength))) {
                subject := add(subject, 0x20)
                result := mload(0x40)
                let output := add(result, 0x20)
                for {} 1 {} {
                    // Copy the `subject` one word at a time.
                    for { let o := 0 } 1 {} {
                        mstore(add(output, o), mload(add(subject, o)))
                        o := add(o, 0x20)
                        if iszero(lt(o, subjectLength)) { break }
                    }
                    output := add(output, subjectLength)
                    times := sub(times, 1)
                    if iszero(times) { break }
                }
                mstore(output, 0) // Zeroize the slot after the string.
                let resultLength := sub(output, add(result, 0x20))
                mstore(result, resultLength) // Store the length.
                // Allocate the memory.
                mstore(0x40, add(result, add(resultLength, 0x20)))
            }
        }
    }

    /// @dev Returns a copy of `subject` sliced from `start` to `end` (exclusive).
    /// `start` and `end` are byte offsets.
    function slice(string memory subject, uint256 start, uint256 end)
        internal
        pure
        returns (string memory result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let subjectLength := mload(subject)
            if iszero(gt(subjectLength, end)) { end := subjectLength }
            if iszero(gt(subjectLength, start)) { start := subjectLength }
            if lt(start, end) {
                result := mload(0x40)
                let resultLength := sub(end, start)
                mstore(result, resultLength)
                subject := add(subject, start)
                let w := not(0x1f)
                // Copy the `subject` one word at a time, backwards.
                for { let o := and(add(resultLength, 0x1f), w) } 1 {} {
                    mstore(add(result, o), mload(add(subject, o)))
                    o := add(o, w) // `sub(o, 0x20)`.
                    if iszero(o) { break }
                }
                // Zeroize the slot after the string.
                mstore(add(add(result, 0x20), resultLength), 0)
                // Allocate memory for the length and the bytes,
                // rounded up to a multiple of 32.
                mstore(0x40, add(result, and(add(resultLength, 0x3f), w)))
            }
        }
    }

    /// @dev Returns a copy of `subject` sliced from `start` to the end of the string.
    /// `start` is a byte offset.
    function slice(string memory subject, uint256 start)
        internal
        pure
        returns (string memory result)
    {
        result = slice(subject, start, uint256(int256(-1)));
    }

    /// @dev Returns all the indices of `search` in `subject`.
    /// The indices are byte offsets.
    function indicesOf(string memory subject, string memory search)
        internal
        pure
        returns (uint256[] memory result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let subjectLength := mload(subject)
            let searchLength := mload(search)

            if iszero(gt(searchLength, subjectLength)) {
                subject := add(subject, 0x20)
                search := add(search, 0x20)
                result := add(mload(0x40), 0x20)

                let subjectStart := subject
                let subjectSearchEnd := add(sub(add(subject, subjectLength), searchLength), 1)
                let h := 0
                if iszero(lt(searchLength, 0x20)) { h := keccak256(search, searchLength) }
                let m := shl(3, sub(0x20, and(searchLength, 0x1f)))
                let s := mload(search)
                for {} 1 {} {
                    let t := mload(subject)
                    // Whether the first `searchLength % 32` bytes of
                    // `subject` and `search` matches.
                    if iszero(shr(m, xor(t, s))) {
                        if h {
                            if iszero(eq(keccak256(subject, searchLength), h)) {
                                subject := add(subject, 1)
                                if iszero(lt(subject, subjectSearchEnd)) { break }
                                continue
                            }
                        }
                        // Append to `result`.
                        mstore(result, sub(subject, subjectStart))
                        result := add(result, 0x20)
                        // Advance `subject` by `searchLength`.
                        subject := add(subject, searchLength)
                        if searchLength {
                            if iszero(lt(subject, subjectSearchEnd)) { break }
                            continue
                        }
                    }
                    subject := add(subject, 1)
                    if iszero(lt(subject, subjectSearchEnd)) { break }
                }
                let resultEnd := result
                // Assign `result` to the free memory pointer.
                result := mload(0x40)
                // Store the length of `result`.
                mstore(result, shr(5, sub(resultEnd, add(result, 0x20))))
                // Allocate memory for result.
                // We allocate one more word, so this array can be recycled for {split}.
                mstore(0x40, add(resultEnd, 0x20))
            }
        }
    }

    /// @dev Returns a arrays of strings based on the `delimiter` inside of the `subject` string.
    function split(string memory subject, string memory delimiter)
        internal
        pure
        returns (string[] memory result)
    {
        uint256[] memory indices = indicesOf(subject, delimiter);
        /// @solidity memory-safe-assembly
        assembly {
            let w := not(0x1f)
            let indexPtr := add(indices, 0x20)
            let indicesEnd := add(indexPtr, shl(5, add(mload(indices), 1)))
            mstore(add(indicesEnd, w), mload(subject))
            mstore(indices, add(mload(indices), 1))
            let prevIndex := 0
            for {} 1 {} {
                let index := mload(indexPtr)
                mstore(indexPtr, 0x60)
                if iszero(eq(index, prevIndex)) {
                    let element := mload(0x40)
                    let elementLength := sub(index, prevIndex)
                    mstore(element, elementLength)
                    // Copy the `subject` one word at a time, backwards.
                    for { let o := and(add(elementLength, 0x1f), w) } 1 {} {
                        mstore(add(element, o), mload(add(add(subject, prevIndex), o)))
                        o := add(o, w) // `sub(o, 0x20)`.
                        if iszero(o) { break }
                    }
                    // Zeroize the slot after the string.
                    mstore(add(add(element, 0x20), elementLength), 0)
                    // Allocate memory for the length and the bytes,
                    // rounded up to a multiple of 32.
                    mstore(0x40, add(element, and(add(elementLength, 0x3f), w)))
                    // Store the `element` into the array.
                    mstore(indexPtr, element)
                }
                prevIndex := add(index, mload(delimiter))
                indexPtr := add(indexPtr, 0x20)
                if iszero(lt(indexPtr, indicesEnd)) { break }
            }
            result := indices
            if iszero(mload(delimiter)) {
                result := add(indices, 0x20)
                mstore(result, sub(mload(indices), 2))
            }
        }
    }

    /// @dev Returns a concatenated string of `a` and `b`.
    /// Cheaper than `string.concat()` and does not de-align the free memory pointer.
    function concat(string memory a, string memory b)
        internal
        pure
        returns (string memory result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let w := not(0x1f)
            result := mload(0x40)
            let aLength := mload(a)
            // Copy `a` one word at a time, backwards.
            for { let o := and(add(aLength, 0x20), w) } 1 {} {
                mstore(add(result, o), mload(add(a, o)))
                o := add(o, w) // `sub(o, 0x20)`.
                if iszero(o) { break }
            }
            let bLength := mload(b)
            let output := add(result, aLength)
            // Copy `b` one word at a time, backwards.
            for { let o := and(add(bLength, 0x20), w) } 1 {} {
                mstore(add(output, o), mload(add(b, o)))
                o := add(o, w) // `sub(o, 0x20)`.
                if iszero(o) { break }
            }
            let totalLength := add(aLength, bLength)
            let last := add(add(result, 0x20), totalLength)
            // Zeroize the slot after the string.
            mstore(last, 0)
            // Stores the length.
            mstore(result, totalLength)
            // Allocate memory for the length and the bytes,
            // rounded up to a multiple of 32.
            mstore(0x40, and(add(last, 0x1f), w))
        }
    }

    /// @dev Returns a copy of the string in either lowercase or UPPERCASE.
    /// WARNING! This function is only compatible with 7-bit ASCII strings.
    function toCase(string memory subject, bool toUpper)
        internal
        pure
        returns (string memory result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let length := mload(subject)
            if length {
                result := add(mload(0x40), 0x20)
                subject := add(subject, 1)
                let flags := shl(add(70, shl(5, toUpper)), 0x3ffffff)
                let w := not(0)
                for { let o := length } 1 {} {
                    o := add(o, w)
                    let b := and(0xff, mload(add(subject, o)))
                    mstore8(add(result, o), xor(b, and(shr(b, flags), 0x20)))
                    if iszero(o) { break }
                }
                result := mload(0x40)
                mstore(result, length) // Store the length.
                let last := add(add(result, 0x20), length)
                mstore(last, 0) // Zeroize the slot after the string.
                mstore(0x40, add(last, 0x20)) // Allocate the memory.
            }
        }
    }

    /// @dev Returns a string from a small bytes32 string.
    /// `smallString` must be null terminated, or behavior will be undefined.
    function fromSmallString(bytes32 smallString) internal pure returns (string memory result) {
        if (smallString == bytes32(0)) return result;
        /// @solidity memory-safe-assembly
        assembly {
            result := mload(0x40)
            let n := 0
            for {} 1 {} {
                n := add(n, 1)
                if iszero(byte(n, smallString)) { break } // Scan for '\0'.
            }
            mstore(result, n)
            let o := add(result, 0x20)
            mstore(o, smallString)
            mstore(add(o, n), 0)
            mstore(0x40, add(result, 0x40))
        }
    }

    /// @dev Returns a lowercased copy of the string.
    /// WARNING! This function is only compatible with 7-bit ASCII strings.
    function lower(string memory subject) internal pure returns (string memory result) {
        result = toCase(subject, false);
    }

    /// @dev Returns an UPPERCASED copy of the string.
    /// WARNING! This function is only compatible with 7-bit ASCII strings.
    function upper(string memory subject) internal pure returns (string memory result) {
        result = toCase(subject, true);
    }

    /// @dev Escapes the string to be used within HTML tags.
    function escapeHTML(string memory s) internal pure returns (string memory result) {
        /// @solidity memory-safe-assembly
        assembly {
            let end := add(s, mload(s))
            result := add(mload(0x40), 0x20)
            // Store the bytes of the packed offsets and strides into the scratch space.
            // `packed = (stride << 5) | offset`. Max offset is 20. Max stride is 6.
            mstore(0x1f, 0x900094)
            mstore(0x08, 0xc0000000a6ab)
            // Store "&quot;&amp;&#39;&lt;&gt;" into the scratch space.
            mstore(0x00, shl(64, 0x2671756f743b26616d703b262333393b266c743b2667743b))
            for {} iszero(eq(s, end)) {} {
                s := add(s, 1)
                let c := and(mload(s), 0xff)
                // Not in `["\"","'","&","<",">"]`.
                if iszero(and(shl(c, 1), 0x500000c400000000)) {
                    mstore8(result, c)
                    result := add(result, 1)
                    continue
                }
                let t := shr(248, mload(c))
                mstore(result, mload(and(t, 0x1f)))
                result := add(result, shr(5, t))
            }
            let last := result
            mstore(last, 0) // Zeroize the slot after the string.
            result := mload(0x40)
            mstore(result, sub(last, add(result, 0x20))) // Store the length.
            mstore(0x40, add(last, 0x20)) // Allocate the memory.
        }
    }

    /// @dev Escapes the string to be used within double-quotes in a JSON.
    /// If `addDoubleQuotes` is true, the result will be enclosed in double-quotes.
    function escapeJSON(string memory s, bool addDoubleQuotes)
        internal
        pure
        returns (string memory result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let end := add(s, mload(s))
            result := add(mload(0x40), 0x20)
            if addDoubleQuotes {
                mstore8(result, 34)
                result := add(1, result)
            }
            // Store "\\u0000" in scratch space.
            // Store "0123456789abcdef" in scratch space.
            // Also, store `{0x08:"b", 0x09:"t", 0x0a:"n", 0x0c:"f", 0x0d:"r"}`.
            // into the scratch space.
            mstore(0x15, 0x5c75303030303031323334353637383961626364656662746e006672)
            // Bitmask for detecting `["\"","\\"]`.
            let e := or(shl(0x22, 1), shl(0x5c, 1))
            for {} iszero(eq(s, end)) {} {
                s := add(s, 1)
                let c := and(mload(s), 0xff)
                if iszero(lt(c, 0x20)) {
                    if iszero(and(shl(c, 1), e)) {
                        // Not in `["\"","\\"]`.
                        mstore8(result, c)
                        result := add(result, 1)
                        continue
                    }
                    mstore8(result, 0x5c) // "\\".
                    mstore8(add(result, 1), c)
                    result := add(result, 2)
                    continue
                }
                if iszero(and(shl(c, 1), 0x3700)) {
                    // Not in `["\b","\t","\n","\f","\d"]`.
                    mstore8(0x1d, mload(shr(4, c))) // Hex value.
                    mstore8(0x1e, mload(and(c, 15))) // Hex value.
                    mstore(result, mload(0x19)) // "\\u00XX".
                    result := add(result, 6)
                    continue
                }
                mstore8(result, 0x5c) // "\\".
                mstore8(add(result, 1), mload(add(c, 8)))
                result := add(result, 2)
            }
            if addDoubleQuotes {
                mstore8(result, 34)
                result := add(1, result)
            }
            let last := result
            mstore(last, 0) // Zeroize the slot after the string.
            result := mload(0x40)
            mstore(result, sub(last, add(result, 0x20))) // Store the length.
            mstore(0x40, add(last, 0x20)) // Allocate the memory.
        }
    }

    /// @dev Escapes the string to be used within double-quotes in a JSON.
    function escapeJSON(string memory s) internal pure returns (string memory result) {
        result = escapeJSON(s, false);
    }

    /// @dev Returns whether `a` equals `b`.
    function eq(string memory a, string memory b) internal pure returns (bool result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := eq(keccak256(add(a, 0x20), mload(a)), keccak256(add(b, 0x20), mload(b)))
        }
    }

    /// @dev Returns whether `a` equals `b`. For small strings up to 32 bytes.
    /// `b` must be null terminated, or behavior will be undefined.
    function eqs(string memory a, bytes32 b) internal pure returns (bool result) {
        /// @solidity memory-safe-assembly
        assembly {
            // These should be evaluated on compile time, as far as possible.
            let x := and(b, add(not(b), 1))
            let r := or(shl(8, iszero(b)), shl(7, iszero(iszero(shr(128, x)))))
            r := or(r, shl(6, iszero(iszero(shr(64, shr(r, x))))))
            r := or(r, shl(5, lt(0xffffffff, shr(r, x))))
            r := or(r, shl(4, lt(0xffff, shr(r, x))))
            r := or(r, shl(3, lt(0xff, shr(r, x))))
            result := gt(eq(mload(a), sub(32, shr(3, r))), shr(r, xor(b, mload(add(a, 0x20)))))
        }
    }

    /// @dev Packs a single string with its length into a single word.
    /// Returns `bytes32(0)` if the length is zero or greater than 31.
    function packOne(string memory a) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            // We don't need to zero right pad the string,
            // since this is our own custom non-standard packing scheme.
            result :=
                mul(
                    // Load the length and the bytes.
                    mload(add(a, 0x1f)),
                    // `length != 0 && length < 32`. Abuses underflow.
                    // Assumes that the length is valid and within the block gas limit.
                    lt(sub(mload(a), 1), 0x1f)
                )
        }
    }

    /// @dev Unpacks a string packed using {packOne}.
    /// Returns the empty string if `packed` is `bytes32(0)`.
    /// If `packed` is not an output of {packOne}, the output behavior is undefined.
    function unpackOne(bytes32 packed) internal pure returns (string memory result) {
        /// @solidity memory-safe-assembly
        assembly {
            // Grab the free memory pointer.
            result := mload(0x40)
            // Allocate 2 words (1 for the length, 1 for the bytes).
            mstore(0x40, add(result, 0x40))
            // Zeroize the length slot.
            mstore(result, 0)
            // Store the length and bytes.
            mstore(add(result, 0x1f), packed)
            // Right pad with zeroes.
            mstore(add(add(result, 0x20), mload(result)), 0)
        }
    }

    /// @dev Packs two strings with their lengths into a single word.
    /// Returns `bytes32(0)` if combined length is zero or greater than 30.
    function packTwo(string memory a, string memory b) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let aLength := mload(a)
            // We don't need to zero right pad the strings,
            // since this is our own custom non-standard packing scheme.
            result :=
                mul(
                    // Load the length and the bytes of `a` and `b`.
                    or(
                        shl(shl(3, sub(0x1f, aLength)), mload(add(a, aLength))),
                        mload(sub(add(b, 0x1e), aLength))
                    ),
                    // `totalLength != 0 && totalLength < 31`. Abuses underflow.
                    // Assumes that the lengths are valid and within the block gas limit.
                    lt(sub(add(aLength, mload(b)), 1), 0x1e)
                )
        }
    }

    /// @dev Unpacks strings packed using {packTwo}.
    /// Returns the empty strings if `packed` is `bytes32(0)`.
    /// If `packed` is not an output of {packTwo}, the output behavior is undefined.
    function unpackTwo(bytes32 packed)
        internal
        pure
        returns (string memory resultA, string memory resultB)
    {
        /// @solidity memory-safe-assembly
        assembly {
            // Grab the free memory pointer.
            resultA := mload(0x40)
            resultB := add(resultA, 0x40)
            // Allocate 2 words for each string (1 for the length, 1 for the byte). Total 4 words.
            mstore(0x40, add(resultB, 0x40))
            // Zeroize the length slots.
            mstore(resultA, 0)
            mstore(resultB, 0)
            // Store the lengths and bytes.
            mstore(add(resultA, 0x1f), packed)
            mstore(add(resultB, 0x1f), mload(add(add(resultA, 0x20), mload(resultA))))
            // Right pad with zeroes.
            mstore(add(add(resultA, 0x20), mload(resultA)), 0)
            mstore(add(add(resultB, 0x20), mload(resultB)), 0)
        }
    }

    /// @dev Directly returns `a` without copying.
    function directReturn(string memory a) internal pure {
        assembly {
            // Assumes that the string does not start from the scratch space.
            let retStart := sub(a, 0x20)
            let retSize := add(mload(a), 0x40)
            // Right pad with zeroes. Just in case the string is produced
            // by a method that doesn't zero right pad.
            mstore(add(retStart, retSize), 0)
            // Store the return offset.
            mstore(retStart, 0x20)
            // End the transaction, returning the string.
            return(retStart, retSize)
        }
    }
}

File 10 of 13: Ownable.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Simple single owner authorization mixin.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol)
///
/// @dev Note:
/// This implementation does NOT auto-initialize the owner to `msg.sender`.
/// You MUST call the `_initializeOwner` in the constructor / initializer.
///
/// While the ownable portion follows
/// [EIP-173](https://eips.ethereum.org/EIPS/eip-173) for compatibility,
/// the nomenclature for the 2-step ownership handover may be unique to this codebase.
abstract contract Ownable {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The caller is not authorized to call the function.
    error Unauthorized();

    /// @dev The `newOwner` cannot be the zero address.
    error NewOwnerIsZeroAddress();

    /// @dev The `pendingOwner` does not have a valid handover request.
    error NoHandoverRequest();

    /// @dev Cannot double-initialize.
    error AlreadyInitialized();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                           EVENTS                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The ownership is transferred from `oldOwner` to `newOwner`.
    /// This event is intentionally kept the same as OpenZeppelin's Ownable to be
    /// compatible with indexers and [EIP-173](https://eips.ethereum.org/EIPS/eip-173),
    /// despite it not being as lightweight as a single argument event.
    event OwnershipTransferred(address indexed oldOwner, address indexed newOwner);

    /// @dev An ownership handover to `pendingOwner` has been requested.
    event OwnershipHandoverRequested(address indexed pendingOwner);

    /// @dev The ownership handover to `pendingOwner` has been canceled.
    event OwnershipHandoverCanceled(address indexed pendingOwner);

    /// @dev `keccak256(bytes("OwnershipTransferred(address,address)"))`.
    uint256 private constant _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE =
        0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0;

    /// @dev `keccak256(bytes("OwnershipHandoverRequested(address)"))`.
    uint256 private constant _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE =
        0xdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d;

    /// @dev `keccak256(bytes("OwnershipHandoverCanceled(address)"))`.
    uint256 private constant _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE =
        0xfa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                          STORAGE                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The owner slot is given by:
    /// `bytes32(~uint256(uint32(bytes4(keccak256("_OWNER_SLOT_NOT")))))`.
    /// It is intentionally chosen to be a high value
    /// to avoid collision with lower slots.
    /// The choice of manual storage layout is to enable compatibility
    /// with both regular and upgradeable contracts.
    bytes32 internal constant _OWNER_SLOT =
        0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927;

    /// The ownership handover slot of `newOwner` is given by:
    /// ```
    ///     mstore(0x00, or(shl(96, user), _HANDOVER_SLOT_SEED))
    ///     let handoverSlot := keccak256(0x00, 0x20)
    /// ```
    /// It stores the expiry timestamp of the two-step ownership handover.
    uint256 private constant _HANDOVER_SLOT_SEED = 0x389a75e1;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     INTERNAL FUNCTIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Override to return true to make `_initializeOwner` prevent double-initialization.
    function _guardInitializeOwner() internal pure virtual returns (bool guard) {}

    /// @dev Initializes the owner directly without authorization guard.
    /// This function must be called upon initialization,
    /// regardless of whether the contract is upgradeable or not.
    /// This is to enable generalization to both regular and upgradeable contracts,
    /// and to save gas in case the initial owner is not the caller.
    /// For performance reasons, this function will not check if there
    /// is an existing owner.
    function _initializeOwner(address newOwner) internal virtual {
        if (_guardInitializeOwner()) {
            /// @solidity memory-safe-assembly
            assembly {
                let ownerSlot := _OWNER_SLOT
                if sload(ownerSlot) {
                    mstore(0x00, 0x0dc149f0) // `AlreadyInitialized()`.
                    revert(0x1c, 0x04)
                }
                // Clean the upper 96 bits.
                newOwner := shr(96, shl(96, newOwner))
                // Store the new value.
                sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner))))
                // Emit the {OwnershipTransferred} event.
                log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)
            }
        } else {
            /// @solidity memory-safe-assembly
            assembly {
                // Clean the upper 96 bits.
                newOwner := shr(96, shl(96, newOwner))
                // Store the new value.
                sstore(_OWNER_SLOT, newOwner)
                // Emit the {OwnershipTransferred} event.
                log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)
            }
        }
    }

    /// @dev Sets the owner directly without authorization guard.
    function _setOwner(address newOwner) internal virtual {
        if (_guardInitializeOwner()) {
            /// @solidity memory-safe-assembly
            assembly {
                let ownerSlot := _OWNER_SLOT
                // Clean the upper 96 bits.
                newOwner := shr(96, shl(96, newOwner))
                // Emit the {OwnershipTransferred} event.
                log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)
                // Store the new value.
                sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner))))
            }
        } else {
            /// @solidity memory-safe-assembly
            assembly {
                let ownerSlot := _OWNER_SLOT
                // Clean the upper 96 bits.
                newOwner := shr(96, shl(96, newOwner))
                // Emit the {OwnershipTransferred} event.
                log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)
                // Store the new value.
                sstore(ownerSlot, newOwner)
            }
        }
    }

    /// @dev Throws if the sender is not the owner.
    function _checkOwner() internal view virtual {
        /// @solidity memory-safe-assembly
        assembly {
            // If the caller is not the stored owner, revert.
            if iszero(eq(caller(), sload(_OWNER_SLOT))) {
                mstore(0x00, 0x82b42900) // `Unauthorized()`.
                revert(0x1c, 0x04)
            }
        }
    }

    /// @dev Returns how long a two-step ownership handover is valid for in seconds.
    /// Override to return a different value if needed.
    /// Made internal to conserve bytecode. Wrap it in a public function if needed.
    function _ownershipHandoverValidFor() internal view virtual returns (uint64) {
        return 48 * 3600;
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  PUBLIC UPDATE FUNCTIONS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Allows the owner to transfer the ownership to `newOwner`.
    function transferOwnership(address newOwner) public payable virtual onlyOwner {
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(shl(96, newOwner)) {
                mstore(0x00, 0x7448fbae) // `NewOwnerIsZeroAddress()`.
                revert(0x1c, 0x04)
            }
        }
        _setOwner(newOwner);
    }

    /// @dev Allows the owner to renounce their ownership.
    function renounceOwnership() public payable virtual onlyOwner {
        _setOwner(address(0));
    }

    /// @dev Request a two-step ownership handover to the caller.
    /// The request will automatically expire in 48 hours (172800 seconds) by default.
    function requestOwnershipHandover() public payable virtual {
        unchecked {
            uint256 expires = block.timestamp + _ownershipHandoverValidFor();
            /// @solidity memory-safe-assembly
            assembly {
                // Compute and set the handover slot to `expires`.
                mstore(0x0c, _HANDOVER_SLOT_SEED)
                mstore(0x00, caller())
                sstore(keccak256(0x0c, 0x20), expires)
                // Emit the {OwnershipHandoverRequested} event.
                log2(0, 0, _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE, caller())
            }
        }
    }

    /// @dev Cancels the two-step ownership handover to the caller, if any.
    function cancelOwnershipHandover() public payable virtual {
        /// @solidity memory-safe-assembly
        assembly {
            // Compute and set the handover slot to 0.
            mstore(0x0c, _HANDOVER_SLOT_SEED)
            mstore(0x00, caller())
            sstore(keccak256(0x0c, 0x20), 0)
            // Emit the {OwnershipHandoverCanceled} event.
            log2(0, 0, _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE, caller())
        }
    }

    /// @dev Allows the owner to complete the two-step ownership handover to `pendingOwner`.
    /// Reverts if there is no existing ownership handover requested by `pendingOwner`.
    function completeOwnershipHandover(address pendingOwner) public payable virtual onlyOwner {
        /// @solidity memory-safe-assembly
        assembly {
            // Compute and set the handover slot to 0.
            mstore(0x0c, _HANDOVER_SLOT_SEED)
            mstore(0x00, pendingOwner)
            let handoverSlot := keccak256(0x0c, 0x20)
            // If the handover does not exist, or has expired.
            if gt(timestamp(), sload(handoverSlot)) {
                mstore(0x00, 0x6f5e8818) // `NoHandoverRequest()`.
                revert(0x1c, 0x04)
            }
            // Set the handover slot to 0.
            sstore(handoverSlot, 0)
        }
        _setOwner(pendingOwner);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   PUBLIC READ FUNCTIONS                    */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the owner of the contract.
    function owner() public view virtual returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := sload(_OWNER_SLOT)
        }
    }

    /// @dev Returns the expiry timestamp for the two-step ownership handover to `pendingOwner`.
    function ownershipHandoverExpiresAt(address pendingOwner)
        public
        view
        virtual
        returns (uint256 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            // Compute the handover slot.
            mstore(0x0c, _HANDOVER_SLOT_SEED)
            mstore(0x00, pendingOwner)
            // Load the handover slot.
            result := sload(keccak256(0x0c, 0x20))
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         MODIFIERS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Marks a function as only callable by the owner.
    modifier onlyOwner() virtual {
        _checkOwner();
        _;
    }
}

File 11 of 13: OwnableRoles.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

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

/// @notice Simple single owner and multiroles authorization mixin.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol)
/// @dev While the ownable portion follows [EIP-173](https://eips.ethereum.org/EIPS/eip-173)
/// for compatibility, the nomenclature for the 2-step ownership handover and roles
/// may be unique to this codebase.
abstract contract OwnableRoles is Ownable {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                           EVENTS                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The `user`'s roles is updated to `roles`.
    /// Each bit of `roles` represents whether the role is set.
    event RolesUpdated(address indexed user, uint256 indexed roles);

    /// @dev `keccak256(bytes("RolesUpdated(address,uint256)"))`.
    uint256 private constant _ROLES_UPDATED_EVENT_SIGNATURE =
        0x715ad5ce61fc9595c7b415289d59cf203f23a94fa06f04af7e489a0a76e1fe26;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                          STORAGE                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The role slot of `user` is given by:
    /// ```
    ///     mstore(0x00, or(shl(96, user), _ROLE_SLOT_SEED))
    ///     let roleSlot := keccak256(0x00, 0x20)
    /// ```
    /// This automatically ignores the upper bits of the `user` in case
    /// they are not clean, as well as keep the `keccak256` under 32-bytes.
    ///
    /// Note: This is equivalent to `uint32(bytes4(keccak256("_OWNER_SLOT_NOT")))`.
    uint256 private constant _ROLE_SLOT_SEED = 0x8b78c6d8;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     INTERNAL FUNCTIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Overwrite the roles directly without authorization guard.
    function _setRoles(address user, uint256 roles) internal virtual {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x0c, _ROLE_SLOT_SEED)
            mstore(0x00, user)
            // Store the new value.
            sstore(keccak256(0x0c, 0x20), roles)
            // Emit the {RolesUpdated} event.
            log3(0, 0, _ROLES_UPDATED_EVENT_SIGNATURE, shr(96, mload(0x0c)), roles)
        }
    }

    /// @dev Updates the roles directly without authorization guard.
    /// If `on` is true, each set bit of `roles` will be turned on,
    /// otherwise, each set bit of `roles` will be turned off.
    function _updateRoles(address user, uint256 roles, bool on) internal virtual {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x0c, _ROLE_SLOT_SEED)
            mstore(0x00, user)
            let roleSlot := keccak256(0x0c, 0x20)
            // Load the current value.
            let current := sload(roleSlot)
            // Compute the updated roles if `on` is true.
            let updated := or(current, roles)
            // Compute the updated roles if `on` is false.
            // Use `and` to compute the intersection of `current` and `roles`,
            // `xor` it with `current` to flip the bits in the intersection.
            if iszero(on) { updated := xor(current, and(current, roles)) }
            // Then, store the new value.
            sstore(roleSlot, updated)
            // Emit the {RolesUpdated} event.
            log3(0, 0, _ROLES_UPDATED_EVENT_SIGNATURE, shr(96, mload(0x0c)), updated)
        }
    }

    /// @dev Grants the roles directly without authorization guard.
    /// Each bit of `roles` represents the role to turn on.
    function _grantRoles(address user, uint256 roles) internal virtual {
        _updateRoles(user, roles, true);
    }

    /// @dev Removes the roles directly without authorization guard.
    /// Each bit of `roles` represents the role to turn off.
    function _removeRoles(address user, uint256 roles) internal virtual {
        _updateRoles(user, roles, false);
    }

    /// @dev Throws if the sender does not have any of the `roles`.
    function _checkRoles(uint256 roles) internal view virtual {
        /// @solidity memory-safe-assembly
        assembly {
            // Compute the role slot.
            mstore(0x0c, _ROLE_SLOT_SEED)
            mstore(0x00, caller())
            // Load the stored value, and if the `and` intersection
            // of the value and `roles` is zero, revert.
            if iszero(and(sload(keccak256(0x0c, 0x20)), roles)) {
                mstore(0x00, 0x82b42900) // `Unauthorized()`.
                revert(0x1c, 0x04)
            }
        }
    }

    /// @dev Throws if the sender is not the owner,
    /// and does not have any of the `roles`.
    /// Checks for ownership first, then lazily checks for roles.
    function _checkOwnerOrRoles(uint256 roles) internal view virtual {
        /// @solidity memory-safe-assembly
        assembly {
            // If the caller is not the stored owner.
            // Note: `_ROLE_SLOT_SEED` is equal to `_OWNER_SLOT_NOT`.
            if iszero(eq(caller(), sload(not(_ROLE_SLOT_SEED)))) {
                // Compute the role slot.
                mstore(0x0c, _ROLE_SLOT_SEED)
                mstore(0x00, caller())
                // Load the stored value, and if the `and` intersection
                // of the value and `roles` is zero, revert.
                if iszero(and(sload(keccak256(0x0c, 0x20)), roles)) {
                    mstore(0x00, 0x82b42900) // `Unauthorized()`.
                    revert(0x1c, 0x04)
                }
            }
        }
    }

    /// @dev Throws if the sender does not have any of the `roles`,
    /// and is not the owner.
    /// Checks for roles first, then lazily checks for ownership.
    function _checkRolesOrOwner(uint256 roles) internal view virtual {
        /// @solidity memory-safe-assembly
        assembly {
            // Compute the role slot.
            mstore(0x0c, _ROLE_SLOT_SEED)
            mstore(0x00, caller())
            // Load the stored value, and if the `and` intersection
            // of the value and `roles` is zero, revert.
            if iszero(and(sload(keccak256(0x0c, 0x20)), roles)) {
                // If the caller is not the stored owner.
                // Note: `_ROLE_SLOT_SEED` is equal to `_OWNER_SLOT_NOT`.
                if iszero(eq(caller(), sload(not(_ROLE_SLOT_SEED)))) {
                    mstore(0x00, 0x82b42900) // `Unauthorized()`.
                    revert(0x1c, 0x04)
                }
            }
        }
    }

    /// @dev Convenience function to return a `roles` bitmap from an array of `ordinals`.
    /// This is meant for frontends like Etherscan, and is therefore not fully optimized.
    /// Not recommended to be called on-chain.
    /// Made internal to conserve bytecode. Wrap it in a public function if needed.
    function _rolesFromOrdinals(uint8[] memory ordinals) internal pure returns (uint256 roles) {
        /// @solidity memory-safe-assembly
        assembly {
            for { let i := shl(5, mload(ordinals)) } i { i := sub(i, 0x20) } {
                // We don't need to mask the values of `ordinals`, as Solidity
                // cleans dirty upper bits when storing variables into memory.
                roles := or(shl(mload(add(ordinals, i)), 1), roles)
            }
        }
    }

    /// @dev Convenience function to return an array of `ordinals` from the `roles` bitmap.
    /// This is meant for frontends like Etherscan, and is therefore not fully optimized.
    /// Not recommended to be called on-chain.
    /// Made internal to conserve bytecode. Wrap it in a public function if needed.
    function _ordinalsFromRoles(uint256 roles) internal pure returns (uint8[] memory ordinals) {
        /// @solidity memory-safe-assembly
        assembly {
            // Grab the pointer to the free memory.
            ordinals := mload(0x40)
            let ptr := add(ordinals, 0x20)
            let o := 0
            // The absence of lookup tables, De Bruijn, etc., here is intentional for
            // smaller bytecode, as this function is not meant to be called on-chain.
            for { let t := roles } 1 {} {
                mstore(ptr, o)
                // `shr` 5 is equivalent to multiplying by 0x20.
                // Push back into the ordinals array if the bit is set.
                ptr := add(ptr, shl(5, and(t, 1)))
                o := add(o, 1)
                t := shr(o, roles)
                if iszero(t) { break }
            }
            // Store the length of `ordinals`.
            mstore(ordinals, shr(5, sub(ptr, add(ordinals, 0x20))))
            // Allocate the memory.
            mstore(0x40, ptr)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  PUBLIC UPDATE FUNCTIONS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Allows the owner to grant `user` `roles`.
    /// If the `user` already has a role, then it will be an no-op for the role.
    function grantRoles(address user, uint256 roles) public payable virtual onlyOwner {
        _grantRoles(user, roles);
    }

    /// @dev Allows the owner to remove `user` `roles`.
    /// If the `user` does not have a role, then it will be an no-op for the role.
    function revokeRoles(address user, uint256 roles) public payable virtual onlyOwner {
        _removeRoles(user, roles);
    }

    /// @dev Allow the caller to remove their own roles.
    /// If the caller does not have a role, then it will be an no-op for the role.
    function renounceRoles(uint256 roles) public payable virtual {
        _removeRoles(msg.sender, roles);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   PUBLIC READ FUNCTIONS                    */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the roles of `user`.
    function rolesOf(address user) public view virtual returns (uint256 roles) {
        /// @solidity memory-safe-assembly
        assembly {
            // Compute the role slot.
            mstore(0x0c, _ROLE_SLOT_SEED)
            mstore(0x00, user)
            // Load the stored value.
            roles := sload(keccak256(0x0c, 0x20))
        }
    }

    /// @dev Returns whether `user` has any of `roles`.
    function hasAnyRole(address user, uint256 roles) public view virtual returns (bool) {
        return rolesOf(user) & roles != 0;
    }

    /// @dev Returns whether `user` has all of `roles`.
    function hasAllRoles(address user, uint256 roles) public view virtual returns (bool) {
        return rolesOf(user) & roles == roles;
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         MODIFIERS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Marks a function as only callable by an account with `roles`.
    modifier onlyRoles(uint256 roles) virtual {
        _checkRoles(roles);
        _;
    }

    /// @dev Marks a function as only callable by the owner or by an account
    /// with `roles`. Checks for ownership first, then lazily checks for roles.
    modifier onlyOwnerOrRoles(uint256 roles) virtual {
        _checkOwnerOrRoles(roles);
        _;
    }

    /// @dev Marks a function as only callable by an account with `roles`
    /// or the owner. Checks for roles first, then lazily checks for ownership.
    modifier onlyRolesOrOwner(uint256 roles) virtual {
        _checkRolesOrOwner(roles);
        _;
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       ROLE CONSTANTS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    // IYKYK

    uint256 internal constant _ROLE_0 = 1 << 0;
    uint256 internal constant _ROLE_1 = 1 << 1;
    uint256 internal constant _ROLE_2 = 1 << 2;
    uint256 internal constant _ROLE_3 = 1 << 3;
    uint256 internal constant _ROLE_4 = 1 << 4;
    uint256 internal constant _ROLE_5 = 1 << 5;
    uint256 internal constant _ROLE_6 = 1 << 6;
    uint256 internal constant _ROLE_7 = 1 << 7;
    uint256 internal constant _ROLE_8 = 1 << 8;
    uint256 internal constant _ROLE_9 = 1 << 9;
    uint256 internal constant _ROLE_10 = 1 << 10;
    uint256 internal constant _ROLE_11 = 1 << 11;
    uint256 internal constant _ROLE_12 = 1 << 12;
    uint256 internal constant _ROLE_13 = 1 << 13;
    uint256 internal constant _ROLE_14 = 1 << 14;
    uint256 internal constant _ROLE_15 = 1 << 15;
    uint256 internal constant _ROLE_16 = 1 << 16;
    uint256 internal constant _ROLE_17 = 1 << 17;
    uint256 internal constant _ROLE_18 = 1 << 18;
    uint256 internal constant _ROLE_19 = 1 << 19;
    uint256 internal constant _ROLE_20 = 1 << 20;
    uint256 internal constant _ROLE_21 = 1 << 21;
    uint256 internal constant _ROLE_22 = 1 << 22;
    uint256 internal constant _ROLE_23 = 1 << 23;
    uint256 internal constant _ROLE_24 = 1 << 24;
    uint256 internal constant _ROLE_25 = 1 << 25;
    uint256 internal constant _ROLE_26 = 1 << 26;
    uint256 internal constant _ROLE_27 = 1 << 27;
    uint256 internal constant _ROLE_28 = 1 << 28;
    uint256 internal constant _ROLE_29 = 1 << 29;
    uint256 internal constant _ROLE_30 = 1 << 30;
    uint256 internal constant _ROLE_31 = 1 << 31;
    uint256 internal constant _ROLE_32 = 1 << 32;
    uint256 internal constant _ROLE_33 = 1 << 33;
    uint256 internal constant _ROLE_34 = 1 << 34;
    uint256 internal constant _ROLE_35 = 1 << 35;
    uint256 internal constant _ROLE_36 = 1 << 36;
    uint256 internal constant _ROLE_37 = 1 << 37;
    uint256 internal constant _ROLE_38 = 1 << 38;
    uint256 internal constant _ROLE_39 = 1 << 39;
    uint256 internal constant _ROLE_40 = 1 << 40;
    uint256 internal constant _ROLE_41 = 1 << 41;
    uint256 internal constant _ROLE_42 = 1 << 42;
    uint256 internal constant _ROLE_43 = 1 << 43;
    uint256 internal constant _ROLE_44 = 1 << 44;
    uint256 internal constant _ROLE_45 = 1 << 45;
    uint256 internal constant _ROLE_46 = 1 << 46;
    uint256 internal constant _ROLE_47 = 1 << 47;
    uint256 internal constant _ROLE_48 = 1 << 48;
    uint256 internal constant _ROLE_49 = 1 << 49;
    uint256 internal constant _ROLE_50 = 1 << 50;
    uint256 internal constant _ROLE_51 = 1 << 51;
    uint256 internal constant _ROLE_52 = 1 << 52;
    uint256 internal constant _ROLE_53 = 1 << 53;
    uint256 internal constant _ROLE_54 = 1 << 54;
    uint256 internal constant _ROLE_55 = 1 << 55;
    uint256 internal constant _ROLE_56 = 1 << 56;
    uint256 internal constant _ROLE_57 = 1 << 57;
    uint256 internal constant _ROLE_58 = 1 << 58;
    uint256 internal constant _ROLE_59 = 1 << 59;
    uint256 internal constant _ROLE_60 = 1 << 60;
    uint256 internal constant _ROLE_61 = 1 << 61;
    uint256 internal constant _ROLE_62 = 1 << 62;
    uint256 internal constant _ROLE_63 = 1 << 63;
    uint256 internal constant _ROLE_64 = 1 << 64;
    uint256 internal constant _ROLE_65 = 1 << 65;
    uint256 internal constant _ROLE_66 = 1 << 66;
    uint256 internal constant _ROLE_67 = 1 << 67;
    uint256 internal constant _ROLE_68 = 1 << 68;
    uint256 internal constant _ROLE_69 = 1 << 69;
    uint256 internal constant _ROLE_70 = 1 << 70;
    uint256 internal constant _ROLE_71 = 1 << 71;
    uint256 internal constant _ROLE_72 = 1 << 72;
    uint256 internal constant _ROLE_73 = 1 << 73;
    uint256 internal constant _ROLE_74 = 1 << 74;
    uint256 internal constant _ROLE_75 = 1 << 75;
    uint256 internal constant _ROLE_76 = 1 << 76;
    uint256 internal constant _ROLE_77 = 1 << 77;
    uint256 internal constant _ROLE_78 = 1 << 78;
    uint256 internal constant _ROLE_79 = 1 << 79;
    uint256 internal constant _ROLE_80 = 1 << 80;
    uint256 internal constant _ROLE_81 = 1 << 81;
    uint256 internal constant _ROLE_82 = 1 << 82;
    uint256 internal constant _ROLE_83 = 1 << 83;
    uint256 internal constant _ROLE_84 = 1 << 84;
    uint256 internal constant _ROLE_85 = 1 << 85;
    uint256 internal constant _ROLE_86 = 1 << 86;
    uint256 internal constant _ROLE_87 = 1 << 87;
    uint256 internal constant _ROLE_88 = 1 << 88;
    uint256 internal constant _ROLE_89 = 1 << 89;
    uint256 internal constant _ROLE_90 = 1 << 90;
    uint256 internal constant _ROLE_91 = 1 << 91;
    uint256 internal constant _ROLE_92 = 1 << 92;
    uint256 internal constant _ROLE_93 = 1 << 93;
    uint256 internal constant _ROLE_94 = 1 << 94;
    uint256 internal constant _ROLE_95 = 1 << 95;
    uint256 internal constant _ROLE_96 = 1 << 96;
    uint256 internal constant _ROLE_97 = 1 << 97;
    uint256 internal constant _ROLE_98 = 1 << 98;
    uint256 internal constant _ROLE_99 = 1 << 99;
    uint256 internal constant _ROLE_100 = 1 << 100;
    uint256 internal constant _ROLE_101 = 1 << 101;
    uint256 internal constant _ROLE_102 = 1 << 102;
    uint256 internal constant _ROLE_103 = 1 << 103;
    uint256 internal constant _ROLE_104 = 1 << 104;
    uint256 internal constant _ROLE_105 = 1 << 105;
    uint256 internal constant _ROLE_106 = 1 << 106;
    uint256 internal constant _ROLE_107 = 1 << 107;
    uint256 internal constant _ROLE_108 = 1 << 108;
    uint256 internal constant _ROLE_109 = 1 << 109;
    uint256 internal constant _ROLE_110 = 1 << 110;
    uint256 internal constant _ROLE_111 = 1 << 111;
    uint256 internal constant _ROLE_112 = 1 << 112;
    uint256 internal constant _ROLE_113 = 1 << 113;
    uint256 internal constant _ROLE_114 = 1 << 114;
    uint256 internal constant _ROLE_115 = 1 << 115;
    uint256 internal constant _ROLE_116 = 1 << 116;
    uint256 internal constant _ROLE_117 = 1 << 117;
    uint256 internal constant _ROLE_118 = 1 << 118;
    uint256 internal constant _ROLE_119 = 1 << 119;
    uint256 internal constant _ROLE_120 = 1 << 120;
    uint256 internal constant _ROLE_121 = 1 << 121;
    uint256 internal constant _ROLE_122 = 1 << 122;
    uint256 internal constant _ROLE_123 = 1 << 123;
    uint256 internal constant _ROLE_124 = 1 << 124;
    uint256 internal constant _ROLE_125 = 1 << 125;
    uint256 internal constant _ROLE_126 = 1 << 126;
    uint256 internal constant _ROLE_127 = 1 << 127;
    uint256 internal constant _ROLE_128 = 1 << 128;
    uint256 internal constant _ROLE_129 = 1 << 129;
    uint256 internal constant _ROLE_130 = 1 << 130;
    uint256 internal constant _ROLE_131 = 1 << 131;
    uint256 internal constant _ROLE_132 = 1 << 132;
    uint256 internal constant _ROLE_133 = 1 << 133;
    uint256 internal constant _ROLE_134 = 1 << 134;
    uint256 internal constant _ROLE_135 = 1 << 135;
    uint256 internal constant _ROLE_136 = 1 << 136;
    uint256 internal constant _ROLE_137 = 1 << 137;
    uint256 internal constant _ROLE_138 = 1 << 138;
    uint256 internal constant _ROLE_139 = 1 << 139;
    uint256 internal constant _ROLE_140 = 1 << 140;
    uint256 internal constant _ROLE_141 = 1 << 141;
    uint256 internal constant _ROLE_142 = 1 << 142;
    uint256 internal constant _ROLE_143 = 1 << 143;
    uint256 internal constant _ROLE_144 = 1 << 144;
    uint256 internal constant _ROLE_145 = 1 << 145;
    uint256 internal constant _ROLE_146 = 1 << 146;
    uint256 internal constant _ROLE_147 = 1 << 147;
    uint256 internal constant _ROLE_148 = 1 << 148;
    uint256 internal constant _ROLE_149 = 1 << 149;
    uint256 internal constant _ROLE_150 = 1 << 150;
    uint256 internal constant _ROLE_151 = 1 << 151;
    uint256 internal constant _ROLE_152 = 1 << 152;
    uint256 internal constant _ROLE_153 = 1 << 153;
    uint256 internal constant _ROLE_154 = 1 << 154;
    uint256 internal constant _ROLE_155 = 1 << 155;
    uint256 internal constant _ROLE_156 = 1 << 156;
    uint256 internal constant _ROLE_157 = 1 << 157;
    uint256 internal constant _ROLE_158 = 1 << 158;
    uint256 internal constant _ROLE_159 = 1 << 159;
    uint256 internal constant _ROLE_160 = 1 << 160;
    uint256 internal constant _ROLE_161 = 1 << 161;
    uint256 internal constant _ROLE_162 = 1 << 162;
    uint256 internal constant _ROLE_163 = 1 << 163;
    uint256 internal constant _ROLE_164 = 1 << 164;
    uint256 internal constant _ROLE_165 = 1 << 165;
    uint256 internal constant _ROLE_166 = 1 << 166;
    uint256 internal constant _ROLE_167 = 1 << 167;
    uint256 internal constant _ROLE_168 = 1 << 168;
    uint256 internal constant _ROLE_169 = 1 << 169;
    uint256 internal constant _ROLE_170 = 1 << 170;
    uint256 internal constant _ROLE_171 = 1 << 171;
    uint256 internal constant _ROLE_172 = 1 << 172;
    uint256 internal constant _ROLE_173 = 1 << 173;
    uint256 internal constant _ROLE_174 = 1 << 174;
    uint256 internal constant _ROLE_175 = 1 << 175;
    uint256 internal constant _ROLE_176 = 1 << 176;
    uint256 internal constant _ROLE_177 = 1 << 177;
    uint256 internal constant _ROLE_178 = 1 << 178;
    uint256 internal constant _ROLE_179 = 1 << 179;
    uint256 internal constant _ROLE_180 = 1 << 180;
    uint256 internal constant _ROLE_181 = 1 << 181;
    uint256 internal constant _ROLE_182 = 1 << 182;
    uint256 internal constant _ROLE_183 = 1 << 183;
    uint256 internal constant _ROLE_184 = 1 << 184;
    uint256 internal constant _ROLE_185 = 1 << 185;
    uint256 internal constant _ROLE_186 = 1 << 186;
    uint256 internal constant _ROLE_187 = 1 << 187;
    uint256 internal constant _ROLE_188 = 1 << 188;
    uint256 internal constant _ROLE_189 = 1 << 189;
    uint256 internal constant _ROLE_190 = 1 << 190;
    uint256 internal constant _ROLE_191 = 1 << 191;
    uint256 internal constant _ROLE_192 = 1 << 192;
    uint256 internal constant _ROLE_193 = 1 << 193;
    uint256 internal constant _ROLE_194 = 1 << 194;
    uint256 internal constant _ROLE_195 = 1 << 195;
    uint256 internal constant _ROLE_196 = 1 << 196;
    uint256 internal constant _ROLE_197 = 1 << 197;
    uint256 internal constant _ROLE_198 = 1 << 198;
    uint256 internal constant _ROLE_199 = 1 << 199;
    uint256 internal constant _ROLE_200 = 1 << 200;
    uint256 internal constant _ROLE_201 = 1 << 201;
    uint256 internal constant _ROLE_202 = 1 << 202;
    uint256 internal constant _ROLE_203 = 1 << 203;
    uint256 internal constant _ROLE_204 = 1 << 204;
    uint256 internal constant _ROLE_205 = 1 << 205;
    uint256 internal constant _ROLE_206 = 1 << 206;
    uint256 internal constant _ROLE_207 = 1 << 207;
    uint256 internal constant _ROLE_208 = 1 << 208;
    uint256 internal constant _ROLE_209 = 1 << 209;
    uint256 internal constant _ROLE_210 = 1 << 210;
    uint256 internal constant _ROLE_211 = 1 << 211;
    uint256 internal constant _ROLE_212 = 1 << 212;
    uint256 internal constant _ROLE_213 = 1 << 213;
    uint256 internal constant _ROLE_214 = 1 << 214;
    uint256 internal constant _ROLE_215 = 1 << 215;
    uint256 internal constant _ROLE_216 = 1 << 216;
    uint256 internal constant _ROLE_217 = 1 << 217;
    uint256 internal constant _ROLE_218 = 1 << 218;
    uint256 internal constant _ROLE_219 = 1 << 219;
    uint256 internal constant _ROLE_220 = 1 << 220;
    uint256 internal constant _ROLE_221 = 1 << 221;
    uint256 internal constant _ROLE_222 = 1 << 222;
    uint256 internal constant _ROLE_223 = 1 << 223;
    uint256 internal constant _ROLE_224 = 1 << 224;
    uint256 internal constant _ROLE_225 = 1 << 225;
    uint256 internal constant _ROLE_226 = 1 << 226;
    uint256 internal constant _ROLE_227 = 1 << 227;
    uint256 internal constant _ROLE_228 = 1 << 228;
    uint256 internal constant _ROLE_229 = 1 << 229;
    uint256 internal constant _ROLE_230 = 1 << 230;
    uint256 internal constant _ROLE_231 = 1 << 231;
    uint256 internal constant _ROLE_232 = 1 << 232;
    uint256 internal constant _ROLE_233 = 1 << 233;
    uint256 internal constant _ROLE_234 = 1 << 234;
    uint256 internal constant _ROLE_235 = 1 << 235;
    uint256 internal constant _ROLE_236 = 1 << 236;
    uint256 internal constant _ROLE_237 = 1 << 237;
    uint256 internal constant _ROLE_238 = 1 << 238;
    uint256 internal constant _ROLE_239 = 1 << 239;
    uint256 internal constant _ROLE_240 = 1 << 240;
    uint256 internal constant _ROLE_241 = 1 << 241;
    uint256 internal constant _ROLE_242 = 1 << 242;
    uint256 internal constant _ROLE_243 = 1 << 243;
    uint256 internal constant _ROLE_244 = 1 << 244;
    uint256 internal constant _ROLE_245 = 1 << 245;
    uint256 internal constant _ROLE_246 = 1 << 246;
    uint256 internal constant _ROLE_247 = 1 << 247;
    uint256 internal constant _ROLE_248 = 1 << 248;
    uint256 internal constant _ROLE_249 = 1 << 249;
    uint256 internal constant _ROLE_250 = 1 << 250;
    uint256 internal constant _ROLE_251 = 1 << 251;
    uint256 internal constant _ROLE_252 = 1 << 252;
    uint256 internal constant _ROLE_253 = 1 << 253;
    uint256 internal constant _ROLE_254 = 1 << 254;
    uint256 internal constant _ROLE_255 = 1 << 255;
}

File 12 of 13: ReentrancyGuard.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.22;

/// @notice Gas optimized reentrancy protection for smart contracts
/// @author Cheezburger (https://cheezburger.lol)
abstract contract ReentrancyGuard {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    error ReentrancyDetected();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                          STORAGE                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    uint8 private locked = 1;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         MODIFIERS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    modifier nonReentrant() virtual {
        if (locked == 2) {
            revert ReentrancyDetected();
        }
        locked = 2;
        _;
        locked = 1;
    }
}

File 13 of 13: SafeTransferLib.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SafeTransferLib.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)
///
/// @dev Note:
/// - For ETH transfers, please use `forceSafeTransferETH` for DoS protection.
/// - For ERC20s, this implementation won't check that a token has code,
///   responsibility is delegated to the caller.
library SafeTransferLib {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The ETH transfer has failed.
    error ETHTransferFailed();

    /// @dev The ERC20 `transferFrom` has failed.
    error TransferFromFailed();

    /// @dev The ERC20 `transfer` has failed.
    error TransferFailed();

    /// @dev The ERC20 `approve` has failed.
    error ApproveFailed();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         CONSTANTS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Suggested gas stipend for contract receiving ETH that disallows any storage writes.
    uint256 internal constant GAS_STIPEND_NO_STORAGE_WRITES = 2300;

    /// @dev Suggested gas stipend for contract receiving ETH to perform a few
    /// storage reads and writes, but low enough to prevent griefing.
    uint256 internal constant GAS_STIPEND_NO_GRIEF = 100000;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       ETH OPERATIONS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    // If the ETH transfer MUST succeed with a reasonable gas budget, use the force variants.
    //
    // The regular variants:
    // - Forwards all remaining gas to the target.
    // - Reverts if the target reverts.
    // - Reverts if the current contract has insufficient balance.
    //
    // The force variants:
    // - Forwards with an optional gas stipend
    //   (defaults to `GAS_STIPEND_NO_GRIEF`, which is sufficient for most cases).
    // - If the target reverts, or if the gas stipend is exhausted,
    //   creates a temporary contract to force send the ETH via `SELFDESTRUCT`.
    //   Future compatible with `SENDALL`: https://eips.ethereum.org/EIPS/eip-4758.
    // - Reverts if the current contract has insufficient balance.
    //
    // The try variants:
    // - Forwards with a mandatory gas stipend.
    // - Instead of reverting, returns whether the transfer succeeded.

    /// @dev Sends `amount` (in wei) ETH to `to`.
    function safeTransferETH(address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(call(gas(), to, amount, codesize(), 0x00, codesize(), 0x00)) {
                mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                revert(0x1c, 0x04)
            }
        }
    }

    /// @dev Sends all the ETH in the current contract to `to`.
    function safeTransferAllETH(address to) internal {
        /// @solidity memory-safe-assembly
        assembly {
            // Transfer all the ETH and check if it succeeded or not.
            if iszero(call(gas(), to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) {
                mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                revert(0x1c, 0x04)
            }
        }
    }

    /// @dev Force sends `amount` (in wei) ETH to `to`, with a `gasStipend`.
    function forceSafeTransferETH(address to, uint256 amount, uint256 gasStipend) internal {
        /// @solidity memory-safe-assembly
        assembly {
            if lt(selfbalance(), amount) {
                mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                revert(0x1c, 0x04)
            }
            if iszero(call(gasStipend, to, amount, codesize(), 0x00, codesize(), 0x00)) {
                mstore(0x00, to) // Store the address in scratch space.
                mstore8(0x0b, 0x73) // Opcode `PUSH20`.
                mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
                if iszero(create(amount, 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.
            }
        }
    }

    /// @dev Force sends all the ETH in the current contract to `to`, with a `gasStipend`.
    function forceSafeTransferAllETH(address to, uint256 gasStipend) internal {
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(call(gasStipend, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) {
                mstore(0x00, to) // Store the address in scratch space.
                mstore8(0x0b, 0x73) // Opcode `PUSH20`.
                mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
                if iszero(create(selfbalance(), 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.
            }
        }
    }

    /// @dev Force sends `amount` (in wei) ETH to `to`, with `GAS_STIPEND_NO_GRIEF`.
    function forceSafeTransferETH(address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            if lt(selfbalance(), amount) {
                mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                revert(0x1c, 0x04)
            }
            if iszero(call(GAS_STIPEND_NO_GRIEF, to, amount, codesize(), 0x00, codesize(), 0x00)) {
                mstore(0x00, to) // Store the address in scratch space.
                mstore8(0x0b, 0x73) // Opcode `PUSH20`.
                mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
                if iszero(create(amount, 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.
            }
        }
    }

    /// @dev Force sends all the ETH in the current contract to `to`, with `GAS_STIPEND_NO_GRIEF`.
    function forceSafeTransferAllETH(address to) internal {
        /// @solidity memory-safe-assembly
        assembly {
            // forgefmt: disable-next-item
            if iszero(call(GAS_STIPEND_NO_GRIEF, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) {
                mstore(0x00, to) // Store the address in scratch space.
                mstore8(0x0b, 0x73) // Opcode `PUSH20`.
                mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
                if iszero(create(selfbalance(), 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.
            }
        }
    }

    /// @dev Sends `amount` (in wei) ETH to `to`, with a `gasStipend`.
    function trySafeTransferETH(address to, uint256 amount, uint256 gasStipend)
        internal
        returns (bool success)
    {
        /// @solidity memory-safe-assembly
        assembly {
            success := call(gasStipend, to, amount, codesize(), 0x00, codesize(), 0x00)
        }
    }

    /// @dev Sends all the ETH in the current contract to `to`, with a `gasStipend`.
    function trySafeTransferAllETH(address to, uint256 gasStipend)
        internal
        returns (bool success)
    {
        /// @solidity memory-safe-assembly
        assembly {
            success := call(gasStipend, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      ERC20 OPERATIONS                      */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Sends `amount` of ERC20 `token` from `from` to `to`.
    /// Reverts upon failure.
    ///
    /// The `from` account must have at least `amount` approved for
    /// the current contract to manage.
    function safeTransferFrom(address token, address from, address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x60, amount) // Store the `amount` argument.
            mstore(0x40, to) // Store the `to` argument.
            mstore(0x2c, shl(96, from)) // Store the `from` argument.
            mstore(0x0c, 0x23b872dd000000000000000000000000) // `transferFrom(address,address,uint256)`.
            // Perform the transfer, reverting upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
                    call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)
                )
            ) {
                mstore(0x00, 0x7939f424) // `TransferFromFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x60, 0) // Restore the zero slot to zero.
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Sends all of ERC20 `token` from `from` to `to`.
    /// Reverts upon failure.
    ///
    /// The `from` account must have their entire balance approved for
    /// the current contract to manage.
    function safeTransferAllFrom(address token, address from, address to)
        internal
        returns (uint256 amount)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x40, to) // Store the `to` argument.
            mstore(0x2c, shl(96, from)) // Store the `from` argument.
            mstore(0x0c, 0x70a08231000000000000000000000000) // `balanceOf(address)`.
            // Read the balance, reverting upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    gt(returndatasize(), 0x1f), // At least 32 bytes returned.
                    staticcall(gas(), token, 0x1c, 0x24, 0x60, 0x20)
                )
            ) {
                mstore(0x00, 0x7939f424) // `TransferFromFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x00, 0x23b872dd) // `transferFrom(address,address,uint256)`.
            amount := mload(0x60) // The `amount` is already at 0x60. We'll need to return it.
            // Perform the transfer, reverting upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
                    call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)
                )
            ) {
                mstore(0x00, 0x7939f424) // `TransferFromFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x60, 0) // Restore the zero slot to zero.
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Sends `amount` of ERC20 `token` from the current contract to `to`.
    /// Reverts upon failure.
    function safeTransfer(address token, address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x14, to) // Store the `to` argument.
            mstore(0x34, amount) // Store the `amount` argument.
            mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`.
            // Perform the transfer, reverting upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
                    call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
                )
            ) {
                mstore(0x00, 0x90b8ec18) // `TransferFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
        }
    }

    /// @dev Sends all of ERC20 `token` from the current contract to `to`.
    /// Reverts upon failure.
    function safeTransferAll(address token, address to) internal returns (uint256 amount) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, 0x70a08231) // Store the function selector of `balanceOf(address)`.
            mstore(0x20, address()) // Store the address of the current contract.
            // Read the balance, reverting upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    gt(returndatasize(), 0x1f), // At least 32 bytes returned.
                    staticcall(gas(), token, 0x1c, 0x24, 0x34, 0x20)
                )
            ) {
                mstore(0x00, 0x90b8ec18) // `TransferFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x14, to) // Store the `to` argument.
            amount := mload(0x34) // The `amount` is already at 0x34. We'll need to return it.
            mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`.
            // Perform the transfer, reverting upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
                    call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
                )
            ) {
                mstore(0x00, 0x90b8ec18) // `TransferFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
        }
    }

    /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract.
    /// Reverts upon failure.
    function safeApprove(address token, address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x14, to) // Store the `to` argument.
            mstore(0x34, amount) // Store the `amount` argument.
            mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.
            // Perform the approval, reverting upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
                    call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
                )
            ) {
                mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
        }
    }

    /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract.
    /// If the initial attempt to approve fails, attempts to reset the approved amount to zero,
    /// then retries the approval again (some tokens, e.g. USDT, requires this).
    /// Reverts upon failure.
    function safeApproveWithRetry(address token, address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x14, to) // Store the `to` argument.
            mstore(0x34, amount) // Store the `amount` argument.
            mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.
            // Perform the approval, retrying upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
                    call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
                )
            ) {
                mstore(0x34, 0) // Store 0 for the `amount`.
                mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.
                pop(call(gas(), token, 0, 0x10, 0x44, codesize(), 0x00)) // Reset the approval.
                mstore(0x34, amount) // Store back the original `amount`.
                // Retry the approval, reverting upon failure.
                if iszero(
                    and(
                        or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
                        call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
                    )
                ) {
                    mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`.
                    revert(0x1c, 0x04)
                }
            }
            mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
        }
    }

    /// @dev Returns the amount of ERC20 `token` owned by `account`.
    /// Returns zero if the `token` does not exist.
    function balanceOf(address token, address account) internal view returns (uint256 amount) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x14, account) // Store the `account` argument.
            mstore(0x00, 0x70a08231000000000000000000000000) // `balanceOf(address)`.
            amount :=
                mul(
                    mload(0x20),
                    and( // The arguments of `and` are evaluated from right to left.
                        gt(returndatasize(), 0x1f), // At least 32 bytes returned.
                        staticcall(gas(), token, 0x10, 0x24, 0x20, 0x20)
                    )
                )
        }
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"string","name":"website","type":"string"},{"internalType":"string","name":"social","type":"string"},{"internalType":"uint256","name":"supply","type":"uint256"}],"internalType":"struct CheezburgerStructs.TokenCustomization","name":"_customization","type":"tuple"},{"internalType":"address","name":"_factory","type":"address"},{"internalType":"address","name":"_router","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AllowanceOverflow","type":"error"},{"inputs":[],"name":"AllowanceUnderflow","type":"error"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"CannotReceiveEtherDirectly","type":"error"},{"inputs":[],"name":"CannotUseCHZBNamespace","type":"error"},{"inputs":[],"name":"EmptyAddressNotAllowed","type":"error"},{"inputs":[],"name":"EmptyNumericUserId","type":"error"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"IncorrectPoolOpeningFee","type":"error"},{"inputs":[],"name":"InsufficientAllowance","type":"error"},{"inputs":[],"name":"InsufficientBalance","type":"error"},{"inputs":[],"name":"InvalidPermit","type":"error"},{"inputs":[],"name":"NewOwnerIsZeroAddress","type":"error"},{"inputs":[],"name":"NoHandoverRequest","type":"error"},{"inputs":[],"name":"PermitExpired","type":"error"},{"inputs":[],"name":"ReentrancyDetected","type":"error"},{"inputs":[],"name":"SocialNotOpened","type":"error"},{"inputs":[],"name":"SupplyAllocationExceeded","type":"error"},{"inputs":[],"name":"SupplyOverflow","type":"error"},{"inputs":[],"name":"TotalSupplyOverflow","type":"error"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"TransferToToken","type":"error"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"TransferToZeroAddress","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"inputs":[{"internalType":"uint256","name":"userId","type":"uint256"}],"name":"UserIdAlreadyExist","type":"error"},{"inputs":[],"name":"UserIdNotFound","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[],"name":"GlobalSettingsChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"uint256","name":"creationAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"currentOutOfCirculationSupply","type":"uint256"}],"name":"LiquidityLessTokenDeployed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[],"name":"PairingAmountsChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"roles","type":"uint256"}],"name":"RolesUpdated","type":"event"},{"anonymous":false,"inputs":[],"name":"SettingsChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"userId","type":"uint256"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"uint256","name":"creationAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"currentOutOfCirculationSupply","type":"uint256"}],"name":"SocialTokenDeployed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pair","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"SocialTokenFeeWithdrawal","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"result","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burnFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cancelOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"contract ICheezburgerFactory","name":"factory","type":"address"},{"internalType":"address","name":"router","type":"address"}],"internalType":"struct CheezburgerDeployerKit.GlobalSettings","name":"_globalSettings","type":"tuple"}],"name":"changeGlobalSettings","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_socialPairingAmount","type":"uint256"},{"internalType":"uint256","name":"_tokenPairingAmount","type":"uint256"}],"name":"changePairingAmounts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"pairingAmount","type":"uint256"},{"internalType":"uint256","name":"leftSideSupply","type":"uint256"},{"internalType":"uint256","name":"openFeeWei","type":"uint256"},{"internalType":"uint8","name":"poolCreatorFeePercentage","type":"uint8"},{"components":[{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"uint16","name":"percentStart","type":"uint16"},{"internalType":"uint16","name":"percentEnd","type":"uint16"}],"internalType":"struct CheezburgerStructs.DynamicSettings","name":"walletSettings","type":"tuple"},{"components":[{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"uint16","name":"percentStart","type":"uint16"},{"internalType":"uint16","name":"percentEnd","type":"uint16"}],"internalType":"struct CheezburgerStructs.DynamicSettings","name":"feeSettings","type":"tuple"}],"internalType":"struct CheezburgerDeployerKit.SocialSettings","name":"_socialSettings","type":"tuple"},{"components":[{"internalType":"uint256","name":"pairingAmount","type":"uint256"},{"internalType":"uint256","name":"openFeeWei","type":"uint256"}],"internalType":"struct CheezburgerDeployerKit.TokenSettings","name":"_tokenSettings","type":"tuple"}],"name":"changeSettings","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"completeOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"userId","type":"uint256"}],"name":"deploySocialTokenWithCHZB","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"string","name":"website","type":"string"},{"internalType":"string","name":"social","type":"string"},{"internalType":"uint256","name":"supply","type":"uint256"}],"internalType":"struct CheezburgerStructs.TokenCustomization","name":"_customization","type":"tuple"},{"components":[{"internalType":"uint8","name":"feeThresholdPercent","type":"uint8"},{"internalType":"address[]","name":"feeAddresses","type":"address[]"},{"internalType":"uint8[]","name":"feePercentages","type":"uint8[]"}],"internalType":"struct CheezburgerStructs.LiquiditySettings","name":"_liquidity","type":"tuple"},{"components":[{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"uint16","name":"percentStart","type":"uint16"},{"internalType":"uint16","name":"percentEnd","type":"uint16"}],"internalType":"struct CheezburgerStructs.DynamicSettings","name":"_fee","type":"tuple"},{"components":[{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"uint16","name":"percentStart","type":"uint16"},{"internalType":"uint16","name":"percentEnd","type":"uint16"}],"internalType":"struct CheezburgerStructs.DynamicSettings","name":"_wallet","type":"tuple"},{"components":[{"internalType":"address","name":"feeReceiver","type":"address"},{"internalType":"uint8","name":"feePercentage","type":"uint8"}],"internalType":"struct CheezburgerStructs.ReferralSettings","name":"_referral","type":"tuple"}],"name":"deployTokenWithCHZB","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"globalSettings","outputs":[{"internalType":"contract ICheezburgerFactory","name":"factory","type":"address"},{"internalType":"address","name":"router","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"grantRoles","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"hasAllRoles","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"hasAnyRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"outOfCirculationTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"result","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"ownershipHandoverExpiresAt","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"renounceRoles","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"requestOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"revokeRoles","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"rolesOf","outputs":[{"internalType":"uint256","name":"roles","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"social","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"socialIds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"socialSettings","outputs":[{"internalType":"uint256","name":"pairingAmount","type":"uint256"},{"internalType":"uint256","name":"leftSideSupply","type":"uint256"},{"internalType":"uint256","name":"openFeeWei","type":"uint256"},{"internalType":"uint8","name":"poolCreatorFeePercentage","type":"uint8"},{"components":[{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"uint16","name":"percentStart","type":"uint16"},{"internalType":"uint16","name":"percentEnd","type":"uint16"}],"internalType":"struct CheezburgerStructs.DynamicSettings","name":"walletSettings","type":"tuple"},{"components":[{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"uint16","name":"percentStart","type":"uint16"},{"internalType":"uint16","name":"percentEnd","type":"uint16"}],"internalType":"struct CheezburgerStructs.DynamicSettings","name":"feeSettings","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"socialTokens","outputs":[{"internalType":"address","name":"factory","type":"address"},{"internalType":"address","name":"router","type":"address"},{"internalType":"address","name":"pair","type":"address"},{"internalType":"address","name":"creator","type":"address"},{"internalType":"address","name":"leftSide","type":"address"},{"internalType":"address","name":"rightSide","type":"address"},{"components":[{"internalType":"uint8","name":"feeThresholdPercent","type":"uint8"},{"internalType":"address[]","name":"feeAddresses","type":"address[]"},{"internalType":"uint8[]","name":"feePercentages","type":"uint8[]"}],"internalType":"struct CheezburgerStructs.LiquiditySettings","name":"liquidity","type":"tuple"},{"components":[{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"uint16","name":"percentStart","type":"uint16"},{"internalType":"uint16","name":"percentEnd","type":"uint16"}],"internalType":"struct CheezburgerStructs.DynamicSettings","name":"fee","type":"tuple"},{"components":[{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"uint16","name":"percentStart","type":"uint16"},{"internalType":"uint16","name":"percentEnd","type":"uint16"}],"internalType":"struct CheezburgerStructs.DynamicSettings","name":"wallet","type":"tuple"},{"components":[{"internalType":"address","name":"feeReceiver","type":"address"},{"internalType":"uint8","name":"feePercentage","type":"uint8"}],"internalType":"struct CheezburgerStructs.ReferralSettings","name":"referral","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenSettings","outputs":[{"internalType":"uint256","name":"pairingAmount","type":"uint256"},{"internalType":"uint256","name":"openFeeWei","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"website","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawCreationFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_userId","type":"uint256"},{"internalType":"address","name":"_to","type":"address"}],"name":"withdrawFeesOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

60806040525f805460ff191660011790553480156200001c575f80fd5b5060405162003ae538038062003ae58339810160408190526200003f91620005cc565b6001600160a01b03821615806200005d57506001600160a01b038116155b156200007c576040516387e5f21360e01b815260040160405180910390fd5b82516012906200008d908262000766565b506020830151601390620000a2908262000766565b506040830151600190620000b7908262000766565b506060830151600290620000cc908262000766565b50620000d833620001b8565b6200010233620000eb6012600a62000941565b8560800151620000fc919062000958565b620001f4565b6040805160c0810182525f808252620f424060208084019190915282840182905260046060808501919091528451808201865262127500815261012c81840152611324818701526080850152845190810185526201518081526101f48183015260c88186015260a0840152835180850190945281845283015262000186916200028b565b604080518082019091526001600160a01b03808416825282166020820152620001af906200034e565b50505062000972565b6001600160a01b0316638b78c6d819819055805f7f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08180a35b50565b620002015f8383620003b6565b6805345cdf77eb68f44c5481810181811015620002255763e5cfe9575f526004601cfd5b806805345cdf77eb68f44c5550506387a211a2600c52815f526020600c208181540181555080602052600c5160601c5f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602080a3620002875f83836200040b565b5050565b6010620002988162000466565b60208381015160075560408085015160085560608501516009805460ff191660ff90921691909117905560808501518051600a5580830151600b80549284015161ffff92831663ffffffff19948516176201000091841682021790915560a08801518051600c5580860151600d805492870151918516929095169190911792160217905590830151600f55517f85a52584e2a604db198ab2f447cba2fc038a972048381c24b40219ef7a83df70905f90a1505050565b6200035862000499565b8051600480546001600160a01b039283166001600160a01b0319918216179091556020830151600580549190931691161790556040517fe8b17a7524058d1a342afefcf40dad4efc8d3d505c865b90ba810c43cff793e6905f90a150565b6001600160a01b03831615801590620003d757506001600160a01b03821630145b156200040657604051634ae889f760e01b81526001600160a01b03831660048201526024015b60405180910390fd5b505050565b6001600160a01b0382161580156200043357506387a211a2600c9081525f8052602090205415155b15620004065760405163281a1b1360e01b81526001600160a01b03808516600483015283166024820152604401620003fd565b638b78c6d819543314620001f157638b78c6d8600c52335f52806020600c205416620001f1576382b429005f526004601cfd5b638b78c6d819543314620004b4576382b429005f526004601cfd5b565b634e487b7160e01b5f52604160045260245ffd5b60405160a081016001600160401b0381118282101715620004ef57620004ef620004b6565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620005205762000520620004b6565b604052919050565b5f82601f83011262000538575f80fd5b81516001600160401b03811115620005545762000554620004b6565b60206200056a601f8301601f19168201620004f5565b82815285828487010111156200057e575f80fd5b5f5b838110156200059d57858101830151828201840152820162000580565b505f928101909101919091529392505050565b80516001600160a01b0381168114620005c7575f80fd5b919050565b5f805f60608486031215620005df575f80fd5b83516001600160401b0380821115620005f6575f80fd5b9085019060a082880312156200060a575f80fd5b62000614620004ca565b82518281111562000623575f80fd5b620006318982860162000528565b82525060208301518281111562000646575f80fd5b620006548982860162000528565b6020830152506040830151828111156200066c575f80fd5b6200067a8982860162000528565b60408301525060608301518281111562000692575f80fd5b620006a08982860162000528565b60608301525060808301516080820152809550505050620006c460208501620005b0565b9150620006d460408501620005b0565b90509250925092565b600181811c90821680620006f257607f821691505b6020821081036200071157634e487b7160e01b5f52602260045260245ffd5b50919050565b601f8211156200040657805f5260205f20601f840160051c810160208510156200073e5750805b601f840160051c820191505b818110156200075f575f81556001016200074a565b5050505050565b81516001600160401b03811115620007825762000782620004b6565b6200079a81620007938454620006dd565b8462000717565b602080601f831160018114620007d0575f8415620007b85750858301515b5f19600386901b1c1916600185901b1785556200082a565b5f85815260208120601f198616915b828110156200080057888601518255948401946001909101908401620007df565b50858210156200081e57878501515f19600388901b60f8161c191681555b505060018460011b0185555b505050505050565b634e487b7160e01b5f52601160045260245ffd5b600181815b808511156200088657815f19048211156200086a576200086a62000832565b808516156200087857918102915b93841c93908002906200084b565b509250929050565b5f826200089e575060016200093b565b81620008ac57505f6200093b565b8160018114620008c55760028114620008d057620008f0565b60019150506200093b565b60ff841115620008e457620008e462000832565b50506001821b6200093b565b5060208310610133831016604e8410600b841016171562000915575081810a6200093b565b62000921838362000846565b805f190482111562000937576200093762000832565b0290505b92915050565b5f6200095160ff8416836200088e565b9392505050565b80820281158282048414176200093b576200093b62000832565b61316580620009805f395ff3fe6080604052600436106102c4575f3560e01c806370a0823111610170578063cfcd8b76116100d1578063de3c3e2c11610087578063f04e283e11610062578063f04e283e14610844578063f2fde38b14610857578063fee81cf41461086a575f80fd5b8063de3c3e2c146107e7578063e29c24fd14610812578063e2cc88a714610825575f80fd5b8063d505accf116100b7578063d505accf14610781578063dbcae73f146107a0578063dd62ed3e146107b3575f80fd5b8063cfcd8b761461072d578063d324657214610762575f80fd5b8063876ad4471161012657806395d89b411161010c57806395d89b41146106e6578063a9059cbb146106fa578063beb0a41614610719575f80fd5b8063876ad4471461068b5780638da5cb5b146106ba575f80fd5b80637233f2be116101565780637233f2be1461062757806379cc67901461063b5780637ecebe001461065a575f80fd5b806370a08231146105ee578063715018a61461061f575f80fd5b8063307770611161022557806342966c68116101db5780635224b55d116101b65780635224b55d146105b257806354d1f13d146105d15780636ca2826b146105d9575f80fd5b806342966c681461054b5780634a4ee7b11461056a578063514e62fc1461057d575f80fd5b806334d1c00a1161020b57806334d1c00a1461048b578063359ecf10146105185780633644e51514610537575f80fd5b8063307770611461045c578063313ce56714610470575f80fd5b80631cd64df41161027a57806323b872dd1161026057806323b872dd1461040457806325692962146104235780632de948071461042b575f80fd5b80631cd64df4146103895780631dcf615e146103be575f80fd5b806318160ddd116102aa57806318160ddd1461033f578063183a4f6e146103615780631c10893f14610376575f80fd5b806306fdde03146102e6578063095ea7b314610310575f80fd5b366102e25760405163668a64f760e11b815260040160405180910390fd5b5f80fd5b3480156102f1575f80fd5b506102fa61089b565b60405161030791906123b5565b60405180910390f35b34801561031b575f80fd5b5061032f61032a3660046123e2565b61092b565b6040519015158152602001610307565b34801561034a575f80fd5b5061035361097a565b604051908152602001610307565b61037461036f36600461240c565b610995565b005b6103746103843660046123e2565b6109a2565b348015610394575f80fd5b5061032f6103a33660046123e2565b638b78c6d8600c9081525f9290925260209091205481161490565b3480156103c9575f80fd5b506004546005546103e4916001600160a01b03908116911682565b604080516001600160a01b03938416815292909116602083015201610307565b34801561040f575f80fd5b5061032f61041e366004612423565b6109b8565b610374610a88565b348015610436575f80fd5b50610353610445366004612461565b638b78c6d8600c9081525f91909152602090205490565b348015610467575f80fd5b50610374610ad5565b34801561047b575f80fd5b5060405160128152602001610307565b348015610496575f80fd5b506006546007546008546009546040805160608082018352600a548252600b5461ffff808216602080860191909152620100009283900482168587015285519384018652600c548452600d54808316918501919091529190910416928101929092526105069594939260ff169186565b6040516103079695949392919061247c565b348015610523575f80fd5b506103536105323660046124e0565b610ae9565b348015610542575f80fd5b50610353610b07565b348015610556575f80fd5b5061037461056536600461240c565b610b83565b6103746105783660046123e2565b610b8d565b348015610588575f80fd5b5061032f6105973660046123e2565b638b78c6d8600c9081525f9290925260209091205416151590565b3480156105bd575f80fd5b506103746105cc366004612657565b610b9f565b610374610c60565b3480156105e4575f80fd5b5061035360035481565b3480156105f9575f80fd5b50610353610608366004612461565b6387a211a2600c9081525f91909152602090205490565b610374610c99565b348015610632575f80fd5b506102fa610cac565b348015610646575f80fd5b506103746106553660046123e2565b610cbb565b348015610665575f80fd5b50610353610674366004612461565b6338377508600c9081525f91909152602090205490565b348015610696575f80fd5b50600e54600f546106a5919082565b60408051928352602083019190915201610307565b3480156106c5575f80fd5b50638b78c6d819545b6040516001600160a01b039091168152602001610307565b3480156106f1575f80fd5b506102fa610cd0565b348015610705575f80fd5b5061032f6107143660046123e2565b610cdf565b348015610724575f80fd5b506102fa610d6c565b348015610738575f80fd5b5061074c61074736600461240c565b610d7b565b6040516103079a999897969594939291906127b5565b34801561076d575f80fd5b5061037461077c366004612881565b610f34565b34801561078c575f80fd5b5061037461079b3660046128a1565b610fb9565b6106ce6107ae36600461240c565b61114c565b3480156107be575f80fd5b506103536107cd36600461290d565b602052637f5e9f20600c9081525f91909152603490205490565b3480156107f2575f80fd5b50610353610801366004612461565b60116020525f908152604090205481565b6106ce610820366004612b5a565b611758565b348015610830575f80fd5b5061037461083f366004612c90565b6118b8565b610374610852366004612461565b61192b565b610374610865366004612461565b611965565b348015610875575f80fd5b50610353610884366004612461565b63389a75e1600c9081525f91909152602090205490565b6060601280546108aa90612ccf565b80601f01602080910402602001604051908101604052809291908181526020018280546108d690612ccf565b80156109215780601f106108f857610100808354040283529160200191610921565b820191905f5260205f20905b81548152906001019060200180831161090457829003601f168201915b5050505050905090565b5f82602052637f5e9f20600c52335f52816034600c2055815f52602c5160601c337f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560205fa350600192915050565b5f60035461098f6805345cdf77eb68f44c5490565b03905090565b61099f338261198b565b50565b6109aa611996565b6109b482826119b0565b5050565b5f6109c48484846119bc565b8360601b33602052637f5e9f208117600c526034600c2080546001810115610a0157808511156109fb576313be252b5f526004601cfd5b84810382555b50506387a211a28117600c526020600c20805480851115610a295763f4d678b85f526004601cfd5b84810382555050835f526020600c208381540181555082602052600c5160601c8160601c7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602080a350610a7e848484611a0a565b5060019392505050565b5f6202a30067ffffffffffffffff164201905063389a75e1600c52335f52806020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d5f80a250565b6004610ae081611a62565b61099f33611a86565b5f6002610af581611a62565b610aff8484611ab0565b949350505050565b5f80610b1161089b565b8051906020012090506040517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81528160208201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6604082015246606082015230608082015260a081209250505090565b61099f3382611b3e565b610b95611996565b6109b4828261198b565b6010610baa81611bc4565b60208381015160075560408085015160085560608501516009805460ff191660ff90921691909117905560808501518051600a5580830151600b80549284015161ffff92831663ffffffff19948516176201000091841682021790915560a08801518051600c5580860151600d805492870151918516929095169190911792160217905590830151600f55517f85a52584e2a604db198ab2f447cba2fc038a972048381c24b40219ef7a83df70905f90a1505050565b63389a75e1600c52335f525f6020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c925f80a2565b610ca1611996565b610caa5f611bf5565b565b6060600280546108aa90612ccf565b610cc6823383611c32565b6109b48282611b3e565b6060601380546108aa90612ccf565b5f610ceb3384846119bc565b6387a211a2600c52335f526020600c20805480841115610d125763f4d678b85f526004601cfd5b83810382555050825f526020600c208281540181555081602052600c5160601c337fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602080a3610d63338484611a0a565b50600192915050565b6060600180546108aa90612ccf565b601060209081525f9182526040918290208054600182015460028301546003840154600485015460058601548851606081018a5260068801805460ff1682526007890180548c51818d0281018d01909d52808d526001600160a01b03998a169c988a169b978a169a968a16999586169895909416969294919385840193830182828015610e2f57602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610e11575b5050505050815260200160028201805480602002602001604051908101604052809291908181526020018280548015610ea257602002820191905f5260205f20905f905b825461010083900a900460ff16815260206001928301818104948501949093039092029101808411610e735790505b505050919092525050604080516060808201835260098601548252600a86015461ffff808216602080860191909152620100009283900482168587015285519384018652600b8901548452600c890154808316858301529290920416828501528351808501909452600d909601546001600160a01b0381168452600160a01b900460ff1695830195909552929391508a565b6008610f3f81611bc4565b5f6019610f4a61097a565b610f549190612d07565b905080841180610f6357508083115b15610f8157604051630b1af1c560e01b815260040160405180910390fd5b6006849055600e8390556040517f5e61ef6a89edc7c475a1c786c7687a2c66ab5a996d29f9601a78281bf9580a08905f90a150505050565b5f610fc261089b565b80519060200120905084421115610fe057631a15a3cc5f526004601cfd5b6040518860601b60601c98508760601b60601c975065383775081901600e52885f526020600c2080547f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f83528360208401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6604084015246606084015230608084015260a08320602e527f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c983528a60208401528960408401528860608401528060808401528760a084015260c08320604e526042602c205f528660ff16602052856040528460605260208060805f60015afa8b3d51146110e85763ddafbaef5f526004601cfd5b019055777f5e9f20000000000000000000000000000000000000000088176040526034602c2087905587897f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925602060608501a360405250505f606052505050505050565b5f805460ff166002036111725760405163c5f2be5160e01b815260040160405180910390fd5b5f805460ff1916600217815582900361119e5760405163aef4e71760e01b815260040160405180910390fd5b5f828152601060205260409020600401546001600160a01b0316156111de576040516310ca6e0960e01b8152600481018390526024015b60405180910390fd5b6040805160028082526060820183525f926020830190803683370190505090505f815f8151811061121157611211612d26565b60200260200101906001600160a01b031690816001600160a01b031681525050308160018151811061124557611245612d26565b6001600160a01b0392909216602092830291909101909101526040805160018082528183019092525f918160200160208202803683370190505090506032815f8151811061129557611295612d26565b602002602001019060ff16908160ff16815250505f6112b385611c73565b90505f6115206040518060a00160405280611303856040518060400160405280600981526020017f2028536f6369616c290000000000000000000000000000000000000000000000815250611cb5565b81526020016113476040518060400160405280600781526020017f43485a422d582d0000000000000000000000000000000000000000000000000081525086611cb5565b81526020016001805461135990612ccf565b80601f016020809104026020016040519081016040528092919081815260200182805461138590612ccf565b80156113d05780601f106113a7576101008083540402835291602001916113d0565b820191905f5260205f20905b8154815290600101906020018083116113b357829003601f168201915b50505050508152602001600280546113e790612ccf565b80601f016020809104026020016040519081016040528092919081815260200182805461141390612ccf565b801561145e5780601f106114355761010080835404028352916020019161145e565b820191905f5260205f20905b81548152906001019060200180831161144157829003601f168201915b50505091835250506007546020918201526040805160608082018352600282528184018a905281830189905282518082018452600c548152600d5461ffff80821683880152620100009182900481168387015285519384018652600a548452600b54808216978501979097529504909416928101929092526009549092919060ff166114fc57604080518082019091525f8082526020820152611515565b6040805180820190915233815260095460ff1660208201525b600654600854611d0f565b5f878152601060209081526040918290208351815473ffffffffffffffffffffffffffffffffffffffff199081166001600160a01b03928316178355858401516001840180548316918416919091179055938501516002830180548616918316919091179055606085015160038301805486169183169190911790556080850151600483018054861691831691909117905560a085015160058301805490951691161790925560c0830151805160068401805460ff191660ff9092169190911781558183015180519596508695929391926116019260078701920190612256565b506040820151805161161d9160028401916020909101906122c6565b50505060e082015180516009830155602080820151600a8401805460409485015161ffff9081166201000090810263ffffffff1993841695831695909517949094179092556101008701518051600b88015580850151600c88018054928801518516909502919092169190921617179055610120909301518051600d90930180549185015160ff16600160a01b027fffffffffffffffffffffff0000000000000000000000000000000000000000009092166001600160a01b039485161791909117905560808401805183165f9081526011909452928190208990556006549251600354915192169189917fcc3e9264e04b0c3e95caab810e2b79dcf92ad5a919096173776c77ae4f32db119161173691815260200190565b60405180910390a46080015193505050505f805460ff19166001179055919050565b5f805460ff1660020361177e5760405163c5f2be5160e01b815260040160405180910390fd5b5f805460ff191660021790556020868101516040805180820190915260058082527f43485a422d000000000000000000000000000000000000000000000000000000918401919091529181018290209051909111157f779f6a5034e01e3f8c94a4dd8ce33ae89e62528ef26eb9bb20ca5c37a9596fd69091141680156118165750638b78c6d8600c908152335f526020908190205416155b156118345760405163361cb83960e11b815260040160405180910390fd5b5f61184d8787878787600e5f0154600e60010154611d0f565b9050600e5f015481608001516001600160a01b03167fffbb7fa028a13c99395f25007a703011e59272cbf40f7a02823f34629c27ef2760035460405161189591815260200190565b60405180910390a36080015190505f805460ff1916600117905595945050505050565b6118c0611996565b8051600480546001600160a01b0392831673ffffffffffffffffffffffffffffffffffffffff19918216179091556020830151600580549190931691161790556040517fe8b17a7524058d1a342afefcf40dad4efc8d3d505c865b90ba810c43cff793e6905f90a150565b611933611996565b63389a75e1600c52805f526020600c20805442111561195957636f5e88185f526004601cfd5b5f905561099f81611bf5565b61196d611996565b8060601b61198257637448fbae5f526004601cfd5b61099f81611bf5565b6109b482825f611f16565b638b78c6d819543314610caa576382b429005f526004601cfd5b6109b482826001611f16565b6001600160a01b038316158015906119dc57506001600160a01b03821630145b15611a0557604051634ae889f760e01b81526001600160a01b03831660048201526024016111d5565b505050565b6001600160a01b038216158015611a3157506387a211a2600c9081525f8052602090205415155b15611a055760405163281a1b1360e01b81526001600160a01b038085166004830152831660248201526044016111d5565b638b78c6d8600c52335f52806020600c20541661099f576382b429005f526004601cfd5b5f385f384785620186a0f161099f57805f526073600b5360ff6020536016600b47f061099f573838fd5b5f828152601060205260408120600201546001600160a01b031680611ae85760405163252fe3c560e01b815260040160405180910390fd5b5f611af38285611f6d565b905080846001600160a01b0316836001600160a01b03167f0d3436d46d19d0f7b8fe80eef1d937706e673070d9099df32fd119aa611736d260405160405180910390a4949350505050565b611b49825f836119bc565b6387a211a2600c52815f526020600c20805480831115611b705763f4d678b85f526004601cfd5b82900390556805345cdf77eb68f44c805482900390555f8181526001600160a01b0383167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602083a36109b4825f83611a0a565b638b78c6d81954331461099f57638b78c6d8600c52335f52806020600c20541661099f576382b429005f526004601cfd5b638b78c6d81980546001600160a01b039092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a355565b81602052637f5e9f20600c52825f526034600c2080546001810115611c6c5780831115611c66576313be252b5f526004601cfd5b82810382555b5050505050565b60606080604051019050602081016040525f8152805f19835b928101926030600a8206018453600a900480611c8c575050819003601f19909101908152919050565b6040518251601f19906020810182165b8581015184820152820180611cc5575083518184018360208301165b8681015182820152840180611ce15750505f910183810160208101929092528352603f011660405292915050565b611daf60408051610140810182525f808252602080830182905282840182905260608084018390526080840183905260a084018390528451808201865283815280830182905280860182905260c08501528451808201865283815280830184905280860184905260e08501528451908101855282815280820183905280850183905261010084015283518085019094528184528301529061012082015290565b813414611dd857604051633c0ef5cb60e11b8152346004820152602481018390526044016111d5565b611de23084611fe5565b600454611dfa9030906001600160a01b031685612073565b5f60045f015f9054906101000a90046001600160a01b03166001600160a01b031663bec8acc88a60046001015f9054906101000a90046001600160a01b031630888d8d8d8d6040518963ffffffff1660e01b8152600401611e62989796959493929190612d3a565b6020604051808303815f875af1158015611e7e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ea29190612e8b565b6004549091505f90611ebd906001600160a01b0316836120bc565b9050611ecd81604001515f611f6d565b5084611ed761097a565b01611ee061097a565b1115611eff57604051637ebdee1b60e01b815260040160405180910390fd5b60038054860190559150505b979650505050505050565b638b78c6d8600c52825f526020600c20805483811783611f37575080841681185b80835580600c5160601c7f715ad5ce61fc9595c7b415289d59cf203f23a94fa06f04af7e489a0a76e1fe265f80a3505050505050565b5f6370a082315f5230602052602060346024601c865afa601f3d1116611f9a576390b8ec185f526004601cfd5b8160145260345190506fa9059cbb0000000000000000000000005f5260205f604460105f875af13d1560015f51141716611fdb576390b8ec185f526004601cfd5b5f60345292915050565b611ff05f83836119bc565b6805345cdf77eb68f44c54818101818110156120135763e5cfe9575f526004601cfd5b806805345cdf77eb68f44c5550506387a211a2600c52815f526020600c208181540181555080602052600c5160601c5f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602080a36109b45f8383611a0a565b81601452806034526f095ea7b30000000000000000000000005f5260205f604460105f875af13d1560015f511417166120b357633e3f8f735f526004601cfd5b5f603452505050565b61215c60408051610140810182525f808252602080830182905282840182905260608084018390526080840183905260a084018390528451808201865283815280830182905280860182905260c08501528451808201865283815280830184905280860184905260e08501528451908101855282815280820183905280850183905261010084015283518085019094528184528301529061012082015290565b5f805f805f805f805f808c6001600160a01b03166301b7cc648d6040518263ffffffff1660e01b81526004016121a191906001600160a01b0391909116815260200190565b5f60405180830381865afa1580156121bb573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526121e29190810190613050565b60408051610140810182526001600160a01b039b8c168152998b1660208b0152978a169789019790975294881660608801529287166080870152951660a085015260c084019490945260e08301939093526101008201929092526101208101919091529d9c50505050505050505050505050565b828054828255905f5260205f209081019282156122b6579160200282015b828111156122b6578251825473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116178255602090920191600190910190612274565b506122c292915061235e565b5090565b828054828255905f5260205f2090601f016020900481019282156122b6579160200282015f5b8382111561232957835183826101000a81548160ff021916908360ff16021790555092602001926001016020815f010492830192600103026122ec565b80156123555782816101000a81549060ff02191690556001016020815f01049283019260010302612329565b50506122c29291505b5b808211156122c2575f815560010161235f565b5f81518084525f5b818110156123965760208185018101518683018201520161237a565b505f602082860101526020601f19601f83011685010191505092915050565b602081525f6123c76020830184612372565b9392505050565b6001600160a01b038116811461099f575f80fd5b5f80604083850312156123f3575f80fd5b82356123fe816123ce565b946020939093013593505050565b5f6020828403121561241c575f80fd5b5035919050565b5f805f60608486031215612435575f80fd5b8335612440816123ce565b92506020840135612450816123ce565b929592945050506040919091013590565b5f60208284031215612471575f80fd5b81356123c7816123ce565b8681526020808201879052604080830187905260ff86166060840152845160808401528482015161ffff90811660a085015285820151811660c0850152845160e0850152918401518216610100840152830151166101208201526101408101611f0b565b5f80604083850312156124f1575f80fd5b823591506020830135612503816123ce565b809150509250929050565b634e487b7160e01b5f52604160045260245ffd5b6040516060810167ffffffffffffffff811182821017156125455761254561250e565b60405290565b6040805190810167ffffffffffffffff811182821017156125455761254561250e565b60405160a0810167ffffffffffffffff811182821017156125455761254561250e565b604051601f8201601f1916810167ffffffffffffffff811182821017156125ba576125ba61250e565b604052919050565b60ff8116811461099f575f80fd5b61ffff8116811461099f575f80fd5b5f606082840312156125ef575f80fd5b6125f7612522565b905081358152602082013561260b816125d0565b6020820152604082013561261e816125d0565b604082015292915050565b5f60408284031215612639575f80fd5b61264161254b565b9050813581526020820135602082015292915050565b5f8082840361018081121561266a575f80fd5b61014080821215612679575f80fd5b604051915060c0820182811067ffffffffffffffff8211171561269e5761269e61250e565b806040525084358252602085013560208301526040850135604083015260608501356126c9816125c2565b60608301526126db86608087016125df565b60808301526126ed8660e087016125df565b60a083015281935061270186828701612629565b925050509250929050565b5f6060830160ff80845116855260208085015160608288015283815180865260808901915083830195505f92505b808310156127635785516001600160a01b0316825294830194600192909201919083019061273a565b50604087810151898303918a01919091528051808352908401955090830191505f905b808210156127a857855185168352948301949183019160019190910190612786565b5090979650505050505050565b5f6101e06001600160a01b03808e168452808d166020850152808c166040850152808b166060850152808a16608085015280891660a0850152508060c08401526128018184018861270c565b865160e0850152602087015161ffff908116610100860152604088015116610120850152915061282e9050565b8351610140830152602084015161ffff90811661016084015260408501511661018083015282516001600160a01b03166101a0830152602083015160ff166101c08301529b9a5050505050505050505050565b5f8060408385031215612892575f80fd5b50508035926020909101359150565b5f805f805f805f60e0888a0312156128b7575f80fd5b87356128c2816123ce565b965060208801356128d2816123ce565b9550604088013594506060880135935060808801356128f0816125c2565b9699959850939692959460a0840135945060c09093013592915050565b5f806040838503121561291e575f80fd5b8235612929816123ce565b91506020830135612503816123ce565b5f82601f830112612948575f80fd5b813567ffffffffffffffff8111156129625761296261250e565b612975601f8201601f1916602001612591565b818152846020838601011115612989575f80fd5b816020850160208301375f918101602001919091529392505050565b5f67ffffffffffffffff8211156129be576129be61250e565b5060051b60200190565b5f82601f8301126129d7575f80fd5b813560206129ec6129e7836129a5565b612591565b8083825260208201915060208460051b870101935086841115612a0d575f80fd5b602086015b84811015612a32578035612a25816125c2565b8352918301918301612a12565b509695505050505050565b5f60608284031215612a4d575f80fd5b612a55612522565b90508135612a62816125c2565b815260208281013567ffffffffffffffff80821115612a7f575f80fd5b818501915085601f830112612a92575f80fd5b8135612aa06129e7826129a5565b81815260059190911b83018401908481019088831115612abe575f80fd5b938501935b82851015612ae5578435612ad6816123ce565b82529385019390850190612ac3565b80868801525050506040850135925080831115612b00575f80fd5b5050612b0e848285016129c8565b60408301525092915050565b5f60408284031215612b2a575f80fd5b612b3261254b565b90508135612b3f816123ce565b81526020820135612b4f816125c2565b602082015292915050565b5f805f805f6101408688031215612b6f575f80fd5b853567ffffffffffffffff80821115612b86575f80fd5b9087019060a0828a031215612b99575f80fd5b612ba161256e565b823582811115612baf575f80fd5b612bbb8b828601612939565b825250602083013582811115612bcf575f80fd5b612bdb8b828601612939565b602083015250604083013582811115612bf2575f80fd5b612bfe8b828601612939565b604083015250606083013582811115612c15575f80fd5b612c218b828601612939565b60608301525060808301356080820152809750506020880135915080821115612c48575f80fd5b50612c5588828901612a3d565b945050612c6587604088016125df565b9250612c748760a088016125df565b9150612c84876101008801612b1a565b90509295509295909350565b5f60408284031215612ca0575f80fd5b612ca861254b565b8235612cb3816123ce565b81526020830135612cc3816123ce565b60208201529392505050565b600181811c90821680612ce357607f821691505b602082108103612d0157634e487b7160e01b5f52602260045260245ffd5b50919050565b5f82612d2157634e487b7160e01b5f52601260045260245ffd5b500490565b634e487b7160e01b5f52603260045260245ffd5b5f6101a08083528a5160a082850152612d57610240850182612372565b91505060208b015161019f1980858403016101c0860152612d788383612372565b925060408d0151915080858403016101e0860152612d968383612372565b925060608d01519150808584030161020086015250612db58282612372565b91505060808b0151610220840152612dd8602084018b6001600160a01b03169052565b6001600160a01b03891660408401528760608401528281036080840152612dff818861270c565b865160a0850152602087015161ffff90811660c086015260408801511660e08501529150612e2a9050565b8351610100830152602084015161ffff90811661012084015260408501511661014083015282516001600160a01b0316610160830152602083015160ff166101808301529998505050505050505050565b8051612e86816123ce565b919050565b5f60208284031215612e9b575f80fd5b81516123c7816123ce565b5f82601f830112612eb5575f80fd5b81516020612ec56129e7836129a5565b8083825260208201915060208460051b870101935086841115612ee6575f80fd5b602086015b84811015612a32578051612efe816125c2565b8352918301918301612eeb565b5f60608284031215612f1b575f80fd5b612f23612522565b90508151612f30816125c2565b815260208281015167ffffffffffffffff80821115612f4d575f80fd5b818501915085601f830112612f60575f80fd5b8151612f6e6129e7826129a5565b81815260059190911b83018401908481019088831115612f8c575f80fd5b938501935b82851015612fb3578451612fa4816123ce565b82529385019390850190612f91565b80868801525050506040850151925080831115612fce575f80fd5b5050612b0e84828501612ea6565b5f60608284031215612fec575f80fd5b612ff4612522565b9050815181526020820151613008816125d0565b6020820152604082015161261e816125d0565b5f6040828403121561302b575f80fd5b61303361254b565b90508151613040816123ce565b81526020820151612b4f816125c2565b5f805f805f805f805f806101e08b8d03121561306a575f80fd5b8a51613075816123ce565b60208c0151909a50613086816123ce565b60408c0151909950613097816123ce565b60608c01519098506130a8816123ce565b60808c01519097506130b9816123ce565b95506130c760a08c01612e7b565b945060c08b015167ffffffffffffffff8111156130e2575f80fd5b6130ee8d828e01612f0b565b9450506130fe8c60e08d01612fdc565b925061310e8c6101408d01612fdc565b915061311e8c6101a08d0161301b565b90509295989b9194979a509295985056fea2646970667358221220794159239f1deb143ed3a080e0bb6e618d2d7f7775a71578db816f68d6c56c5164736f6c634300081600330000000000000000000000000000000000000000000000000000000000000060000000000000000000000000b51b7d01c94ceff686e6463ce1ea461c2bb8276b0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000003b2e0f44000000000000000000000000000000000000000000000000000000000000000b436865657a627572676572000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000443485a4200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001768747470733a2f2f636865657a6275726765722e6c6f6c000000000000000000000000000000000000000000000000000000000000000000000000000000001768747470733a2f2f636865657a6275726765722e6c6f6c000000000000000000

Deployed Bytecode

0x6080604052600436106102c4575f3560e01c806370a0823111610170578063cfcd8b76116100d1578063de3c3e2c11610087578063f04e283e11610062578063f04e283e14610844578063f2fde38b14610857578063fee81cf41461086a575f80fd5b8063de3c3e2c146107e7578063e29c24fd14610812578063e2cc88a714610825575f80fd5b8063d505accf116100b7578063d505accf14610781578063dbcae73f146107a0578063dd62ed3e146107b3575f80fd5b8063cfcd8b761461072d578063d324657214610762575f80fd5b8063876ad4471161012657806395d89b411161010c57806395d89b41146106e6578063a9059cbb146106fa578063beb0a41614610719575f80fd5b8063876ad4471461068b5780638da5cb5b146106ba575f80fd5b80637233f2be116101565780637233f2be1461062757806379cc67901461063b5780637ecebe001461065a575f80fd5b806370a08231146105ee578063715018a61461061f575f80fd5b8063307770611161022557806342966c68116101db5780635224b55d116101b65780635224b55d146105b257806354d1f13d146105d15780636ca2826b146105d9575f80fd5b806342966c681461054b5780634a4ee7b11461056a578063514e62fc1461057d575f80fd5b806334d1c00a1161020b57806334d1c00a1461048b578063359ecf10146105185780633644e51514610537575f80fd5b8063307770611461045c578063313ce56714610470575f80fd5b80631cd64df41161027a57806323b872dd1161026057806323b872dd1461040457806325692962146104235780632de948071461042b575f80fd5b80631cd64df4146103895780631dcf615e146103be575f80fd5b806318160ddd116102aa57806318160ddd1461033f578063183a4f6e146103615780631c10893f14610376575f80fd5b806306fdde03146102e6578063095ea7b314610310575f80fd5b366102e25760405163668a64f760e11b815260040160405180910390fd5b5f80fd5b3480156102f1575f80fd5b506102fa61089b565b60405161030791906123b5565b60405180910390f35b34801561031b575f80fd5b5061032f61032a3660046123e2565b61092b565b6040519015158152602001610307565b34801561034a575f80fd5b5061035361097a565b604051908152602001610307565b61037461036f36600461240c565b610995565b005b6103746103843660046123e2565b6109a2565b348015610394575f80fd5b5061032f6103a33660046123e2565b638b78c6d8600c9081525f9290925260209091205481161490565b3480156103c9575f80fd5b506004546005546103e4916001600160a01b03908116911682565b604080516001600160a01b03938416815292909116602083015201610307565b34801561040f575f80fd5b5061032f61041e366004612423565b6109b8565b610374610a88565b348015610436575f80fd5b50610353610445366004612461565b638b78c6d8600c9081525f91909152602090205490565b348015610467575f80fd5b50610374610ad5565b34801561047b575f80fd5b5060405160128152602001610307565b348015610496575f80fd5b506006546007546008546009546040805160608082018352600a548252600b5461ffff808216602080860191909152620100009283900482168587015285519384018652600c548452600d54808316918501919091529190910416928101929092526105069594939260ff169186565b6040516103079695949392919061247c565b348015610523575f80fd5b506103536105323660046124e0565b610ae9565b348015610542575f80fd5b50610353610b07565b348015610556575f80fd5b5061037461056536600461240c565b610b83565b6103746105783660046123e2565b610b8d565b348015610588575f80fd5b5061032f6105973660046123e2565b638b78c6d8600c9081525f9290925260209091205416151590565b3480156105bd575f80fd5b506103746105cc366004612657565b610b9f565b610374610c60565b3480156105e4575f80fd5b5061035360035481565b3480156105f9575f80fd5b50610353610608366004612461565b6387a211a2600c9081525f91909152602090205490565b610374610c99565b348015610632575f80fd5b506102fa610cac565b348015610646575f80fd5b506103746106553660046123e2565b610cbb565b348015610665575f80fd5b50610353610674366004612461565b6338377508600c9081525f91909152602090205490565b348015610696575f80fd5b50600e54600f546106a5919082565b60408051928352602083019190915201610307565b3480156106c5575f80fd5b50638b78c6d819545b6040516001600160a01b039091168152602001610307565b3480156106f1575f80fd5b506102fa610cd0565b348015610705575f80fd5b5061032f6107143660046123e2565b610cdf565b348015610724575f80fd5b506102fa610d6c565b348015610738575f80fd5b5061074c61074736600461240c565b610d7b565b6040516103079a999897969594939291906127b5565b34801561076d575f80fd5b5061037461077c366004612881565b610f34565b34801561078c575f80fd5b5061037461079b3660046128a1565b610fb9565b6106ce6107ae36600461240c565b61114c565b3480156107be575f80fd5b506103536107cd36600461290d565b602052637f5e9f20600c9081525f91909152603490205490565b3480156107f2575f80fd5b50610353610801366004612461565b60116020525f908152604090205481565b6106ce610820366004612b5a565b611758565b348015610830575f80fd5b5061037461083f366004612c90565b6118b8565b610374610852366004612461565b61192b565b610374610865366004612461565b611965565b348015610875575f80fd5b50610353610884366004612461565b63389a75e1600c9081525f91909152602090205490565b6060601280546108aa90612ccf565b80601f01602080910402602001604051908101604052809291908181526020018280546108d690612ccf565b80156109215780601f106108f857610100808354040283529160200191610921565b820191905f5260205f20905b81548152906001019060200180831161090457829003601f168201915b5050505050905090565b5f82602052637f5e9f20600c52335f52816034600c2055815f52602c5160601c337f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560205fa350600192915050565b5f60035461098f6805345cdf77eb68f44c5490565b03905090565b61099f338261198b565b50565b6109aa611996565b6109b482826119b0565b5050565b5f6109c48484846119bc565b8360601b33602052637f5e9f208117600c526034600c2080546001810115610a0157808511156109fb576313be252b5f526004601cfd5b84810382555b50506387a211a28117600c526020600c20805480851115610a295763f4d678b85f526004601cfd5b84810382555050835f526020600c208381540181555082602052600c5160601c8160601c7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602080a350610a7e848484611a0a565b5060019392505050565b5f6202a30067ffffffffffffffff164201905063389a75e1600c52335f52806020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d5f80a250565b6004610ae081611a62565b61099f33611a86565b5f6002610af581611a62565b610aff8484611ab0565b949350505050565b5f80610b1161089b565b8051906020012090506040517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81528160208201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6604082015246606082015230608082015260a081209250505090565b61099f3382611b3e565b610b95611996565b6109b4828261198b565b6010610baa81611bc4565b60208381015160075560408085015160085560608501516009805460ff191660ff90921691909117905560808501518051600a5580830151600b80549284015161ffff92831663ffffffff19948516176201000091841682021790915560a08801518051600c5580860151600d805492870151918516929095169190911792160217905590830151600f55517f85a52584e2a604db198ab2f447cba2fc038a972048381c24b40219ef7a83df70905f90a1505050565b63389a75e1600c52335f525f6020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c925f80a2565b610ca1611996565b610caa5f611bf5565b565b6060600280546108aa90612ccf565b610cc6823383611c32565b6109b48282611b3e565b6060601380546108aa90612ccf565b5f610ceb3384846119bc565b6387a211a2600c52335f526020600c20805480841115610d125763f4d678b85f526004601cfd5b83810382555050825f526020600c208281540181555081602052600c5160601c337fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602080a3610d63338484611a0a565b50600192915050565b6060600180546108aa90612ccf565b601060209081525f9182526040918290208054600182015460028301546003840154600485015460058601548851606081018a5260068801805460ff1682526007890180548c51818d0281018d01909d52808d526001600160a01b03998a169c988a169b978a169a968a16999586169895909416969294919385840193830182828015610e2f57602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610e11575b5050505050815260200160028201805480602002602001604051908101604052809291908181526020018280548015610ea257602002820191905f5260205f20905f905b825461010083900a900460ff16815260206001928301818104948501949093039092029101808411610e735790505b505050919092525050604080516060808201835260098601548252600a86015461ffff808216602080860191909152620100009283900482168587015285519384018652600b8901548452600c890154808316858301529290920416828501528351808501909452600d909601546001600160a01b0381168452600160a01b900460ff1695830195909552929391508a565b6008610f3f81611bc4565b5f6019610f4a61097a565b610f549190612d07565b905080841180610f6357508083115b15610f8157604051630b1af1c560e01b815260040160405180910390fd5b6006849055600e8390556040517f5e61ef6a89edc7c475a1c786c7687a2c66ab5a996d29f9601a78281bf9580a08905f90a150505050565b5f610fc261089b565b80519060200120905084421115610fe057631a15a3cc5f526004601cfd5b6040518860601b60601c98508760601b60601c975065383775081901600e52885f526020600c2080547f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f83528360208401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6604084015246606084015230608084015260a08320602e527f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c983528a60208401528960408401528860608401528060808401528760a084015260c08320604e526042602c205f528660ff16602052856040528460605260208060805f60015afa8b3d51146110e85763ddafbaef5f526004601cfd5b019055777f5e9f20000000000000000000000000000000000000000088176040526034602c2087905587897f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925602060608501a360405250505f606052505050505050565b5f805460ff166002036111725760405163c5f2be5160e01b815260040160405180910390fd5b5f805460ff1916600217815582900361119e5760405163aef4e71760e01b815260040160405180910390fd5b5f828152601060205260409020600401546001600160a01b0316156111de576040516310ca6e0960e01b8152600481018390526024015b60405180910390fd5b6040805160028082526060820183525f926020830190803683370190505090505f815f8151811061121157611211612d26565b60200260200101906001600160a01b031690816001600160a01b031681525050308160018151811061124557611245612d26565b6001600160a01b0392909216602092830291909101909101526040805160018082528183019092525f918160200160208202803683370190505090506032815f8151811061129557611295612d26565b602002602001019060ff16908160ff16815250505f6112b385611c73565b90505f6115206040518060a00160405280611303856040518060400160405280600981526020017f2028536f6369616c290000000000000000000000000000000000000000000000815250611cb5565b81526020016113476040518060400160405280600781526020017f43485a422d582d0000000000000000000000000000000000000000000000000081525086611cb5565b81526020016001805461135990612ccf565b80601f016020809104026020016040519081016040528092919081815260200182805461138590612ccf565b80156113d05780601f106113a7576101008083540402835291602001916113d0565b820191905f5260205f20905b8154815290600101906020018083116113b357829003601f168201915b50505050508152602001600280546113e790612ccf565b80601f016020809104026020016040519081016040528092919081815260200182805461141390612ccf565b801561145e5780601f106114355761010080835404028352916020019161145e565b820191905f5260205f20905b81548152906001019060200180831161144157829003601f168201915b50505091835250506007546020918201526040805160608082018352600282528184018a905281830189905282518082018452600c548152600d5461ffff80821683880152620100009182900481168387015285519384018652600a548452600b54808216978501979097529504909416928101929092526009549092919060ff166114fc57604080518082019091525f8082526020820152611515565b6040805180820190915233815260095460ff1660208201525b600654600854611d0f565b5f878152601060209081526040918290208351815473ffffffffffffffffffffffffffffffffffffffff199081166001600160a01b03928316178355858401516001840180548316918416919091179055938501516002830180548616918316919091179055606085015160038301805486169183169190911790556080850151600483018054861691831691909117905560a085015160058301805490951691161790925560c0830151805160068401805460ff191660ff9092169190911781558183015180519596508695929391926116019260078701920190612256565b506040820151805161161d9160028401916020909101906122c6565b50505060e082015180516009830155602080820151600a8401805460409485015161ffff9081166201000090810263ffffffff1993841695831695909517949094179092556101008701518051600b88015580850151600c88018054928801518516909502919092169190921617179055610120909301518051600d90930180549185015160ff16600160a01b027fffffffffffffffffffffff0000000000000000000000000000000000000000009092166001600160a01b039485161791909117905560808401805183165f9081526011909452928190208990556006549251600354915192169189917fcc3e9264e04b0c3e95caab810e2b79dcf92ad5a919096173776c77ae4f32db119161173691815260200190565b60405180910390a46080015193505050505f805460ff19166001179055919050565b5f805460ff1660020361177e5760405163c5f2be5160e01b815260040160405180910390fd5b5f805460ff191660021790556020868101516040805180820190915260058082527f43485a422d000000000000000000000000000000000000000000000000000000918401919091529181018290209051909111157f779f6a5034e01e3f8c94a4dd8ce33ae89e62528ef26eb9bb20ca5c37a9596fd69091141680156118165750638b78c6d8600c908152335f526020908190205416155b156118345760405163361cb83960e11b815260040160405180910390fd5b5f61184d8787878787600e5f0154600e60010154611d0f565b9050600e5f015481608001516001600160a01b03167fffbb7fa028a13c99395f25007a703011e59272cbf40f7a02823f34629c27ef2760035460405161189591815260200190565b60405180910390a36080015190505f805460ff1916600117905595945050505050565b6118c0611996565b8051600480546001600160a01b0392831673ffffffffffffffffffffffffffffffffffffffff19918216179091556020830151600580549190931691161790556040517fe8b17a7524058d1a342afefcf40dad4efc8d3d505c865b90ba810c43cff793e6905f90a150565b611933611996565b63389a75e1600c52805f526020600c20805442111561195957636f5e88185f526004601cfd5b5f905561099f81611bf5565b61196d611996565b8060601b61198257637448fbae5f526004601cfd5b61099f81611bf5565b6109b482825f611f16565b638b78c6d819543314610caa576382b429005f526004601cfd5b6109b482826001611f16565b6001600160a01b038316158015906119dc57506001600160a01b03821630145b15611a0557604051634ae889f760e01b81526001600160a01b03831660048201526024016111d5565b505050565b6001600160a01b038216158015611a3157506387a211a2600c9081525f8052602090205415155b15611a055760405163281a1b1360e01b81526001600160a01b038085166004830152831660248201526044016111d5565b638b78c6d8600c52335f52806020600c20541661099f576382b429005f526004601cfd5b5f385f384785620186a0f161099f57805f526073600b5360ff6020536016600b47f061099f573838fd5b5f828152601060205260408120600201546001600160a01b031680611ae85760405163252fe3c560e01b815260040160405180910390fd5b5f611af38285611f6d565b905080846001600160a01b0316836001600160a01b03167f0d3436d46d19d0f7b8fe80eef1d937706e673070d9099df32fd119aa611736d260405160405180910390a4949350505050565b611b49825f836119bc565b6387a211a2600c52815f526020600c20805480831115611b705763f4d678b85f526004601cfd5b82900390556805345cdf77eb68f44c805482900390555f8181526001600160a01b0383167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602083a36109b4825f83611a0a565b638b78c6d81954331461099f57638b78c6d8600c52335f52806020600c20541661099f576382b429005f526004601cfd5b638b78c6d81980546001600160a01b039092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a355565b81602052637f5e9f20600c52825f526034600c2080546001810115611c6c5780831115611c66576313be252b5f526004601cfd5b82810382555b5050505050565b60606080604051019050602081016040525f8152805f19835b928101926030600a8206018453600a900480611c8c575050819003601f19909101908152919050565b6040518251601f19906020810182165b8581015184820152820180611cc5575083518184018360208301165b8681015182820152840180611ce15750505f910183810160208101929092528352603f011660405292915050565b611daf60408051610140810182525f808252602080830182905282840182905260608084018390526080840183905260a084018390528451808201865283815280830182905280860182905260c08501528451808201865283815280830184905280860184905260e08501528451908101855282815280820183905280850183905261010084015283518085019094528184528301529061012082015290565b813414611dd857604051633c0ef5cb60e11b8152346004820152602481018390526044016111d5565b611de23084611fe5565b600454611dfa9030906001600160a01b031685612073565b5f60045f015f9054906101000a90046001600160a01b03166001600160a01b031663bec8acc88a60046001015f9054906101000a90046001600160a01b031630888d8d8d8d6040518963ffffffff1660e01b8152600401611e62989796959493929190612d3a565b6020604051808303815f875af1158015611e7e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ea29190612e8b565b6004549091505f90611ebd906001600160a01b0316836120bc565b9050611ecd81604001515f611f6d565b5084611ed761097a565b01611ee061097a565b1115611eff57604051637ebdee1b60e01b815260040160405180910390fd5b60038054860190559150505b979650505050505050565b638b78c6d8600c52825f526020600c20805483811783611f37575080841681185b80835580600c5160601c7f715ad5ce61fc9595c7b415289d59cf203f23a94fa06f04af7e489a0a76e1fe265f80a3505050505050565b5f6370a082315f5230602052602060346024601c865afa601f3d1116611f9a576390b8ec185f526004601cfd5b8160145260345190506fa9059cbb0000000000000000000000005f5260205f604460105f875af13d1560015f51141716611fdb576390b8ec185f526004601cfd5b5f60345292915050565b611ff05f83836119bc565b6805345cdf77eb68f44c54818101818110156120135763e5cfe9575f526004601cfd5b806805345cdf77eb68f44c5550506387a211a2600c52815f526020600c208181540181555080602052600c5160601c5f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602080a36109b45f8383611a0a565b81601452806034526f095ea7b30000000000000000000000005f5260205f604460105f875af13d1560015f511417166120b357633e3f8f735f526004601cfd5b5f603452505050565b61215c60408051610140810182525f808252602080830182905282840182905260608084018390526080840183905260a084018390528451808201865283815280830182905280860182905260c08501528451808201865283815280830184905280860184905260e08501528451908101855282815280820183905280850183905261010084015283518085019094528184528301529061012082015290565b5f805f805f805f805f808c6001600160a01b03166301b7cc648d6040518263ffffffff1660e01b81526004016121a191906001600160a01b0391909116815260200190565b5f60405180830381865afa1580156121bb573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526121e29190810190613050565b60408051610140810182526001600160a01b039b8c168152998b1660208b0152978a169789019790975294881660608801529287166080870152951660a085015260c084019490945260e08301939093526101008201929092526101208101919091529d9c50505050505050505050505050565b828054828255905f5260205f209081019282156122b6579160200282015b828111156122b6578251825473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116178255602090920191600190910190612274565b506122c292915061235e565b5090565b828054828255905f5260205f2090601f016020900481019282156122b6579160200282015f5b8382111561232957835183826101000a81548160ff021916908360ff16021790555092602001926001016020815f010492830192600103026122ec565b80156123555782816101000a81549060ff02191690556001016020815f01049283019260010302612329565b50506122c29291505b5b808211156122c2575f815560010161235f565b5f81518084525f5b818110156123965760208185018101518683018201520161237a565b505f602082860101526020601f19601f83011685010191505092915050565b602081525f6123c76020830184612372565b9392505050565b6001600160a01b038116811461099f575f80fd5b5f80604083850312156123f3575f80fd5b82356123fe816123ce565b946020939093013593505050565b5f6020828403121561241c575f80fd5b5035919050565b5f805f60608486031215612435575f80fd5b8335612440816123ce565b92506020840135612450816123ce565b929592945050506040919091013590565b5f60208284031215612471575f80fd5b81356123c7816123ce565b8681526020808201879052604080830187905260ff86166060840152845160808401528482015161ffff90811660a085015285820151811660c0850152845160e0850152918401518216610100840152830151166101208201526101408101611f0b565b5f80604083850312156124f1575f80fd5b823591506020830135612503816123ce565b809150509250929050565b634e487b7160e01b5f52604160045260245ffd5b6040516060810167ffffffffffffffff811182821017156125455761254561250e565b60405290565b6040805190810167ffffffffffffffff811182821017156125455761254561250e565b60405160a0810167ffffffffffffffff811182821017156125455761254561250e565b604051601f8201601f1916810167ffffffffffffffff811182821017156125ba576125ba61250e565b604052919050565b60ff8116811461099f575f80fd5b61ffff8116811461099f575f80fd5b5f606082840312156125ef575f80fd5b6125f7612522565b905081358152602082013561260b816125d0565b6020820152604082013561261e816125d0565b604082015292915050565b5f60408284031215612639575f80fd5b61264161254b565b9050813581526020820135602082015292915050565b5f8082840361018081121561266a575f80fd5b61014080821215612679575f80fd5b604051915060c0820182811067ffffffffffffffff8211171561269e5761269e61250e565b806040525084358252602085013560208301526040850135604083015260608501356126c9816125c2565b60608301526126db86608087016125df565b60808301526126ed8660e087016125df565b60a083015281935061270186828701612629565b925050509250929050565b5f6060830160ff80845116855260208085015160608288015283815180865260808901915083830195505f92505b808310156127635785516001600160a01b0316825294830194600192909201919083019061273a565b50604087810151898303918a01919091528051808352908401955090830191505f905b808210156127a857855185168352948301949183019160019190910190612786565b5090979650505050505050565b5f6101e06001600160a01b03808e168452808d166020850152808c166040850152808b166060850152808a16608085015280891660a0850152508060c08401526128018184018861270c565b865160e0850152602087015161ffff908116610100860152604088015116610120850152915061282e9050565b8351610140830152602084015161ffff90811661016084015260408501511661018083015282516001600160a01b03166101a0830152602083015160ff166101c08301529b9a5050505050505050505050565b5f8060408385031215612892575f80fd5b50508035926020909101359150565b5f805f805f805f60e0888a0312156128b7575f80fd5b87356128c2816123ce565b965060208801356128d2816123ce565b9550604088013594506060880135935060808801356128f0816125c2565b9699959850939692959460a0840135945060c09093013592915050565b5f806040838503121561291e575f80fd5b8235612929816123ce565b91506020830135612503816123ce565b5f82601f830112612948575f80fd5b813567ffffffffffffffff8111156129625761296261250e565b612975601f8201601f1916602001612591565b818152846020838601011115612989575f80fd5b816020850160208301375f918101602001919091529392505050565b5f67ffffffffffffffff8211156129be576129be61250e565b5060051b60200190565b5f82601f8301126129d7575f80fd5b813560206129ec6129e7836129a5565b612591565b8083825260208201915060208460051b870101935086841115612a0d575f80fd5b602086015b84811015612a32578035612a25816125c2565b8352918301918301612a12565b509695505050505050565b5f60608284031215612a4d575f80fd5b612a55612522565b90508135612a62816125c2565b815260208281013567ffffffffffffffff80821115612a7f575f80fd5b818501915085601f830112612a92575f80fd5b8135612aa06129e7826129a5565b81815260059190911b83018401908481019088831115612abe575f80fd5b938501935b82851015612ae5578435612ad6816123ce565b82529385019390850190612ac3565b80868801525050506040850135925080831115612b00575f80fd5b5050612b0e848285016129c8565b60408301525092915050565b5f60408284031215612b2a575f80fd5b612b3261254b565b90508135612b3f816123ce565b81526020820135612b4f816125c2565b602082015292915050565b5f805f805f6101408688031215612b6f575f80fd5b853567ffffffffffffffff80821115612b86575f80fd5b9087019060a0828a031215612b99575f80fd5b612ba161256e565b823582811115612baf575f80fd5b612bbb8b828601612939565b825250602083013582811115612bcf575f80fd5b612bdb8b828601612939565b602083015250604083013582811115612bf2575f80fd5b612bfe8b828601612939565b604083015250606083013582811115612c15575f80fd5b612c218b828601612939565b60608301525060808301356080820152809750506020880135915080821115612c48575f80fd5b50612c5588828901612a3d565b945050612c6587604088016125df565b9250612c748760a088016125df565b9150612c84876101008801612b1a565b90509295509295909350565b5f60408284031215612ca0575f80fd5b612ca861254b565b8235612cb3816123ce565b81526020830135612cc3816123ce565b60208201529392505050565b600181811c90821680612ce357607f821691505b602082108103612d0157634e487b7160e01b5f52602260045260245ffd5b50919050565b5f82612d2157634e487b7160e01b5f52601260045260245ffd5b500490565b634e487b7160e01b5f52603260045260245ffd5b5f6101a08083528a5160a082850152612d57610240850182612372565b91505060208b015161019f1980858403016101c0860152612d788383612372565b925060408d0151915080858403016101e0860152612d968383612372565b925060608d01519150808584030161020086015250612db58282612372565b91505060808b0151610220840152612dd8602084018b6001600160a01b03169052565b6001600160a01b03891660408401528760608401528281036080840152612dff818861270c565b865160a0850152602087015161ffff90811660c086015260408801511660e08501529150612e2a9050565b8351610100830152602084015161ffff90811661012084015260408501511661014083015282516001600160a01b0316610160830152602083015160ff166101808301529998505050505050505050565b8051612e86816123ce565b919050565b5f60208284031215612e9b575f80fd5b81516123c7816123ce565b5f82601f830112612eb5575f80fd5b81516020612ec56129e7836129a5565b8083825260208201915060208460051b870101935086841115612ee6575f80fd5b602086015b84811015612a32578051612efe816125c2565b8352918301918301612eeb565b5f60608284031215612f1b575f80fd5b612f23612522565b90508151612f30816125c2565b815260208281015167ffffffffffffffff80821115612f4d575f80fd5b818501915085601f830112612f60575f80fd5b8151612f6e6129e7826129a5565b81815260059190911b83018401908481019088831115612f8c575f80fd5b938501935b82851015612fb3578451612fa4816123ce565b82529385019390850190612f91565b80868801525050506040850151925080831115612fce575f80fd5b5050612b0e84828501612ea6565b5f60608284031215612fec575f80fd5b612ff4612522565b9050815181526020820151613008816125d0565b6020820152604082015161261e816125d0565b5f6040828403121561302b575f80fd5b61303361254b565b90508151613040816123ce565b81526020820151612b4f816125c2565b5f805f805f805f805f806101e08b8d03121561306a575f80fd5b8a51613075816123ce565b60208c0151909a50613086816123ce565b60408c0151909950613097816123ce565b60608c01519098506130a8816123ce565b60808c01519097506130b9816123ce565b95506130c760a08c01612e7b565b945060c08b015167ffffffffffffffff8111156130e2575f80fd5b6130ee8d828e01612f0b565b9450506130fe8c60e08d01612fdc565b925061310e8c6101408d01612fdc565b915061311e8c6101a08d0161301b565b90509295989b9194979a509295985056fea2646970667358221220794159239f1deb143ed3a080e0bb6e618d2d7f7775a71578db816f68d6c56c5164736f6c63430008160033

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

0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000b51b7d01c94ceff686e6463ce1ea461c2bb8276b0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000003b2e0f44000000000000000000000000000000000000000000000000000000000000000b436865657a627572676572000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000443485a4200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001768747470733a2f2f636865657a6275726765722e6c6f6c000000000000000000000000000000000000000000000000000000000000000000000000000000001768747470733a2f2f636865657a6275726765722e6c6f6c000000000000000000

-----Decoded View---------------
Arg [0] : _customization (tuple): System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput]
Arg [1] : _factory (address): 0xb51B7D01c94CEFF686E6463CE1eA461C2bb8276B
Arg [2] : _router (address): 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D

-----Encoded View---------------
16 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [1] : 000000000000000000000000b51b7d01c94ceff686e6463ce1ea461c2bb8276b
Arg [2] : 0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d
Arg [3] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [4] : 00000000000000000000000000000000000000000000000000000000000000e0
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000120
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000160
Arg [7] : 000000000000000000000000000000000000000000000000000000003b2e0f44
Arg [8] : 000000000000000000000000000000000000000000000000000000000000000b
Arg [9] : 436865657a627572676572000000000000000000000000000000000000000000
Arg [10] : 0000000000000000000000000000000000000000000000000000000000000004
Arg [11] : 43485a4200000000000000000000000000000000000000000000000000000000
Arg [12] : 0000000000000000000000000000000000000000000000000000000000000017
Arg [13] : 68747470733a2f2f636865657a6275726765722e6c6f6c000000000000000000
Arg [14] : 0000000000000000000000000000000000000000000000000000000000000017
Arg [15] : 68747470733a2f2f636865657a6275726765722e6c6f6c000000000000000000


Deployed Bytecode Sourcemap

2366:8525:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5818:28;;-1:-1:-1;;;5818:28:0;;;;;;;;;;;2366:8525;;;;6142:98;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;7435:573:5;;;;;;;;;;-1:-1:-1;7435:573:5;;;;;:::i;:::-;;:::i;:::-;;;1311:14:13;;1304:22;1286:41;;1274:2;1259:18;7435:573:5;1146:187:13;6739:164:0;;;;;;;;;;;;;:::i;:::-;;;1484:25:13;;;1472:2;1457:18;6739:164:0;1338:177:13;10127:109:10;;;;;;:::i;:::-;;:::i;:::-;;9588:123;;;;;;:::i;:::-;;:::i;11178:139::-;;;;;;;;;;-1:-1:-1;11178:139:10;;;;;:::i;:::-;10769:15;10763:4;10756:29;;;11257:4;10798:18;;;;10898:4;10882:21;;;10876:28;11280:21;;:30;;11178:139;4182:36:1;;;;;;;;;;-1:-1:-1;4182:36:1;;;;;;-1:-1:-1;;;;;4182:36:1;;;;;;;;;;;-1:-1:-1;;;;;2118:15:13;;;2100:34;;2170:15;;;;2165:2;2150:18;;2143:43;2012:18;4182:36:1;1837:355:13;9969:2191:5;;;;;;;;;;-1:-1:-1;9969:2191:5;;;;;:::i;:::-;;:::i;9021:617:9:-;;;:::i;10567:353:10:-;;;;;;;;;;-1:-1:-1;10567:353:10;;;;;:::i;:::-;10769:15;10763:4;10756:29;;;10627:13;10798:18;;;;10898:4;10882:21;;10876:28;;10567:353;7935:176:0;;;;;;;;;;;;;:::i;5860:82:5:-;;;;;;;;;;-1:-1:-1;5860:82:5;;5933:2;3052:36:13;;3040:2;3025:18;5860:82:5;2910:184:13;4224:36:1;;;;;;;;;;-1:-1:-1;4224:36:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;7661:197:0:-;;;;;;;;;;-1:-1:-1;7661:197:0;;;;;:::i;:::-;;:::i;16620:693:5:-;;;;;;;;;;;;;:::i;7244:81:0:-;;;;;;;;;;-1:-1:-1;7244:81:0;;;;;:::i;:::-;;:::i;9856:125:10:-;;;;;;:::i;:::-;;:::i;10982:134::-;;;;;;;;;;-1:-1:-1;10982:134:10;;;;;:::i;:::-;10769:15;10763:4;10756:29;;;11060:4;10798:18;;;;10898:4;10882:21;;;10876:28;11083:21;:26;;;10982:134;8454:698:0;;;;;;;;;;-1:-1:-1;8454:698:0;;;;;:::i;:::-;;:::i;9720:456:9:-;;;:::i;4081:37:1:-;;;;;;;;;;;;;;;;6548:286:5;;;;;;;;;;-1:-1:-1;6548:286:5;;;;;:::i;:::-;6716:18;6710:4;6703:32;;;6611:14;6748:19;;;;6812:4;6796:21;;6790:28;;6548:286;8762:100:9;;;:::i;6447:85:0:-;;;;;;;;;;;;;:::i;7421:153::-;;;;;;;;;;-1:-1:-1;7421:153:0;;;;;:::i;:::-;;:::i;12800:340:5:-;;;;;;;;;;-1:-1:-1;12800:340:5;;;;;:::i;:::-;13023:17;13017:4;13010:31;;;12860:14;13054:19;;;;13118:4;13102:21;;13096:28;;12800:340;4266:34:1;;;;;;;;;;-1:-1:-1;4266:34:1;;;;;;;;;;;;;8161:25:13;;;8217:2;8202:18;;8195:34;;;;8134:18;4266:34:1;7987:248:13;11408:182:9;;;;;;;;;;-1:-1:-1;;;11556:18:9;11408:182;;;-1:-1:-1;;;;;8404:55:13;;;8386:74;;8374:2;8359:18;11408:182:9;8240:226:13;6246:102:0;;;;;;;;;;;;;:::i;8195:1406:5:-;;;;;;;;;;-1:-1:-1;8195:1406:5;;;;;:::i;:::-;;:::i;6354:87:0:-;;;;;;;;;;;;;:::i;4307:45:1:-;;;;;;;;;;-1:-1:-1;4307:45:1;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;;;;;;:::i;9276:613:0:-;;;;;;;;;;-1:-1:-1;9276:613:0;;;;;:::i;:::-;;:::i;13324:3215:5:-;;;;;;;;;;-1:-1:-1;13324:3215:5;;;;;:::i;:::-;;:::i;4622:2198:1:-;;;;;;:::i;:::-;;:::i;6929:375:5:-;;;;;;;;;;-1:-1:-1;6929:375:5;;;;;:::i;:::-;7144:4;7137:21;7184:20;7178:4;7171:34;;;7041:14;7218:19;;;;7282:4;7266:21;;7260:28;;6929:375;4358:44:1;;;;;;;;;;-1:-1:-1;4358:44:1;;;;;:::i;:::-;;;;;;;;;;;;;;6902:953;;;;;;:::i;:::-;;:::i;8180:187:0:-;;;;;;;;;;-1:-1:-1;8180:187:0;;;;;:::i;:::-;;:::i;10363:708:9:-;;;;;;:::i;:::-;;:::i;8348:349::-;;;;;;:::i;:::-;;:::i;11693:435::-;;;;;;;;;;-1:-1:-1;11693:435:9;;;;;:::i;:::-;11963:19;11957:4;11950:33;;;11812:14;11996:26;;;;12106:4;12090:21;;12084:28;;11693:435;6142:98:0;6196:13;6228:5;6221:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6142:98;:::o;7435:573:5:-;7509:4;7668:7;7662:4;7655:21;7702:20;7696:4;7689:34;7749:8;7743:4;7736:22;7801:6;7794:4;7788;7778:21;7771:37;7876:6;7870:4;7863:20;7964:4;7958:11;7954:2;7950:20;7940:8;7913:25;7907:4;7901;7896:75;-1:-1:-1;7997:4:5;7435:573;;;;:::o;6739:164:0:-;6792:7;6864:22;;6842:19;6447:18:5;6441:25;;6287:195;6842:19:0;:44;6835:51;;6739:164;:::o;10127:109:10:-;10198:31;10211:10;10223:5;10198:12;:31::i;:::-;10127:109;:::o;9588:123::-;12517:13:9;:11;:13::i;:::-;9680:24:10::1;9692:4;9698:5;9680:11;:24::i;:::-;9588:123:::0;;:::o;9969:2191:5:-;10057:4;10073:38;10094:4;10100:2;10104:6;10073:20;:38::i;:::-;10208:4;10204:2;10200:13;10301:8;10295:4;10288:22;10346:20;10339:5;10336:31;10330:4;10323:45;10418:4;10412;10402:21;10460:13;10454:20;10572:1;10560:10;10556:18;10553:418;;;10688:10;10680:6;10677:22;10674:159;;;10735:10;10729:4;10722:24;10810:4;10804;10797:18;10674:159;10949:6;10937:10;10933:23;10918:13;10911:46;10553:418;;;11067:18;11060:5;11057:29;11051:4;11044:43;11139:4;11133;11123:21;11182:15;11176:22;11272:11;11264:6;11261:23;11258:146;;;11316:10;11310:4;11303:24;11385:4;11379;11372:18;11258:146;11513:6;11500:11;11496:24;11479:15;11472:49;;;11596:2;11590:4;11583:16;11649:4;11643;11633:21;11899:6;11883:13;11877:20;11873:33;11858:13;11851:56;;11975:6;11969:4;11962:20;12069:4;12063:11;12059:2;12055:20;12047:5;12043:2;12039:14;12012:25;12006:4;12000;11995:81;;12095:37;12115:4;12121:2;12125:6;12095:19;:37::i;:::-;-1:-1:-1;12149:4:5;9969:2191;;;;;:::o;9021:617:9:-;9114:15;7972:9;9132:46;;:15;:46;9114:64;;9346:19;9340:4;9333:33;9396:8;9390:4;9383:22;9452:7;9445:4;9439;9429:21;9422:38;9599:8;9552:45;9549:1;9546;9541:67;9248:374;9021:617::o;7935:176:0:-;12731:6:10;11733:18;11745:5;11733:11;:18::i;:::-;8053:51:0::1;8093:10;8053:39;:51::i;7661:197::-:0;7796:7;12683:6:10;11733:18;11745:5;11733:11;:18::i;:::-;7822:29:0::1;7838:7;7847:3;7822:15;:29::i;:::-;7815:36:::0;7661:197;-1:-1:-1;;;;7661:197:0:o;16620:693:5:-;16677:14;;16900:6;:4;:6::i;:::-;16884:24;;;;;;16873:35;;16999:4;16993:11;17060:16;17057:1;17050:27;17111:8;17104:4;17101:1;17097:12;17090:30;17154:13;17147:4;17144:1;17140:12;17133:35;17202:9;17195:4;17192:1;17188:12;17181:31;17246:9;17239:4;17236:1;17232:12;17225:31;17292:4;17289:1;17279:18;17269:28;;;16970:337;16620:693;:::o;7244:81:0:-;7293:25;7299:10;7311:6;7293:5;:25::i;9856:125:10:-;12517:13:9;:11;:13::i;:::-;9949:25:10::1;9962:4;9968:5;9949:12;:25::i;8454:698:0:-:0;12827:6:10;11991:25;12010:5;11991:18;:25::i;:::-;8714:30:0::1;::::0;;::::1;::::0;8682:29;:62;8782:26:::1;::::0;;::::1;::::0;8754:25;:54;8860:53:::1;::::0;::::1;::::0;8818:39;:95;;-1:-1:-1;;8818:95:0::1;;::::0;;::::1;::::0;;;::::1;::::0;;8955:30:::1;::::0;::::1;::::0;8923:62;;:29;:62;;;::::1;::::0;;;;;;::::1;::::0;::::1;::::0;;::::1;-1:-1:-1::0;;8923:62:0;;;;;;;::::1;::::0;::::1;;::::0;;;9024:27:::1;::::0;::::1;::::0;8995:56;;:26;:56;;;::::1;::::0;;;;;;::::1;::::0;;;::::1;::::0;;;;;;;;;::::1;;;::::0;;9088:25;;::::1;::::0;9061:24;:52;9128:17;::::1;::::0;-1:-1:-1;;9128:17:0::1;8454:698:::0;;;:::o;9720:456:9:-;9922:19;9916:4;9909:33;9968:8;9962:4;9955:22;10020:1;10013:4;10007;9997:21;9990:32;10151:8;10105:44;10102:1;10099;10094:66;9720:456::o;8762:100::-;12517:13;:11;:13::i;:::-;8834:21:::1;8852:1;8834:9;:21::i;:::-;8762:100::o:0;6447:85:0:-;6486:13;6518:7;6511:14;;;;;:::i;7421:153::-;7491:44;7507:7;7516:10;7528:6;7491:15;:44::i;:::-;7545:22;7551:7;7560:6;7545:5;:22::i;6246:102::-;6302:13;6334:7;6327:14;;;;;:::i;8195:1406:5:-;8265:4;8281:44;8302:10;8314:2;8318:6;8281:20;:44::i;:::-;8474:18;8468:4;8461:32;8519:8;8513:4;8506:22;8580:4;8574;8564:21;8623:15;8617:22;8713:11;8705:6;8702:23;8699:146;;;8757:10;8751:4;8744:24;8826:4;8820;8813:18;8699:146;8954:6;8941:11;8937:24;8920:15;8913:49;;;9037:2;9031:4;9024:16;9090:4;9084;9074:21;9340:6;9324:13;9318:20;9314:33;9299:13;9292:56;;9416:6;9410:4;9403:20;9504:4;9498:11;9494:2;9490:20;9480:8;9453:25;9447:4;9441;9436:75;9530:43;9550:10;9562:2;9566:6;9530:19;:43::i;:::-;-1:-1:-1;9590:4:5;8195:1406;;;;:::o;6354:87:0:-;6394:13;6426:8;6419:15;;;;;:::i;4307:45:1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;4307:45:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;4307:45:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;4307:45:1;;;;-1:-1:-1;;4307:45:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;4307:45:1;;;;-1:-1:-1;;;4307:45:1;;;;;;;;;;;;;;-1:-1:-1;4307:45:1;:::o;9276:613:0:-;12779:6:10;11991:25;12010:5;11991:18;:25::i;:::-;9449:28:0::1;9496:2;9480:13;:11;:13::i;:::-;:18;;;;:::i;:::-;9449:49;;9578:20;9555;:43;:101;;;;9636:20;9614:19;:42;9555:101;9538:187;;;9688:26;;-1:-1:-1::0;;;9688:26:0::1;;;;;;;;;;;9538:187;9734:14;:51:::0;;;9795:13:::1;:49:::0;;;9859:23:::1;::::0;::::1;::::0;9734:28:::1;::::0;9859:23:::1;9439:450;9276:613:::0;;;:::o;13324:3215:5:-;13523:16;13720:6;:4;:6::i;:::-;13704:24;;;;;;13693:35;;13896:8;13883:11;13880:25;13877:142;;;13937:10;13931:4;13924:24;14000:4;13994;13987:18;13877:142;14047:4;14041:11;14163:5;14159:2;14155:14;14151:2;14147:23;14138:32;;14210:7;14206:2;14202:16;14198:2;14194:25;14183:36;;14303:39;14297:4;14290:53;14369:5;14363:4;14356:19;14421:4;14415;14405:21;14463:9;14457:16;14541;14538:1;14531:27;14592:8;14585:4;14582:1;14578:12;14571:30;14635:13;14628:4;14625:1;14621:12;14614:35;14683:9;14676:4;14673:1;14669:12;14662:31;14727:9;14720:4;14717:1;14713:12;14706:31;14776:4;14773:1;14763:18;14757:4;14750:32;14845:16;14842:1;14835:27;14896:5;14889:4;14886:1;14882:12;14875:27;14936:7;14929:4;14926:1;14922:12;14915:29;14978:5;14971:4;14968:1;14964:12;14957:27;15018:10;15011:4;15008:1;15004:12;14997:32;15063:8;15056:4;15053:1;15049:12;15042:30;15111:4;15108:1;15098:18;15092:4;15085:32;15206:4;15200;15190:21;15184:4;15177:35;15248:1;15242:4;15238:12;15232:4;15225:26;15277:1;15271:4;15264:15;15305:1;15299:4;15292:15;15365:4;15359;15353;15350:1;15347;15340:5;15329:41;15786:5;15767:16;15761:23;15758:34;15748:159;;15825:10;15819:4;15812:24;15888:4;15882;15875:18;15748:159;15992:18;15974:37;;16190:30;16187:43;;16181:4;16174:57;16267:4;16261;16251:21;16244:36;;;16222:7;16387:5;16360:25;-1:-1:-1;16347:4:5;16340:12;;16335:67;16422:4;16415:15;-1:-1:-1;;16492:1:5;16486:4;16479:15;-1:-1:-1;;;;;;13324:3215:5:o;4622:2198:1:-;4726:7;1182:6:11;;;;1192:1;1182:11;1178:69;;1216:20;;-1:-1:-1;;;1216:20:11;;;;;;;;;;;1178:69;1256:6;:10;;-1:-1:-1;;1256:10:11;1265:1;1256:10;;;4783:11:1;;;4779:69:::1;;4817:20;;-1:-1:-1::0;;;4817:20:1::1;;;;;;;;;;;4779:69;4950:1;4909:20:::0;;;:12:::1;:20;::::0;;;;:29:::1;;::::0;-1:-1:-1;;;;;4909:29:1::1;:43:::0;4905:107:::1;;4975:26;::::0;-1:-1:-1;;;4975:26:1;;::::1;::::0;::::1;1484:25:13::0;;;1457:18;;4975:26:1::1;;;;;;;;4905:107;5145:16;::::0;;5159:1:::1;5145:16:::0;;;;;::::1;::::0;;5113:29:::1;::::0;5145:16:::1;::::0;::::1;::::0;;::::1;::::0;::::1;;::::0;-1:-1:-1;5145:16:1::1;5113:48;;5197:1;5171:12;5184:1;5171:15;;;;;;;;:::i;:::-;;;;;;:28;-1:-1:-1::0;;;;;5171:28:1::1;;;-1:-1:-1::0;;;;;5171:28:1::1;;;::::0;::::1;5235:4;5209:12;5222:1;5209:15;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;5209:31:1;;;::::1;:15;::::0;;::::1;::::0;;;;;;;:31;5311:14:::1;::::0;;5323:1:::1;5311:14:::0;;;;;::::1;::::0;;;5279:29:::1;::::0;5311:14:::1;;;;;;;;;;;::::0;-1:-1:-1;5311:14:1::1;5279:46;;5355:2;5335:14;5350:1;5335:17;;;;;;;;:::i;:::-;;;;;;:22;;;;;;;;;::::0;::::1;5431:26;5460:17;:6;:15;:17::i;:::-;5431:46;;5488:18;5509:986;5538:291;;;;;;;;5581:43;5598:12;5581:43;;;;;;;;;;;;;;;;::::0;:16:::1;:43::i;:::-;5538:291;;;;5650:41;;;;;;;;;;;;;;;;;::::0;5678:12:::1;5650:16;:41::i;:::-;5538:291;;;;5718:8;5538:291;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5752:7;5538:291;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;;;5538:291:1;;;-1:-1:-1;;5785:29:1;;5538:291:::1;::::0;;::::1;::::0;5843:165:::1;::::0;;::::1;::::0;;::::1;::::0;;5900:1:::1;5843:165:::0;;;;::::1;::::0;;;;;;;;;5509:986;;;;::::1;::::0;;6022:26;5509:986;;;;;::::1;::::0;;::::1;::::0;;::::1;::::0;;;;;::::1;::::0;::::1;::::0;;;;;;;;::::1;::::0;;6062:29;5509:986;;;;;;;::::1;::::0;;::::1;::::0;;;;;::::1;::::0;;::::1;::::0;;;;;;;6105:39;;5843:165;;5509:986;;5843:165:::1;6105:39;:299;;6343:61;::::0;;;;::::1;::::0;;;-1:-1:-1;6343:61:1;;;::::1;::::0;::::1;::::0;6105:299:::1;;;6167:157;::::0;;;;::::1;::::0;;;6219:10:::1;6167:157:::0;;6266:39;;::::1;;6167:157;::::0;::::1;::::0;6105:299:::1;6418:14;:28:::0;6460:25;;5509:15:::1;:986::i;:::-;6529:20;::::0;;;:12:::1;:20;::::0;;;;;;;;:28;;;;-1:-1:-1;;6529:28:1;;::::1;-1:-1:-1::0;;;;;6529:28:1;;::::1;;::::0;;;;::::1;::::0;-1:-1:-1;6529:28:1;::::1;::::0;;;::::1;::::0;;::::1;::::0;;;::::1;::::0;;;;::::1;::::0;::::1;::::0;::::1;::::0;;;::::1;::::0;;::::1;::::0;;;::::1;::::0;;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;;::::1;::::0;;::::1;::::0;;;::::1;::::0;;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;;::::1;::::0;;::::1;::::0;;;::::1;::::0;;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;;;::::1;::::0;::::1;;::::0;;;::::1;::::0;::::1;::::0;;;::::1;::::0;::::1;::::0;;-1:-1:-1;;6529:28:1::1;;::::0;;::::1;::::0;;;::::1;::::0;;;;::::1;::::0;;;;;-1:-1:-1;6529:28:1;;;;;;::::1;::::0;;;;;::::1;::::0;::::1;:::i;:::-;-1:-1:-1::0;6529:28:1::1;::::0;::::1;::::0;;;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;:::i;:::-;-1:-1:-1::0;;;6529:28:1::1;::::0;::::1;::::0;;;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;;;;;;::::1;::::0;;::::1;::::0;::::1;::::0;;::::1;::::0;;;::::1;-1:-1:-1::0;;6529:28:1;;;;;::::1;::::0;;;;;;;::::1;::::0;;;::::1;::::0;::::1;::::0;;;::::1;::::0;::::1;::::0;;;::::1;::::0;;;;;;;;::::1;::::0;;::::1;::::0;;::::1;::::0;;;;;;;::::1;::::0;::::1;::::0;;::::1;::::0;;::::1;::::0;;;::::1;::::0;;::::1;::::0;;;;::::1;::::0;::::1;;-1:-1:-1::0;;;6529:28:1::1;::::0;;;;-1:-1:-1;;;;;6529:28:1;;::::1;::::0;;;;::::1;::::0;;6577:14:::1;::::0;::::1;::::0;;6567:25;::::1;6529:28;6567:25:::0;;;:9:::1;:25:::0;;;;;;;:34;;;6698:14:::1;:28:::0;6670:14;;6740:22:::1;::::0;6617:155;;;::::1;::::0;6595:6;;6617:155:::1;::::0;::::1;::::0;1484:25:13;;1472:2;1457:18;;1338:177;6617:155:1::1;;;;;;;;6798:14;;::::0;;-1:-1:-1;;;;1287:6:11;:10;;-1:-1:-1;;1287:10:11;1296:1;1287:10;;;4622:2198:1;;-1:-1:-1;4622:2198:1:o;6902:953::-;7191:7;1182:6:11;;;;1192:1;1182:11;1178:69;;1216:20;;-1:-1:-1;;;1216:20:11;;;;;;;;;;;1178:69;1256:6;:10;;-1:-1:-1;;1256:10:11;1265:1;1256:10;;;7248:21:1::1;::::0;;::::1;::::0;7227:52:::1;::::0;;;;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;::::1;::::0;;;;27298:18:8;;;27288:43;;;27230:14;;-1:-1:-1;;;27206:40:8;27353:42;27264:149;;;27185:242;7227:107:1::1;;;;-1:-1:-1::0;10769:15:10;10763:4;10756:29;;;7307:10:1::1;11060:4:10::0;10798:18;12875:6:::1;10882:21:::0;;;;10876:28;11083:21;:26;7227:107:1::1;7210:191;;;7366:24;;-1:-1:-1::0;;;7366:24:1::1;;;;;;;;;;;7210:191;7411:18;7432:218;7461:14;7489:10;7513:4;7531:7;7552:9;7575:13;:27;;;7616:13;:24;;;7432:15;:218::i;:::-;7411:239;;7734:13;:27;;;7706:5;:14;;;-1:-1:-1::0;;;;;7666:141:1::1;;7775:22;;7666:141;;;;1484:25:13::0;;1472:2;1457:18;;1338:177;7666:141:1::1;;;;;;;;7833:14;;::::0;;-1:-1:-1;1287:6:11;:10;;-1:-1:-1;;1287:10:11;1296:1;1287:10;;;6902:953:1;;-1:-1:-1;;;;;6902:953:1:o;8180:187:0:-;12517:13:9;:11;:13::i;:::-;8290:32:0;;:14:::1;:32:::0;;-1:-1:-1;;;;;8290:32:0;;::::1;-1:-1:-1::0;;8290:32:0;;::::1;;::::0;;;::::1;::::0;::::1;::::0;;;;;;;::::1;::::0;::::1;;::::0;;8337:23:::1;::::0;::::1;::::0;8290:32:::1;::::0;8337:23:::1;8180:187:::0;:::o;10363:708:9:-;12517:13;:11;:13::i;:::-;10597:19:::1;10591:4;10584:33;10643:12;10637:4;10630:26;10705:4;10699;10689:21;10811:12;10805:19;10792:11;10789:36;10786:157;;;10857:10;10851:4;10844:24;10924:4;10918;10911:18;10786:157;11020:1;10999:23:::0;;11041::::1;11051:12:::0;11041:9:::1;:23::i;8348:349::-:0;12517:13;:11;:13::i;:::-;8520:8:::1;8516:2;8512:17;8502:150;;8562:10;8556:4;8549:24;8633:4;8627;8620:18;8502:150;8671:19;8681:8;8671:9;:19::i;4304:117:10:-:0;4382:32;4395:4;4401:5;4408;4382:12;:32::i;7292:355:9:-;-1:-1:-1;;7498:18:9;7488:8;7485:32;7475:156;;7550:10;7544:4;7537:24;7612:4;7606;7599:18;4053:115:10;4130:31;4143:4;4149:5;4156:4;4130:12;:31::i;10178:352:0:-;-1:-1:-1;;;;;10430:18:0;;;;;;:41;;-1:-1:-1;;;;;;10452:19:0;;10466:4;10452:19;10430:41;10426:98;;;10494:19;;-1:-1:-1;;;10494:19:0;;-1:-1:-1;;;;;8404:55:13;;10494:19:0;;;8386:74:13;8359:18;;10494:19:0;8240:226:13;10426:98:0;10178:352;;;:::o;10536:353::-;-1:-1:-1;;;;;10773:16:0;;;:45;;;;-1:-1:-1;6716:18:5;6710:4;6703:32;;;10817:1:0;6748:19:5;;6812:4;6796:21;;6790:28;10793:25:0;;10773:45;10769:114;;;10841:31;;-1:-1:-1;;;10841:31:0;;-1:-1:-1;;;;;2118:15:13;;;10841:31:0;;;2100:34:13;2170:15;;2150:18;;;2143:43;2012:18;;10841:31:0;1837:355:13;4495:554:10;4680:15;4674:4;4667:29;4722:8;4716:4;4709:22;4913:5;4905:4;4899;4889:21;4883:28;4879:40;4869:164;;4952:10;4946:4;4939:24;5014:4;5008;5001:18;6322:606:12;6581:4;6569:10;6563:4;6551:10;6536:13;6532:2;6510:20;6505:81;6495:417;;6619:2;6613:4;6606:16;6692:4;6686;6678:19;6748:4;6742;6734:19;6834:4;6828;6813:13;6806:33;6796:79;;6862:10;6850;6843:30;9963:402:1;10058:7;10100:21;;;:12;:21;;;;;:26;;;-1:-1:-1;;;;;10100:26:1;;10137:72;;10182:16;;-1:-1:-1;;;10182:16:1;;;;;;;;;;;10137:72;10218:14;10235:42;10267:4;10273:3;10235:31;:42::i;:::-;10218:59;;10328:6;10323:3;-1:-1:-1;;;;;10292:43:1;10317:4;-1:-1:-1;;;;;10292:43:1;;;;;;;;;;;10352:6;9963:402;-1:-1:-1;;;;9963:402:1:o;19295:1119:5:-;19367:46;19388:4;19402:1;19406:6;19367:20;:46::i;:::-;19562:18;19556:4;19549:32;19607:4;19601;19594:18;19664:4;19658;19648:21;19707:15;19701:22;19797:11;19789:6;19786:23;19783:146;;;19841:10;19835:4;19828:24;19910:4;19904;19897:18;19783:146;20021:24;;;19997:49;;20156:18;20150:25;;20146:38;;;20119:66;;-1:-1:-1;20240:20:5;;;-1:-1:-1;;;;;20317:22:5;;20290:25;20284:4;-1:-1:-1;20273:70:5;20362:45;20382:4;20396:1;20400:6;20362:19;:45::i;5219:802:10:-;-1:-1:-1;;5507:27:10;5497:8;5494:41;5484:521;;5610:15;5604:4;5597:29;5656:8;5650:4;5643:22;5859:5;5851:4;5845;5835:21;5829:28;5825:40;5815:176;;5902:10;5896:4;5889:24;5968:4;5962;5955:18;6145:1089:9;-1:-1:-1;;7093:16:9;;-1:-1:-1;;;;;6941:26:9;;;;;;7053:38;7050:1;;7042:78;7177:27;6145:1089::o;22532:947:5:-;22773:7;22767:4;22760:21;22807:20;22801:4;22794:34;22854:5;22848:4;22841:19;22910:4;22904;22894:21;22952:13;22946:20;23064:1;23052:10;23048:18;23045:418;;;23180:10;23172:6;23169:22;23166:159;;;23227:10;23221:4;23214:24;23302:4;23296;23289:18;23166:159;23441:6;23429:10;23425:23;23410:13;23403:46;23045:418;;;22532:947;;;:::o;1551:1641:8:-;1607:17;2052:4;2045;2039:11;2035:22;2028:29;;2151:4;2146:3;2142:14;2136:4;2129:28;2232:1;2227:3;2220:14;2333:3;2363:1;2359:6;2572:5;2554:402;2610:11;;;;2791:2;2805;2795:13;;2787:22;2610:11;2774:36;2897:2;2887:13;;2917:25;2554:402;2917:25;-1:-1:-1;;2984:13:8;;;-1:-1:-1;;3097:14:8;;;3157:19;;;3097:14;1551:1641;-1:-1:-1;1551:1641:8:o;36617:1365::-;36863:4;36857:11;36896:8;;-1:-1:-1;;36825:9:8;37004:4;36991:18;;36987:26;;36972:210;37068:9;;;37062:16;37046:14;;;37039:40;37101:9;;37146:22;36972:210;37146:22;36976:39;37216:1;37210:8;37257:7;37249:6;37245:20;37372:1;37365:4;37356:7;37352:18;37348:26;37333:210;37429:9;;;37423:16;37407:14;;;37400:40;37462:9;;37507:22;37333:210;37507:22;-1:-1:-1;;37732:1:8;37575:21;;37621:35;;;37637:4;37621:35;;37719:15;;;;37781:27;;37946:15;;37942:23;37936:4;37929:37;37629:6;36617:1365;-1:-1:-1;;36617:1365:8:o;8144:1732:1:-;8468:12;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8468:12:1;8539:11;8526:9;:24;8522:109;;8573:47;;-1:-1:-1;;;8573:47:1;;8597:9;8573:47;;;8161:25:13;8202:18;;;8195:34;;;8134:18;;8573:47:1;7987:248:13;8522:109:1;8809:36;8823:4;8830:14;8809:5;:36::i;:::-;8987:14;:22;8911:137;;8960:4;;-1:-1:-1;;;;;8987:22:1;9024:14;8911:27;:137::i;:::-;9087:20;9110:14;:22;;;;;;;;;;-1:-1:-1;;;;;9110:22:1;-1:-1:-1;;;;;9110:38:1;;9162:14;9190;:21;;;;;;;;;;-1:-1:-1;;;;;9190:21:1;9233:4;9252:14;9280:10;9304:4;9322:7;9343:9;9110:252;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;9429:14;:22;9087:275;;-1:-1:-1;9399:18:1;;9420:46;;-1:-1:-1;;;;;9429:22:1;9087:275;9420:8;:46::i;:::-;9399:67;;9503:64;9543:5;:10;;;9564:1;9503:31;:64::i;:::-;;9687:14;9671:13;:11;:13::i;:::-;:30;9655:13;:11;:13::i;:::-;:46;9651:108;;;9728:16;;-1:-1:-1;;;9728:16:1;;;;;;;;;;;9651:108;9797:22;;;:39;;9772:64;;9864:5;-1:-1:-1;;8144:1732:1;;;;;;;;;;:::o;2952:967:10:-;3118:15;3112:4;3105:29;3160:4;3154;3147:18;3210:4;3204;3194:21;3288:8;3282:15;3395:5;3386:7;3383:18;3639:2;3629:62;;-1:-1:-1;3669:19:10;;;3656:33;;3629:62;3763:7;3753:8;3746:25;3895:7;3887:4;3881:11;3877:2;3873:20;3841:30;3838:1;3835;3830:73;;;;2952:967;;;:::o;12425:1612:12:-;12495:14;12600:10;12594:4;12587:24;12693:9;12687:4;12680:23;13053:4;13047;13041;13035;13028:5;13021;13010:48;12952:4;12934:16;12931:26;12846:230;12819:386;;13122:10;13116:4;13109:24;13186:4;13180;13173:18;12819:386;13231:2;13225:4;13218:16;13291:4;13285:11;13275:21;;13383:34;13377:4;13370:48;13772:4;13766;13760;13754;13751:1;13744:5;13737;13732:45;13666:16;13659:24;13655:1;13648:4;13642:11;13639:18;13636:48;13551:244;13524:400;;13841:10;13835:4;13828:24;13905:4;13899;13892:18;13524:400;13950:1;13944:4;13937:15;12425:1612;;;;:::o;17717:1172:5:-;17787:44;17816:1;17820:2;17824:6;17787:20;:44::i;:::-;17938:18;17932:25;18017:6;17998:17;17994:30;18114:17;18096:16;18093:39;18090:162;;;18164:10;18158:4;18151:24;18233:4;18227;18220:18;18090:162;18339:16;18319:18;18312:44;;;18442:18;18436:4;18429:32;18487:2;18481:4;18474:16;18540:4;18534;18524:21;18656:6;18640:13;18634:20;18630:33;18615:13;18608:56;;18732:6;18726:4;18719:20;18813:4;18807:11;18803:2;18799:20;18796:1;18769:25;18763:4;18757;18752:68;18839:43;18867:1;18871:2;18875:6;18839:19;:43::i;14171:936:12:-;14333:2;14327:4;14320:16;14390:6;14384:4;14377:20;14455:34;14449:4;14442:48;14843:4;14837;14831;14825;14822:1;14815:5;14808;14803:45;14737:16;14730:24;14726:1;14719:4;14713:11;14710:18;14707:48;14622:244;14595:399;;14912:10;14906:4;14899:24;14975:4;14969;14962:18;14595:399;15020:1;15014:4;15007:15;14171:936;;;:::o;1391:993:2:-;1506:12;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1506:12:2;1544:23;1581:22;1617:20;1651:16;1681:17;1712:18;1744:35;1793:27;1834:30;1878:33;1924:8;-1:-1:-1;;;;;1924:23:2;;1948:12;1924:37;;;;;;;;;;;;;;-1:-1:-1;;;;;8404:55:13;;;;8386:74;;8374:2;8359:18;;8240:226;1924:37:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;1924:37:2;;;;;;;;;;;;:::i;:::-;1991:386;;;;;;;;-1:-1:-1;;;;;1991:386:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1391:993;-1:-1:-1;;;;;;;;;;;;;1391:993:2:o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14:423:13;56:3;94:5;88:12;121:6;116:3;109:19;146:1;156:162;170:6;167:1;164:13;156:162;;;232:4;288:13;;;284:22;;278:29;260:11;;;256:20;;249:59;185:12;156:162;;;160:3;363:1;356:4;347:6;342:3;338:16;334:27;327:38;426:4;419:2;415:7;410:2;402:6;398:15;394:29;389:3;385:39;381:50;374:57;;;14:423;;;;:::o;442:220::-;591:2;580:9;573:21;554:4;611:45;652:2;641:9;637:18;629:6;611:45;:::i;:::-;603:53;442:220;-1:-1:-1;;;442:220:13:o;667:154::-;-1:-1:-1;;;;;746:5:13;742:54;735:5;732:65;722:93;;811:1;808;801:12;826:315;894:6;902;955:2;943:9;934:7;930:23;926:32;923:52;;;971:1;968;961:12;923:52;1010:9;997:23;1029:31;1054:5;1029:31;:::i;:::-;1079:5;1131:2;1116:18;;;;1103:32;;-1:-1:-1;;;826:315:13:o;1520:180::-;1579:6;1632:2;1620:9;1611:7;1607:23;1603:32;1600:52;;;1648:1;1645;1638:12;1600:52;-1:-1:-1;1671:23:13;;1520:180;-1:-1:-1;1520:180:13:o;2197:456::-;2274:6;2282;2290;2343:2;2331:9;2322:7;2318:23;2314:32;2311:52;;;2359:1;2356;2349:12;2311:52;2398:9;2385:23;2417:31;2442:5;2417:31;:::i;:::-;2467:5;-1:-1:-1;2524:2:13;2509:18;;2496:32;2537:33;2496:32;2537:33;:::i;:::-;2197:456;;2589:7;;-1:-1:-1;;;2643:2:13;2628:18;;;;2615:32;;2197:456::o;2658:247::-;2717:6;2770:2;2758:9;2749:7;2745:23;2741:32;2738:52;;;2786:1;2783;2776:12;2738:52;2825:9;2812:23;2844:31;2869:5;2844:31;:::i;3400:728::-;3815:25;;;3871:2;3856:18;;;3849:34;;;3914:2;3899:18;;;3892:34;;;3974:4;3962:17;;3957:2;3942:18;;3935:45;3180:12;;4046:3;4031:19;;3168:25;3228:16;;;3222:23;3264:6;3302:21;;;3286:14;;;3279:45;3366:16;;;3360:23;3356:32;;3340:14;;;3333:56;3180:12;;4117:3;4102:19;;3168:25;3228:16;;;3222:23;3302:21;;3286:14;;;3279:45;3366:16;;3360:23;3356:32;3340:14;;;3333:56;3802:3;3787:19;;4060:62;3099:296;4133:315;4201:6;4209;4262:2;4250:9;4241:7;4237:23;4233:32;4230:52;;;4278:1;4275;4268:12;4230:52;4314:9;4301:23;4291:33;;4374:2;4363:9;4359:18;4346:32;4387:31;4412:5;4387:31;:::i;:::-;4437:5;4427:15;;;4133:315;;;;;:::o;4635:127::-;4696:10;4691:3;4687:20;4684:1;4677:31;4727:4;4724:1;4717:15;4751:4;4748:1;4741:15;4767:253;4839:2;4833:9;4881:4;4869:17;;4916:18;4901:34;;4937:22;;;4898:62;4895:88;;;4963:18;;:::i;:::-;4999:2;4992:22;4767:253;:::o;5025:257::-;5097:4;5091:11;;;5129:17;;5176:18;5161:34;;5197:22;;;5158:62;5155:88;;;5223:18;;:::i;5287:253::-;5359:2;5353:9;5401:4;5389:17;;5436:18;5421:34;;5457:22;;;5418:62;5415:88;;;5483:18;;:::i;5545:275::-;5616:2;5610:9;5681:2;5662:13;;-1:-1:-1;;5658:27:13;5646:40;;5716:18;5701:34;;5737:22;;;5698:62;5695:88;;;5763:18;;:::i;:::-;5799:2;5792:22;5545:275;;-1:-1:-1;5545:275:13:o;5825:114::-;5909:4;5902:5;5898:16;5891:5;5888:27;5878:55;;5929:1;5926;5919:12;5944:117;6029:6;6022:5;6018:18;6011:5;6008:29;5998:57;;6051:1;6048;6041:12;6066:499;6128:5;6176:4;6164:9;6159:3;6155:19;6151:30;6148:50;;;6194:1;6191;6184:12;6148:50;6216:22;;:::i;:::-;6207:31;;6274:9;6261:23;6254:5;6247:38;6337:2;6326:9;6322:18;6309:32;6350;6374:7;6350:32;:::i;:::-;6409:2;6398:14;;6391:31;6474:2;6459:18;;6446:32;6487;6446;6487;:::i;:::-;6546:2;6535:14;;6528:31;6539:5;6066:499;-1:-1:-1;;6066:499:13:o;6570:288::-;6630:5;6678:4;6666:9;6661:3;6657:19;6653:30;6650:50;;;6696:1;6693;6686:12;6650:50;6718:22;;:::i;:::-;6709:31;;6776:9;6763:23;6756:5;6749:38;6847:2;6836:9;6832:18;6819:32;6814:2;6807:5;6803:14;6796:56;6570:288;;;;:::o;6863:1119::-;6992:6;7000;7044:9;7035:7;7031:23;7074:3;7070:2;7066:12;7063:32;;;7091:1;7088;7081:12;7063:32;7114:6;7140:2;7136;7132:11;7129:31;;;7156:1;7153;7146:12;7129:31;7189:2;7183:9;7169:23;;7231:4;7223:6;7219:17;7302:6;7290:10;7287:22;7266:18;7254:10;7251:34;7248:62;7245:88;;;7313:18;;:::i;:::-;7353:10;7349:2;7342:22;;7401:9;7388:23;7380:6;7373:39;7473:2;7462:9;7458:18;7445:32;7440:2;7432:6;7428:15;7421:57;7539:2;7528:9;7524:18;7511:32;7506:2;7498:6;7494:15;7487:57;7594:2;7583:9;7579:18;7566:32;7607:29;7630:5;7607:29;:::i;:::-;7664:2;7652:15;;7645:30;7709:63;7764:7;7758:3;7743:19;;7709:63;:::i;:::-;7703:3;7695:6;7691:16;7684:89;7808:63;7863:7;7857:3;7846:9;7842:19;7808:63;:::i;:::-;7801:4;7793:6;7789:17;7782:90;7891:6;7881:16;;7916:60;7968:7;7963:2;7952:9;7948:18;7916:60;:::i;:::-;7906:70;;;;6863:1119;;;;;:::o;8471:1246::-;8531:3;8570:4;8565:3;8561:14;8594:4;8637;8629:5;8623:12;8619:23;8614:3;8607:36;8662:4;8712:2;8705:5;8701:14;8695:21;8746:4;8741:2;8736:3;8732:12;8725:26;8773:4;8806:12;8800:19;8841:6;8835:4;8828:20;8875:3;8870;8866:13;8857:22;;8920:2;8906:12;8902:21;8888:35;;8941:1;8932:10;;8951:224;8965:6;8962:1;8959:13;8951:224;;;9032:13;;-1:-1:-1;;;;;9028:62:13;9014:77;;9150:15;;;;8987:1;8980:9;;;;;9113:14;;;;8951:224;;;-1:-1:-1;9223:4:13;9212:16;;;9206:23;9261:15;;;9245:14;;;9238:39;;;;9329:21;;9359:23;;;9439;;;;-1:-1:-1;9400:14:13;;;;-1:-1:-1;;;9492:198:13;9508:8;9503:3;9500:17;9492:198;;;9581:15;;9577:24;;9563:39;;9663:17;;;;9624:14;;;;9536:1;9527:11;;;;;9492:198;;;-1:-1:-1;9706:5:13;;8471:1246;-1:-1:-1;;;;;;;8471:1246:13:o;9944:1352::-;10558:4;10587:3;-1:-1:-1;;;;;10690:2:13;10682:6;10678:15;10667:9;10660:34;10742:2;10734:6;10730:15;10725:2;10714:9;10710:18;10703:43;10794:2;10786:6;10782:15;10777:2;10766:9;10762:18;10755:43;10846:2;10838:6;10834:15;10829:2;10818:9;10814:18;10807:43;10899:2;10891:6;10887:15;10881:3;10870:9;10866:19;10859:44;10952:2;10944:6;10940:15;10934:3;10923:9;10919:19;10912:44;;10993:2;10987:3;10976:9;10972:19;10965:31;11013:63;11072:2;11061:9;11057:18;11049:6;11013:63;:::i;:::-;3180:12;;11142:3;11127:19;;3168:25;3239:4;3228:16;;3222:23;3264:6;3302:21;;;3286:14;;;3279:45;3377:4;3366:16;;3360:23;3356:32;3340:14;;;3333:56;11005:71;-1:-1:-1;11085:62:13;;-1:-1:-1;3099:296:13;11085:62;3180:12;;11213:3;11198:19;;3168:25;3239:4;3228:16;;3222:23;3264:6;3302:21;;;3286:14;;;3279:45;3377:4;3366:16;;3360:23;3356:32;3340:14;;;3333:56;9808:12;;-1:-1:-1;;;;;9804:61:13;11285:3;11270:19;;9792:74;9919:4;9908:16;;9902:23;9927:4;9898:34;9882:14;;;9875:58;9944:1352;;;;;;;;;;;;;:::o;11301:248::-;11369:6;11377;11430:2;11418:9;11409:7;11405:23;11401:32;11398:52;;;11446:1;11443;11436:12;11398:52;-1:-1:-1;;11469:23:13;;;11539:2;11524:18;;;11511:32;;-1:-1:-1;11301:248:13:o;11554:801::-;11665:6;11673;11681;11689;11697;11705;11713;11766:3;11754:9;11745:7;11741:23;11737:33;11734:53;;;11783:1;11780;11773:12;11734:53;11822:9;11809:23;11841:31;11866:5;11841:31;:::i;:::-;11891:5;-1:-1:-1;11948:2:13;11933:18;;11920:32;11961:33;11920:32;11961:33;:::i;:::-;12013:7;-1:-1:-1;12067:2:13;12052:18;;12039:32;;-1:-1:-1;12118:2:13;12103:18;;12090:32;;-1:-1:-1;12174:3:13;12159:19;;12146:33;12188:31;12146:33;12188:31;:::i;:::-;11554:801;;;;-1:-1:-1;11554:801:13;;;;12238:7;12292:3;12277:19;;12264:33;;-1:-1:-1;12344:3:13;12329:19;;;12316:33;;11554:801;-1:-1:-1;;11554:801:13:o;12360:388::-;12428:6;12436;12489:2;12477:9;12468:7;12464:23;12460:32;12457:52;;;12505:1;12502;12495:12;12457:52;12544:9;12531:23;12563:31;12588:5;12563:31;:::i;:::-;12613:5;-1:-1:-1;12670:2:13;12655:18;;12642:32;12683:33;12642:32;12683:33;:::i;12753:531::-;12796:5;12849:3;12842:4;12834:6;12830:17;12826:27;12816:55;;12867:1;12864;12857:12;12816:55;12903:6;12890:20;12929:18;12925:2;12922:26;12919:52;;;12951:18;;:::i;:::-;12995:55;13038:2;13019:13;;-1:-1:-1;;13015:27:13;13044:4;13011:38;12995:55;:::i;:::-;13075:2;13066:7;13059:19;13121:3;13114:4;13109:2;13101:6;13097:15;13093:26;13090:35;13087:55;;;13138:1;13135;13128:12;13087:55;13203:2;13196:4;13188:6;13184:17;13177:4;13168:7;13164:18;13151:55;13251:1;13226:16;;;13244:4;13222:27;13215:38;;;;13230:7;12753:531;-1:-1:-1;;;12753:531:13:o;13289:183::-;13349:4;13382:18;13374:6;13371:30;13368:56;;;13404:18;;:::i;:::-;-1:-1:-1;13449:1:13;13445:14;13461:4;13441:25;;13289:183::o;13477:739::-;13529:5;13582:3;13575:4;13567:6;13563:17;13559:27;13549:55;;13600:1;13597;13590:12;13549:55;13636:6;13623:20;13662:4;13686:60;13702:43;13742:2;13702:43;:::i;:::-;13686:60;:::i;:::-;13768:3;13792:2;13787:3;13780:15;13820:4;13815:3;13811:14;13804:21;;13877:4;13871:2;13868:1;13864:10;13856:6;13852:23;13848:34;13834:48;;13905:3;13897:6;13894:15;13891:35;;;13922:1;13919;13912:12;13891:35;13958:4;13950:6;13946:17;13972:215;13988:6;13983:3;13980:15;13972:215;;;14068:3;14055:17;14085:29;14108:5;14085:29;:::i;:::-;14127:18;;14165:12;;;;14005;;13972:215;;;-1:-1:-1;14205:5:13;13477:739;-1:-1:-1;;;;;;13477:739:13:o;14221:1335::-;14285:5;14333:4;14321:9;14316:3;14312:19;14308:30;14305:50;;;14351:1;14348;14341:12;14305:50;14373:22;;:::i;:::-;14364:31;;14432:9;14419:23;14451:31;14474:7;14451:31;:::i;:::-;14491:22;;14532:2;14570:18;;;14557:32;14608:18;14638:14;;;14635:34;;;14665:1;14662;14655:12;14635:34;14703:6;14692:9;14688:22;14678:32;;14748:3;14741:4;14737:2;14733:13;14729:23;14719:51;;14766:1;14763;14756:12;14719:51;14802:2;14789:16;14825:60;14841:43;14881:2;14841:43;:::i;14825:60::-;14919:15;;;15001:1;14997:10;;;;14989:19;;14985:28;;;14950:12;;;;15025:15;;;15022:35;;;15053:1;15050;15043:12;15022:35;15077:11;;;;15097:223;15113:6;15108:3;15105:15;15097:223;;;15195:3;15182:17;15212:33;15237:7;15212:33;:::i;:::-;15258:20;;15130:12;;;;15298;;;;15097:223;;;15352:5;15347:2;15340:5;15336:14;15329:29;;;;15411:2;15400:9;15396:18;15383:32;15367:48;;15440:2;15430:8;15427:16;15424:36;;;15456:1;15453;15446:12;15424:36;;;15492:57;15545:3;15534:8;15523:9;15519:24;15492:57;:::i;:::-;15487:2;15480:5;15476:14;15469:81;;14221:1335;;;;:::o;15561:435::-;15624:5;15672:4;15660:9;15655:3;15651:19;15647:30;15644:50;;;15690:1;15687;15680:12;15644:50;15712:22;;:::i;:::-;15703:31;;15771:9;15758:23;15790:33;15815:7;15790:33;:::i;:::-;15832:22;;15906:2;15891:18;;15878:32;15919:31;15878:32;15919:31;:::i;:::-;15977:2;15966:14;;15959:31;15970:5;15561:435;-1:-1:-1;;15561:435:13:o;16001:1841::-;16267:6;16275;16283;16291;16299;16352:3;16340:9;16331:7;16327:23;16323:33;16320:53;;;16369:1;16366;16359:12;16320:53;16409:9;16396:23;16438:18;16479:2;16471:6;16468:14;16465:34;;;16495:1;16492;16485:12;16465:34;16518:22;;;;16574:4;16556:16;;;16552:27;16549:47;;;16592:1;16589;16582:12;16549:47;16618:22;;:::i;:::-;16678:2;16665:16;16706:2;16696:8;16693:16;16690:36;;;16722:1;16719;16712:12;16690:36;16749:45;16786:7;16775:8;16771:2;16767:17;16749:45;:::i;:::-;16742:5;16735:60;;16841:2;16837;16833:11;16820:25;16870:2;16860:8;16857:16;16854:36;;;16886:1;16883;16876:12;16854:36;16922:45;16959:7;16948:8;16944:2;16940:17;16922:45;:::i;:::-;16917:2;16910:5;16906:14;16899:69;;17014:2;17010;17006:11;16993:25;17043:2;17033:8;17030:16;17027:36;;;17059:1;17056;17049:12;17027:36;17095:45;17132:7;17121:8;17117:2;17113:17;17095:45;:::i;:::-;17090:2;17083:5;17079:14;17072:69;;17187:2;17183;17179:11;17166:25;17216:2;17206:8;17203:16;17200:36;;;17232:1;17229;17222:12;17200:36;17268:45;17305:7;17294:8;17290:2;17286:17;17268:45;:::i;:::-;17263:2;17256:5;17252:14;17245:69;;17368:3;17364:2;17360:12;17347:26;17341:3;17334:5;17330:15;17323:51;17393:5;17383:15;;;17451:2;17440:9;17436:18;17423:32;17407:48;;17480:2;17470:8;17467:16;17464:36;;;17496:1;17493;17486:12;17464:36;;17519:70;17581:7;17570:8;17559:9;17555:24;17519:70;:::i;:::-;17509:80;;;17608:62;17662:7;17657:2;17646:9;17642:18;17608:62;:::i;:::-;17598:72;;17689:64;17745:7;17738:4;17727:9;17723:20;17689:64;:::i;:::-;17679:74;;17772:64;17828:7;17822:3;17811:9;17807:19;17772:64;:::i;:::-;17762:74;;16001:1841;;;;;;;;:::o;17847:495::-;17937:6;17990:2;17978:9;17969:7;17965:23;17961:32;17958:52;;;18006:1;18003;17996:12;17958:52;18032:22;;:::i;:::-;18091:9;18078:23;18110:33;18135:7;18110:33;:::i;:::-;18152:22;;18226:2;18211:18;;18198:32;18239:33;18198:32;18239:33;:::i;:::-;18299:2;18288:14;;18281:31;18292:5;17847:495;-1:-1:-1;;;17847:495:13:o;18347:380::-;18426:1;18422:12;;;;18469;;;18490:61;;18544:4;18536:6;18532:17;18522:27;;18490:61;18597:2;18589:6;18586:14;18566:18;18563:38;18560:161;;18643:10;18638:3;18634:20;18631:1;18624:31;18678:4;18675:1;18668:15;18706:4;18703:1;18696:15;18560:161;;18347:380;;;:::o;18732:217::-;18772:1;18798;18788:132;;18842:10;18837:3;18833:20;18830:1;18823:31;18877:4;18874:1;18867:15;18905:4;18902:1;18895:15;18788:132;-1:-1:-1;18934:9:13;;18732:217::o;18954:127::-;19015:10;19010:3;19006:20;19003:1;18996:31;19046:4;19043:1;19036:15;19070:4;19067:1;19060:15;19418:2012;20048:4;20077:3;20107:2;20096:9;20089:21;20145:6;20139:13;20188:4;20183:2;20172:9;20168:18;20161:32;20216:52;20263:3;20252:9;20248:19;20234:12;20216:52;:::i;:::-;20202:66;;;20317:4;20309:6;20305:17;20299:24;20346:3;20342:8;20415:2;20403:9;20395:6;20391:22;20387:31;20381:3;20370:9;20366:19;20359:60;20442:41;20476:6;20460:14;20442:41;:::i;:::-;20428:55;;20532:4;20524:6;20520:17;20514:24;20492:46;;20603:2;20591:9;20583:6;20579:22;20575:31;20569:3;20558:9;20554:19;20547:60;20630:41;20664:6;20648:14;20630:41;:::i;:::-;20616:55;;20720:4;20712:6;20708:17;20702:24;20680:46;;20791:2;20779:9;20771:6;20767:22;20763:31;20757:3;20746:9;20742:19;20735:60;;20818:41;20852:6;20836:14;20818:41;:::i;:::-;20804:55;;;20914:4;20906:6;20902:17;20896:24;20890:3;20879:9;20875:19;20868:53;20930:48;20972:4;20961:9;20957:20;20949:6;-1:-1:-1;;;;;1771:54:13;1759:67;;1705:127;20930:48;-1:-1:-1;;;;;1771:54:13;;21029:4;21014:20;;1759:67;21073:6;21066:4;21055:9;21051:20;21044:36;21130:9;21122:6;21118:22;21111:4;21100:9;21096:20;21089:52;21158:51;21202:6;21194;21158:51;:::i;:::-;3180:12;;21275:4;21260:20;;3168:25;3239:4;3228:16;;3222:23;3264:6;3302:21;;;3286:14;;;3279:45;3377:4;3366:16;;3360:23;3356:32;3340:14;;;3333:56;21150:59;-1:-1:-1;21218:63:13;;-1:-1:-1;3099:296:13;21218:63;3180:12;;21347:3;21332:19;;3168:25;3239:4;3228:16;;3222:23;3264:6;3302:21;;;3286:14;;;3279:45;3377:4;3366:16;;3360:23;3356:32;3340:14;;;3333:56;9808:12;;-1:-1:-1;;;;;9804:61:13;21419:3;21404:19;;9792:74;9919:4;9908:16;;9902:23;9927:4;9898:34;9882:14;;;9875:58;19418:2012;;;;;;;;;;;:::o;21435:138::-;21514:13;;21536:31;21514:13;21536:31;:::i;:::-;21435:138;;;:::o;21578:251::-;21648:6;21701:2;21689:9;21680:7;21676:23;21672:32;21669:52;;;21717:1;21714;21707:12;21669:52;21749:9;21743:16;21768:31;21793:5;21768:31;:::i;21834:736::-;21897:5;21950:3;21943:4;21935:6;21931:17;21927:27;21917:55;;21968:1;21965;21958:12;21917:55;21997:6;21991:13;22023:4;22047:60;22063:43;22103:2;22063:43;:::i;22047:60::-;22129:3;22153:2;22148:3;22141:15;22181:4;22176:3;22172:14;22165:21;;22238:4;22232:2;22229:1;22225:10;22217:6;22213:23;22209:34;22195:48;;22266:3;22258:6;22255:15;22252:35;;;22283:1;22280;22273:12;22252:35;22319:4;22311:6;22307:17;22333:208;22349:6;22344:3;22341:15;22333:208;;;22422:3;22416:10;22439:29;22462:5;22439:29;:::i;:::-;22481:18;;22519:12;;;;22366;;22333:208;;22575:1322;22650:5;22698:4;22686:9;22681:3;22677:19;22673:30;22670:50;;;22716:1;22713;22706:12;22670:50;22738:22;;:::i;:::-;22729:31;;22790:9;22784:16;22809:31;22832:7;22809:31;:::i;:::-;22849:22;;22890:2;22921:18;;;22915:25;22959:18;22989:14;;;22986:34;;;23016:1;23013;23006:12;22986:34;23054:6;23043:9;23039:22;23029:32;;23099:3;23092:4;23088:2;23084:13;23080:23;23070:51;;23117:1;23114;23107:12;23070:51;23146:2;23140:9;23169:60;23185:43;23225:2;23185:43;:::i;23169:60::-;23263:15;;;23345:1;23341:10;;;;23333:19;;23329:28;;;23294:12;;;;23369:15;;;23366:35;;;23397:1;23394;23387:12;23366:35;23421:11;;;;23441:216;23457:6;23452:3;23449:15;23441:216;;;23532:3;23526:10;23549:33;23574:7;23549:33;:::i;:::-;23595:20;;23474:12;;;;23635;;;;23441:216;;;23689:5;23684:2;23677:5;23673:14;23666:29;;;;23741:2;23730:9;23726:18;23720:25;23704:41;;23770:2;23760:8;23757:16;23754:36;;;23786:1;23783;23776:12;23754:36;;;23822:68;23886:3;23875:8;23864:9;23860:24;23822:68;:::i;23902:489::-;23975:5;24023:4;24011:9;24006:3;24002:19;23998:30;23995:50;;;24041:1;24038;24031:12;23995:50;24063:22;;:::i;:::-;24054:31;;24114:9;24108:16;24101:5;24094:31;24170:2;24159:9;24155:18;24149:25;24183:32;24207:7;24183:32;:::i;:::-;24242:2;24231:14;;24224:31;24300:2;24285:18;;24279:25;24313:32;24279:25;24313:32;:::i;24396:432::-;24470:5;24518:4;24506:9;24501:3;24497:19;24493:30;24490:50;;;24536:1;24533;24526:12;24490:50;24558:22;;:::i;:::-;24549:31;;24610:9;24604:16;24629:33;24654:7;24629:33;:::i;:::-;24671:22;;24738:2;24723:18;;24717:25;24751:31;24717:25;24751:31;:::i;24833:1564::-;25119:6;25127;25135;25143;25151;25159;25167;25175;25183;25191;25244:3;25232:9;25223:7;25219:23;25215:33;25212:53;;;25261:1;25258;25251:12;25212:53;25293:9;25287:16;25312:31;25337:5;25312:31;:::i;:::-;25412:2;25397:18;;25391:25;25362:5;;-1:-1:-1;25425:33:13;25391:25;25425:33;:::i;:::-;25529:2;25514:18;;25508:25;25477:7;;-1:-1:-1;25542:33:13;25508:25;25542:33;:::i;:::-;25646:2;25631:18;;25625:25;25594:7;;-1:-1:-1;25659:33:13;25625:25;25659:33;:::i;:::-;25763:3;25748:19;;25742:26;25711:7;;-1:-1:-1;25777:33:13;25742:26;25777:33;:::i;:::-;25829:7;-1:-1:-1;25855:50:13;25900:3;25885:19;;25855:50;:::i;:::-;25845:60;;25949:3;25938:9;25934:19;25928:26;25977:18;25969:6;25966:30;25963:50;;;26009:1;26006;25999:12;25963:50;26032:79;26103:7;26094:6;26083:9;26079:22;26032:79;:::i;:::-;26022:89;;;26130:74;26196:7;26190:3;26179:9;26175:19;26130:74;:::i;:::-;26120:84;;26223:74;26289:7;26283:3;26272:9;26268:19;26223:74;:::i;:::-;26213:84;;26316:75;26383:7;26377:3;26366:9;26362:19;26316:75;:::i;:::-;26306:85;;24833:1564;;;;;;;;;;;;;:::o

Swarm Source

ipfs://794159239f1deb143ed3a080e0bb6e618d2d7f7775a71578db816f68d6c56c51
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

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