ETH Price: $1,623.05 (+4.46%)

Contract

0x5606Cd69B61bD6Ed0Fd9aDACD56188D9D6F57645

Overview

ETH Balance

9.951247523656365293 ETH

ETH Value

$16,151.35 (@ $1,623.05/ETH)

Token Holdings

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Sell Tokens65993652025-04-13 3:19:0112 mins ago1744514341IN
Vibe: Factory
0 ETH0.000010030.04525
Buy Tokens65734922025-04-12 19:56:587 hrs ago1744487818IN
Vibe: Factory
0.0004 ETH0.000009910.04525
Buy Tokens65690752025-04-12 18:37:148 hrs ago1744483034IN
Vibe: Factory
0.0001 ETH0.000010980.04525
Buy Tokens65689032025-04-12 18:34:018 hrs ago1744482841IN
Vibe: Factory
0.0001 ETH0.000011310.04525
Sell Tokens65671682025-04-12 18:03:349 hrs ago1744481014IN
Vibe: Factory
0 ETH0.000011110.04525
Buy Tokens65637642025-04-12 17:04:2710 hrs ago1744477467IN
Vibe: Factory
0.006 ETH0.000008460.04525
Sell Tokens65635812025-04-12 17:01:2410 hrs ago1744477284IN
Vibe: Factory
0 ETH0.000015350.04525
Buy Tokens65607042025-04-12 16:11:4211 hrs ago1744474302IN
Vibe: Factory
0.002 ETH0.000009020.04525
Buy Tokens65606502025-04-12 16:10:4811 hrs ago1744474248IN
Vibe: Factory
0.001 ETH0.000007650.04525
Create Token65606072025-04-12 16:10:0511 hrs ago1744474205IN
Vibe: Factory
0.0005 ETH0.000042950.04525
Create Token65592262025-04-12 15:46:1611 hrs ago1744472776IN
Vibe: Factory
0.0005 ETH0.000050080.04525
Buy Tokens65538172025-04-12 14:12:0913 hrs ago1744467129IN
Vibe: Factory
0.007 ETH0.000011530.04525
Buy Tokens65537932025-04-12 14:11:3213 hrs ago1744467092IN
Vibe: Factory
0.01 ETH0.000010210.04525
Buy Tokens65520942025-04-12 13:42:5013 hrs ago1744465370IN
Vibe: Factory
0.0001 ETH0.000005190.04525
Buy Tokens65520712025-04-12 13:42:2713 hrs ago1744465347IN
Vibe: Factory
0.0001 ETH0.000011240.04525
Sell Tokens65441412025-04-12 11:27:2416 hrs ago1744457244IN
Vibe: Factory
0 ETH0.000006810.04525
Buy Tokens65422772025-04-12 10:55:3816 hrs ago1744455338IN
Vibe: Factory
0.0013 ETH0.000007390.04525
Create Token65422042025-04-12 10:54:2516 hrs ago1744455265IN
Vibe: Factory
0.0005 ETH0.000018410.04525
Create Token65399522025-04-12 10:15:5917 hrs ago1744452959IN
Vibe: Factory
0.0005 ETH0.000015650.04525
Buy Tokens65398852025-04-12 10:14:5217 hrs ago1744452892IN
Vibe: Factory
0.005 ETH0.000006670.04525
Buy Tokens65398542025-04-12 10:14:2117 hrs ago1744452861IN
Vibe: Factory
0.011 ETH0.000011220.04525
Buy Tokens65387712025-04-12 9:55:4417 hrs ago1744451744IN
Vibe: Factory
0.0001 ETH0.000009940.04525
Create Token65378312025-04-12 9:39:5117 hrs ago1744450791IN
Vibe: Factory
0.0006 ETH0.000021760.04525
Create Token65329862025-04-12 8:17:1119 hrs ago1744445831IN
Vibe: Factory
0.0005 ETH0.000018210.04525
Sell Tokens65246092025-04-12 5:54:2221 hrs ago1744437262IN
Vibe: Factory
0 ETH0.000005340.04525
View all transactions

Latest 25 internal transactions (View All)

Parent Transaction Hash Block From To
65993652025-04-13 3:19:0112 mins ago1744514341
Vibe: Factory
0.00588117 ETH
65993652025-04-13 3:19:0112 mins ago1744514341
Vibe: Factory
0.0000594 ETH
65734922025-04-12 19:56:587 hrs ago1744487818
Vibe: Factory
0.000004 ETH
65734922025-04-12 19:56:587 hrs ago1744487818
Vibe: Factory
0.0004 ETH
65690752025-04-12 18:37:148 hrs ago1744483034
Vibe: Factory
0.000001 ETH
65690752025-04-12 18:37:148 hrs ago1744483034
Vibe: Factory
0.0001 ETH
65689032025-04-12 18:34:018 hrs ago1744482841
Vibe: Factory
0.000001 ETH
65689032025-04-12 18:34:018 hrs ago1744482841
Vibe: Factory
0.0001 ETH
65671682025-04-12 18:03:349 hrs ago1744481014
Vibe: Factory
0.00000058 ETH
65671682025-04-12 18:03:349 hrs ago1744481014
Vibe: Factory
0 ETH
65637642025-04-12 17:04:2710 hrs ago1744477467
Vibe: Factory
0.00006 ETH
65637642025-04-12 17:04:2710 hrs ago1744477467
Vibe: Factory
0.006 ETH
65636002025-04-12 17:01:4310 hrs ago1744477303
Vibe: Factory
0.00980099 ETH
65636002025-04-12 17:01:4310 hrs ago1744477303
Vibe: Factory
0.00009899 ETH
65635812025-04-12 17:01:2410 hrs ago1744477284
Vibe: Factory
0.00686069 ETH
65635812025-04-12 17:01:2410 hrs ago1744477284
Vibe: Factory
0.00006929 ETH
65607252025-04-12 16:12:0311 hrs ago1744474323
Vibe: Factory
0.00196019 ETH
65607252025-04-12 16:12:0311 hrs ago1744474323
Vibe: Factory
0.00001979 ETH
65607042025-04-12 16:11:4211 hrs ago1744474302
Vibe: Factory
0.00002 ETH
65607042025-04-12 16:11:4211 hrs ago1744474302
Vibe: Factory
0.002 ETH
65606702025-04-12 16:11:0811 hrs ago1744474268
Vibe: Factory
0.00073516 ETH
65606702025-04-12 16:11:0811 hrs ago1744474268
Vibe: Factory
0.00000742 ETH
65606502025-04-12 16:10:4811 hrs ago1744474248
Vibe: Factory
0.00001 ETH
65606502025-04-12 16:10:4811 hrs ago1744474248
Vibe: Factory
0.001 ETH
65606072025-04-12 16:10:0511 hrs ago1744474205
Vibe: Factory
0.0005 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Factory

Compiler Version
v0.8.24-1.0.1

ZkSolc Version
v1.5.7

Optimization Enabled:
Yes with Mode 3

Other Settings:
cancun EvmVersion, MIT license
File 1 of 15 : Factory.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.24;

import {Owned} from "@solmate/auth/Owned.sol";
import {FixedPointMathLib} from "@solmate/utils/FixedPointMathLib.sol";
import {IFactory} from "./interfaces/IFactory.sol";
import {IUniswapV2Factory} from "./interfaces/IUniswapV2Factory.sol";
import {IUniswapV2Pair} from "./interfaces/IUniswapV2Pair.sol";
import {IWETH} from "./interfaces/IWETH.sol";
import {FeeHandler} from "./FeeHandler.sol";
import {LPTokenHolder} from "./LPTokenHolder.sol";
import {Token} from "./Token.sol";

contract Factory is IFactory, Owned {
    using FixedPointMathLib for uint256;

    uint256 public constant MAX_TRADING_FEE = 0.05e18; // 5%

    uint256 public constant MAX_LAUNCH_FEE = 0.05e18; // 5%

    uint256 public constant MINIMUM_VIRTUAL_LIQUIDITY = 0.01 ether;

    IWETH public immutable weth;

    IUniswapV2Factory public immutable uniswapV2Factory;

    FeeHandler public feeHandler;

    LPTokenHolder public lpTokenHolder;

    // Protocol treasury address
    address public treasury;

    // Amount of "fake" ETH liquidity each pair starts with
    uint256 public virtualLiquidity;

    // Amount of ETH to be raised for bonding to end
    uint256 public targetETHRaised;

    // Fee (in ETH) for creating tokens
    uint256 public createFee;

    // Fee (%) for buying and selling tokens
    uint256 public tradingFee;

    // Fee (%) for launching tokens to DEX
    uint256 public launchFee;

    // Reserves and additional info for each token
    mapping(address => Pair) public pairs;

    // ======================================== CONSTRUCTOR ========================================

    struct FactoryParams {
        address owner;
        address treasury;
        address weth;
        address uniswapV2Factory;
        uint256 virtualLiquidity;
        uint256 targetETHRaised;
        uint256 createFee;
        uint256 tradingFee;
        uint256 launchFee;
    }

    constructor(FactoryParams memory factoryParams) Owned(factoryParams.owner) {
        if (factoryParams.virtualLiquidity < MINIMUM_VIRTUAL_LIQUIDITY) revert MinimumLiquidityTooSmall();

        weth = IWETH(factoryParams.weth);
        uniswapV2Factory = IUniswapV2Factory(factoryParams.uniswapV2Factory);

        treasury = factoryParams.treasury;
        virtualLiquidity = factoryParams.virtualLiquidity;
        targetETHRaised = factoryParams.targetETHRaised;

        _setFees(factoryParams.createFee, factoryParams.tradingFee, factoryParams.launchFee);
    }

    // ======================================== ADMIN FUNCTIONS ========================================

    function setFeeHandler(address _feeHandler) external onlyOwner {
        feeHandler = FeeHandler(_feeHandler);
    }

    function setLpTokenHolder(address _lpTokenHolder) external onlyOwner {
        lpTokenHolder = LPTokenHolder(_lpTokenHolder);
    }

    function setTreasury(address _treasury) external onlyOwner {
        treasury = _treasury;
    }

    function setVirtualLiquidity(uint256 _virtualLiquidity) external onlyOwner {
        if (_virtualLiquidity < MINIMUM_VIRTUAL_LIQUIDITY) revert MinimumLiquidityTooSmall();

        virtualLiquidity = _virtualLiquidity;
    }

    function setTargetETHRaised(uint256 _targetETHRaised) external onlyOwner {
        targetETHRaised = _targetETHRaised;
    }

    function setFees(uint256 _createFee, uint256 _tradingFee, uint256 _launchFee) external onlyOwner {
        _setFees(_createFee, _tradingFee, _launchFee);
    }

    function _setFees(uint256 _createFee, uint256 _tradingFee, uint256 _launchFee) internal {
        if (_tradingFee > MAX_TRADING_FEE || _launchFee > MAX_LAUNCH_FEE) revert FeeTooLarge();

        createFee = _createFee;
        tradingFee = _tradingFee;
        launchFee = _launchFee;
    }

    // ======================================== USER FUNCTIONS ========================================

    function createToken(string memory name, string memory symbol, string memory metadata, bytes32 salt)
        external
        payable
        returns (address tokenAddress, uint256 amountOut)
    {
        uint256 _createFee = createFee;
        if (msg.value < _createFee) revert InsufficientETHForCreateFee();

        Token token = new Token{salt: salt}(name, symbol, metadata, msg.sender);
        tokenAddress = address(token);

        pairs[tokenAddress] = Pair({
            virtualLiquidity: virtualLiquidity,
            reserveETH: virtualLiquidity,
            reserveToken: token.INITIAL_AMOUNT()
        });

        feeHandler.rollJackpot();

        // minAmountOut not needed here as token was just created
        uint256 amountIn = msg.value - _createFee;
        if (amountIn != 0) amountOut = _buyTokens(tokenAddress, amountIn, 0);

        feeHandler.handleCreateFee{value: _createFee}(msg.sender);

        emit TokenCreated(tokenAddress, msg.sender);
    }

    function buyTokens(address token, uint256 minAmountOut) external payable returns (uint256 amountOut) {
        Pair memory pair = pairs[token];
        if (pair.virtualLiquidity == 0) revert InvalidToken();

        uint256 actualLiquidity = pair.reserveETH - pair.virtualLiquidity;
        if (actualLiquidity >= targetETHRaised) revert TargetETHRaisedReached();

        feeHandler.rollJackpot();

        amountOut = _buyTokens(token, msg.value, minAmountOut);
    }

    function sellTokens(address token, uint256 amountIn, uint256 minAmountOut) external returns (uint256 amountOut) {
        Pair storage pair = pairs[token];
        if (pair.virtualLiquidity == 0) revert InvalidToken();

        uint256 actualLiquidity = pair.reserveETH - pair.virtualLiquidity;
        if (actualLiquidity >= targetETHRaised) revert TargetETHRaisedReached();

        amountOut = _getAmountOut(amountIn, pair.reserveToken, pair.reserveETH);

        // In theory, this check should never fail
        if (amountOut > actualLiquidity) revert InsufficientETHLiquidity();

        pair.reserveToken += amountIn;
        pair.reserveETH -= amountOut;

        uint256 feeAmount;
        (feeAmount, amountOut) = _subtractFee(amountOut, tradingFee);

        if (amountOut < minAmountOut) revert InsufficientAmountOut();

        feeHandler.rollJackpot();
        feeHandler.handleTradingFee{value: feeAmount}(msg.sender, Token(token).creator());

        Token(token).transferFrom(msg.sender, address(this), amountIn);
        _transferETH(msg.sender, amountOut);

        emit TokenSold(msg.sender, token, amountOut, amountIn);
    }

    function launchToken(address token) external returns (address uniswapV2Pair) {
        Pair memory pair = pairs[token];
        if (pair.virtualLiquidity == 0) revert InvalidToken();

        uint256 actualLiquidity = pair.reserveETH - pair.virtualLiquidity;
        if (actualLiquidity < targetETHRaised) revert TargetETHRaisedNotReached();

        delete pairs[token];

        (uint256 feeAmount, uint256 ethAmount) = _subtractFee(actualLiquidity, launchFee);
        uint256 tokenAmount = pair.reserveToken;

        // Burn tokens equal to ratio of reserveETH removed to maintain constant price
        uint256 burnAmount = (pair.virtualLiquidity + feeAmount) * tokenAmount / pair.reserveETH;
        tokenAmount -= burnAmount;
        Token(token).burn(burnAmount);

        uniswapV2Pair = uniswapV2Factory.getPair(address(weth), address(token));
        if (uniswapV2Pair == address(0)) {
            uniswapV2Pair = uniswapV2Factory.createPair(address(weth), address(token));
        }

        weth.deposit{value: ethAmount}();
        weth.transfer(uniswapV2Pair, ethAmount);
        Token(token).transfer(uniswapV2Pair, tokenAmount);

        /* 
        This is guaranteed to be the first mint as:
        - Token is non-transferable before launch
        - UniswapV2Pair.mint() cannot be called without providing both WETH and token liquidity
        */
        IUniswapV2Pair(uniswapV2Pair).mint(address(lpTokenHolder));

        lpTokenHolder.addLaunchedToken(token, uniswapV2Pair);
        Token(token).enableTransfers();

        feeHandler.rollJackpot();
        feeHandler.handleLaunchFee{value: feeAmount}();

        emit TokenLaunched(token, uniswapV2Pair);
    }

    // ======================================== VIEW FUNCTIONS ========================================

    function previewBuyTokens(address token, uint256 amountIn) external view returns (uint256 amountOut) {
        Pair memory pair = pairs[token];

        amountIn -= amountIn.mulWadDown(tradingFee);
        amountOut = _getAmountOut(amountIn, pair.reserveETH, pair.reserveToken);
    }

    function previewSellTokens(address token, uint256 amountIn) external view returns (uint256 amountOut) {
        Pair memory pair = pairs[token];

        amountOut = _getAmountOut(amountIn, pair.reserveToken, pair.reserveETH);

        uint256 actualLiquidity = pair.reserveETH - pair.virtualLiquidity;
        if (amountOut > actualLiquidity) revert InsufficientETHLiquidity();

        amountOut -= amountOut.mulWadDown(tradingFee);
    }

    function tokenPrice(address token) external view returns (uint256 price) {
        Pair memory pair = pairs[token];
        price = pair.reserveETH.divWadDown(pair.reserveToken);
    }

    function bondingCurveProgress(address token) external view returns (uint256 progress) {
        Pair memory pair = pairs[token];
        uint256 actualLiquidity = pair.reserveETH - pair.virtualLiquidity;
        progress = actualLiquidity.divWadDown(targetETHRaised);
    }

    // ======================================== HELPER FUNCTIONS ========================================

    function _buyTokens(address token, uint256 ethAmount, uint256 minAmountOut) internal returns (uint256 amountOut) {
        Pair storage pair = pairs[token];

        (uint256 feeAmount, uint256 amountIn) = _subtractFee(ethAmount, tradingFee);
        amountOut = _getAmountOut(amountIn, pair.reserveETH, pair.reserveToken);

        pair.reserveETH += amountIn;
        pair.reserveToken -= amountOut;

        if (amountOut < minAmountOut) revert InsufficientAmountOut();

        Token(token).transfer(msg.sender, amountOut);

        feeHandler.handleTradingFee{value: feeAmount}(msg.sender, Token(token).creator());

        emit TokenBought(msg.sender, token, amountIn, amountOut);
    }

    function _subtractFee(uint256 amount, uint256 fee)
        internal
        pure
        returns (uint256 feeAmount, uint256 remainingAmount)
    {
        feeAmount = amount.mulWadDown(fee);
        remainingAmount = amount - feeAmount;
    }

    function _getAmountOut(uint256 amountIn, uint256 reserveIn, uint256 reserveOut) internal pure returns (uint256) {
        if (amountIn == 0) revert InsufficientAmountIn();
        if (reserveIn == 0 || reserveOut == 0) revert InsufficientLiquidity();

        return (amountIn * reserveOut) / (reserveIn + amountIn);
    }

    function _transferETH(address to, uint256 amount) internal {
        (bool success,) = payable(to).call{value: amount}("");
        if (!success) revert ETHTransferFailed();
    }

    receive() external payable {}
}

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

/// @notice Simple single owner authorization mixin.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Owned.sol)
abstract contract Owned {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

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

    /*//////////////////////////////////////////////////////////////
                            OWNERSHIP STORAGE
    //////////////////////////////////////////////////////////////*/

    address public owner;

    modifier onlyOwner() virtual {
        require(msg.sender == owner, "UNAUTHORIZED");

        _;
    }

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

    constructor(address _owner) {
        owner = _owner;

        emit OwnershipTransferred(address(0), _owner);
    }

    /*//////////////////////////////////////////////////////////////
                             OWNERSHIP LOGIC
    //////////////////////////////////////////////////////////////*/

    function transferOwnership(address newOwner) public virtual onlyOwner {
        owner = newOwner;

        emit OwnershipTransferred(msg.sender, newOwner);
    }
}

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

/// @notice Arithmetic library with operations for fixed-point numbers.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol)
/// @author Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol)
library FixedPointMathLib {
    /*//////////////////////////////////////////////////////////////
                    SIMPLIFIED FIXED POINT OPERATIONS
    //////////////////////////////////////////////////////////////*/

    uint256 internal constant MAX_UINT256 = 2**256 - 1;

    uint256 internal constant WAD = 1e18; // The scalar of ETH and most ERC20s.

    function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) {
        return mulDivDown(x, y, WAD); // Equivalent to (x * y) / WAD rounded down.
    }

    function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) {
        return mulDivUp(x, y, WAD); // Equivalent to (x * y) / WAD rounded up.
    }

    function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) {
        return mulDivDown(x, WAD, y); // Equivalent to (x * WAD) / y rounded down.
    }

    function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) {
        return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up.
    }

    /*//////////////////////////////////////////////////////////////
                    LOW LEVEL FIXED POINT OPERATIONS
    //////////////////////////////////////////////////////////////*/

    function mulDivDown(
        uint256 x,
        uint256 y,
        uint256 denominator
    ) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            // Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y))
            if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) {
                revert(0, 0)
            }

            // Divide x * y by the denominator.
            z := div(mul(x, y), denominator)
        }
    }

    function mulDivUp(
        uint256 x,
        uint256 y,
        uint256 denominator
    ) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            // Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y))
            if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) {
                revert(0, 0)
            }

            // If x * y modulo the denominator is strictly greater than 0,
            // 1 is added to round up the division of x * y by the denominator.
            z := add(gt(mod(mul(x, y), denominator), 0), div(mul(x, y), denominator))
        }
    }

    function rpow(
        uint256 x,
        uint256 n,
        uint256 scalar
    ) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            switch x
            case 0 {
                switch n
                case 0 {
                    // 0 ** 0 = 1
                    z := scalar
                }
                default {
                    // 0 ** n = 0
                    z := 0
                }
            }
            default {
                switch mod(n, 2)
                case 0 {
                    // If n is even, store scalar in z for now.
                    z := scalar
                }
                default {
                    // If n is odd, store x in z for now.
                    z := x
                }

                // Shifting right by 1 is like dividing by 2.
                let half := shr(1, scalar)

                for {
                    // Shift n right by 1 before looping to halve it.
                    n := shr(1, n)
                } n {
                    // Shift n right by 1 each iteration to halve it.
                    n := shr(1, n)
                } {
                    // Revert immediately if x ** 2 would overflow.
                    // Equivalent to iszero(eq(div(xx, x), x)) here.
                    if shr(128, x) {
                        revert(0, 0)
                    }

                    // Store x squared.
                    let xx := mul(x, x)

                    // Round to the nearest number.
                    let xxRound := add(xx, half)

                    // Revert if xx + half overflowed.
                    if lt(xxRound, xx) {
                        revert(0, 0)
                    }

                    // Set x to scaled xxRound.
                    x := div(xxRound, scalar)

                    // If n is even:
                    if mod(n, 2) {
                        // Compute z * x.
                        let zx := mul(z, x)

                        // If z * x overflowed:
                        if iszero(eq(div(zx, x), z)) {
                            // Revert if x is non-zero.
                            if iszero(iszero(x)) {
                                revert(0, 0)
                            }
                        }

                        // Round to the nearest number.
                        let zxRound := add(zx, half)

                        // Revert if zx + half overflowed.
                        if lt(zxRound, zx) {
                            revert(0, 0)
                        }

                        // Return properly scaled zxRound.
                        z := div(zxRound, scalar)
                    }
                }
            }
        }
    }

    /*//////////////////////////////////////////////////////////////
                        GENERAL NUMBER UTILITIES
    //////////////////////////////////////////////////////////////*/

    function sqrt(uint256 x) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            let y := x // We start y at x, which will help us make our initial estimate.

            z := 181 // The "correct" value is 1, but this saves a multiplication later.

            // This segment is to get a reasonable initial estimate for the Babylonian method. With a bad
            // start, the correct # of bits increases ~linearly each iteration instead of ~quadratically.

            // We check y >= 2^(k + 8) but shift right by k bits
            // each branch to ensure that if x >= 256, then y >= 256.
            if iszero(lt(y, 0x10000000000000000000000000000000000)) {
                y := shr(128, y)
                z := shl(64, z)
            }
            if iszero(lt(y, 0x1000000000000000000)) {
                y := shr(64, y)
                z := shl(32, z)
            }
            if iszero(lt(y, 0x10000000000)) {
                y := shr(32, y)
                z := shl(16, z)
            }
            if iszero(lt(y, 0x1000000)) {
                y := shr(16, y)
                z := shl(8, z)
            }

            // Goal was to get z*z*y within a small factor of x. More iterations could
            // get y in a tighter range. Currently, we will have y in [256, 256*2^16).
            // We ensured y >= 256 so that the relative difference between y and y+1 is small.
            // That's not possible if x < 256 but we can just verify those cases exhaustively.

            // Now, z*z*y <= x < z*z*(y+1), and y <= 2^(16+8), and either y >= 256, or x < 256.
            // Correctness can be checked exhaustively for x < 256, so we assume y >= 256.
            // Then z*sqrt(y) is within sqrt(257)/sqrt(256) of sqrt(x), or about 20bps.

            // For s in the range [1/256, 256], the estimate f(s) = (181/1024) * (s+1) is in the range
            // (1/2.84 * sqrt(s), 2.84 * sqrt(s)), with largest error when s = 1 and when s = 256 or 1/256.

            // Since y is in [256, 256*2^16), let a = y/65536, so that a is in [1/256, 256). Then we can estimate
            // sqrt(y) using sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2^18.

            // There is no overflow risk here since y < 2^136 after the first branch above.
            z := shr(18, mul(z, add(y, 65536))) // A mul() is saved from starting z at 181.

            // Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough.
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))

            // If x+1 is a perfect square, the Babylonian method cycles between
            // floor(sqrt(x)) and ceil(sqrt(x)). This statement ensures we return floor.
            // See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division
            // Since the ceil is rare, we save gas on the assignment and repeat division in the rare case.
            // If you don't care whether the floor or ceil square root is returned, you can remove this statement.
            z := sub(z, lt(div(x, z), z))
        }
    }

    function unsafeMod(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            // Mod x by y. Note this will return
            // 0 instead of reverting if y is zero.
            z := mod(x, y)
        }
    }

    function unsafeDiv(uint256 x, uint256 y) internal pure returns (uint256 r) {
        /// @solidity memory-safe-assembly
        assembly {
            // Divide x by y. Note this will return
            // 0 instead of reverting if y is zero.
            r := div(x, y)
        }
    }

    function unsafeDivUp(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            // Add 1 to x * y if x % y > 0. Note this will
            // return 0 instead of reverting if y is zero.
            z := add(gt(mod(x, y), 0), div(x, y))
        }
    }
}

File 4 of 15 : IFactory.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.24;

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

interface IFactory {
    error MinimumLiquidityTooSmall();
    error FeeTooLarge();
    error InsufficientETHForCreateFee();
    error TargetETHRaisedTooLarge();
    error TargetETHRaisedReached();
    error TargetETHRaisedNotReached();
    error InsufficientAmountIn();
    error InsufficientAmountOut();
    error InsufficientLiquidity();
    error InsufficientETHLiquidity();
    error InvalidToken();
    error ETHTransferFailed();

    event TokenCreated(address indexed token, address indexed creator);

    event TokenBought(address indexed user, address indexed token, uint256 indexed ethAmount, uint256 tokenAmount);

    event TokenSold(address indexed user, address indexed token, uint256 indexed ethAmount, uint256 tokenAmount);

    event TokenLaunched(address indexed token, address indexed uniswapV2Pair);

    struct Pair {
        uint256 virtualLiquidity;
        uint256 reserveETH;
        uint256 reserveToken;
    }

    function treasury() external view returns (address);

    function virtualLiquidity() external view returns (uint256);

    function targetETHRaised() external view returns (uint256);

    function createFee() external view returns (uint256);

    function tradingFee() external view returns (uint256);

    function launchFee() external view returns (uint256);

    function pairs(address)
        external
        view
        returns (uint256 virtualLiquidity, uint256 reserveETH, uint256 reserveToken);

    function setTreasury(address _treasury) external;

    function setVirtualLiquidity(uint256 _virtualLiquidity) external;

    function setTargetETHRaised(uint256 _targetETHRaised) external;

    function setFees(uint256 _createFee, uint256 _tradingFee, uint256 _launchFee) external;

    function createToken(string memory name, string memory symbol, string memory metadata, bytes32 salt)
        external
        payable
        returns (address tokenAddress, uint256 amountOut);

    function buyTokens(address token, uint256 minAmountOut) external payable returns (uint256);

    function sellTokens(address token, uint256 amountIn, uint256 minAmountOut) external returns (uint256 amountOut);

    function launchToken(address token) external returns (address uniswapV2Pair);

    function previewBuyTokens(address token, uint256 amountIn) external view returns (uint256 amountOut);

    function previewSellTokens(address token, uint256 amountIn) external view returns (uint256 amountOut);

    function tokenPrice(address token) external view returns (uint256 price);

    function bondingCurveProgress(address token) external view returns (uint256 progress);
}

File 5 of 15 : IUniswapV2Factory.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.24;

interface IUniswapV2Factory {
    function getPair(address tokenA, address tokenB) external view returns (address pair);

    function createPair(address tokenA, address tokenB) external returns (address pair);
}

File 6 of 15 : IUniswapV2Pair.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.24;

interface IUniswapV2Pair {
    function token0() external view returns (address);

    function getReserves() external view returns (uint112 _reserve0, uint112 _reserve1, uint32);

    function totalSupply() external view returns (uint256);

    function balanceOf(address account) external view returns (uint256);

    function transfer(address to, uint256 value) external returns (bool);

    function mint(address to) external returns (uint256 liquidity);

    function burn(address to) external returns (uint256 amount0, uint256 amount1);
}

File 7 of 15 : IWETH.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.24;

interface IWETH {
    function balanceOf(address account) external view returns (uint256);

    function deposit() external payable;

    function withdraw(uint256 wad) external;

    function transfer(address dst, uint256 wad) external returns (bool);
}

File 8 of 15 : FeeHandler.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.24;

import {IFeeHandler} from "./interfaces/IFeeHandler.sol";
import {FixedPointMathLib} from "@solmate/utils/FixedPointMathLib.sol";
import {FactoryOwned} from "./FactoryOwned.sol";

contract FeeHandler is IFeeHandler, FactoryOwned {
    using FixedPointMathLib for uint256;

    uint256 public constant MAX_JACKPOT_PROBABILITY = 0.05e18; // 5%

    uint256 public constant MAX_FORCE_AWARD_JACKPOT_BUFFER = 1 days;

    // Configuration for jackpot
    JackpotConfig public jackpotConfig;

    // Configuration for % of fees that are added to the pot
    FeeConfig public feeConfig;

    // Block number at which rollJackpot() was last called
    uint256 public lastRolledBlockNumber;

    // ID of jackpot that hasn't been locked (ie. fees accrue to its pot)
    uint256 public nextJackpotId;

    // Mapping of jackpot ID to jackpot state
    mapping(uint256 => JackpotState) public jackpotStateById;

    // Amount of ETH accrued to users
    mapping(address => uint256) public accruedETH;

    // ======================================== CONSTRUCTOR ========================================

    constructor(
        address _factory,
        JackpotConfig memory _jackpotConfig,
        FeeConfig memory _feeConfig
    ) FactoryOwned(_factory) {
        _setJackpotConfig(_jackpotConfig);
        _setFeeConfig(_feeConfig);
    }

    // ======================================== ADMIN FUNCTIONS ========================================

    function setJackpotConfig(JackpotConfig memory config) external onlyFactoryOwner {
        _setJackpotConfig(config);
    }

    function setFeeConfig(FeeConfig memory config) external onlyFactoryOwner {
        _setFeeConfig(config);
    }

    function _setJackpotConfig(JackpotConfig memory config) internal {
        if (!config.lotteryEnabled) {
            if (config.jackpotProbability != 0
                || config.minimumJackpotAmount != 0
                || config.feeTicketPrice != 0
                || config.directTicketPrice != 0
                || config.forceAwardJackpotBuffer != 0
            ) revert InvalidJackpotConfig();
        } else {
            if (config.jackpotProbability == 0
                || config.minimumJackpotAmount == 0
                || config.feeTicketPrice == 0
                || config.forceAwardJackpotBuffer == 0
            ) revert InvalidJackpotConfig();

            if (config.jackpotProbability > MAX_JACKPOT_PROBABILITY) revert JackpotProbabilityTooHigh();
            if (config.forceAwardJackpotBuffer > MAX_FORCE_AWARD_JACKPOT_BUFFER) revert AwardJackpotBufferTooLarge();
            if (config.directTicketPrice < config.feeTicketPrice) revert DirectTicketPriceTooLow();
        }

        jackpotConfig = config;
    }

    function _setFeeConfig(FeeConfig memory config) internal {
        if (
            config.tradingFeeToCreator + config.tradingFeeToPot > FixedPointMathLib.WAD
            || config.createFeeToPot > FixedPointMathLib.WAD 
            || config.launchFeeToPot > FixedPointMathLib.WAD
            || config.buyTicketToPot > FixedPointMathLib.WAD
        ) revert FeeTooHigh();

        feeConfig = config;
    }

    function commitAdminEntropy(uint256 jackpotId, bytes32 adminEntropyHash) external onlyFactoryOwner {
        JackpotState storage jackpotState = jackpotStateById[jackpotId];
        if (jackpotState.lockedBlockNumber != 0) revert JackpotLocked();

        jackpotState.adminEntropyHash = adminEntropyHash;
    }

    // ======================================== FACTORY FUNCTIONS ========================================

    function handleCreateFee(address user) external payable onlyFactory {
        uint256 amount = msg.value;

        if (jackpotConfig.lotteryEnabled) {
            uint256 noOfTickets = amount / jackpotConfig.feeTicketPrice;
            _addTickets(user, noOfTickets == 0 ? 1 : noOfTickets);

            amount = _subtractFeeToPot(amount, feeConfig.createFeeToPot);
        }

        accruedETH[treasury()] += amount;
    }

    function handleTradingFee(address user, address tokenCreator) external payable onlyFactory {
        uint256 amount = msg.value;

        uint256 amountToCreator = amount.mulWadDown(feeConfig.tradingFeeToCreator);
        accruedETH[tokenCreator] += amountToCreator;

        if (jackpotConfig.lotteryEnabled) {
            uint256 noOfTickets = amount / jackpotConfig.feeTicketPrice;
            if (noOfTickets != 0) _addTickets(user, noOfTickets);
            
            amount = _subtractFeeToPot(amount, feeConfig.tradingFeeToPot);
        }

        accruedETH[treasury()] += amount - amountToCreator;
    }

    function handleLaunchFee() external payable onlyFactory {
        uint256 amount = msg.value;

        if (jackpotConfig.lotteryEnabled) {
            amount = _subtractFeeToPot(amount, feeConfig.launchFeeToPot);
        }

        accruedETH[treasury()] += amount;
    }

    function rollJackpot() external onlyFactory {
        if (!jackpotConfig.lotteryEnabled) return;

        if (block.number == lastRolledBlockNumber) return;
        lastRolledBlockNumber = block.number;

        uint256 _nextJackpotId = nextJackpotId;
        JackpotState storage jackpotState = jackpotStateById[_nextJackpotId];
        if (
            jackpotState.nextTicketId == 0 
            || jackpotState.pot < jackpotConfig.minimumJackpotAmount
            || jackpotState.adminEntropyHash == bytes32(0)
        ) return;

        uint256 entropy = uint256(_getEntropy(_nextJackpotId, block.number - 1));
        if (entropy % FixedPointMathLib.WAD >= jackpotConfig.jackpotProbability) return;

        jackpotState.lockedBlockNumber = block.number;
        jackpotState.lockedTimestamp = block.timestamp;
        nextJackpotId++;
    }

    // ======================================== USER FUNCTIONS ========================================

    function collectETH() external returns (uint256 ethReceived) {
        ethReceived = accruedETH[msg.sender];
        accruedETH[msg.sender] = 0;

        _transferETH(msg.sender, ethReceived);
    }

    function buyTickets() external payable {
        if (!jackpotConfig.lotteryEnabled) revert LotteryDisabled();

        uint256 ethAmount = msg.value;
        uint256 noOfTickets = ethAmount / jackpotConfig.directTicketPrice;
        if (noOfTickets == 0) revert ValueBelowTicketPrice();

        _addTickets(msg.sender, noOfTickets);

        ethAmount = _subtractFeeToPot(ethAmount, feeConfig.buyTicketToPot);

        accruedETH[treasury()] += ethAmount;
    }

    function donateToPot() external payable {
        if (!jackpotConfig.lotteryEnabled) revert LotteryDisabled();

        uint256 _nextJackpotId = nextJackpotId;
        jackpotStateById[_nextJackpotId].pot += msg.value;

        emit JackpotDonated(_nextJackpotId, msg.value);
    }

    function commitCrowdEntropy(uint256 jackpotId) external {
        if (jackpotId >= nextJackpotId) revert JackpotNotLocked();

        JackpotState storage jackpotState = jackpotStateById[jackpotId];
        if (jackpotState.crowdEntropy != bytes32(0)) revert AlreadyCommited();

        jackpotState.crowdEntropy = _getCrowdEntropy(jackpotId);
    }

    function awardJackpot(uint256 jackpotId, bytes32 adminEntropy) external {
        if (jackpotId >= nextJackpotId) revert JackpotNotLocked();

        JackpotState storage jackpotState = jackpotStateById[jackpotId];

        if (keccak256(abi.encodePacked(adminEntropy)) != jackpotState.adminEntropyHash) {
            revert AdminRandomnessMismatch();
        }

        bytes32 _crowdEntropy = _getCrowdEntropy(jackpotId);
        jackpotState.crowdEntropy = _crowdEntropy;

        bytes32 entropy = keccak256(abi.encodePacked(_crowdEntropy, adminEntropy));
        _awardJackpot(jackpotId, entropy);
    }

    function forceAwardJackpot(uint256 jackpotId) external {
        if (jackpotId >= nextJackpotId) revert JackpotNotLocked();

        JackpotState storage jackpotState = jackpotStateById[jackpotId];
        if (block.timestamp < jackpotState.lockedTimestamp + jackpotConfig.forceAwardJackpotBuffer) {
            revert TooEarly();
        }

        bytes32 _crowdEntropy = _getCrowdEntropy(jackpotId);
        jackpotState.crowdEntropy = _crowdEntropy;

        _awardJackpot(jackpotId, _crowdEntropy);
    }

    // ======================================== VIEW FUNCTIONS ========================================

    function currentJackpotSize() external view returns (uint256) {
        return jackpotStateById[nextJackpotId].pot;
    }

    function ticketFromIndex(uint256 jackpotId, uint256 index) external view returns (Ticket memory) {
        return jackpotStateById[jackpotId].tickets[index];
    }

    function ticketQueueLength(uint256 jackpotId) external view returns (uint256) {
        return jackpotStateById[jackpotId].tickets.length;
    }

    // ======================================== HELPER FUNCTIONS ========================================

    function _subtractFeeToPot(uint256 amount, uint256 feeToPot) internal returns (uint256) {
        uint256 amountToPot = amount.mulWadDown(feeToPot);
        jackpotStateById[nextJackpotId].pot += amountToPot;

        return amount - amountToPot;
    }

    function _addTickets(address user, uint256 noOfTickets) internal {
        uint256 _nextJackpotId = nextJackpotId;
        JackpotState storage jackpotState = jackpotStateById[_nextJackpotId];

        Ticket memory ticket = Ticket({user: user, firstTicketId: jackpotState.nextTicketId});
        jackpotState.tickets.push(ticket);
        jackpotState.nextTicketId += noOfTickets;

        emit TicketAdded(_nextJackpotId, user, noOfTickets);
    }

    // From https://github.com/OpenZeppelin/openzeppelin-contracts/blob/932fddf69a699a9a80fd2396fd1a2ab91cdda123/contracts/utils/structs/Checkpoints.sol#L247-L255
    function _findTicketId(Ticket[] storage tickets, uint256 ticketId) internal view returns (address) {
        uint256 low = 0;
        uint256 high = tickets.length;

        while (low < high) {
            uint256 mid = (high + low) / 2;

            if (tickets[mid].firstTicketId > ticketId) {
                high = mid;
            } else {
                low = mid + 1;
            }
        }

        // high should always be non-zero, _findTicketId() is always called with ticketId in range
        return tickets[high - 1].user;
    }

    function _awardJackpot(uint256 jackpotId, bytes32 entropy) internal {
        JackpotState storage jackpotState = jackpotStateById[jackpotId];

        uint256 _pot = jackpotState.pot;
        if (_pot == 0) revert JackpotAlreadyAwarded();

        uint256 winningTicketId = uint256(entropy) % jackpotState.nextTicketId;
        address winner = _findTicketId(jackpotState.tickets, winningTicketId);

        jackpotState.pot = 0;
        accruedETH[winner] += _pot;

        emit JackpotWon(jackpotId, winner, _pot);
    }

    function _getCrowdEntropy(uint256 jackpotId) internal view returns (bytes32) {
        JackpotState storage jackpotState = jackpotStateById[jackpotId];

        bytes32 entropy = jackpotState.crowdEntropy;
        if (entropy != bytes32(0)) return entropy;

        uint256 lockedBlockNumber = jackpotState.lockedBlockNumber;
        if (lockedBlockNumber == 0) revert JackpotNotLocked();

        /*
        Crowd entropy is sourced from the 5th block after the block at which the jackpot was locked.
        If 256 blocks have passed since the 5th block, use the earliest blockhash available.
        */
        uint256 earliestBlockNumber = block.number - 255;
        uint256 selectedBlockNumber = lockedBlockNumber + 5;
        if (block.number <= selectedBlockNumber) revert TooEarly();

        return _getEntropy(
            jackpotId,
            selectedBlockNumber > earliestBlockNumber ? selectedBlockNumber : earliestBlockNumber
        );
    }

    // Include jackpot ID to get different entropy for multiple jackpots in the same block
    function _getEntropy(uint256 jackpotId, uint256 blockNumber) internal view returns (bytes32) {
        return keccak256(abi.encodePacked(jackpotId, blockhash(blockNumber)));
    }
}

File 9 of 15 : LPTokenHolder.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.24;

import {FixedPointMathLib} from "@solmate/utils/FixedPointMathLib.sol";
import {IFactory} from "./interfaces/IFactory.sol";
import {IOwned} from "./interfaces/IOwned.sol";
import {IToken} from "./interfaces/IToken.sol";
import {IUniswapV2Pair} from "./interfaces/IUniswapV2Pair.sol";
import {FactoryOwned} from "./FactoryOwned.sol";

contract LPTokenHolder is FactoryOwned {
    using FixedPointMathLib for uint256;

    struct LaunchInfo {
        address pairAddress;
        uint256 initialLiquidity;
    }

    mapping(address => LaunchInfo) public launchInfo;

    // ======================================== CONSTRUCTOR ========================================

    constructor(address _factory) FactoryOwned(_factory) {}

    // ======================================== ADMIN FUNCTIONS ========================================

    function collectFeesFromAMM(address token) external onlyFactoryOwner {
        (IUniswapV2Pair pair, uint256 lpToBurn) = _lpTokensToBurn(token);

        pair.transfer(address(pair), lpToBurn);
        pair.burn(treasury());
    }

    // ======================================== FACTORY FUNCTIONS ========================================

    function addLaunchedToken(address token, address pairAddress) external onlyFactory {
        (,, uint256 ownedLiquidity) = _lpTokensAndLiquidityOwned(pairAddress);
        launchInfo[token] = LaunchInfo({pairAddress: pairAddress, initialLiquidity: ownedLiquidity});
    }

    // ======================================== VIEW FUNCTIONS ========================================

    function previewCollectFeesFromAMM(address token)
        external
        view
        returns (uint256 wethReceived, uint256 tokenReceived)
    {
        (IUniswapV2Pair pair, uint256 lpToBurn) = _lpTokensToBurn(token);

        uint256 lpTotalSupply = pair.totalSupply();
        (uint256 reserve0, uint256 reserve1,) = pair.getReserves();

        wethReceived = reserve0.mulDivDown(lpToBurn, lpTotalSupply);
        tokenReceived = reserve1.mulDivDown(lpToBurn, lpTotalSupply);

        if (pair.token0() == token) {
            (tokenReceived, wethReceived) = (wethReceived, tokenReceived);
        }
    }

    // ======================================== HELPER FUNCTIONS ========================================

    function _lpTokensToBurn(address token) internal view returns (IUniswapV2Pair pair, uint256 lpToBurn) {
        LaunchInfo memory info = launchInfo[token];

        uint256 lpOwned;
        uint256 ownedLiquidity;
        (pair, lpOwned, ownedLiquidity) = _lpTokensAndLiquidityOwned(info.pairAddress);

        lpToBurn = lpOwned.mulDivDown(ownedLiquidity - info.initialLiquidity, ownedLiquidity);
    }

    function _lpTokensAndLiquidityOwned(address pairAddress)
        internal
        view
        returns (IUniswapV2Pair pair, uint256 lpOwned, uint256 ownedLiquidity)
    {
        pair = IUniswapV2Pair(pairAddress);
        lpOwned = pair.balanceOf(address(this));
        (uint256 reserve0, uint256 reserve1,) = pair.getReserves();

        uint256 currentLiquidity = (reserve0 * reserve1).sqrt();
        ownedLiquidity = currentLiquidity.mulDivDown(lpOwned, pair.totalSupply());
    }
}

File 10 of 15 : Token.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.24;

import {ERC20} from "@solmate/tokens/ERC20.sol";

contract Token is ERC20 {
    error NotFactory();

    uint256 public constant INITIAL_AMOUNT = 1000_000_000e18;

    address public immutable factory;

    address public immutable creator;

    string public metadata;

    bool public transfersEnabled;

    constructor(string memory _name, string memory _symbol, string memory _metadata, address _creator)
        ERC20(_name, _symbol, 18)
    {
        factory = msg.sender;
        metadata = _metadata;
        creator = _creator;

        _mint(factory, INITIAL_AMOUNT);
    }

    function enableTransfers() external {
        if (msg.sender != factory) revert NotFactory();

        transfersEnabled = true;
    }

    function burn(uint256 amount) external {
        if (msg.sender != factory) revert NotFactory();

        _burn(msg.sender, amount);
    }

    function transfer(address to, uint256 amount) public override returns (bool) {
        if (!transfersEnabled && msg.sender != factory) revert NotFactory();

        return super.transfer(to, amount);
    }

    function transferFrom(address from, address to, uint256 amount) public override returns (bool) {
        if (!transfersEnabled && msg.sender != factory) revert NotFactory();

        return super.transferFrom(from, to, amount);
    }
}

File 11 of 15 : IFeeHandler.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.24;

interface IFeeHandler {
    error InvalidJackpotConfig();
    error JackpotProbabilityTooHigh();
    error FeeTooHigh();
    error DirectTicketPriceTooLow();
    error AwardJackpotBufferTooLarge();
    error LotteryDisabled();
    error ValueBelowTicketPrice();
    error JackpotLocked();
    error JackpotNotLocked();
    error AlreadyCommited();
    error TooEarly();
    error AdminRandomnessMismatch();
    error JackpotAlreadyAwarded();

    event TicketAdded(uint256 indexed jackpotId, address indexed user, uint256 indexed noOfTicketsAdded);

    event JackpotWon(uint256 indexed jackpotId, address indexed user, uint256 indexed ethAmount);

    event JackpotDonated(uint256 indexed jackpotId, uint256 indexed ethAmount);

    struct Ticket {
        address user;
        uint256 firstTicketId;
    }

    struct JackpotState {
        // The next ticketId to assign. Also represents the total number of tickets
        uint256 nextTicketId;

        // Cumulative ticket queue
        Ticket[] tickets;

        // Amount of ETH in the pot
        uint256 pot;

        // Hash of random bytes32 from the admin
        bytes32 adminEntropyHash;

        // Random bytes32 from blockhash
        bytes32 crowdEntropy;

        // Block number at which the jackpot was locked
        uint256 lockedBlockNumber;

        // TImestamp as which the jackpot was locked
        uint256 lockedTimestamp;
    }

    struct JackpotConfig {
        // Switch to enable/disable the lottery
        bool lotteryEnabled;

        // Probability of activating the jackpot, out of 1e18
        uint256 jackpotProbability;

        // Minimum ETH in the pot for someone to win
        uint256 minimumJackpotAmount;

        // Minimum fee amount for a ticket
        uint256 feeTicketPrice;

        // Price to buy one ticket
        uint256 directTicketPrice;

        // Number of seconds passed before forceAwardJackpot() can be called
        uint256 forceAwardJackpotBuffer;
    }

    struct FeeConfig {
        // % of fees added to the pot
        uint256 createFeeToPot;
        uint256 tradingFeeToPot;
        uint256 launchFeeToPot;

        // % added to the pot when a ticket is bought
        uint256 buyTicketToPot;
        
        // % of trading fee sent to token creator
        uint256 tradingFeeToCreator;
    }

    function lastRolledBlockNumber() external view returns (uint256);

    function nextJackpotId() external view returns (uint256);

    function accruedETH(address user) external view returns (uint256);

    function currentJackpotSize() external view returns (uint256);

    function ticketFromIndex(uint256 jackpotId, uint256 index) external view returns (Ticket memory);

    function ticketQueueLength(uint256 jackpotId) external view returns (uint256);

    function setJackpotConfig(JackpotConfig memory config) external;

    function setFeeConfig(FeeConfig memory config) external;

    function commitAdminEntropy(uint256 jackpotId, bytes32 adminEntropyHash) external;

    function handleCreateFee(address user) external payable;

    function handleTradingFee(address user, address tokenCreator) external payable;

    function handleLaunchFee() external payable;

    function rollJackpot() external;

    function collectETH() external returns (uint256 ethReceived);

    function buyTickets() external payable;

    function donateToPot() external payable;

    function commitCrowdEntropy(uint256 jackpotId) external;

    function awardJackpot(uint256 jackpotId, bytes32 adminEntropy) external;

    function forceAwardJackpot(uint256 jackpotId) external;
}

File 12 of 15 : FactoryOwned.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.24;

import {IOwned} from "./interfaces/IOwned.sol";
import {IFactory} from "./interfaces/IFactory.sol";

abstract contract FactoryOwned {
    error NotFactory();
    error NotFactoryOwner();
    error ETHTransferFailed();

    address public immutable factory;

    // ======================================== MODIFIERS ========================================

    modifier onlyFactory() {
        if (msg.sender != factory) revert NotFactory();

        _;
    }

    modifier onlyFactoryOwner() {
        if (msg.sender != factoryOwner()) revert NotFactoryOwner();

        _;
    }

    // ======================================== CONSTRUCTOR ========================================

    constructor(address _factory) {
        factory = _factory;
    }

    // ======================================== VIEW FUNCTIONS ========================================

    function factoryOwner() public view returns (address) {
        return IOwned(factory).owner();
    }

    function treasury() public view returns (address) {
        return IFactory(factory).treasury();
    }

    // ======================================== HELPER FUNCTIONS ========================================

    function _transferETH(address to, uint256 amount) internal {
        (bool success,) = payable(to).call{value: amount}("");
        if (!success) revert ETHTransferFailed();
    }
}

File 13 of 15 : IOwned.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.24;

interface IOwned {
    function owner() external view returns (address);
}

File 14 of 15 : IToken.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.24;

interface IToken {
    function transfer(address to, uint256 value) external returns (bool);
}

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

/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)
/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)
/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.
abstract contract ERC20 {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

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

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

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

    string public name;

    string public symbol;

    uint8 public immutable decimals;

    /*//////////////////////////////////////////////////////////////
                              ERC20 STORAGE
    //////////////////////////////////////////////////////////////*/

    uint256 public totalSupply;

    mapping(address => uint256) public balanceOf;

    mapping(address => mapping(address => uint256)) public allowance;

    /*//////////////////////////////////////////////////////////////
                            EIP-2612 STORAGE
    //////////////////////////////////////////////////////////////*/

    uint256 internal immutable INITIAL_CHAIN_ID;

    bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;

    mapping(address => uint256) public nonces;

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

    constructor(
        string memory _name,
        string memory _symbol,
        uint8 _decimals
    ) {
        name = _name;
        symbol = _symbol;
        decimals = _decimals;

        INITIAL_CHAIN_ID = block.chainid;
        INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
    }

    /*//////////////////////////////////////////////////////////////
                               ERC20 LOGIC
    //////////////////////////////////////////////////////////////*/

    function approve(address spender, uint256 amount) public virtual returns (bool) {
        allowance[msg.sender][spender] = amount;

        emit Approval(msg.sender, spender, amount);

        return true;
    }

    function transfer(address to, uint256 amount) public virtual returns (bool) {
        balanceOf[msg.sender] -= amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(msg.sender, to, amount);

        return true;
    }

    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) public virtual returns (bool) {
        uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.

        if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;

        balanceOf[from] -= amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(from, to, amount);

        return true;
    }

    /*//////////////////////////////////////////////////////////////
                             EIP-2612 LOGIC
    //////////////////////////////////////////////////////////////*/

    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual {
        require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");

        // Unchecked because the only math done is incrementing
        // the owner's nonce which cannot realistically overflow.
        unchecked {
            address recoveredAddress = ecrecover(
                keccak256(
                    abi.encodePacked(
                        "\x19\x01",
                        DOMAIN_SEPARATOR(),
                        keccak256(
                            abi.encode(
                                keccak256(
                                    "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
                                ),
                                owner,
                                spender,
                                value,
                                nonces[owner]++,
                                deadline
                            )
                        )
                    )
                ),
                v,
                r,
                s
            );

            require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");

            allowance[recoveredAddress][spender] = value;
        }

        emit Approval(owner, spender, value);
    }

    function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
        return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();
    }

    function computeDomainSeparator() internal view virtual returns (bytes32) {
        return
            keccak256(
                abi.encode(
                    keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
                    keccak256(bytes(name)),
                    keccak256("1"),
                    block.chainid,
                    address(this)
                )
            );
    }

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

    function _mint(address to, uint256 amount) internal virtual {
        totalSupply += amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

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

    function _burn(address from, uint256 amount) internal virtual {
        balanceOf[from] -= amount;

        // Cannot underflow because a user's balance
        // will never be larger than the total supply.
        unchecked {
            totalSupply -= amount;
        }

        emit Transfer(from, address(0), amount);
    }
}

Settings
{
  "viaIR": false,
  "codegen": "yul",
  "remappings": [
    "@solmate/=lib/solmate/src/",
    "ds-test/=lib/solmate/lib/ds-test/src/",
    "forge-std/=lib/forge-std/src/",
    "solmate/=lib/solmate/src/"
  ],
  "evmVersion": "cancun",
  "outputSelection": {
    "*": {
      "*": [
        "abi",
        "metadata"
      ],
      "": [
        "ast"
      ]
    }
  },
  "optimizer": {
    "enabled": true,
    "mode": "3",
    "fallback_to_optimizing_for_size": false,
    "disable_system_request_memoization": true
  },
  "metadata": {},
  "libraries": {},
  "enableEraVMExtensions": false,
  "forceEVMLA": false
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"components":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"treasury","type":"address"},{"internalType":"address","name":"weth","type":"address"},{"internalType":"address","name":"uniswapV2Factory","type":"address"},{"internalType":"uint256","name":"virtualLiquidity","type":"uint256"},{"internalType":"uint256","name":"targetETHRaised","type":"uint256"},{"internalType":"uint256","name":"createFee","type":"uint256"},{"internalType":"uint256","name":"tradingFee","type":"uint256"},{"internalType":"uint256","name":"launchFee","type":"uint256"}],"internalType":"struct Factory.FactoryParams","name":"factoryParams","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ETHTransferFailed","type":"error"},{"inputs":[],"name":"FeeTooLarge","type":"error"},{"inputs":[],"name":"InsufficientAmountIn","type":"error"},{"inputs":[],"name":"InsufficientAmountOut","type":"error"},{"inputs":[],"name":"InsufficientETHForCreateFee","type":"error"},{"inputs":[],"name":"InsufficientETHLiquidity","type":"error"},{"inputs":[],"name":"InsufficientLiquidity","type":"error"},{"inputs":[],"name":"InvalidToken","type":"error"},{"inputs":[],"name":"MinimumLiquidityTooSmall","type":"error"},{"inputs":[],"name":"TargetETHRaisedNotReached","type":"error"},{"inputs":[],"name":"TargetETHRaisedReached","type":"error"},{"inputs":[],"name":"TargetETHRaisedTooLarge","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"uint256","name":"ethAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"TokenBought","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"creator","type":"address"}],"name":"TokenCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"uniswapV2Pair","type":"address"}],"name":"TokenLaunched","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"uint256","name":"ethAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"TokenSold","type":"event"},{"inputs":[],"name":"MAX_LAUNCH_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_TRADING_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINIMUM_VIRTUAL_LIQUIDITY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"bondingCurveProgress","outputs":[{"internalType":"uint256","name":"progress","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"minAmountOut","type":"uint256"}],"name":"buyTokens","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"createFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"string","name":"metadata","type":"string"},{"internalType":"bytes32","name":"salt","type":"bytes32"}],"name":"createToken","outputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"feeHandler","outputs":[{"internalType":"contract FeeHandler","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"launchFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"launchToken","outputs":[{"internalType":"address","name":"uniswapV2Pair","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lpTokenHolder","outputs":[{"internalType":"contract LPTokenHolder","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"pairs","outputs":[{"internalType":"uint256","name":"virtualLiquidity","type":"uint256"},{"internalType":"uint256","name":"reserveETH","type":"uint256"},{"internalType":"uint256","name":"reserveToken","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"}],"name":"previewBuyTokens","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"}],"name":"previewSellTokens","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"minAmountOut","type":"uint256"}],"name":"sellTokens","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feeHandler","type":"address"}],"name":"setFeeHandler","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_createFee","type":"uint256"},{"internalType":"uint256","name":"_tradingFee","type":"uint256"},{"internalType":"uint256","name":"_launchFee","type":"uint256"}],"name":"setFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_lpTokenHolder","type":"address"}],"name":"setLpTokenHolder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_targetETHRaised","type":"uint256"}],"name":"setTargetETHRaised","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_treasury","type":"address"}],"name":"setTreasury","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_virtualLiquidity","type":"uint256"}],"name":"setVirtualLiquidity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"targetETHRaised","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"tokenPrice","outputs":[{"internalType":"uint256","name":"price","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tradingFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"treasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"uniswapV2Factory","outputs":[{"internalType":"contract IUniswapV2Factory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"virtualLiquidity","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"weth","outputs":[{"internalType":"contract IWETH","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]

9c4d535b00000000000000000000000000000000000000000000000000000000000000000100042d55571168071b091e4c1107db516e3bc03a97dc3a3d67279b6aa7930c00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000120000000000000000000000000b9939862351af711b015ca5facdb557b5da65315000000000000000000000000b9939862351af711b015ca5facdb557b5da653150000000000000000000000003439153eb7af838ad19d56e1571fbd09333c2809000000000000000000000000566d7510dee58360a64c9827257cf6d0dc43985e0000000000000000000000000000000000000000000000001bc16d674ec80000000000000000000000000000000000000000000000000000f9ccd8a1c50800000000000000000000000000000000000000000000000000000001c6bf52634000000000000000000000000000000000000000000000000000002386f26fc1000000000000000000000000000000000000000000000000000000470de4df820000

Deployed Bytecode

0x0003000000000002000f0000000000020000006003100270000003b0033001970002000000310355000100000001035500000001002001900000001f0000c13d0000008002000039000000400020043f000000040030008c000000480000413d000000000401043b000000e004400270000003bf0040009c0000004c0000213d000003d50040009c000000a50000a13d000003d60040009c000000cc0000213d000003dc0040009c000001670000213d000003df0040009c000002240000613d000003e00040009c000005260000c13d0000000001000416000000000001004b000005260000c13d0000000701000039000003750000013d0000000002000416000000000002004b000005260000c13d0000001f02300039000003b102200197000000c002200039000000400020043f0000001f0430018f000003b205300198000000c002500039000000300000613d000000c006000039000000000701034f000000007807043c0000000006860436000000000026004b0000002c0000c13d000000000004004b0000003d0000613d000000000151034f0000000304400210000000000502043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f0000000000120435000001200030008c000005260000413d000000400100043d000003b30010009c0000005b0000a13d0000041201000041000000000010043f0000004101000039000000040010043f000004050100004100000ebd00010430000000000003004b000005260000c13d000000000100001900000ebc0001042e000003c00040009c000000bf0000a13d000003c10040009c000000e50000213d000003c70040009c000001700000213d000003ca0040009c000002500000613d000003cb0040009c000005260000c13d0000000001000416000000000001004b000005260000c13d0000000201000039000001ec0000013d0000012002100039000000400020043f000000c00600043d000003b40060009c000005260000213d0000000002610436000b00000002001d000000e00200043d000003b40020009c000005260000213d0000000b030000290000000000230435000001000200043d000003b40020009c000005260000213d0000004003100039000a00000003001d0000000000230435000001200200043d000003b40020009c000005260000213d0000006003100039000500000003001d00000000002304350000008002100039000001400300043d000800000002001d000900000003001d0000000000320435000000a003100039000001600200043d000700000003001d0000000000230435000000c003100039000001800200043d000200000003001d0000000000230435000000e003100039000001a00200043d000600000003001d00000000002304350000010002100039000001c00100043d000300000002001d0000000000120435000000000100041a000003b501100197000000000161019f000000000010041b000000400100043d000400000001001d0000000001000414000003b00010009c000003b001008041000000c001100210000003b6011001c70000800d020000390000000303000039000003b70400004100000000050000190ebb0eb10000040f0000000100200190000005260000613d0000000901000029000003b80010009c000003e10000213d000003be0100004100000004020000290000000000120435000003b00020009c000003b0020080410000004001200210000003bc011001c700000ebd00010430000003e10040009c000000fe0000a13d000003e20040009c000001380000213d000003e50040009c000001ce0000613d000003e60040009c000005260000c13d000000240030008c000005260000413d0000000002000416000000000002004b000005260000c13d0000000401100370000000000101043b000000000200041a000003b4022001970000000003000411000000000023004b000003cf0000c13d000003b80010009c000003dd0000213d000003be01000041000000800010043f000003ff0100004100000ebd00010430000003cc0040009c0000010b0000a13d000003cd0040009c000001470000213d000003d00040009c000001e10000613d000003d10040009c000005260000c13d0000000001000416000000000001004b000005260000c13d0000000601000039000003750000013d000003d70040009c000001790000213d000003da0040009c000002550000613d000003db0040009c000005260000c13d000000240030008c000005260000413d0000000002000416000000000002004b000005260000c13d0000000401100370000000000101043b000b00000001001d000003b40010009c000005260000213d000000000100041a000003b4011001970000000002000411000000000012004b000000000100003900000001010060390ebb0e520000040f00000001010000390000034e0000013d000003c20040009c000001b20000213d000003c50040009c000001040000613d000003c60040009c000005260000c13d000000240030008c000005260000413d0000000002000416000000000002004b000005260000c13d0000000401100370000000000101043b000b00000001001d000003b40010009c000005260000213d000000000100041a000003b4011001970000000002000411000000000012004b000000000100003900000001010060390ebb0e520000040f00000003010000390000034e0000013d000003e70040009c000003810000613d000003e80040009c000003710000613d000003e90040009c000005260000c13d0000000001000416000000000001004b000005260000c13d000003b901000041000000800010043f000003eb0100004100000ebc0001042e000003d20040009c000003a60000613d000003d30040009c000003790000613d000003d40040009c000005260000c13d000000240030008c000005260000413d0000000002000416000000000002004b000005260000c13d0000000401100370000000000101043b000003b40010009c000005260000213d000000000010043f0000000901000039000000200010043f0000000001000414000003b00010009c000003b001008041000000c001100210000003ec011001c700008010020000390ebb0eb60000040f0000000100200190000005260000613d000000000101043b000000e002000039000000400020043f000000000201041a000000800020043f0000000103100039000000000303041a000000a00030043f0000000201100039000000000101041a000000c00010043f000000000123004b000004460000413d000004010010009c000005260000213d0000000502000039000000000202041a000003c80000013d000003e30040009c000001e80000613d000003e40040009c000005260000c13d0000000001000416000000000001004b000005260000c13d0000000001000412000f00000001001d000e00000000003d0000800501000039000000440300003900000000040004150000000f0440008a000003170000013d000003ce0040009c000001ee0000613d000003cf0040009c000005260000c13d000000640030008c000005260000413d0000000002000416000000000002004b000005260000c13d0000004402100370000000000202043b0000002403100370000000000303043b000000000400041a000003b4044001970000000005000411000000000045004b000003cf0000c13d000003b90030009c000003d90000213d000003ba0020009c000003d90000813d0000000401100370000000000101043b0000000604000039000000000014041b0000000701000039000000000031041b0000000801000039000000000021041b000000000100001900000ebc0001042e000003dd0040009c0000030d0000613d000003de0040009c000005260000c13d0000000001000416000000000001004b000005260000c13d0000000301000039000001ec0000013d000003c80040009c0000031b0000613d000003c90040009c000005260000c13d0000000001000416000000000001004b000005260000c13d0000000501000039000003750000013d000003d80040009c0000033c0000613d000003d90040009c000005260000c13d000000240030008c000005260000413d0000000002000416000000000002004b000005260000c13d0000000401100370000000000101043b000b00000001001d000003b40010009c000005260000213d0000000b01000029000000000010043f0000000901000039000000200010043f0000000001000414000003b00010009c000003b001008041000000c001100210000003ec011001c700008010020000390ebb0eb60000040f0000000100200190000005260000613d000000400500043d000004030050009c000000420000213d000000000301043b0000006001500039000000400010043f000000000103041a00000000041504360000000102300039000000000202041a000000000024043500000040065000390000000203300039000000000303041a0000000000360435000000000001004b000003390000613d000000000212004b000004460000413d000700000006001d000800000005001d000900000004001d0000000501000039000000000101041a000a00000002001d000000000012004b000004e90000813d000000400100043d000004130200004100000a800000013d000003c30040009c000003540000613d000003c40040009c000005260000c13d000000240030008c000005260000413d0000000002000416000000000002004b000005260000c13d0000000401100370000000000101043b000003b40010009c000005260000213d000000000010043f0000000901000039000000200010043f00000000010000190ebb0e870000040f0000000202100039000000000202041a0000000103100039000000000303041a000000000101041a000000800010043f000000a00030043f000000c00020043f000003ea0100004100000ebc0001042e000000240030008c000005260000413d0000000001000416000000000001004b000005260000c13d000000000100041a000003b4011001970000000002000411000000000012004b000000000100003900000001010060390ebb0e520000040f00000004010000390000000101100367000000000101043b0000000502000039000000000012041b000000000100001900000ebc0001042e0000000001000416000000000001004b000005260000c13d0000040001000041000000800010043f000003eb0100004100000ebc0001042e0000000001000416000000000001004b000005260000c13d0000000101000039000000000101041a0000037d0000013d000000440030008c000005260000413d0000000002000416000000000002004b000005260000c13d0000000402100370000000000202043b000003b40020009c000005260000213d0000002401100370000000000101043b000b00000001001d000000000020043f0000000901000039000000200010043f0000000001000414000003b00010009c000003b001008041000000c001100210000003ec011001c700008010020000390ebb0eb60000040f0000000100200190000005260000613d000000000101043b000000e002000039000000400020043f000000000201041a000000800020043f0000000102100039000000000202041a000000a00020043f0000000201100039000000000301041a000000c00030043f0000000701000039000000000101041a000000000001004b000002180000613d00000428041001290000000b0040006c000005260000413d0000000b011000b9000003ee0110012a0000000b0110006b000004460000413d0ebb0e660000040f000000400200043d0000000000120435000003b00020009c000003b0020080410000004001200210000003fe011001c700000ebc0001042e000000440030008c000005260000413d0000000002000416000000000002004b000005260000c13d0000000401100370000000000101043b000003b40010009c000005260000213d000000000010043f0000000901000039000000200010043f0000000001000414000003b00010009c000003b001008041000000c001100210000003ec011001c700008010020000390ebb0eb60000040f0000000100200190000005260000613d000000400300043d000004030030009c000000420000213d000000000401043b0000006001300039000000400010043f000000000104041a00000000051304360000000102400039000000000202041a000000000025043500000040053000390000000203400039000000000303041a000000000035043500000024040000390000000104400367000000000404043b000000000004004b0000044f0000c13d000000400100043d000004270200004100000a800000013d0000000001000416000000000001004b000005260000c13d0000000801000039000003750000013d000000840030008c000005260000413d0000000404100370000000000504043b000003f20050009c000005260000213d0000002304500039000000000034004b000005260000813d0000000406500039000000000461034f000000000404043b000003f20040009c000000420000213d0000001f0740003900000429077001970000003f077000390000042907700197000004150070009c000000420000213d0000008007700039000000400070043f000000800040043f00000000054500190000002405500039000000000035004b000005260000213d0000002005600039000000000651034f00000429074001980000001f0840018f000000a0057000390000027c0000613d000000a009000039000000000a06034f00000000ab0a043c0000000009b90436000000000059004b000002780000c13d000000000008004b000002890000613d000000000676034f0000000307800210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000a00440003900000000000404350000002404100370000000000704043b000003f20070009c000005260000213d0000002304700039000000000034004b000005260000813d0000000408700039000000000481034f000000000604043b000003f20060009c000000420000213d0000001f0460003900000429044001970000003f044000390000042904400197000000400500043d0000000004450019000000000054004b00000000090000390000000109004039000003f20040009c000000420000213d0000000100900190000000420000c13d000000400040043f000000000465043600000000076700190000002407700039000000000037004b000005260000213d0000002007800039000000000871034f00000429096001980000001f0a60018f0000000007940019000002b60000613d000000000b08034f000000000c04001900000000bd0b043c000000000cdc043600000000007c004b000002b20000c13d00000000000a004b000002c30000613d000000000898034f0000000309a00210000000000a070433000000000a9a01cf000000000a9a022f000000000808043b0000010009900089000000000898022f00000000089801cf0000000008a8019f0000000000870435000000000664001900000000000604350000004406100370000000000906043b000003f20090009c000005260000213d0000002306900039000000000036004b000005260000813d000000040a9000390000000006a1034f000000000806043b000003f20080009c000000420000213d0000001f0680003900000429066001970000003f066000390000042906600197000000400700043d0000000006670019000000000076004b000000000b000039000000010b004039000003f20060009c000000420000213d0000000100b00190000000420000c13d000000400060043f000000000687043600000000098900190000002409900039000000000039004b000005260000213d0000002003a00039000000000931034f000004290a8001980000001f0b80018f0000000003a60019000002f00000613d000000000c09034f000000000d06001900000000ce0c043c000000000ded043600000000003d004b000002ec0000c13d00000000000b004b000002fd0000613d0000000009a9034f000000030ab00210000000000b030433000000000bab01cf000000000bab022f000000000909043b000001000aa000890000000009a9022f0000000009a901cf0000000009b9019f000000000093043500000000038600190000000000030435000000400300043d0000000608000039000000000808041a0000000009000416000b00000008001d000a000000890053000005f30000813d0000041f010000410000000000130435000003b00030009c000003b0030080410000004001300210000003bc011001c700000ebd000104300000000001000416000000000001004b000005260000c13d0000000001000412000d00000001001d000c00200000003d0000800501000039000000440300003900000000040004150000000d0440008a000000050440021000000406020000410ebb0e980000040f0000037d0000013d000000640030008c000005260000413d0000000002000416000000000002004b000005260000c13d0000000402100370000000000202043b000b00000002001d000003b40020009c000005260000213d0000002401100370000000000101043b000a00000001001d0000000b01000029000000000010043f0000000901000039000000200010043f0000000001000414000003b00010009c000003b001008041000000c001100210000003ec011001c700008010020000390ebb0eb60000040f0000000100200190000005260000613d000000000401043b000000000304041a000000000003004b000004130000c13d000000400100043d000004140200004100000a800000013d000000240030008c000005260000413d0000000002000416000000000002004b000005260000c13d0000000401100370000000000101043b000b00000001001d000003b40010009c000005260000213d000000000100041a000003b4011001970000000002000411000000000012004b000000000100003900000001010060390ebb0e520000040f0000000201000039000000000201041a000003b5022001970000000b022001af000000000021041b000000000100001900000ebc0001042e000000240030008c000005260000413d0000000002000416000000000002004b000005260000c13d0000000401100370000000000601043b000003b40060009c000005260000213d000000000100041a000003b4051001970000000002000411000000000052004b000003cf0000c13d000003b501100197000000000161019f000000000010041b0000000001000414000003b00010009c000003b001008041000000c001100210000003b6011001c70000800d020000390000000303000039000003b7040000410ebb0eb10000040f00000001002001900000004a0000c13d000005260000013d0000000001000416000000000001004b000005260000c13d0000000401000039000000000101041a000000800010043f000003eb0100004100000ebc0001042e0000000001000416000000000001004b000005260000c13d000000000100041a000003b401100197000000800010043f000003eb0100004100000ebc0001042e000000440030008c000005260000413d0000000401100370000000000101043b000b00000001001d000003b40010009c000005260000213d0000000b01000029000000000010043f0000000901000039000000200010043f0000000001000414000003b00010009c000003b001008041000000c001100210000003ec011001c700008010020000390ebb0eb60000040f0000000100200190000005260000613d000000000301043b000000e001000039000000400010043f000000000103041a000000800010043f0000000102300039000000000202041a000000a00020043f0000000203300039000000000303041a000000c00030043f000000000001004b000004440000c13d0000041401000041000000e00010043f000004240100004100000ebd00010430000000240030008c000005260000413d0000000002000416000000000002004b000005260000c13d0000000401100370000000000101043b000003b40010009c000005260000213d000000000010043f0000000901000039000000200010043f0000000001000414000003b00010009c000003b001008041000000c001100210000003ec011001c700008010020000390ebb0eb60000040f0000000100200190000005260000613d000000000201043b000000e001000039000000400010043f000000000102041a000000800010043f0000000101200039000000000101041a000000a00010043f0000000202200039000000000202041a000000c00020043f000004010010009c000005260000213d000000000002004b000005260000613d000003ee011000d100000000012100d9000000e00010043f000004020100004100000ebc0001042e0000042101000041000000800010043f0000002001000039000000840010043f0000000c01000039000000a40010043f0000042201000041000000c40010043f000004230100004100000ebd00010430000003bb01000041000000800010043f000003ff0100004100000ebd000104300000000402000039000000000012041b000000000100001900000ebc0001042e0000000a010000290000000001010433000003b401100197000000800010043f00000005020000290000000002020433000003b402200197000000a00020043f0000000b030000290000000003030433000003b4033001970000000305000039000000000405041a000003b504400197000000000334019f000000000035041b000000080300002900000000030304330000000404000039000000000034041b000000070300002900000000030304330000000504000039000000000034041b00000006030000290000000003030433000003b90030009c0000044c0000213d00000003040000290000000004040433000003ba0040009c0000044c0000813d000000020500002900000000050504330000000606000039000000000056041b0000000705000039000000000035041b0000000803000039000000000043041b0000014000000443000001600010044300000020010000390000018000100443000001a000200443000001000010044300000002010000390000012000100443000003bd0100004100000ebc0001042e0000000101400039000000000201041a000000000332004b000004460000413d0000000505000039000000000505041a000000000053004b000004e20000813d0000000a0000006b0000024d0000613d0000000204400039000000000504041a000000000005004b00000a7e0000613d0000000a062000b90000000a076000fa000000000027004b000004460000c13d0000000a0050002a000004460000413d0000000a0550002900090000005600e1000000090030006b0000045f0000213d000000000054041b000000090220006c000004460000413d000000000021041b0000000701000039000000000101041a000000000001004b000004360000613d0000042802100129000000090020006c000005260000413d00000009011000b9000700000001001d000003ee0110012a000600000001001d0008000900100073000004460000413d00000044010000390000000101100367000000000101043b000000080010006b000005b50000813d000000400100043d000004250200004100000a800000013d000000000112004b000004620000813d0000041201000041000000000010043f0000001101000039000000040010043f000004050100004100000ebd00010430000000400100043d000003bb0200004100000a800000013d000000000003004b00000a7e0000613d000000000002004b00000a7e0000613d00000000052400a900000000064500d9000000000026004b000004460000c13d000000000034001a000004460000413d000000000212004b000004460000413d000000000134001900000000011500d9000000000021004b0000051f0000a13d000000400100043d000004200200004100000a800000013d0000000502000039000000000202041a000000000021004b000004e50000813d0000000101000039000000000101041a000003ef020000410000000000200443000003b401100197000a00000001001d00000004001004430000000001000414000003b00010009c000003b001008041000000c001100210000003f0011001c700008002020000390ebb0eb60000040f000000010020019000000d7f0000613d000000000101043b000000000001004b000005260000613d000000400200043d000003f101000041000900000002001d000000000012043500000000010004140000000a02000029000000040020008c000004910000613d0000000902000029000003b00020009c000003b0020080410000004002200210000003b00010009c000003b001008041000000c001100210000000000121019f000003bc011001c70000000a020000290ebb0eb10000040f0000006003100270000003b00030019d000200000001035500000001002001900000052d0000613d0000000901000029000003f20010009c000000420000213d0000000901000029000000400010043f0000000b01000029000000000010043f0000000901000039000000200010043f0000000001000414000003b00010009c000003b001008041000000c001100210000003ec011001c700008010020000390ebb0eb60000040f0000000100200190000005260000613d0000000002000416000000000101043b0000000703000039000000000303041a000000000003004b000004ac0000613d0000042804300129000000000024004b000005260000413d00000000033200a9000800000003001d000a03ee003001320000000a0320006c000900000003001d000004460000413d0000000a0020006c0000024d0000613d0000000102100039000000000302041a000000000003004b00000a7e0000613d0000000201100039000000000401041a000000000004004b00000a7e0000613d00000009054000b900000009065000fa000000000046004b000004460000c13d000000090030002a000004460000413d0000000903300029000000000032041b00070000003500e1000000070240006c000004460000413d000000000021041b00000024010000390000000101100367000000000101043b000000070010006b000004410000413d000000400300043d0000002401300039000000070200002900000000002104350000040c0100004100000000001304350000000001000411000003b402100197000600000003001d0000000401300039000400000002001d000000000021043500000000010004140000000b02000029000000040020008c000006ab0000c13d0000000003000031000000200030008c00000020040000390000000004034019000006d60000013d000000400100043d000003ed0200004100000a800000013d000003ed01000041000000e00010043f000004240100004100000ebd000104300000000b01000029000000000010043f0000000901000039000000200010043f0000000001000414000003b00010009c000003b001008041000000c001100210000003ec011001c700008010020000390ebb0eb60000040f0000000100200190000005260000613d000000000101043b000000000001041b0000000102100039000000000002041b0000000201100039000000000001041b0000000801000039000000000101041a000000000001004b000005030000613d00000428021001290000000a0020006c000005260000413d0000000a011000b9000400000001001d000003ee0110012a000600000001001d0005000a00100073000000090400002900000008010000290000000703000029000004460000413d0000000002010433000000060020002a000004460000413d0000000001030433000000060320002a00000000021300a9000005160000613d00000000033200d9000000000013004b000004460000c13d0000000003040433000000000003004b0000054c0000c13d0000041201000041000000000010043f0000001201000039000000040010043f000004050100004100000ebd000104300000000702000039000000000202041a000000000002004b000005280000613d0000042803200129000000000013004b000005280000813d000000000100001900000ebd0001043000000000021200a9000003ee0220012a000000000121004b0000021d0000813d000004460000013d000003b0033001970000001f0530018f000003b206300198000000400200043d0000000004620019000005390000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000005350000c13d000000000005004b000005460000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001404350000006001300210000003b00020009c000003b0020080410000004002200210000000000112019f00000ebd0001043000090000003200e1000000090110006c000800000001001d000004460000413d000003ef0100004100000000001004430000000b0100002900000004001004430000000001000414000003b00010009c000003b001008041000000c001100210000003f0011001c700008002020000390ebb0eb60000040f000000010020019000000d7f0000613d000000000101043b000000000001004b000005260000613d000000400200043d00000404010000410000000000120435000700000002001d00000004012000390000000902000029000000000021043500000000010004140000000b02000029000000040020008c0000057b0000613d0000000702000029000003b00020009c000003b0020080410000004002200210000003b00010009c000003b001008041000000c001100210000000000121019f00000405011001c70000000b020000290ebb0eb10000040f0000006003100270000003b00030019d000200000001035500000001002001900000065c0000613d0000000701000029000003f20010009c000000420000213d0000000701000029000000400010043f0000040601000041000000000010044300000000010004120000000400100443000000200100003900000024001004430000000001000414000003b00010009c000003b001008041000000c00110021000000407011001c700008005020000390ebb0eb60000040f000000010020019000000d7f0000613d000000000101043b000900000001001d000004060100004100000000001004430000000001000412000000040010044300000024000004430000000001000414000003b00010009c000003b001008041000000c00110021000000407011001c700008005020000390ebb0eb60000040f000000010020019000000d7f0000613d0000000902000029000003b404200197000000000101043b000000400500043d00000024025000390000000b03000029000000000032043500000408020000410000000000250435000003b402100197000900000005001d0000000401500039000200000002001d00000000002104350000000001000414000700000004001d000000040040008c000008870000c13d0000000004000031000000200040008c0000002004008039000008b20000013d0000000101000039000400000001001d000000000101041a000003ef020000410000000000200443000003b401100197000500000001001d00000004001004430000000001000414000003b00010009c000003b001008041000000c001100210000003f0011001c700008002020000390ebb0eb60000040f000000010020019000000d7f0000613d000000000101043b000000000001004b000005260000613d000000400200043d000003f101000041000300000002001d000000000012043500000000010004140000000502000029000000040020008c000005e10000613d0000000302000029000003b00020009c000003b0020080410000004002200210000003b00010009c000003b001008041000000c001100210000000000121019f000003bc011001c700000005020000290ebb0eb10000040f0000006003100270000003b00030019d000200000001035500000001002001900000069e0000613d0000000301000029000003f20010009c000000420000213d0000000302000029000000400020043f0000000101000039000000000101041a000500000001001d000003f301000041000000000012043500000000010004140000000b02000029000000040020008c0000075c0000c13d0000000004000031000000200040008c0000002004008039000007870000013d000004160030009c000000420000213d00000084083000390000002409300039000004170a0000410000000000a9043500000000002804350000010409300039000000800200043d00000000002904350000012409300039000000000002004b000006080000613d000000000a000019000000000b9a0019000000a00ca00039000000000c0c04330000000000cb0435000000200aa0003900000000002a004b000006010000413d000000000a92001900000000000a04350000001f02200039000004290220019700000000029200190000000009820049000000a40a30003900000000009a043500000000050504330000000002520436000000000005004b0000061c0000613d0000000009000019000000000a290019000000000b490019000000000b0b04330000000000ba04350000002009900039000000000059004b000006150000413d000000000425001900000000000404350000001f04500039000004290440019700000000022400190000000004820049000000c405300039000000000045043500000000040704330000000002420436000000000004004b000006300000613d000000000500001900000000072500190000000008650019000000000808043300000000008704350000002005500039000000000045004b000006290000413d00000000052400190000000000050435000000e405300039000000000600041100000000006504350000001f044000390000042904400197000000000434004900000000022400190000006401100370000000000101043b000000840420008a0000006405300039000000000600041400000000004504350000004404300039000000600500003900000000005404350000041804000041000000000043043500000004043000390000000000140435000003b00020009c000003b0020080410000006001200210000003b00030009c000003b0030080410000004002300210000000000121019f000003b00060009c000003b006008041000000c002600210000000000112019f000003b6011001c700008006020000390ebb0eb10000040f0000000100200190000006690000613d000000000201043b000000000002004b0000068d0000c13d000000020100036700000000020000310000066d0000013d000003b0033001970000001f0530018f000003b206300198000000400200043d0000000004620019000005390000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000006640000c13d000005390000013d00020000000103550000006002100270000003b00020019d000003b00220019700000429052001980000001f0620018f000000400300043d0000000004530019000006780000613d000000000701034f0000000008030019000000007907043c0000000008980436000000000048004b000006740000c13d000000000006004b000006850000613d000000000151034f0000000305600210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000003b00020009c000003b0020080410000006001200210000003b00030009c000003b0030080410000004002300210000000000112019f00000ebd000104300000000401000039000000000101041a000600000001001d000000400300043d0000041901000041000900000003001d00000000001304350000000001000414000003b402200197000800000002001d000000040020008c000007c50000c13d0000000003000031000000200030008c00000020040000390000000004034019000007f00000013d000003b0033001970000001f0530018f000003b206300198000000400200043d0000000004620019000005390000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000006a60000c13d000005390000013d0000000602000029000003b00020009c000003b0020080410000004002200210000003b00010009c000003b001008041000000c001100210000000000121019f000003f6011001c70000000b020000290ebb0eb10000040f0000006003100270000003b003300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000605700029000006c50000613d000000000801034f0000000609000029000000008a08043c0000000009a90436000000000059004b000006c10000c13d000000000006004b000006d20000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000008da0000613d0000001f01400039000000600110018f0000000604100029000000000014004b00000000020000390000000102004039000500000004001d000003f20040009c000000420000213d0000000100200190000000420000c13d0000000502000029000000400020043f000000200030008c000005260000413d00000006020000290000000002020433000000000002004b0000000004000039000000010400c039000000000042004b000005260000c13d0000000102000039000000000202041a000600000002001d000003f3020000410000000504000029000000000024043500000000020004140000000b04000029000000040040008c000007230000613d0000000501000029000003b00010009c000003b0010080410000004001100210000003b00020009c000003b002008041000000c002200210000000000112019f000003bc011001c70000000b020000290ebb0eb60000040f0000006003100270000003b003300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000505700029000007100000613d000000000801034f0000000509000029000000008a08043c0000000009a90436000000000059004b0000070c0000c13d000000000006004b0000071d0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000090a0000613d0000001f01400039000000600110018f0000000501100029000003f20010009c000000420000213d000000400010043f000000200030008c000005260000413d00000005010000290000000001010433000500000001001d000003b40010009c000005260000213d0000000601000029000003b402100197000003ef010000410000000000100443000600000002001d00000004002004430000000001000414000003b00010009c000003b001008041000000c001100210000003f0011001c700008002020000390ebb0eb60000040f000000010020019000000d7f0000613d000000000101043b000000000001004b000005260000613d000000400200043d000000240120003900000005030000290000000000310435000003f4010000410000000000120435000500000002001d00000004012000390000000402000029000000000021043500000000010004140000000602000029000000040020008c00000bbd0000613d0000000502000029000003b00020009c000003b0020080410000004002200210000003b00010009c000003b001008041000000c001100210000000000121019f0000000802000029000003ee0020009c00000bb20000813d000003f6011001c7000000060200002900000bb70000013d0000000302000029000003b00020009c000003b0020080410000004002200210000003b00010009c000003b001008041000000c001100210000000000121019f000003bc011001c70000000b020000290ebb0eb60000040f0000006003100270000003b003300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000305700029000007760000613d000000000801034f0000000309000029000000008a08043c0000000009a90436000000000059004b000007720000c13d000000000006004b000007830000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000008e60000613d0000001f01400039000000600110018f0000000301100029000003f20010009c000000420000213d000000400010043f000000200040008c000005260000413d00000003010000290000000001010433000300000001001d000003b40010009c000005260000213d0000000501000029000003b402100197000003ef010000410000000000100443000500000002001d00000004002004430000000001000414000003b00010009c000003b001008041000000c001100210000003f0011001c700008002020000390ebb0eb60000040f000000010020019000000d7f0000613d000000000101043b000000000001004b000005260000613d000000400200043d000003f40100004100000000001204350000002401200039000100000001001d000000030300002900000000003104350000000001000411000003b401100197000200000002001d0000000402200039000300000002001d000000000012043500000000010004140000000502000029000000040020008c0000098b0000613d0000000202000029000003b00020009c000003b0020080410000004002200210000003b00010009c000003b001008041000000c001100210000000000121019f0000000702000029000003ee0020009c000009800000813d000003f6011001c70000000502000029000009850000013d0000000902000029000003b00020009c000003b0020080410000004002200210000003b00010009c000003b001008041000000c001100210000000000121019f000003bc011001c700000008020000290ebb0eb60000040f0000006003100270000003b003300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000905700029000007df0000613d000000000801034f0000000909000029000000008a08043c0000000009a90436000000000059004b000007db0000c13d000000000006004b000007ec0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000008f20000613d0000001f01400039000000600110018f0000000902100029000000000012004b00000000010000390000000101004039000700000002001d000003f20020009c000000420000213d0000000100100190000000420000c13d0000000701000029000000400010043f000000200030008c000005260000413d0000000701000029000004030010009c000000420000213d0000000901000029000000000101043300000007030000290000006002300039000000400020043f0000004002300039000900000002001d000000000012043500000006010000290000000002130436000500000002001d00000000001204350000000801000029000000000010043f0000000901000039000000200010043f0000000001000414000003b00010009c000003b001008041000000c001100210000003ec011001c700008010020000390ebb0eb60000040f0000000100200190000005260000613d00000007020000290000000002020433000000000101043b000000000021041b000000050200002900000000020204330000000103100039000000000023041b000000020110003900000009020000290000000002020433000000000021041b0000000101000039000000000101041a000003ef020000410000000000200443000003b401100197000900000001001d00000004001004430000000001000414000003b00010009c000003b001008041000000c001100210000003f0011001c700008002020000390ebb0eb60000040f000000010020019000000d7f0000613d000000000101043b000000000001004b000005260000613d000000400200043d000003f101000041000700000002001d000000000012043500000000010004140000000902000029000000040020008c000008520000613d0000000702000029000003b00020009c000003b0020080410000004002200210000003b00010009c000003b001008041000000c001100210000000000121019f000003bc011001c700000009020000290ebb0eb10000040f0000006003100270000003b00030019d00020000000103550000000100200190000009f20000613d0000000701000029000003f20010009c000000420000213d0000000701000029000000400010043f00000000020004160000000b0020006c000900000000001d00000a380000c13d0000000101000039000000000101041a000003ef020000410000000000200443000003b401100197000a00000001001d00000004001004430000000001000414000003b00010009c000003b001008041000000c001100210000003f0011001c700008002020000390ebb0eb60000040f000000010020019000000d7f0000613d000000000101043b000000000001004b000005260000613d000000400200043d0000041b010000410000000001120436000600000001001d000700000002001d00000004012000390000000002000411000000000021043500000000010004140000000a02000029000000040020008c00000c830000613d0000000702000029000003b00020009c000003b0020080410000004002200210000003b00010009c000003b001008041000000c001100210000000000121019f0000000b0000006b00000c780000c13d00000405011001c70000000a0200002900000c7d0000013d0000000902000029000003b00020009c000003b0020080410000004002200210000003b00010009c000003b001008041000000c001100210000000000121019f000003f6011001c700000007020000290ebb0eb60000040f0000006003100270000003b003300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000905700029000008a10000613d000000000801034f0000000909000029000000008a08043c0000000009a90436000000000059004b0000089d0000c13d000000000006004b000008ae0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000008fe0000613d0000001f01400039000000600110018f0000000903100029000000000013004b00000000020000390000000102004039000300000003001d000003f20030009c000000420000213d0000000100200190000000420000c13d0000000302000029000000400020043f000000200040008c000005260000413d00000009020000290000000002020433000900000002001d000003b40020009c000005260000213d000000090000006b0000094e0000c13d000000030400002900000024024000390000000b0300002900000000003204350000040902000041000000000024043500000004024000390000000203000029000000000032043500000000020004140000000703000029000000040030008c000009160000c13d0000000301100029000003f20010009c000000420000213d000000400010043f000009490000013d0000001f0530018f000003b206300198000000400200043d0000000004620019000005390000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000008e10000c13d000005390000013d0000001f0530018f000003b206300198000000400200043d0000000004620019000005390000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000008ed0000c13d000005390000013d0000001f0530018f000003b206300198000000400200043d0000000004620019000005390000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000008f90000c13d000005390000013d0000001f0530018f000003b206300198000000400200043d0000000004620019000005390000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000009050000c13d000005390000013d0000001f0530018f000003b206300198000000400200043d0000000004620019000005390000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000009110000c13d000005390000013d0000000301000029000003b00010009c000003b0010080410000004001100210000003b00020009c000003b002008041000000c002200210000000000112019f000003f6011001c700000007020000290ebb0eb10000040f0000006003100270000003b003300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000305700029000009300000613d000000000801034f0000000309000029000000008a08043c0000000009a90436000000000059004b0000092c0000c13d000000000006004b0000093d0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000009740000613d0000001f01400039000000600110018f0000000301100029000003f20010009c000000420000213d000000400010043f000000200030008c000005260000413d00000003010000290000000001010433000900000001001d000003b40010009c000005260000213d000003ef010000410000000000100443000000020100002900000004001004430000000001000414000003b00010009c000003b001008041000000c001100210000003f0011001c700008002020000390ebb0eb60000040f000000010020019000000d7f0000613d000000000101043b000000000001004b000005260000613d000000400200043d0000040a01000041000700000002001d000000000012043500000000010004140000000202000029000000040020008c00000a0a0000613d0000000702000029000003b00020009c000003b0020080410000004002200210000003b00010009c000003b001008041000000c001100210000000000121019f0000000a03000029000000060030006c000009ff0000c13d000003bc011001c7000000020200002900000a040000013d0000001f0530018f000003b206300198000000400200043d0000000004620019000005390000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000097b0000c13d000005390000013d000003f5011001c700008009020000390000000603000029000000050400002900000000050000190ebb0eb10000040f00020000000103550000006003100270000003b00030019d0000000100200190000009a40000613d0000000201000029000003f20010009c000000420000213d0000000202000029000000400020043f000003f701000041000000000012043500000000010004110000000303000029000000000013043500000000010004100000000103000029000000000013043500000044012000390000000a02000029000000000021043500000000010004140000000b02000029000000040020008c000009b10000c13d0000000003000031000000200030008c00000020040000390000000004034019000009dc0000013d000003b0033001970000001f0530018f000003b206300198000000400200043d0000000004620019000005390000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000009ac0000c13d000005390000013d0000000202000029000003b00020009c000003b0020080410000004002200210000003b00010009c000003b001008041000000c001100210000000000121019f000003f8011001c70000000b020000290ebb0eb10000040f0000006003100270000003b003300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000205700029000009cb0000613d000000000801034f0000000209000029000000008a08043c0000000009a90436000000000059004b000009c70000c13d000000000006004b000009d80000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000000a2c0000613d0000001f01400039000000600110018f0000000201100029000003f20010009c000000420000213d000000400010043f000000200030008c000005260000413d00000002020000290000000002020433000000000002004b0000000004000039000000010400c039000000000042004b000005260000c13d00000000020004140000000004000411000000040040008c00000be60000c13d000003f20030009c000000420000213d00000bfa0000013d000003b0033001970000001f0530018f000003b206300198000000400200043d0000000004620019000005390000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000009fa0000c13d000005390000013d0000040b011001c700008009020000390000000503000029000000020400002900000000050000190ebb0eb10000040f00020000000103550000006003100270000003b00030019d000000010020019000000a1f0000613d0000000701000029000003f20010009c000000420000213d0000000703000029000000400030043f0000002401300039000000050200002900000000002104350000040c01000041000000000013043500000004013000390000000902000029000000000021043500000000010004140000000202000029000000040020008c00000a860000c13d0000000004000031000000200040008c000000200400803900000ab10000013d000003b0033001970000001f0530018f000003b206300198000000400200043d0000000004620019000005390000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00000a270000c13d000005390000013d0000001f0530018f000003b206300198000000400200043d0000000004620019000005390000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00000a330000c13d000005390000013d0000000801000029000000000010043f0000000901000039000000200010043f0000000001000414000003b00010009c000003b001008041000000c001100210000003ec011001c700008010020000390ebb0eb60000040f0000000100200190000005260000613d000000000101043b0000000702000039000000000202041a000000000002004b00000a4d0000613d00000428032001290000000a0030006c000005260000413d0000000a022000b9000500000002001d000003ee0220012a000700000002001d0006000a00200073000004460000413d00000007030000290000000a0030006b0000024d0000613d0000000102100039000000000302041a000000000003004b00000a7e0000613d0000000201100039000000000401041a000000000004004b00000a7e0000613d00000006054000b900000006065000fa000000000046004b000004460000c13d000000060030002a000004460000413d0000000603300029000000000032041b00090000003500e1000000090240006c000004460000413d000000000021041b000000400300043d0000002401300039000000090200002900000000002104350000040c0100004100000000001304350000000001000411000003b402100197000a00000003001d0000000401300039000300000002001d000000000021043500000000010004140000000802000029000000040020008c00000cfd0000c13d0000000004000031000000200040008c000000200400803900000d280000013d000000400100043d00000426020000410000000000210435000003b00010009c000003b0010080410000004001100210000003bc011001c700000ebd000104300000000702000029000003b00020009c000003b0020080410000004002200210000003b00010009c000003b001008041000000c001100210000000000121019f000003f6011001c700000002020000290ebb0eb10000040f0000006003100270000003b003300197000000200030008c000000200400003900000000040340190000001f0640018f0000002007400190000000070570002900000aa00000613d000000000801034f0000000709000029000000008a08043c0000000009a90436000000000059004b00000a9c0000c13d000000000006004b00000aad0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000000ba60000613d0000001f01400039000000600110018f0000000702100029000a00000002001d000003f20020009c000000420000213d0000000a02000029000000400020043f000000200040008c000005260000413d00000007020000290000000002020433000000000002004b0000000003000039000000010300c039000000000032004b000005260000c13d0000000a040000290000002402400039000000080300002900000000003204350000040c02000041000000000024043500000004024000390000000903000029000000000032043500000000020004140000000b03000029000000040030008c00000c420000c13d0000000a02100029000800000002001d000003f20020009c000000420000213d0000000802000029000000400020043f0000000a020000290000000002020433000000000002004b0000000003000039000000010300c039000000000032004b000005260000c13d0000000202000039000000000202041a0000040d03000041000000080400002900000000003404350000000403400039000003b402200197000a00000002001d000000000023043500000000020004140000000903000029000000040030008c00000cb90000c13d0000000801100029000003f20010009c000000420000213d000000400010043f000003ef0100004100000000001004430000000a0100002900000004001004430000000001000414000003b00010009c000003b001008041000000c001100210000003f0011001c700008002020000390ebb0eb60000040f000000010020019000000d7f0000613d000000000101043b000000000001004b000005260000613d000000400300043d0000002401300039000000090200002900000000002104350000040e010000410000000000130435000800000003001d00000004013000390000000b02000029000000000021043500000000010004140000000a02000029000000040020008c00000b1b0000613d0000000802000029000003b00020009c000003b0020080410000004002200210000003b00010009c000003b001008041000000c001100210000000000121019f000003f6011001c70000000a020000290ebb0eb10000040f0000006003100270000003b00030019d0002000000010355000000010020019000000d8c0000613d0000000801000029000003f20010009c000000420000213d0000000801000029000000400010043f000003ef0100004100000000001004430000000b0100002900000004001004430000000001000414000003b00010009c000003b001008041000000c001100210000003f0011001c700008002020000390ebb0eb60000040f000000010020019000000d7f0000613d000000000101043b000000000001004b000005260000613d000000400200043d0000040f01000041000a00000002001d000000000012043500000000010004140000000b02000029000000040020008c00000b480000613d0000000a02000029000003b00020009c000003b0020080410000004002200210000003b00010009c000003b001008041000000c001100210000000000121019f000003bc011001c70000000b020000290ebb0eb10000040f0000006003100270000003b00030019d0002000000010355000000010020019000000dd90000613d0000000a01000029000003f20010009c000000420000213d0000000a01000029000000400010043f0000000101000039000000000101041a000003ef020000410000000000200443000003b401100197000800000001001d00000004001004430000000001000414000003b00010009c000003b001008041000000c001100210000003f0011001c700008002020000390ebb0eb60000040f000000010020019000000d7f0000613d000000000101043b000000000001004b000005260000613d000000400200043d000003f101000041000a00000002001d000000000012043500000000010004140000000802000029000000040020008c00000b780000613d0000000a02000029000003b00020009c000003b0020080410000004002200210000003b00010009c000003b001008041000000c001100210000000000121019f000003bc011001c700000008020000290ebb0eb10000040f0000006003100270000003b00030019d0002000000010355000000010020019000000de60000613d0000000a01000029000003f20010009c000000420000213d0000000a01000029000000400010043f0000000101000039000000000101041a000003ef020000410000000000200443000003b401100197000800000001001d00000004001004430000000001000414000003b00010009c000003b001008041000000c001100210000003f0011001c700008002020000390ebb0eb60000040f000000010020019000000d7f0000613d000000000101043b000000000001004b000005260000613d000000400200043d0000041001000041000a00000002001d000000000012043500000000010004140000000802000029000000040020008c00000dfe0000613d0000000a02000029000003b00020009c000003b0020080410000004002200210000003b00010009c000003b001008041000000c001100210000000000121019f0000000402000029000003ee0020009c00000df30000813d000003bc011001c7000000080200002900000df80000013d0000001f0530018f000003b206300198000000400200043d0000000004620019000005390000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00000bad0000c13d000005390000013d000003f5011001c700008009020000390000000a03000029000000060400002900000000050000190ebb0eb10000040f00020000000103550000006003100270000003b00030019d000000010020019000000bd90000613d0000000501000029000003f20010009c000000420000213d0000000502000029000000400020043f00000007010000290000000000120435000003b00020009c000003b00200804100000040012002100000000002000414000003b00020009c000003b002008041000000c002200210000000000112019f000003fc011001c70000800d0200003900000004030000390000041a0400004100000000050004110000000b0600002900000009070000290ebb0eb10000040f0000000100200190000005260000613d000000400100043d000000070200002900000c390000013d000003b0033001970000001f0530018f000003b206300198000000400200043d0000000004620019000005390000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00000be10000c13d000005390000013d000003b00020009c000003b002008041000000c0012002100000000603000029000000090030006b00000bee0000c13d000000000200041100000bf20000013d000003b6011001c70000800902000039000000080300002900000000050000190ebb0eb10000040f000400000002001d00020000000103550000006001100270000003b00010019d000003b00310019800000c1f0000613d000000400100043d0000001f02300039000003f9022001970000003f02200039000003fa042001970000000002140019000000000042004b00000000040000390000000104004039000003f20020009c000000420000213d0000000100400190000000420000c13d000000400020043f000000000531043600000429023001980000001f0330018f0000000001250019000000020400036700000c120000613d000000000604034f000000006706043c0000000005750436000000000015004b00000c0e0000c13d000000000003004b00000c1f0000613d000000000224034f0000000303300210000000000401043300000000043401cf000000000434022f000000000202043b0000010003300089000000000232022f00000000023201cf000000000242019f00000000002104350000000401000029000000010010019000000c3f0000613d000000400100043d0000000a020000290000000000210435000003b00010009c000003b00100804100000040011002100000000002000414000003b00020009c000003b002008041000000c002200210000000000112019f000003fc011001c70000800d020000390000000403000039000003fd0400004100000000050004110000000b0600002900000008070000290ebb0eb10000040f0000000100200190000005260000613d000000400100043d00000008020000290000000000210435000003b00010009c000003b0010080410000004001100210000003fe011001c700000ebc0001042e000000400100043d000003fb0200004100000a800000013d0000000a01000029000003b00010009c000003b0010080410000004001100210000003b00020009c000003b002008041000000c002200210000000000112019f000003f6011001c70000000b020000290ebb0eb10000040f0000006003100270000003b003300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000a0570002900000c5c0000613d000000000801034f0000000a09000029000000008a08043c0000000009a90436000000000059004b00000c580000c13d000000000006004b00000c690000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000000cad0000613d0000001f01400039000000600110018f0000000a02100029000800000002001d000003f20020009c000000420000213d0000000802000029000000400020043f000000200030008c000005260000413d00000ad50000013d0000041c011001c700008009020000390000000b030000290000000a0400002900000000050000190ebb0eb10000040f00020000000103550000006003100270000003b00030019d000000010020019000000ca00000613d0000000701000029000003f20010009c000000420000213d0000000701000029000000400010043f0000000001000414000003b00010009c000003b001008041000000c001100210000003b6011001c70000800d0200003900000003030000390000041d04000041000000080500002900000000060004110ebb0eb10000040f0000000100200190000005260000613d000000090100002900000006020000290000000000120435000000080100002900000007020000290000000000120435000003b00020009c000003b00200804100000040012002100000041e011001c700000ebc0001042e000003b0033001970000001f0530018f000003b206300198000000400200043d0000000004620019000005390000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00000ca80000c13d000005390000013d0000001f0530018f000003b206300198000000400200043d0000000004620019000005390000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00000cb40000c13d000005390000013d0000000801000029000800000001001d000003b00010009c000003b0010080410000004001100210000003b00020009c000003b002008041000000c002200210000000000112019f00000405011001c700000009020000290ebb0eb10000040f0000006003100270000003b003300197000000200030008c000000200400003900000000040340190000001f0640018f0000002007400190000000080570002900000cd40000613d000000000801034f0000000809000029000000008a08043c0000000009a90436000000000059004b00000cd00000c13d000000000006004b00000ce10000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000000cf10000613d0000001f01400039000000600110018f0000000801100029000003f20010009c000000420000213d000000400010043f000000200030008c000005260000413d0000000201000039000000000101041a000a03b40010019b00000aed0000013d0000001f0530018f000003b206300198000000400200043d0000000004620019000005390000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00000cf80000c13d000005390000013d0000000a02000029000003b00020009c000003b0020080410000004002200210000003b00010009c000003b001008041000000c001100210000000000121019f000003f6011001c700000008020000290ebb0eb10000040f0000006003100270000003b003300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000a0570002900000d170000613d000000000801034f0000000a09000029000000008a08043c0000000009a90436000000000059004b00000d130000c13d000000000006004b00000d240000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000000d800000613d0000001f01400039000000600110018f0000000a03100029000000000013004b00000000020000390000000102004039000400000003001d000003f20030009c000000420000213d0000000100200190000000420000c13d0000000402000029000000400020043f000000200040008c000005260000413d0000000a020000290000000002020433000000000002004b0000000003000039000000010300c039000000000032004b000005260000c13d0000000102000039000000000202041a000a00000002001d000003f3020000410000000403000029000000000023043500000000020004140000000803000029000000040030008c00000d990000c13d0000000401100029000003f20010009c000000420000213d000000400010043f00000004010000290000000001010433000400000001001d000003b40010009c000005260000213d0000000a01000029000003b402100197000003ef010000410000000000100443000a00000002001d00000004002004430000000001000414000003b00010009c000003b001008041000000c001100210000003f0011001c700008002020000390ebb0eb60000040f000000010020019000000d7f0000613d000000000101043b000000000001004b000005260000613d000000400200043d000000240120003900000004030000290000000000310435000003f4010000410000000000120435000400000002001d00000004012000390000000302000029000000000021043500000000010004140000000a02000029000000040020008c00000e1e0000613d0000000402000029000003b00020009c000003b0020080410000004002200210000003b00010009c000003b001008041000000c001100210000000000121019f0000000502000029000003ee0020009c00000e130000813d000003f6011001c70000000a0200002900000e180000013d000000000001042f0000001f0530018f000003b206300198000000400200043d0000000004620019000005390000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00000d870000c13d000005390000013d000003b0033001970000001f0530018f000003b206300198000000400200043d0000000004620019000005390000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00000d940000c13d000005390000013d0000000401000029000003b00010009c000003b0010080410000004001100210000003b00020009c000003b002008041000000c002200210000000000112019f000003bc011001c700000008020000290ebb0eb60000040f0000006003100270000003b003300197000000200030008c000000200400003900000000040340190000001f0640018f0000002007400190000000040570002900000db30000613d000000000801034f0000000409000029000000008a08043c0000000009a90436000000000059004b00000daf0000c13d000000000006004b00000dc00000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000000dcd0000613d0000001f01400039000000600110018f0000000401100029000003f20010009c000000420000213d000000400010043f000000200030008c000005260000413d00000d4c0000013d0000001f0530018f000003b206300198000000400200043d0000000004620019000005390000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00000dd40000c13d000005390000013d000003b0033001970000001f0530018f000003b206300198000000400200043d0000000004620019000005390000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00000de10000c13d000005390000013d000003b0033001970000001f0530018f000003b206300198000000400200043d0000000004620019000005390000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00000dee0000c13d000005390000013d0000040b011001c700008009020000390000000603000029000000080400002900000000050000190ebb0eb10000040f00020000000103550000006003100270000003b00030019d000000010020019000000e380000613d0000000a01000029000003f20010009c000000420000213d0000000a01000029000000400010043f0000000001000414000003b00010009c000003b001008041000000c001100210000003b6011001c70000800d02000039000000030300003900000411040000410000000b0500002900000009060000290ebb0eb10000040f0000000100200190000005260000613d00000009010000290000000a020000290000021e0000013d000003f5011001c7000080090200003900000007030000290000000a0400002900000000050000190ebb0eb10000040f00020000000103550000006003100270000003b00030019d000000010020019000000e450000613d0000000401000029000003f20010009c000000420000213d0000000402000029000000400020043f00000009010000290000000000120435000003b00020009c000003b00200804100000040012002100000000002000414000003b00020009c000003b002008041000000c002200210000000000121019f000003fc011001c70000800d0200003900000004030000390000041a040000410000000005000411000000080600002900000006070000290ebb0eb10000040f0000000100200190000005260000613d0000085b0000013d000003b0033001970000001f0530018f000003b206300198000000400200043d0000000004620019000005390000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00000e400000c13d000005390000013d000003b0033001970000001f0530018f000003b206300198000000400200043d0000000004620019000005390000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00000e4d0000c13d000005390000013d000000000001004b00000e550000613d000000000001042d000000400100043d00000044021000390000042203000041000000000032043500000024021000390000000c03000039000000000032043500000421020000410000000000210435000000040210003900000020030000390000000000320435000003b00010009c000003b0010080410000004001100210000003f8011001c700000ebd00010430000000000001004b00000e750000613d000000000002004b00000e7e0000613d000000000003004b00000e7e0000613d00000000041300a900000000051400d9000000000035004b00000e780000c13d000000000012001a00000e780000413d000000000112001900000000011400d9000000000001042d000000400100043d000004270200004100000e800000013d0000041201000041000000000010043f0000001101000039000000040010043f000004050100004100000ebd00010430000000400100043d00000426020000410000000000210435000003b00010009c000003b0010080410000004001100210000003bc011001c700000ebd00010430000000000001042f0000000002000414000003b00020009c000003b002008041000000c002200210000003b00010009c000003b0010080410000004001100210000000000121019f000003ec011001c700008010020000390ebb0eb60000040f000000010020019000000e960000613d000000000101043b000000000001042d000000000100001900000ebd0001043000000000050100190000000000200443000000040100003900000005024002700000000002020031000000000121043a0000002004400039000000000031004b00000e9b0000413d000003b00030009c000003b00300804100000060013002100000000002000414000003b00020009c000003b002008041000000c002200210000000000112019f0000042a011001c700000000020500190ebb0eb60000040f000000010020019000000eb00000613d000000000101043b000000000001042d000000000001042f00000eb4002104210000000102000039000000000001042d0000000002000019000000000001042d00000eb9002104230000000102000039000000000001042d0000000002000019000000000001042d00000ebb0000043200000ebc0001042e00000ebd000104300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffff00000000000000000000000000000000000000000000000000000001ffffffe000000000000000000000000000000000000000000000000000000000ffffffe0000000000000000000000000000000000000000000000000fffffffffffffedf000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000008be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0000000000000000000000000000000000000000000000000002386f26fc0ffff00000000000000000000000000000000000000000000000000b1a2bc2ec5000000000000000000000000000000000000000000000000000000b1a2bc2ec50001fc5bee1200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000002000000000000000000000000000000c0000001000000000000000000bf7255a1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000084ba3f6800000000000000000000000000000000000000000000000000000000cf3cf57200000000000000000000000000000000000000000000000000000000eeb7f65900000000000000000000000000000000000000000000000000000000f2fde38a00000000000000000000000000000000000000000000000000000000f2fde38b00000000000000000000000000000000000000000000000000000000fe33b30200000000000000000000000000000000000000000000000000000000eeb7f65a00000000000000000000000000000000000000000000000000000000f0f4426000000000000000000000000000000000000000000000000000000000e4e57b9d00000000000000000000000000000000000000000000000000000000e4e57b9e00000000000000000000000000000000000000000000000000000000edf6de8800000000000000000000000000000000000000000000000000000000cf3cf57300000000000000000000000000000000000000000000000000000000d505cc4d0000000000000000000000000000000000000000000000000000000092c5cdbd00000000000000000000000000000000000000000000000000000000c6751dc500000000000000000000000000000000000000000000000000000000c6751dc600000000000000000000000000000000000000000000000000000000cec10c110000000000000000000000000000000000000000000000000000000092c5cdbe00000000000000000000000000000000000000000000000000000000b2db919b0000000000000000000000000000000000000000000000000000000084ba3f69000000000000000000000000000000000000000000000000000000008da5cb5b000000000000000000000000000000000000000000000000000000008daa46b600000000000000000000000000000000000000000000000000000000479266f30000000000000000000000000000000000000000000000000000000068a9415900000000000000000000000000000000000000000000000000000000768121bf00000000000000000000000000000000000000000000000000000000768121c0000000000000000000000000000000000000000000000000000000007a3c86400000000000000000000000000000000000000000000000000000000068a9415a00000000000000000000000000000000000000000000000000000000733140770000000000000000000000000000000000000000000000000000000059d0f7120000000000000000000000000000000000000000000000000000000059d0f7130000000000000000000000000000000000000000000000000000000061d027b300000000000000000000000000000000000000000000000000000000479266f40000000000000000000000000000000000000000000000000000000056f43352000000000000000000000000000000000000000000000000000000002947763a000000000000000000000000000000000000000000000000000000003c93aded000000000000000000000000000000000000000000000000000000003c93adee000000000000000000000000000000000000000000000000000000003fc8cef3000000000000000000000000000000000000000000000000000000002947763b000000000000000000000000000000000000000000000000000000002c1604ff000000000000000000000000000000000000000000000000000000000752881a0000000000000000000000000000000000000000000000000000000007fad3040000000000000000000000000000000000000000000000000000000028ff1d4c000000000000000000000000000000000000006000000080000000000000000000000000000000000000000000000000000000200000008000000000000000000200000000000000000000000000000000000040000000000000000000000000dbadf6bb000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000de0b6b3a76400001806aa1896bbf26568e884a7374b41e002500962caba6a15023a8d90e8508b830200000200000000000000000000000000000024000000000000000000000000e2e9336200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff02d05d3f00000000000000000000000000000000000000000000000000000000a512aee8000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000044000000000000000000000000000000000000000000000000000000000000004400000000000000000000000023b872dd000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000000000000001ffffffffffffffe0000000000000000000000000000000000000000000000003ffffffffffffffe0b12d13eb000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000020000000000000000000000000a8a7473f10e62cf9687e243de1c3ac8b3cbc3dd04b96826beb3a65b59538581400000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000004000000800000000000000000000000000000000000000000000000000000000000000000002386f26fc100000000000000000012725dd1d243aba0e75fe645cc4873f9e65afe688c928e1f210000000000000000000000000000000000000020000000e00000000000000000000000000000000000000000000000000000000000000000ffffffffffffff9f42966c68000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000000000000000000000310ab089e4439a4c15d089f94afb7896ff553aecb10793d0ab882de59d99a32e0200000200000000000000000000000000000044000000000000000000000000e6a4390500000000000000000000000000000000000000000000000000000000c9c6539600000000000000000000000000000000000000000000000000000000d0e30db0000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000004000000000000000000000000a9059cbb000000000000000000000000000000000000000000000000000000006a627842000000000000000000000000000000000000000000000000000000009bdd462500000000000000000000000000000000000000000000000000000000af35c6c7000000000000000000000000000000000000000000000000000000008e87728500000000000000000000000000000000000000000000000000000000ab3e0ae7b7d4c37d3539a4f3e3ac856a540af410acce171c797bbf88c1853b2d4e487b7100000000000000000000000000000000000000000000000000000000ab000f9b00000000000000000000000000000000000000000000000000000000c1ab6dc100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff7f000000000000000000000000000000000000000000000000ffffffffffffff7b01000253a046fa188365fd94c3c3f7136a82f1d54601750e381a096ebcc9f63c3cda33511d41a8a5431b1770c5bc0ddd62e1cd30555d16659b89c0d60f4f9f5713982e37000000000000000000000000000000000000000000000000000000009fa236593f411affe147142a606176190ea6b18be0643332f081175cfe608b6b05bc25a8000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000024000000000000000000000000d5f9bdf12adf29dab0248c349842c3822d53ae2bb4f36352f301630d018c8139000000000000000000000000000000000000004000000000000000000000000084272bd2000000000000000000000000000000000000000000000000000000005473c3930000000000000000000000000000000000000000000000000000000008c379a000000000000000000000000000000000000000000000000000000000554e415554484f52495a4544000000000000000000000000000000000000000000000000000000000000000000000000000000640000008000000000000000000000000000000000000000000000000000000004000000e00000000000000000e52970aa00000000000000000000000000000000000000000000000000000000bb55fd2700000000000000000000000000000000000000000000000000000000df5b2ee600000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0020000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001977934fc75ee57cb424863252d69bfdbdadab9f05c3628911d4c8e276ae2dd4

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

000000000000000000000000b9939862351af711b015ca5facdb557b5da65315000000000000000000000000b9939862351af711b015ca5facdb557b5da653150000000000000000000000003439153eb7af838ad19d56e1571fbd09333c2809000000000000000000000000566d7510dee58360a64c9827257cf6d0dc43985e0000000000000000000000000000000000000000000000001bc16d674ec80000000000000000000000000000000000000000000000000000f9ccd8a1c50800000000000000000000000000000000000000000000000000000001c6bf52634000000000000000000000000000000000000000000000000000002386f26fc1000000000000000000000000000000000000000000000000000000470de4df820000

-----Decoded View---------------
Arg [0] : factoryParams (tuple): System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput]

-----Encoded View---------------
9 Constructor Arguments found :
Arg [0] : 000000000000000000000000b9939862351af711b015ca5facdb557b5da65315
Arg [1] : 000000000000000000000000b9939862351af711b015ca5facdb557b5da65315
Arg [2] : 0000000000000000000000003439153eb7af838ad19d56e1571fbd09333c2809
Arg [3] : 000000000000000000000000566d7510dee58360a64c9827257cf6d0dc43985e
Arg [4] : 0000000000000000000000000000000000000000000000001bc16d674ec80000
Arg [5] : 000000000000000000000000000000000000000000000000f9ccd8a1c5080000
Arg [6] : 0000000000000000000000000000000000000000000000000001c6bf52634000
Arg [7] : 000000000000000000000000000000000000000000000000002386f26fc10000
Arg [8] : 00000000000000000000000000000000000000000000000000470de4df820000


Block Transaction Gas Used Reward
view all blocks produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
[ Download: CSV Export  ]
[ Download: CSV Export  ]

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