ETH Price: $1,623.76 (+4.51%)

Contract

0x4e97755CAa0e75959F62fCde57F544636Ad5cfb8

Overview

ETH Balance

6.43773476945843436 ETH

ETH Value

$10,453.31 (@ $1,623.76/ETH)

Token Holdings

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Collect ETH65637942025-04-12 17:04:5710 hrs ago1744477497IN
Vibe: Fee Handler
0 ETH0.000004120.04525
Collect ETH60300372025-04-06 7:03:316 days ago1743923011IN
Vibe: Fee Handler
0 ETH0.000003950.04525
Collect ETH60300072025-04-06 7:02:586 days ago1743922978IN
Vibe: Fee Handler
0 ETH0.000006040.04525
Collect ETH60120532025-04-06 1:45:567 days ago1743903956IN
Vibe: Fee Handler
0 ETH0.000003950.04525
Collect ETH60120222025-04-06 1:45:247 days ago1743903924IN
Vibe: Fee Handler
0 ETH0.000006040.04525
Collect ETH55653072025-03-31 17:32:0112 days ago1743442321IN
Vibe: Fee Handler
0 ETH0.000004120.04525
Collect ETH53375262025-03-29 0:19:2315 days ago1743207563IN
Vibe: Fee Handler
0 ETH0.00000480.04525
Collect ETH53252612025-03-28 20:43:4215 days ago1743194622IN
Vibe: Fee Handler
0 ETH0.000004120.04525
Collect ETH49997252025-03-24 23:51:4319 days ago1742860303IN
Vibe: Fee Handler
0 ETH0.000004190.04525
Collect ETH46615692025-03-20 22:48:5723 days ago1742510937IN
Vibe: Fee Handler
0 ETH0.000004020.04525
Collect ETH46615432025-03-20 22:48:3123 days ago1742510911IN
Vibe: Fee Handler
0 ETH0.000004870.04525
Collect ETH45585852025-03-19 16:54:2124 days ago1742403261IN
Vibe: Fee Handler
0 ETH0.000004880.04525
Collect ETH42174112025-03-15 16:26:3928 days ago1742055999IN
Vibe: Fee Handler
0 ETH0.000006190.04525
Collect ETH39796682025-03-12 21:08:2431 days ago1741813704IN
Vibe: Fee Handler
0 ETH0.000004190.04525
Collect ETH37748652025-03-10 11:02:4333 days ago1741604563IN
Vibe: Fee Handler
0 ETH0.000004190.04525
Collect ETH33621292025-03-05 14:22:3638 days ago1741184556IN
Vibe: Fee Handler
0 ETH0.000006140.04525
Collect ETH30933662025-03-02 9:17:4341 days ago1740907063IN
Vibe: Fee Handler
0 ETH0.000006130.04525
Collect ETH30496412025-03-01 20:59:5042 days ago1740862790IN
Vibe: Fee Handler
0 ETH0.000004190.04525
Collect ETH26839972025-02-25 13:20:1646 days ago1740489616IN
Vibe: Fee Handler
0 ETH0.000006480.04525
Collect ETH26674342025-02-25 8:39:0246 days ago1740472742IN
Vibe: Fee Handler
0 ETH0.000004190.04525
Collect ETH24511072025-02-22 19:37:0449 days ago1740253024IN
Vibe: Fee Handler
0 ETH0.000005770.04525
Collect ETH23327312025-02-21 10:09:3550 days ago1740132575IN
Vibe: Fee Handler
0 ETH0.000005920.04525
Collect ETH23327182025-02-21 10:09:2250 days ago1740132562IN
Vibe: Fee Handler
0 ETH0.000005920.04525
Collect ETH23327132025-02-21 10:09:1750 days ago1740132557IN
Vibe: Fee Handler
0 ETH0.000006470.04525
Collect ETH23010532025-02-21 1:11:5951 days ago1740100319IN
Vibe: Fee Handler
0 ETH0.000006160.04525
View all transactions

Latest 25 internal transactions (View All)

Parent Transaction Hash Block From To
65993652025-04-13 3:19:0115 mins ago1744514341
Vibe: Fee Handler
0.0000594 ETH
65734922025-04-12 19:56:587 hrs ago1744487818
Vibe: Fee Handler
0.000004 ETH
65690752025-04-12 18:37:148 hrs ago1744483034
Vibe: Fee Handler
0.000001 ETH
65689032025-04-12 18:34:019 hrs ago1744482841
Vibe: Fee Handler
0.000001 ETH
65671682025-04-12 18:03:349 hrs ago1744481014
Vibe: Fee Handler
0 ETH
65637942025-04-12 17:04:5710 hrs ago1744477497
Vibe: Fee Handler
0.00021461 ETH
65637642025-04-12 17:04:2710 hrs ago1744477467
Vibe: Fee Handler
0.00006 ETH
65636002025-04-12 17:01:4310 hrs ago1744477303
Vibe: Fee Handler
0.00009899 ETH
65635812025-04-12 17:01:2410 hrs ago1744477284
Vibe: Fee Handler
0.00006929 ETH
65607252025-04-12 16:12:0311 hrs ago1744474323
Vibe: Fee Handler
0.00001979 ETH
65607042025-04-12 16:11:4211 hrs ago1744474302
Vibe: Fee Handler
0.00002 ETH
65606702025-04-12 16:11:0811 hrs ago1744474268
Vibe: Fee Handler
0.00000742 ETH
65606502025-04-12 16:10:4811 hrs ago1744474248
Vibe: Fee Handler
0.00001 ETH
65606072025-04-12 16:10:0511 hrs ago1744474205
Vibe: Fee Handler
0.0005 ETH
65592262025-04-12 15:46:1611 hrs ago1744472776
Vibe: Fee Handler
0.0005 ETH
65538172025-04-12 14:12:0913 hrs ago1744467129
Vibe: Fee Handler
0.00007 ETH
65537932025-04-12 14:11:3213 hrs ago1744467092
Vibe: Fee Handler
0.0001 ETH
65521542025-04-12 13:43:5013 hrs ago1744465430
Vibe: Fee Handler
0.0000004 ETH
65520942025-04-12 13:42:5013 hrs ago1744465370
Vibe: Fee Handler
0.000001 ETH
65520712025-04-12 13:42:2713 hrs ago1744465347
Vibe: Fee Handler
0.000001 ETH
65441412025-04-12 11:27:2416 hrs ago1744457244
Vibe: Fee Handler
0.00004949 ETH
65441212025-04-12 11:27:0416 hrs ago1744457224
Vibe: Fee Handler
0.00010889 ETH
65422992025-04-12 10:56:0016 hrs ago1744455360
Vibe: Fee Handler
0.00001286 ETH
65422772025-04-12 10:55:3816 hrs ago1744455338
Vibe: Fee Handler
0.000013 ETH
65422042025-04-12 10:54:2516 hrs ago1744455265
Vibe: Fee Handler
0.0005 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
FeeHandler

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 : 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 2 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 3 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 4 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 5 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 6 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 7 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 8 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 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":[{"internalType":"address","name":"_factory","type":"address"},{"components":[{"internalType":"bool","name":"lotteryEnabled","type":"bool"},{"internalType":"uint256","name":"jackpotProbability","type":"uint256"},{"internalType":"uint256","name":"minimumJackpotAmount","type":"uint256"},{"internalType":"uint256","name":"feeTicketPrice","type":"uint256"},{"internalType":"uint256","name":"directTicketPrice","type":"uint256"},{"internalType":"uint256","name":"forceAwardJackpotBuffer","type":"uint256"}],"internalType":"struct IFeeHandler.JackpotConfig","name":"_jackpotConfig","type":"tuple"},{"components":[{"internalType":"uint256","name":"createFeeToPot","type":"uint256"},{"internalType":"uint256","name":"tradingFeeToPot","type":"uint256"},{"internalType":"uint256","name":"launchFeeToPot","type":"uint256"},{"internalType":"uint256","name":"buyTicketToPot","type":"uint256"},{"internalType":"uint256","name":"tradingFeeToCreator","type":"uint256"}],"internalType":"struct IFeeHandler.FeeConfig","name":"_feeConfig","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AdminRandomnessMismatch","type":"error"},{"inputs":[],"name":"AlreadyCommited","type":"error"},{"inputs":[],"name":"AwardJackpotBufferTooLarge","type":"error"},{"inputs":[],"name":"DirectTicketPriceTooLow","type":"error"},{"inputs":[],"name":"ETHTransferFailed","type":"error"},{"inputs":[],"name":"FeeTooHigh","type":"error"},{"inputs":[],"name":"InvalidJackpotConfig","type":"error"},{"inputs":[],"name":"JackpotAlreadyAwarded","type":"error"},{"inputs":[],"name":"JackpotLocked","type":"error"},{"inputs":[],"name":"JackpotNotLocked","type":"error"},{"inputs":[],"name":"JackpotProbabilityTooHigh","type":"error"},{"inputs":[],"name":"LotteryDisabled","type":"error"},{"inputs":[],"name":"NotFactory","type":"error"},{"inputs":[],"name":"NotFactoryOwner","type":"error"},{"inputs":[],"name":"TooEarly","type":"error"},{"inputs":[],"name":"ValueBelowTicketPrice","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"jackpotId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"ethAmount","type":"uint256"}],"name":"JackpotDonated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"jackpotId","type":"uint256"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"ethAmount","type":"uint256"}],"name":"JackpotWon","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"jackpotId","type":"uint256"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"noOfTicketsAdded","type":"uint256"}],"name":"TicketAdded","type":"event"},{"inputs":[],"name":"MAX_FORCE_AWARD_JACKPOT_BUFFER","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_JACKPOT_PROBABILITY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"accruedETH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"jackpotId","type":"uint256"},{"internalType":"bytes32","name":"adminEntropy","type":"bytes32"}],"name":"awardJackpot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"buyTickets","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"collectETH","outputs":[{"internalType":"uint256","name":"ethReceived","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"jackpotId","type":"uint256"},{"internalType":"bytes32","name":"adminEntropyHash","type":"bytes32"}],"name":"commitAdminEntropy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"jackpotId","type":"uint256"}],"name":"commitCrowdEntropy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"currentJackpotSize","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"donateToPot","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"factoryOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeConfig","outputs":[{"internalType":"uint256","name":"createFeeToPot","type":"uint256"},{"internalType":"uint256","name":"tradingFeeToPot","type":"uint256"},{"internalType":"uint256","name":"launchFeeToPot","type":"uint256"},{"internalType":"uint256","name":"buyTicketToPot","type":"uint256"},{"internalType":"uint256","name":"tradingFeeToCreator","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"jackpotId","type":"uint256"}],"name":"forceAwardJackpot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"handleCreateFee","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"handleLaunchFee","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"tokenCreator","type":"address"}],"name":"handleTradingFee","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"jackpotConfig","outputs":[{"internalType":"bool","name":"lotteryEnabled","type":"bool"},{"internalType":"uint256","name":"jackpotProbability","type":"uint256"},{"internalType":"uint256","name":"minimumJackpotAmount","type":"uint256"},{"internalType":"uint256","name":"feeTicketPrice","type":"uint256"},{"internalType":"uint256","name":"directTicketPrice","type":"uint256"},{"internalType":"uint256","name":"forceAwardJackpotBuffer","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"jackpotStateById","outputs":[{"internalType":"uint256","name":"nextTicketId","type":"uint256"},{"internalType":"uint256","name":"pot","type":"uint256"},{"internalType":"bytes32","name":"adminEntropyHash","type":"bytes32"},{"internalType":"bytes32","name":"crowdEntropy","type":"bytes32"},{"internalType":"uint256","name":"lockedBlockNumber","type":"uint256"},{"internalType":"uint256","name":"lockedTimestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastRolledBlockNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextJackpotId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rollJackpot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"createFeeToPot","type":"uint256"},{"internalType":"uint256","name":"tradingFeeToPot","type":"uint256"},{"internalType":"uint256","name":"launchFeeToPot","type":"uint256"},{"internalType":"uint256","name":"buyTicketToPot","type":"uint256"},{"internalType":"uint256","name":"tradingFeeToCreator","type":"uint256"}],"internalType":"struct IFeeHandler.FeeConfig","name":"config","type":"tuple"}],"name":"setFeeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bool","name":"lotteryEnabled","type":"bool"},{"internalType":"uint256","name":"jackpotProbability","type":"uint256"},{"internalType":"uint256","name":"minimumJackpotAmount","type":"uint256"},{"internalType":"uint256","name":"feeTicketPrice","type":"uint256"},{"internalType":"uint256","name":"directTicketPrice","type":"uint256"},{"internalType":"uint256","name":"forceAwardJackpotBuffer","type":"uint256"}],"internalType":"struct IFeeHandler.JackpotConfig","name":"config","type":"tuple"}],"name":"setJackpotConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"jackpotId","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"ticketFromIndex","outputs":[{"components":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"firstTicketId","type":"uint256"}],"internalType":"struct IFeeHandler.Ticket","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"jackpotId","type":"uint256"}],"name":"ticketQueueLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"treasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

9c4d535b000000000000000000000000000000000000000000000000000000000000000001000359f332a2bb24caefb91ccd99ff2cc02c72ddc303c61080994e0be417d3000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001800000000000000000000000005606cd69b61bd6ed0fd9adacd56188d9d6f576450000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000002386f26fc100000000000000000000000000000000000000000000000000003a4965bf58a400000000000000000000000000000000000000000000000000000011c37937e08000000000000000000000000000000000000000000000000000001550f7dca70000000000000000000000000000000000000000000000000000000000000000025800000000000000000000000000000000000000000000000002c68af0bb140000000000000000000000000000000000000000000000000000016345785d8a000000000000000000000000000000000000000000000000000000b1a2bc2ec500000000000000000000000000000000000000000000000000000214e8348c4f00000000000000000000000000000000000000000000000000000058d15e17628000

Deployed Bytecode

0x000200000000000200070000000000020000006003100270000002f10330019700010000003103550000000100200190000000200000c13d0000008002000039000000400020043f000000040030008c000000430000413d000000000201043b000000e002200270000003020020009c000000450000a13d000003030020009c0000005c0000213d0000030d0020009c0000018e0000a13d0000030e0020009c0000024a0000213d000003110020009c000002860000613d000003120020009c000000430000c13d0000000001000416000000000001004b000000430000c13d0000033c01000041000000800010043f0000032c0100004100000bc10001042e0000000002000416000000000002004b000000430000c13d0000001f02300039000002f202200197000000a002200039000000400020043f0000001f0430018f000002f305300198000000a002500039000000310000613d000000a006000039000000000701034f000000007807043c0000000006860436000000000026004b0000002d0000c13d000000000004004b0000003e0000613d000000000151034f0000000304400210000000000502043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f0000000000120435000001800030008c000000430000413d000000a00100043d000002f40010009c000001070000a13d000000000100001900000bc200010430000003160020009c000001100000a13d000003170020009c000001c40000a13d000003180020009c0000025f0000213d0000031b0020009c000002eb0000613d0000031c0020009c000000430000c13d0000000001000416000000000001004b000000430000c13d0000000c01000039000000000101041a000000000010043f0000000d01000039000000200010043f000000400200003900000000010000190bc00b830000040f0000000201100039000004070000013d000003040020009c000001f20000a13d000003050020009c000002680000213d000003080020009c0000030f0000613d000003090020009c000000430000c13d0000000001000416000000000001004b000000430000c13d0000032d0100004100000000001004430000000001000412000000040010044300000024000004430000000001000414000002f10010009c000002f101008041000000c0011002100000032e011001c700008005020000390bc00bbb0000040f00000001002001900000075d0000613d000000000101043b000002f4011001970000000002000411000000000012004b000004e30000c13d000000000100041a000000ff00100190000001f00000613d0000000b01000039000000000101041a000500000001001d0000032f0100004100000000001004430000000001000414000002f10010009c000002f101008041000000c00110021000000330011001c70000800b020000390bc00bbb0000040f00000001002001900000075d0000613d000000000101043b000400000001001d000000050010006c000001f00000613d00000004010000290000000b02000039000000000012041b0000000c01000039000000000101041a000500000001001d000000000010043f0000000d01000039000000200010043f0000000001000414000002f10010009c000002f101008041000000c00110021000000327011001c700008010020000390bc00bbb0000040f0000000100200190000000430000613d000000000101043b000300000001001d000000000101041a000000000001004b000001f00000613d0000000201000039000000000101041a00000003020000290000000202200039000000000202041a000000000012004b000001f00000413d00000003010000290000000301100039000000000101041a000000000001004b000001f00000613d000000040000006b000005ea0000613d000000400100043d000200000001001d00000020021000390000000501000029000100000002001d0000000000120435000003310100004100000000001004430000000401000029000000010110008a00000004001004430000000001000414000002f10010009c000002f101008041000000c00110021000000332011001c70000800b020000390bc00bbb0000040f00000001002001900000075d0000613d000000000101043b00000002030000290000004002300039000000000012043500000040010000390000000000130435000003330030009c0000010a0000213d00000002020000290000006001200039000000400010043f0000000101000029000002f10010009c000002f10100804100000040011002100000000002020433000002f10020009c000002f1020080410000006002200210000000000112019f0000000002000414000002f10020009c000002f102008041000000c002200210000000000112019f00000328011001c700008010020000390bc00bbb0000040f0000000100200190000000430000613d0000000102000039000000000202041a000000000101043b000002fe1010012a000000000021004b000001f00000813d000000030100002900000005011000390000000402000029000000000021041b000003340100004100000000001004430000000001000414000002f10010009c000002f101008041000000c00110021000000330011001c70000800b020000390bc00bbb0000040f00000001002001900000075d0000613d000000000101043b00000003020000290000000602200039000000000012041b0000000c01000039000000000101041a000000010110003a000005ea0000613d0000000c02000039000000000012041b000000000100001900000bc10001042e000000400700043d000002f50070009c0000011d0000a13d0000034901000041000000000010043f0000004101000039000000040010043f0000034a0100004100000bc200010430000003200020009c000002180000213d000003240020009c000003440000613d000003250020009c000003690000613d000003260020009c000000430000c13d0000000001000416000000000001004b000000430000c13d0000000b01000039000004070000013d000000c002700039000000400020043f000000c00200043d000000000002004b0000000003000039000000010300c039000000000032004b000000430000c13d000000000a270436000000e00200043d00000000002a0435000000400c700039000001000200043d00000000002c0435000000600b700039000001200200043d00000000002b04350000008008700039000001400200043d0000000000280435000000a009700039000001600200043d0000000000290435000000400200043d000002f60020009c0000010a0000213d000000a003200039000000400030043f000001800300043d0000000005320436000001a00300043d00000000003504350000004004200039000001c00300043d00000000003404350000006003200039000001e00600043d00000000006304350000008006200039000002000d00043d0000000000d60435000000800010043f000000000a0a04330000000007070433000000000007004b000004e60000c13d00000000000a004b000004f10000c13d000000000a0c043300000000000a004b000004f10000c13d000000000a0b043300000000000a004b000004f10000c13d0000000008080433000000000008004b000004f10000c13d0000000008090433000000000008004b00000000090000190000000008000019000000000b000019000000000c000019000000000a000019000004f10000c13d000000000e00041a0000034c0de00197000000000007004b000000010dd0c1bf0000000000d0041b00000001070000390000000000a7041b000000020a0000390000000000ca041b000000030a0000390000000000ba041b000000040a00003900000000008a041b0000000508000039000000000098041b00000000060604330000000005050433000000000065001a000005ea0000413d0000000008650019000002fe0080009c0000077e0000213d0000000002020433000002fe0020009c0000077e0000213d0000000004040433000002fe0040009c0000077e0000213d0000000003030433000002ff0030009c0000077e0000813d0000000608000039000000000028041b0000000702000039000000000052041b0000000802000039000000000042041b0000000902000039000000000032041b0000000a02000039000000000062041b00000140000004430000016000100443000000200100003900000100001004430000012000700443000003000100004100000bc10001042e000003130020009c000003f90000613d000003140020009c0000040b0000613d000003150020009c000000430000c13d000000a40030008c000000430000413d0000000002000416000000000002004b000000430000c13d0000012002000039000000400020043f0000000402100370000000000202043b000000800020043f0000002402100370000000000202043b000000a00020043f0000004402100370000000000202043b000000c00020043f0000006402100370000000000202043b000000e00020043f0000008401100370000000000101043b000001000010043f0000033d01000041000001200010043f0000032d0100004100000000001004430000000001000412000000040010044300000024000004430000000001000414000002f10010009c000002f101008041000000c0011002100000032e011001c700008005020000390bc00bbb0000040f00000001002001900000075d0000613d000000000201043b0000000001000414000002f402200197000000040020008c000005000000c13d0000000003000031000000200030008c00000020040000390000000004034019000005250000013d0000031d0020009c0000043f0000613d0000031e0020009c000003a40000613d0000031f0020009c000000430000c13d000000000100041a000000ff001001900000047a0000613d0000000c01000039000000000101041a000500000001001d000000000010043f0000000d01000039000000200010043f0000000001000414000002f10010009c000002f101008041000000c00110021000000327011001c700008010020000390bc00bbb0000040f0000000100200190000000430000613d000000000101043b0000000201100039000000000201041a0000000006000416000000000062001a000005ea0000413d0000000002620019000000000021041b0000000001000414000002f10010009c000002f101008041000000c00110021000000328011001c70000800d020000390000000303000039000003420400004100000005050000290bc00bb60000040f0000000100200190000000430000613d000000000100001900000bc10001042e0000030a0020009c000004770000613d0000030b0020009c0000047e0000613d0000030c0020009c000000430000c13d000000240030008c000000430000413d0000000002000416000000000002004b000000430000c13d0000000401100370000000000101043b000000000010043f0000000d01000039000000200010043f000000400200003900000000010000190bc00b830000040f0000000602100039000000000202041a0000000503100039000000000303041a0000000404100039000000000404041a0000000305100039000000000505041a0000000206100039000000000606041a000000000101041a000000800010043f000000a00060043f000000c00050043f000000e00040043f000001000030043f000001200020043f000003360100004100000bc10001042e000003210020009c000003a90000613d000003220020009c000003b00000613d000003230020009c000000430000c13d000000440030008c000000430000413d0000000002000416000000000002004b000000430000c13d000000c002000039000000400020043f000000800000043f000000a00000043f0000000402100370000000000202043b000000000020043f0000000d02000039000000200020043f0000002401100370000000000101043b000500000001001d000000400200003900000000010000190bc00b830000040f000000010110003900000005020000290bc008e60000040f000500000001001d000000400100043d000400000001001d0bc008d00000040f0000000503000029000000000103041a000002f401100197000000040200002900000000021204360000000103300039000000000303041a0000000000320435000000400300043d000000000113043600000000020204330000000000210435000002f10030009c000002f103008041000000400130021000000345011001c700000bc10001042e0000030f0020009c000003c40000613d000003100020009c000000430000c13d0000000001000416000000000001004b000000430000c13d0000000001000412000700000001001d000600000000003d000080050100003900000044030000390000000004000415000000070440008a00000005044002100000032d020000410bc00b980000040f000002f401100197000000800010043f0000032c0100004100000bc10001042e000003190020009c000003dd0000613d0000031a0020009c000000430000c13d0000000001000416000000000001004b000000430000c13d0000000c01000039000004070000013d000003060020009c000003e90000613d000003070020009c000000430000c13d0000000001000416000000000001004b000000430000c13d0000000001000411000000000010043f0000000e01000039000000200010043f0000000001000414000002f10010009c000002f101008041000000c00110021000000327011001c700008010020000390bc00bbb0000040f0000000100200190000000430000613d000000000101043b000000000301041a000000000001041b00000000010004140000000004000411000000040040008c000005950000c13d000000010200003900000000010000310000066d0000013d000000440030008c000000430000413d0000000402100370000000000202043b000500000002001d000002f40020009c000000430000213d0000002401100370000000000101043b000400000001001d000002f40010009c000000430000213d0000032d0100004100000000001004430000000001000412000000040010044300000024000004430000000001000414000002f10010009c000002f101008041000000c0011002100000032e011001c700008005020000390bc00bbb0000040f00000001002001900000075d0000613d000000000101043b000002f4011001970000000002000411000000000012004b000004e30000c13d0000000001000416000200000001001d0000000a01000039000000000101041a000300000001001d000000000001004b000002b10000613d000000010100008a00000003011000fa0000000002000416000000000012004b000000430000213d0000000401000029000002f401100197000000000010043f0000000e01000039000000200010043f0000000001000414000002f10010009c000002f101008041000000c00110021000000327011001c700008010020000390bc00bbb0000040f0000000100200190000000430000613d000000000200041600000003022000b9000002fe0320012a000000000101043b000000000201041a000000000032001a000005ea0000413d000400000003001d0000000002320019000000000021041b000000000100041a000000ff00100190000007d20000c13d00000004020000290004000200200073000005ea0000413d000000400200043d0000033901000041000500000002001d00000000001204350000032d0100004100000000001004430000000001000412000000040010044300000024000004430000000001000414000002f10010009c000002f101008041000000c0011002100000032e011001c700008005020000390bc00bbb0000040f00000001002001900000075d0000613d000000000201043b0000000001000414000002f402200197000000040020008c0000086a0000c13d0000000003000031000000200030008c00000020040000390000000004034019000008940000013d000000240030008c000000430000413d0000000002000416000000000002004b000000430000c13d0000000401100370000000000201043b0000000c01000039000000000101041a000000000012004b000004d50000813d000500000002001d000000000020043f0000000d01000039000000200010043f0000000001000414000002f10010009c000002f101008041000000c00110021000000327011001c700008010020000390bc00bbb0000040f0000000100200190000000430000613d000000000101043b0000000402100039000000000102041a000000000001004b000005f00000c13d0000000501000029000500000002001d0bc00a690000040f0000000502000029000000000012041b000000000100001900000bc10001042e000000240030008c000000430000413d0000000002000416000000000002004b000000430000c13d0000000401100370000000000201043b0000000c01000039000000000101041a000000000012004b000004d50000813d000500000002001d000000000020043f0000000d01000039000000200010043f0000000001000414000002f10010009c000002f101008041000000c00110021000000327011001c700008010020000390bc00bbb0000040f0000000100200190000000430000613d0000000502000039000000000202041a000000000101043b000200000001001d0000000601100039000000000101041a000400000002001d000300000001001d000000000012001a000005ea0000413d000003340100004100000000001004430000000001000414000002f10010009c000002f101008041000000c00110021000000330011001c70000800b020000390bc00bbb0000040f00000001002001900000075d0000613d00000003030000290000000402300029000000000101043b000000000021004b000007250000813d000000400100043d0000033502000041000004f30000013d000000440030008c000000430000413d0000000002000416000000000002004b000000430000c13d0000002402100370000000000202043b000400000002001d0000000401100370000000000101043b000500000001001d0000033d01000041000000800010043f0000032d0100004100000000001004430000000001000412000000040010044300000024000004430000000001000414000002f10010009c000002f101008041000000c0011002100000032e011001c700008005020000390bc00bbb0000040f00000001002001900000075d0000613d000000000201043b0000000001000414000002f402200197000000040020008c0000054d0000c13d0000000003000031000000200030008c00000020040000390000000004034019000005720000013d000000240030008c000000430000413d0000000401100370000000000101043b000500000001001d000002f40010009c000000430000213d0000032d0100004100000000001004430000000001000412000000040010044300000024000004430000000001000414000002f10010009c000002f101008041000000c0011002100000032e011001c700008005020000390bc00bbb0000040f00000001002001900000075d0000613d000000000101043b000002f4011001970000000002000411000000000012004b000004e30000c13d0000000003000416000000000100041a000000ff00100190000006f60000c13d000400000003001d000000400200043d0000033901000041000500000002001d00000000001204350000032d0100004100000000001004430000000001000412000000040010044300000024000004430000000001000414000002f10010009c000002f101008041000000c0011002100000032e011001c700008005020000390bc00bbb0000040f00000001002001900000075d0000613d000000000201043b0000000001000414000002f402200197000000040020008c000007890000c13d0000000003000031000000200030008c00000020040000390000000004034019000007b30000013d0000000001000416000000000001004b000000430000c13d0bc009020000040f000003e10000013d0000000001000416000000000001004b000000430000c13d0000034701000041000000800010043f0000032c0100004100000bc10001042e0000000001000416000000000001004b000000430000c13d0000000a01000039000000000101041a0000000902000039000000000202041a0000000803000039000000000303041a0000000704000039000000000404041a0000000605000039000000000505041a000000800050043f000000a00040043f000000c00030043f000000e00020043f000001000010043f000003460100004100000bc10001042e0000000001000416000000000001004b000000430000c13d0000000501000039000000000101041a0000000402000039000000000202041a0000000303000039000000000303041a0000000204000039000000000404041a0000000105000039000000000505041a000000000600041a000000ff006001900000000006000039000000010600c039000000800060043f000000a00050043f000000c00040043f000000e00030043f000001000020043f000001200010043f000003360100004100000bc10001042e0000000001000416000000000001004b000000430000c13d0bc009830000040f000002f401100197000000400200043d0000000000120435000002f10020009c000002f10200804100000040012002100000032b011001c700000bc10001042e000000240030008c000000430000413d0000000002000416000000000002004b000000430000c13d0000000401100370000000000101043b000002f40010009c000000430000213d000000000010043f0000000e01000039000000200010043f000000400200003900000000010000190bc00b830000040f000004070000013d000000240030008c000000430000413d0000000002000416000000000002004b000000430000c13d0000000401100370000000000101043b000000000010043f0000000d01000039000000200010043f000000400200003900000000010000190bc00b830000040f0000000101100039000000000101041a000000800010043f0000032c0100004100000bc10001042e0000032d0100004100000000001004430000000001000412000000040010044300000024000004430000000001000414000002f10010009c000002f101008041000000c0011002100000032e011001c700008005020000390bc00bbb0000040f00000001002001900000075d0000613d000000000101043b000002f4011001970000000002000411000000000012004b000004e30000c13d0000000002000416000000000100041a000000ff001001900000059d0000c13d000400000002001d0000000003000412000000400200043d0000033901000041000500000002001d00000000001204350000032d010000410000000000100443000000040030044300000024000004430000000001000414000002f10010009c000002f101008041000000c0011002100000032e011001c700008005020000390bc00bbb0000040f00000001002001900000075d0000613d000000000201043b0000000001000414000002f402200197000000040020008c000006a60000c13d0000000003000031000000200030008c00000020040000390000000004034019000006d00000013d000000c40030008c000000430000413d0000000002000416000000000002004b000000430000c13d0000014002000039000000400020043f0000000402100370000000000202043b000000000002004b0000000003000039000000010300c039000000000032004b000000430000c13d000000800020043f0000002402100370000000000202043b000000a00020043f0000004402100370000000000202043b000000c00020043f0000006402100370000000000202043b000000e00020043f0000008402100370000000000202043b000001000020043f000000a401100370000000000101043b000001200010043f0000033d01000041000001400010043f0000032d0100004100000000001004430000000001000412000000040010044300000024000004430000000001000414000002f10010009c000002f101008041000000c0011002100000032e011001c700008005020000390bc00bbb0000040f00000001002001900000075d0000613d000000000201043b0000000001000414000002f402200197000000040020008c0000060b0000c13d0000000003000031000000200030008c00000020040000390000000004034019000006300000013d000000000100041a000000ff00100190000004d90000c13d0000034301000041000000800010043f0000033b0100004100000bc200010430000000440030008c000000430000413d0000000002000416000000000002004b000000430000c13d0000002402100370000000000302043b0000000401100370000000000201043b0000000c01000039000000000101041a000000000012004b000004d50000813d000500000003001d000400000002001d000000000020043f0000000d01000039000000200010043f0000000001000414000002f10010009c000002f101008041000000c00110021000000327011001c700008010020000390bc00bbb0000040f0000000100200190000000430000613d000000000401043b000000400100043d0000002002000039000000000221043600000005030000290000000000320435000003370010009c0000010a0000213d000300000004001d0000004003100039000000400030043f000002f10020009c000002f10200804100000040022002100000000001010433000002f10010009c000002f1010080410000006001100210000000000121019f0000000002000414000002f10020009c000002f102008041000000c002200210000000000112019f00000328011001c700008010020000390bc00bbb0000040f0000000100200190000000430000613d000000000101043b00000003030000290000000302300039000000000202041a000000000021004b000007810000c13d00000004010000290bc00a690000040f00000003020000290000000402200039000000000012041b000000400400043d000300000004001d00000040024000390000000503000029000000000032043500000040020000390000000002240436000500000002001d000000000012043500000000010400190bc008db0000040f0000000301000029000000000201043300000005010000290bc00b830000040f000000000201001900000004010000290bc00ae70000040f000000000100001900000bc10001042e0000034001000041000000800010043f0000033b0100004100000bc2000104300000000401000039000000000101041a000000000001004b000004f90000c13d0000034901000041000000000010043f0000001201000039000000040010043f0000034a0100004100000bc200010430000000400100043d0000034802000041000004f30000013d00000000000a004b000004f10000613d000000000c0c043300000000000c004b000004f10000613d000000000b0b043300000000000b004b000004f10000613d0000000009090433000000000009004b0000073b0000c13d000000400100043d000002fd020000410000000000210435000002f10010009c000002f1010080410000004001100210000002fa011001c700000bc2000104300000000002000416000000000021004b000005c30000a13d0000033a01000041000000800010043f0000033b0100004100000bc200010430000002f10010009c000002f101008041000000c0011002100000033e011001c70bc00bbb0000040f0000006003100270000002f103300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000012005700039000001200a000039000005140000613d000000000801034f000000008908043c000000000a9a043600000000005a004b000005100000c13d000000000006004b000005210000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00010000000103550000000100200190000005f30000613d0000001f01400039000000600110018f0000012001100039000000400010043f000000200030008c000000430000413d000001200200043d000002f40020009c000000430000213d0000000003000411000000000023004b000006a40000c13d000001000200043d000000a00300043d000000000023001a000005ea0000413d0000000004230019000002fe0040009c0000075e0000213d000000800400043d000002fe0040009c0000075e0000213d000000c00500043d000002fe0050009c0000075e0000213d000000e00600043d000002ff0060009c0000075e0000813d0000000601000039000000000041041b0000000701000039000000000031041b0000000801000039000000000051041b0000000901000039000000000061041b0000000a01000039000000000021041b000000000100001900000bc10001042e000002f10010009c000002f101008041000000c0011002100000033b011001c70bc00bbb0000040f0000006003100270000002f103300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000080057001bf000000800a000039000005610000613d000000000801034f000000008908043c000000000a9a043600000000005a004b0000055d0000c13d000000000006004b0000056e0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00010000000103550000000100200190000005ff0000613d0000001f01400039000000600110018f00000080011001bf000000400010043f000000200030008c000000430000413d000000800200043d000002f40020009c000000430000213d0000000003000411000000000023004b000006a40000c13d0000000501000029000000000010043f0000000d01000039000000200010043f0000000001000414000002f10010009c000002f101008041000000c00110021000000327011001c700008010020000390bc00bbb0000040f0000000100200190000000430000613d000000000101043b0000000502100039000000000202041a000000000002004b000007cf0000c13d00000003011000390000000402000029000000000021041b000000000100001900000bc10001042e000002f10010009c000002f101008041000000c001100210000000000003004b000500000003001d000006640000c13d0000000002040019000006670000013d0000000801000039000000000101041a000500000001001d000000000001004b000005a70000613d000000010100008a00000005011000fa0000000002000416000000000021004b000000430000413d0000000c01000039000000000101041a000000000010043f0000000d01000039000000200010043f0000000001000414000002f10010009c000002f101008041000000c00110021000000327011001c700008010020000390bc00bbb0000040f0000000100200190000000430000613d000000000400041600000005024000b9000002fe0220012a000000000101043b0000000201100039000000000301041a000000000023001a000005ea0000413d0000000003230019000000000031041b000000000424004b000005ea0000413d000400000004001d000004230000013d00000000021200d900000000010004110bc00a040000040f0000000901000039000000000101041a000500000001001d000000000001004b000005d00000613d000000010100008a00000005011000fa0000000002000416000000000021004b000000430000413d0000000c01000039000000000101041a000000000010043f0000000d01000039000000200010043f0000000001000414000002f10010009c000002f101008041000000c00110021000000327011001c700008010020000390bc00bbb0000040f0000000100200190000000430000613d000000000400041600000005024000b9000002fe0220012a000000000101043b0000000201100039000000000301041a000000000023001a000005ea0000413d0000000003230019000000000031041b000000000124004b000007400000813d0000034901000041000000000010043f0000001101000039000000040010043f0000034a0100004100000bc200010430000000400100043d0000034102000041000004f30000013d0000001f0530018f000002f306300198000000400200043d00000000046200190000076b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000005fa0000c13d0000076b0000013d0000001f0530018f000002f306300198000000400200043d00000000046200190000076b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000006060000c13d0000076b0000013d000002f10010009c000002f101008041000000c00110021000000344011001c70bc00bbb0000040f0000006003100270000002f103300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000140057001bf000001400a0000390000061f0000613d000000000801034f000000008908043c000000000a9a043600000000005a004b0000061b0000c13d000000000006004b0000062c0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000100000001035500000001002001900000072f0000613d0000001f01400039000000600110018f0000014001100039000000400010043f000000200030008c000000430000413d000001400200043d000002f40020009c000000430000213d0000000003000411000000000023004b000006a40000c13d000000a00300043d000000800200043d000000000002004b000008020000c13d000000000003004b0000080d0000c13d000000c00300043d000000000003004b0000080d0000c13d000000e00300043d000000000003004b0000080d0000c13d000001000300043d000000000003004b0000080d0000c13d000001200300043d000000000003004b000000000500001900000000070000190000000006000019000000000400001900000000030000190000080d0000c13d000000000800041a0000034c01800197000000000002004b000000010110c1bf000000000010041b0000000101000039000000000031041b0000000201000039000000000041041b0000000301000039000000000061041b0000000401000039000000000071041b0000000501000039000000000051041b000000000100001900000bc10001042e00000328011001c7000080090200003900000000050000190bc00bb60000040f000000050300002900010000000103550000006001100270000002f10010019d000002f101100197000000000001004b000006790000c13d000000400100043d000002f10010009c000002f104000041000000000401401900000040044002100000000100200190000006a00000613d00000000003104350000032b014001c700000bc10001042e0000001f041000390000034d044001970000003f044000390000034d05400197000000400400043d0000000005540019000000000045004b00000000060000390000000106004039000003290050009c0000010a0000213d00000001006001900000010a0000c13d000000400050043f00000000061404360000034d091001980000001f0410018f00000000019600190000000105000367000006920000613d000000000705034f000000007807043c0000000006860436000000000016004b0000068e0000c13d000000000004004b0000066f0000613d000000000695034f0000000304400210000000000501043300000000054501cf000000000545022f000000000606043b0000010004400089000000000646022f00000000044601cf000000000454019f00000000004104350000066f0000013d0000032a020000410000000000210435000002fa014001c700000bc2000104300000033f020000410000080e0000013d0000000503000029000002f10030009c000002f1030080410000004003300210000002f10010009c000002f101008041000000c001100210000000000131019f000002fa011001c70bc00bbb0000040f0000006003100270000002f103300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000505700029000006bf0000613d000000000801034f0000000509000029000000008a08043c0000000009a90436000000000059004b000006bb0000c13d000000000006004b000006cc0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00010000000103550000000100200190000007600000613d0000001f01400039000000600210018f0000000501200029000000000021004b00000000020000390000000102004039000003290010009c0000010a0000213d00000001002001900000010a0000c13d000000400010043f000000200030008c000000430000413d00000005010000290000000001010433000002f40010009c000000430000213d000000000010043f0000000e01000039000000200010043f0000000001000414000002f10010009c000002f101008041000000c00110021000000327011001c700008010020000390bc00bbb0000040f0000000100200190000000430000613d000000000101043b000000000201041a0000000403000029000000000032001a000005ea0000413d0000000002320019000000000021041b000000000100001900000bc10001042e0000000301000039000000000101041a000000000001004b000004dd0000613d00000000021300d9000000000031004b000000010200203900000005010000290bc00a040000040f0000000601000039000000000101041a000500000001001d000000000001004b000007090000613d000000010100008a00000005011000fa0000000002000416000000000021004b000000430000413d0000000c01000039000000000101041a000000000010043f0000000d01000039000000200010043f0000000001000414000002f10010009c000002f101008041000000c00110021000000327011001c700008010020000390bc00bbb0000040f0000000100200190000000430000613d000000000400041600000005024000b9000002fe0220012a000000000101043b0000000201100039000000000301041a000000000023001a000005ea0000413d0000000003230019000000000031041b000000000424004b000005ea0000413d000400000004001d000003880000013d00000005010000290bc00a690000040f000000020200002900000004032000390000000002010019000000000013041b00000005010000290bc00ae70000040f000000000100001900000bc10001042e0000001f0530018f000002f306300198000000400200043d00000000046200190000076b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000007360000c13d0000076b0000013d000002f700a0009c000007840000413d000000400100043d000002fc02000041000004f30000013d000400000001001d000000400200043d0000033901000041000500000002001d00000000001204350000032d0100004100000000001004430000000001000412000000040010044300000024000004430000000001000414000002f10010009c000002f101008041000000c0011002100000032e011001c700008005020000390bc00bbb0000040f00000001002001900000075d0000613d000000000201043b0000000001000414000002f402200197000000040020008c000008120000c13d0000000003000031000000200030008c000000200400003900000000040340190000083c0000013d000000000001042f00000301020000410000080e0000013d0000001f0530018f000002f306300198000000400200043d00000000046200190000076b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000007670000c13d000000000005004b000007780000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001404350000006001300210000002f10020009c000002f1020080410000004002200210000000000112019f00000bc200010430000000400100043d0000030102000041000004f30000013d000000400100043d0000033802000041000004f30000013d000002f80090009c000007c90000413d000000400100043d000002fb02000041000004f30000013d0000000503000029000002f10030009c000002f1030080410000004003300210000002f10010009c000002f101008041000000c001100210000000000131019f000002fa011001c70bc00bbb0000040f0000006003100270000002f103300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000505700029000007a20000613d000000000801034f0000000509000029000000008a08043c0000000009a90436000000000059004b0000079e0000c13d000000000006004b000007af0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00010000000103550000000100200190000008520000613d0000001f01400039000000600210018f0000000501200029000000000021004b00000000020000390000000102004039000003290010009c0000010a0000213d00000001002001900000010a0000c13d000000400010043f000000200030008c000000430000413d00000005010000290000000001010433000002f40010009c000000430000213d000000000010043f0000000e01000039000000200010043f0000000001000414000006e50000013d00000000080804330000000000b8004b0000015e0000813d000000400100043d000002f902000041000004f30000013d000000400100043d0000034b02000041000004f30000013d0000000301000039000000000101041a000000000001004b000004dd0000613d0000000002000416000000000021004b000007dc0000213d00000000021200d900000005010000290bc00a040000040f0000000701000039000000000101041a000500000001001d000000000001004b000007e60000613d000000010100008a00000005011000fa0000000002000416000000000021004b000000430000413d0000000c01000039000000000101041a000000000010043f0000000d01000039000000200010043f0000000001000414000002f10010009c000002f101008041000000c00110021000000327011001c700008010020000390bc00bbb0000040f0000000100200190000000430000613d000000000200041600000005022000b9000002fe0220012a000000000101043b0000000201100039000000000301041a000000000023001a000005ea0000413d0000000003230019000000000031041b00000000010004160002000000210053000002cc0000813d000005ea0000013d000000000003004b0000080d0000613d000000c00400043d000000000004004b0000080d0000613d000000e00600043d000000000006004b0000080d0000613d000001200500043d000000000005004b000008c30000c13d000002fd0200004100000000002104350000004001100210000002fa011001c700000bc2000104300000000503000029000002f10030009c000002f1030080410000004003300210000002f10010009c000002f101008041000000c001100210000000000131019f000002fa011001c70bc00bbb0000040f0000006003100270000002f103300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000005057000290000082b0000613d000000000801034f0000000509000029000000008a08043c0000000009a90436000000000059004b000008270000c13d000000000006004b000008380000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000100000001035500000001002001900000085e0000613d0000001f01400039000000600210018f0000000501200029000000000021004b00000000020000390000000102004039000003290010009c0000010a0000213d00000001002001900000010a0000c13d000000400010043f000000200030008c000000430000413d00000005010000290000000001010433000002f40010009c000000430000213d000000000010043f0000000e01000039000000200010043f0000000001000414000006e50000013d0000001f0530018f000002f306300198000000400200043d00000000046200190000076b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000008590000c13d0000076b0000013d0000001f0530018f000002f306300198000000400200043d00000000046200190000076b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000008650000c13d0000076b0000013d0000000503000029000002f10030009c000002f1030080410000004003300210000002f10010009c000002f101008041000000c001100210000000000131019f000002fa011001c70bc00bbb0000040f0000006003100270000002f103300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000505700029000008830000613d000000000801034f0000000509000029000000008a08043c0000000009a90436000000000059004b0000087f0000c13d000000000006004b000008900000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00010000000103550000000100200190000008b70000613d0000001f01400039000000600210018f0000000501200029000000000021004b00000000020000390000000102004039000003290010009c0000010a0000213d00000001002001900000010a0000c13d000000400010043f000000200030008c000000430000413d00000005010000290000000001010433000002f40010009c000000430000213d000000000010043f0000000e01000039000000200010043f0000000001000414000002f10010009c000002f101008041000000c00110021000000327011001c700008010020000390bc00bbb0000040f0000000100200190000000430000613d000000000101043b000000000201041a000000040020002a000005ea0000413d0000000403000029000006f20000013d0000001f0530018f000002f306300198000000400200043d00000000046200190000076b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000008be0000c13d0000076b0000013d000002f70030009c000008c70000413d000002fc020000410000080e0000013d000002f80050009c000008cb0000413d000002fb020000410000080e0000013d000001000700043d000000000067004b000006530000813d000002f9020000410000080e0000013d0000034e0010009c000008d50000813d0000004001100039000000400010043f000000000001042d0000034901000041000000000010043f0000004101000039000000040010043f0000034a0100004100000bc2000104300000034f0010009c000008e00000813d0000006001100039000000400010043f000000000001042d0000034901000041000000000010043f0000004101000039000000040010043f0000034a0100004100000bc2000104300001000000000002000000000301041a000100000002001d000000000023004b000008fa0000a13d000000000010043f0000000001000414000002f10010009c000002f101008041000000c00110021000000350011001c700008010020000390bc00bbb0000040f0000000100200190000009000000613d00000001020000290000000102200210000000000101043b0000000001210019000000000001042d0000034901000041000000000010043f0000003201000039000000040010043f0000034a0100004100000bc200010430000000000100001900000bc2000104300001000000000002000000400200043d0000033d01000041000100000002001d00000000001204350000032d0100004100000000001004430000000001000412000000040010044300000024000004430000000001000414000002f10010009c000002f101008041000000c0011002100000032e011001c700008005020000390bc00bbb0000040f00000001002001900000095e0000613d000000000201043b0000000001000414000002f402200197000000040020008c000009200000c13d0000000003000031000000200030008c00000020040000390000000004034019000000010b0000290000094b0000013d0000000103000029000002f10030009c000002f1030080410000004003300210000002f10010009c000002f101008041000000c001100210000000000131019f000002fa011001c70bc00bbb0000040f000000010b0000290000006003100270000002f103300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b00190000093a0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000009360000c13d000000000006004b000009470000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00010000000103550000000100200190000009650000613d0000001f01400039000000600210018f0000000001b20019000000000021004b00000000020000390000000102004039000003290010009c0000095f0000213d00000001002001900000095f0000c13d000000400010043f0000001f0030008c0000095c0000a13d00000000010b0433000002f40010009c0000095c0000213d000000000001042d000000000100001900000bc200010430000000000001042f0000034901000041000000000010043f0000004101000039000000040010043f0000034a0100004100000bc2000104300000001f0530018f000002f306300198000000400200043d0000000004620019000009700000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000096c0000c13d000000000005004b0000097d0000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001404350000006001300210000002f10020009c000002f1020080410000004002200210000000000112019f00000bc2000104300001000000000002000000400200043d0000033901000041000100000002001d00000000001204350000032d0100004100000000001004430000000001000412000000040010044300000024000004430000000001000414000002f10010009c000002f101008041000000c0011002100000032e011001c700008005020000390bc00bbb0000040f0000000100200190000009df0000613d000000000201043b0000000001000414000002f402200197000000040020008c000009a10000c13d0000000003000031000000200030008c00000020040000390000000004034019000000010b000029000009cc0000013d0000000103000029000002f10030009c000002f1030080410000004003300210000002f10010009c000002f101008041000000c001100210000000000131019f000002fa011001c70bc00bbb0000040f000000010b0000290000006003100270000002f103300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000009bb0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000009b70000c13d000000000006004b000009c80000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00010000000103550000000100200190000009e60000613d0000001f01400039000000600210018f0000000001b20019000000000021004b00000000020000390000000102004039000003290010009c000009e00000213d0000000100200190000009e00000c13d000000400010043f0000001f0030008c000009dd0000a13d00000000010b0433000002f40010009c000009dd0000213d000000000001042d000000000100001900000bc200010430000000000001042f0000034901000041000000000010043f0000004101000039000000040010043f0000034a0100004100000bc2000104300000001f0530018f000002f306300198000000400200043d0000000004620019000009f10000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000009ed0000c13d000000000005004b000009fe0000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001404350000006001300210000002f10020009c000002f1020080410000004002200210000000000112019f00000bc2000104300007000000000002000600000002001d000700000001001d0000000c01000039000000000101041a000500000001001d000000000010043f0000000d01000039000000200010043f0000000001000414000002f10010009c000002f101008041000000c00110021000000327011001c700008010020000390bc00bbb0000040f000000010020019000000a5b0000613d000000000301043b000000400400043d0000034e0040009c00000a5d0000813d000000000103041a0000004002400039000000400020043f0000002002400039000400000002001d00000000001204350000000701000029000002f401100197000700000001001d00000000001404350000000101300039000000000201041a000003290020009c00000a5d0000213d000200000004001d000300000003001d000100000002001d0000000102200039000000000021041b000000000010043f0000000001000414000002f10010009c000002f101008041000000c00110021000000350011001c700008010020000390bc00bbb0000040f000000010020019000000a5b0000613d00000001020000290000000102200210000000000101043b0000000001210019000000000201041a000003510220019700000002030000290000000003030433000002f403300197000000000232019f000000000021041b000000010110003900000004020000290000000002020433000000000021041b0000000302000029000000000102041a0000000607000029000000000071001a00000a630000413d0000000001710019000000000012041b0000000001000414000002f10010009c000002f101008041000000c00110021000000328011001c70000800d0200003900000004030000390000035204000041000000050500002900000007060000290bc00bb60000040f000000010020019000000a5b0000613d000000000001042d000000000100001900000bc2000104300000034901000041000000000010043f0000004101000039000000040010043f0000034a0100004100000bc2000104300000034901000041000000000010043f0000001101000039000000040010043f0000034a0100004100000bc2000104300003000000000002000300000001001d000000000010043f0000000d01000039000000200010043f0000000001000414000002f10010009c000002f101008041000000c00110021000000327011001c700008010020000390bc00bbb0000040f000000010020019000000ac90000613d000000000201043b0000000401200039000000000101041a000000000001004b00000a7d0000613d000000000001042d0000000501200039000000000101041a000200000001001d000000000001004b00000ad20000613d0000032f0100004100000000001004430000000001000414000002f10010009c000002f101008041000000c00110021000000330011001c70000800b020000390bc00bbb0000040f000000010020019000000ad10000613d000000000301043b000000ff0130008c000000020400002900000acb0000413d000003530040009c00000acb0000213d0000000502400039000000400400043d000000000023004b00000ada0000a13d000200000004001d00000020044000390000000303000029000100000004001d000000000034043500000331030000410000000000300443000000000012004b000000000201a01900000004002004430000000001000414000002f10010009c000002f101008041000000c00110021000000332011001c70000800b020000390bc00bbb0000040f000000010020019000000ad10000613d000000000101043b000000020300002900000040023000390000000000120435000000400100003900000000001304350000034f0030009c00000ae10000813d0000006001300039000000400010043f0000000101000029000002f10010009c000002f10100804100000040011002100000000002030433000002f10020009c000002f1020080410000006002200210000000000112019f0000000002000414000002f10020009c000002f102008041000000c002200210000000000112019f00000328011001c700008010020000390bc00bbb0000040f000000010020019000000ac90000613d000000000101043b000000000001042d000000000100001900000bc2000104300000034901000041000000000010043f0000001101000039000000040010043f0000034a0100004100000bc200010430000000000001042f000000400100043d00000340020000410000000000210435000002f10010009c000002f1010080410000004001100210000002fa011001c700000bc20001043000000335010000410000000000140435000002f10040009c000002f1040080410000004001400210000002fa011001c700000bc2000104300000034901000041000000000010043f0000004101000039000000040010043f0000034a0100004100000bc2000104300009000000000002000900000002001d000200000001001d000000000010043f0000000d01000039000000200010043f0000000001000414000002f10010009c000002f101008041000000c00110021000000327011001c700008010020000390bc00bbb0000040f000000010020019000000b660000613d000000000101043b0000000202100039000100000002001d000000000202041a000300000002001d000000000002004b00000b740000613d000000000201041a000000000002004b00000b7c0000613d00000009202000f9000400000002001d0000000102100039000000000302041a000000000003004b00000b6e0000613d0000000001000019000500000002001d000000000031001a00000b6e0000413d000900000003001d000800000001001d0000000001310019000600000001001d0007000100100278000000000102041a000000070010006c00000b680000a13d000000000020043f0000000001000414000002f10010009c000002f101008041000000c00110021000000350011001c700008010020000390bc00bbb0000040f000000010020019000000b660000613d000000000101043b000000060200002900000001022001bf0000000001120019000000000101041a000000040010006c0000000701000029000000090300002900000000030120190000000101100039000000000201001900000008020020290000000001020019000000000032004b000000050200002900000b080000413d000000000003004b00000b6e0000613d0009000100300092000000000102041a000000090010006c00000b680000a13d000000000020043f0000000001000414000002f10010009c000002f101008041000000c00110021000000350011001c700008010020000390bc00bbb0000040f000000010020019000000b660000613d00000009020000290000000102200210000000000101043b0000000001210019000000000101041a0000000102000029000000000002041b000002f401100197000900000001001d000000000010043f0000000e01000039000000200010043f0000000001000414000002f10010009c000002f101008041000000c00110021000000327011001c700008010020000390bc00bbb0000040f000000010020019000000b660000613d000000000101043b000000000201041a000000030020002a00000b6e0000413d00000003070000290000000002720019000000000021041b0000000001000414000002f10010009c000002f101008041000000c00110021000000328011001c70000800d0200003900000004030000390000035404000041000000020500002900000009060000290bc00bb60000040f000000010020019000000b660000613d000000000001042d000000000100001900000bc2000104300000034901000041000000000010043f0000003201000039000000040010043f0000034a0100004100000bc2000104300000034901000041000000000010043f0000001101000039000000040010043f0000034a0100004100000bc200010430000000400100043d00000355020000410000000000210435000002f10010009c000002f1010080410000004001100210000002fa011001c700000bc2000104300000034901000041000000000010043f0000001201000039000000040010043f0000034a0100004100000bc200010430000000000001042f000002f10010009c000002f1010080410000004001100210000002f10020009c000002f1020080410000006002200210000000000112019f0000000002000414000002f10020009c000002f102008041000000c002200210000000000112019f00000328011001c700008010020000390bc00bbb0000040f000000010020019000000b960000613d000000000101043b000000000001042d000000000100001900000bc20001043000000000050100190000000000200443000000050030008c00000ba60000413d000000040100003900000000020000190000000506200210000000000664001900000005066002700000000006060031000000000161043a0000000102200039000000000031004b00000b9e0000413d000002f10030009c000002f10300804100000060013002100000000002000414000002f10020009c000002f102008041000000c002200210000000000112019f00000356011001c700000000020500190bc00bbb0000040f000000010020019000000bb50000613d000000000101043b000000000001042d000000000001042f00000bb9002104210000000102000039000000000001042d0000000002000019000000000001042d00000bbe002104230000000102000039000000000001042d0000000002000019000000000001042d00000bc00000043200000bc10001042e00000bc200010430000000000000000000000000000000000000000000000000000000000000000000000000ffffffff00000000000000000000000000000000000000000000000000000001ffffffe000000000000000000000000000000000000000000000000000000000ffffffe0000000000000000000000000ffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000ffffffffffffff3f000000000000000000000000000000000000000000000000ffffffffffffff5f00000000000000000000000000000000000000000000000000b1a2bc2ec500010000000000000000000000000000000000000000000000000000000000015181cb10b7c2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000c4edc2a80000000000000000000000000000000000000000000000000000000036f8856f000000000000000000000000000000000000000000000000000000003e2e95c5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000de0b6b3a76400010000000200000000000000000000000000000080000001000000000000000000cd4e6167000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070e2ca3200000000000000000000000000000000000000000000000000000000c819982500000000000000000000000000000000000000000000000000000000d27f9b7e00000000000000000000000000000000000000000000000000000000f185f20c00000000000000000000000000000000000000000000000000000000f185f20d00000000000000000000000000000000000000000000000000000000fdff9b8100000000000000000000000000000000000000000000000000000000d27f9b7f00000000000000000000000000000000000000000000000000000000e2e9336200000000000000000000000000000000000000000000000000000000c819982600000000000000000000000000000000000000000000000000000000cafe543500000000000000000000000000000000000000000000000000000000cc4c3bf300000000000000000000000000000000000000000000000000000000a512aee700000000000000000000000000000000000000000000000000000000abbe7fe900000000000000000000000000000000000000000000000000000000abbe7fea00000000000000000000000000000000000000000000000000000000c45a015500000000000000000000000000000000000000000000000000000000a512aee800000000000000000000000000000000000000000000000000000000a7a4d00a0000000000000000000000000000000000000000000000000000000070e2ca33000000000000000000000000000000000000000000000000000000008e8772850000000000000000000000000000000000000000000000000000000094726c56000000000000000000000000000000000000000000000000000000003042ec49000000000000000000000000000000000000000000000000000000004e1415330000000000000000000000000000000000000000000000000000000061d027b20000000000000000000000000000000000000000000000000000000061d027b30000000000000000000000000000000000000000000000000000000068b29241000000000000000000000000000000000000000000000000000000004e14153400000000000000000000000000000000000000000000000000000000585fbb6b000000000000000000000000000000000000000000000000000000003042ec4a000000000000000000000000000000000000000000000000000000004273601c0000000000000000000000000000000000000000000000000000000049e1432c000000000000000000000000000000000000000000000000000000001624e9db000000000000000000000000000000000000000000000000000000001624e9dc000000000000000000000000000000000000000000000000000000001e5eb1d0000000000000000000000000000000000000000000000000000000002793433b0000000000000000000000000000000000000000000000000000000001739f760000000000000000000000000000000000000000000000000000000005bc25a800000000000000000000000000000000000000000000000000000000105e60d702000000000000000000000000000000000000400000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffb12d13eb0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000800000000000000000310ab089e4439a4c15d089f94afb7896ff553aecb10793d0ab882de59d99a32e020000020000000000000000000000000000004400000000000000000000000042cbb15ccdc3cad6266b0e7a08c0454b23bf29dc2df74b6f3c209e9336465bd1020000020000000000000000000000000000000400000000000000000000000080b41246c05cbb406f874e82aa2faf7db11bba9792fe09929e56ef1eee2c2da30200000200000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff9f796b89b91644bc98cd93958e4c9038275d622183e25ac5af08cc6b5d95539132085de6250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000800000000000000000000000000000000000000000000000000000000000000000ffffffffffffffbfa10ef97c0000000000000000000000000000000000000000000000000000000061d027b3000000000000000000000000000000000000000000000000000000003b5a417e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000080000000000000000000000000000000000000000000000000000000000000000000000000000151808da5cb5b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000001200000000000000000428e0b92000000000000000000000000000000000000000000000000000000001f2b976300000000000000000000000000000000000000000000000000000000fc507a31000000000000000000000000000000000000000000000000000000005f1df6b8213d4bbee1273aa2563c83b786eb036f6a018bb88207cd6ef0dfec71c389e7ff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000001400000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a000000080000000000000000000000000000000000000000000000000000000000000000000b1a2bc2ec5000032cc7236000000000000000000000000000000000000000000000000000000004e487b7100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000032e5c6fd00000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000000000000000000000000000000000000000000ffffffffffffffc0000000000000000000000000000000000000000000000000ffffffffffffffa00200000000000000000000000000000000000020000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000d01d70b8d75d0910a4baec7ccd74d96a9df9d19bd539a8ecb156aee1c8aa621afffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaf75adeadf04a8ca4130d3774f98bdb151c71b80eb8ee92a224bced1c538e9408e42b123f000000000000000000000000000000000000000000000000000000000200000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000073ee958f75270946a22983820952bcdb9dd0a6ba77520b10dda8da8a0fcd0253

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

0000000000000000000000005606cd69b61bd6ed0fd9adacd56188d9d6f576450000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000002386f26fc100000000000000000000000000000000000000000000000000003a4965bf58a400000000000000000000000000000000000000000000000000000011c37937e08000000000000000000000000000000000000000000000000000001550f7dca70000000000000000000000000000000000000000000000000000000000000000025800000000000000000000000000000000000000000000000002c68af0bb140000000000000000000000000000000000000000000000000000016345785d8a000000000000000000000000000000000000000000000000000000b1a2bc2ec500000000000000000000000000000000000000000000000000000214e8348c4f00000000000000000000000000000000000000000000000000000058d15e17628000

-----Decoded View---------------
Arg [0] : _factory (address): 0x5606Cd69B61bD6Ed0Fd9aDACD56188D9D6F57645
Arg [1] : _jackpotConfig (tuple): System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput]
Arg [2] : _feeConfig (tuple): System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput]

-----Encoded View---------------
12 Constructor Arguments found :
Arg [0] : 0000000000000000000000005606cd69b61bd6ed0fd9adacd56188d9d6f57645
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [2] : 000000000000000000000000000000000000000000000000002386f26fc10000
Arg [3] : 0000000000000000000000000000000000000000000000003a4965bf58a40000
Arg [4] : 0000000000000000000000000000000000000000000000000011c37937e08000
Arg [5] : 000000000000000000000000000000000000000000000000001550f7dca70000
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000258
Arg [7] : 00000000000000000000000000000000000000000000000002c68af0bb140000
Arg [8] : 000000000000000000000000000000000000000000000000016345785d8a0000
Arg [9] : 00000000000000000000000000000000000000000000000000b1a2bc2ec50000
Arg [10] : 0000000000000000000000000000000000000000000000000214e8348c4f0000
Arg [11] : 0000000000000000000000000000000000000000000000000058d15e17628000


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.