HYPE Price: $23.79 (+7.45%)
 

Overview

HYPE Balance

HyperEVM LogoHyperEVM LogoHyperEVM Logo0.00018 HYPE

HYPE Value

Less Than $0.01 (@ $23.79/HYPE)

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Block
From
To
Resolve Markets200281512025-11-24 3:00:5763 days ago1763953257IN
0x14e93ee3...1fb4e949d
0 HYPE0.00012710.27612159
Resolve Markets200273792025-11-24 2:48:1763 days ago1763952497IN
0x14e93ee3...1fb4e949d
0 HYPE0.000136140.29574231
Resolve Markets200265942025-11-24 2:35:2563 days ago1763951725IN
0x14e93ee3...1fb4e949d
0 HYPE0.000117420.2550734
Resolve Markets200259672025-11-24 2:25:0863 days ago1763951108IN
0x14e93ee3...1fb4e949d
0 HYPE0.000047140.1024052
Resolve Markets200253482025-11-24 2:15:0063 days ago1763950500IN
0x14e93ee3...1fb4e949d
0 HYPE0.000120560.26191388
Resolve Markets200244012025-11-24 1:59:2863 days ago1763949568IN
0x14e93ee3...1fb4e949d
0 HYPE0.000123860.26908368
Resolve Markets200237462025-11-24 1:48:4463 days ago1763948924IN
0x14e93ee3...1fb4e949d
0 HYPE0.000129010.28024901
Resolve Markets200230832025-11-24 1:37:5263 days ago1763948272IN
0x14e93ee3...1fb4e949d
0 HYPE0.000046030.1
Resolve Markets200224712025-11-24 1:27:5063 days ago1763947670IN
0x14e93ee3...1fb4e949d
0 HYPE0.000046030.1
Resolve Markets200218592025-11-24 1:17:4863 days ago1763947068IN
0x14e93ee3...1fb4e949d
0 HYPE0.00012380.26892538
Resolve Markets200212372025-11-24 1:07:3663 days ago1763946456IN
0x14e93ee3...1fb4e949d
0 HYPE0.000078540.17061013
Resolve Markets200206182025-11-24 0:57:2763 days ago1763945847IN
0x14e93ee3...1fb4e949d
0 HYPE0.000128620.27939061
Resolve Markets200200062025-11-24 0:47:2563 days ago1763945245IN
0x14e93ee3...1fb4e949d
0 HYPE0.000046030.1
Resolve Markets200193942025-11-24 0:37:2363 days ago1763944643IN
0x14e93ee3...1fb4e949d
0 HYPE0.000092940.20189759
Resolve Markets200186842025-11-24 0:25:4563 days ago1763943945IN
0x14e93ee3...1fb4e949d
0 HYPE0.000046030.1
Resolve Markets200180712025-11-24 0:15:4263 days ago1763943342IN
0x14e93ee3...1fb4e949d
0 HYPE0.000046030.1
Resolve Markets200174582025-11-24 0:05:3963 days ago1763942739IN
0x14e93ee3...1fb4e949d
0 HYPE0.000127850.27772717
Resolve Markets200168312025-11-23 23:55:2263 days ago1763942122IN
0x14e93ee3...1fb4e949d
0 HYPE0.000046030.1
Resolve Markets200162192025-11-23 23:45:2063 days ago1763941520IN
0x14e93ee3...1fb4e949d
0 HYPE0.00013770.29910342
Resolve Markets200153412025-11-23 23:30:5763 days ago1763940657IN
0x14e93ee3...1fb4e949d
0 HYPE0.000046030.1
Resolve Markets200147292025-11-23 23:20:5563 days ago1763940055IN
0x14e93ee3...1fb4e949d
0 HYPE0.000129180.28060114
Resolve Markets200139072025-11-23 23:07:2663 days ago1763939246IN
0x14e93ee3...1fb4e949d
0 HYPE0.000121740.264456
Resolve Markets200130692025-11-23 22:53:4263 days ago1763938422IN
0x14e93ee3...1fb4e949d
0 HYPE0.000046030.1
Resolve Markets200124562025-11-23 22:43:3963 days ago1763937819IN
0x14e93ee3...1fb4e949d
0 HYPE0.000046030.1
Resolve Markets200118432025-11-23 22:33:3663 days ago1763937216IN
0x14e93ee3...1fb4e949d
0 HYPE0.000046030.1
View all transactions

Latest 4 internal transactions

Advanced mode:
Parent Transaction Hash Block From To
188405962025-11-10 14:29:5677 days ago1762784996
0x14e93ee3...1fb4e949d
0.0997 HYPE
188404422025-11-10 14:27:2477 days ago1762784844
0x14e93ee3...1fb4e949d
0.00012 HYPE
177660832025-10-29 8:52:2689 days ago1761727946
0x14e93ee3...1fb4e949d
0.09988 HYPE
177189742025-10-28 20:00:0989 days ago1761681609
0x14e93ee3...1fb4e949d
0.00012 HYPE
Cross-Chain Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
MarketMakerAMM

Compiler Version
v0.8.28+commit.7893614a

Optimization Enabled:
No with 200 runs

Other Settings:
cancun EvmVersion
File 1 of 2 : MarketMakerAMM.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
import "solady/src/utils/g/EnumerableSetLib.sol";

contract MarketMakerAMM {

    using EnumerableSetLib for Uint256Set;

    event MarketEnter(uint256 indexed MarketId, uint256 indexed RoundId, address indexed User, uint256 AmountIn, uint256 Side, uint256 AmountOut); //0xafdcf9101f4dab5c3b6e53a3ec30d3e897f17b974edceb117d3c12d2d83b0fd9
    event MarketExit(uint256 indexed MarketId, uint256 indexed RoundId, address indexed User, uint256 AmountInA, uint256 AmountInB, uint256 AmountOut); //0x4c686a53bc9329e91f0d0d94d821505fd2c0aef3c09a94ea360d98c0dfb9dee4
    event MarketRedeem(uint256 indexed MarketId, uint256 indexed RoundId, address indexed User, uint256 Result, uint256 AmountOut); //0x3f63856e2d8c431941e15ac15a28d4201c2838a61987308f61a9d5d01aac4839
    event RoundResolvedBy(uint256 indexed RoundId, address indexed Resolver, uint256 Fees); //0xa4151f6c29291b1556b1872bc36e5304d55092b1703f6226eefdb53250765c71

    error NotAuthorised();
    error RoundExpired();
    error AlreadyClaimed();
    error RoundResolved();
    error InvalidRound();
    error InvalidTimestamp();
    error InvalidInput();
    error SlippageReached();
    error RoundNotYetInitialised();
    error InvalidOutput();
    error OracleError();
    error InvalidReserves();

    address internal admin; // slot: 0
    uint256 public fees; //slot1
    uint256 public universalRound; // slot: 2
    uint256 public roundStart; // slot: 3
    mapping(uint256 marketId => mapping(uint256 round => uint256 yesReserves)) internal marketToRoundToYesReserves; // slot: 4
    mapping(uint256 marketId => mapping(uint256 round => uint256 noReserves)) internal marketToRoundToNoReserves; // slot: 5
    mapping(uint256 marketId => mapping(uint256 round => uint256 treasury)) internal marketToRoundToTreasury; // slot: 6
    mapping(address user => mapping(uint256 marketId => mapping(uint256 round => uint256 yesReserves))) internal userToMarketToRoundToYesReserves; // slot: 7
    mapping(address user => mapping(uint256 marketId => mapping(uint256 round => uint256 noReserves))) internal userToMarketToRoundToNoReserves; // slot: 8
    mapping(uint256 marketId => mapping(uint256 round => uint256 price)) internal marketToRoundToPrice; // slot: 9
    mapping(uint256 marketId => mapping(uint256 round => uint256 result)) internal marketToRoundToResult; // slot: 10
    mapping(address user => mapping(uint256 marketId => uint256[] roundIds)) internal userToActiveRoundsPerMarket; // slot: 11
    mapping(address user => mapping(uint256 marketId => mapping(uint256 roundId => uint256 registered))) internal userToRegisteredRound; // slot: 12
    mapping(address user => mapping(uint256 marketId => mapping(uint256 roundId => uint256 redeemed)))  internal userToRedeemedMarketRound;  // slot: 13
    mapping(uint256 marketId => mapping(uint256 round => uint256 outstandingYesShares)) internal marketToRoundToOutYesShares; // slot: 14
    mapping(uint256 marketId => mapping(uint256 round => uint256 outstandingNoShares)) internal marketToRoundToOutNoShares; // slot: 15
    mapping(uint256 roundId => uint256 resolverFees) internal roundIdToResolverFees; // slot: 16
    mapping(uint256 marketId => uint256 delistRound) public marketToDelistingRound; // slot: 17


    Uint256Set private availableMarkets;
    Uint256Set private allMarkets;// slot: 19


    struct MarketData {
        uint256 marketId;
        uint256 roundId;
        uint256 roundStart;
        uint256 marketTreasury;
        uint256 yesReserves;
        uint256 noReserves;
        uint256 outYesReserves;
        uint256 outNoReserves;
        uint256 lastPrice;
        uint256 currentPrice;
        uint256 result;
    }

    struct MarketDataWithHistory {
        uint256 marketId;
        uint256 roundId;
        uint256 roundStart;
        uint256 marketTreasury;
        uint256 yesReserves;
        uint256 noReserves;
        uint256 outYesReserves;
        uint256 outNoReserves;
        uint256 lastPrice;
        uint256 currentPrice;
        uint256 result;
        uint256 delistingRound;
        uint256[] history;
    }

    struct MarketHistory {
        uint256 marketId;
        uint256 roundId;
        uint256 outYesReserves;
        uint256 outNoReserves;
        uint256 openPrice;
        uint256 closePrice;
        uint256 result;
    }

    struct UserData {
        uint256 marketId;
        uint256 roundId;
        uint256 result;
        uint256 outYesReserves;
        uint256 outNoReserves;
        uint256 userYesReserves;
        uint256 userNoReserves;
        uint256 treasury;
        uint256 userRedeemed;
    }

    struct UserToRoundsPerMarket {
        uint256 marketId;
        uint256[] roundIds;
    }

    /**
     * @notice Initializes the MarketMakerAMM contract with initial markets
     * @dev Sets up initial reserves for rounds 1 and 2, fetches initial oracle prices
     * @param initMarketIds Array of market IDs to initialize (e.g., [0, 1, 2] for BTC, HYPE, SOL)
     * 
     * Initializes:
     * - Round 1 as the current round
     * - 425 HYPE initial reserves for YES and NO in rounds 1 and 2
     * - Fetches and stores initial oracle price for round 0
     * - Sets deployer as admin
     */
    constructor(uint256[] memory initMarketIds, address _admin) {
        uint len = initMarketIds.length;
        for(uint i=0; i<len; i++) {
            uint256 marketId = initMarketIds[i];
            marketToRoundToPrice[marketId][0] = _oraclePx(marketId);
            availableMarkets.add(marketId);
            allMarkets.add(marketId);
            marketToRoundToYesReserves[marketId][1] = 425 * 10**18;
            marketToRoundToNoReserves[marketId][1] = 425 * 10**18;
            marketToRoundToYesReserves[marketId][2] = 425 * 10**18;
            marketToRoundToNoReserves[marketId][2] = 425 * 10**18;
        }
        universalRound++;
        roundStart = block.timestamp;
        admin = _admin;
    }



    /**
     * @notice Registers a new market to the AMM
     * @dev Only callable by admin. Market ID must not already exist
     * @param index The market ID to register
     * 
     * @custom:reverts NotAuthorised if caller is not admin
     * @custom:reverts InvalidInput if market ID already exists
     */
    function registerMarket(uint256 index) external {
        if(msg.sender != admin) {
            revert NotAuthorised();
        }
        marketToDelistingRound[index] = 0; //Clear delisting round on potential relisting
        if(!availableMarkets.add(index)) revert InvalidInput();
        allMarkets.add(index);
        uint256 uRound = universalRound + 1;
        marketToRoundToYesReserves[index][uRound] = 425 * 10**18;
        marketToRoundToNoReserves[index][uRound] = 425 * 10**18;
    }

    /**
     * @notice Puts the market Id in schedule for removal, after 5 rounds admin can remove the market Id.
     * @dev Only callable by admin. Market ID must already exist
     * @param index The market ID to remove
     *
     * @custom:reverts NotAuthorised if caller is not admin
     * @custom:reverts InvalidInput if market ID doesn't exist
     */
    function putMarketOnDelist(uint256 index) external {
        if(msg.sender != admin) {
            revert NotAuthorised();
        }
        if(!availableMarkets.contains(index)) revert InvalidInput();
        marketToDelistingRound[index] = universalRound + 5;
    }

    /**
     * @notice Removes an active market from the App
     * @dev Only callable by admin. Market ID must already exist
     * @dev Markets should be scheduled for delete using putMarketOnDelist() before calling this function
     * @param index The market ID to remove
     *
     * @custom:reverts NotAuthorised if caller is not admin
     * @custom:reverts InvalidInput if market ID doesn't exist
     */
    function delistMarket(uint256 index) external {
        if(msg.sender != admin) {
            revert NotAuthorised();
        }
        if(marketToDelistingRound[index] == 0 || marketToDelistingRound[index] > universalRound) revert InvalidInput();
        if(!availableMarkets.remove(index)) revert InvalidInput();
    }

    /**
     * @notice Updates the admin
     * @dev Only callable by admin
     * @param newAdmin The newAdmin's address
     *
     * @custom:reverts NotAuthorised if caller is not admin
     */
    function updateAdmin(address newAdmin) external {
        if(msg.sender != admin) {
            revert NotAuthorised();
        }
        admin = newAdmin;
    }

    /**
     * @notice Buy YES or NO shares in a prediction market
     * @dev Uses AMM formula to calculate shares. Deducts 0.3% fee (60% protocol, 40% resolver)
     * @param minAmountOut Minimum shares expected (slippage protection)
     * @param marketId Market identifier (0=BTC, 1=HYPE, etc.)
     * @param roundId Round identifier (must be current round or next round in pre-market)
     * @param side 0 for YES (price will increase), 1 for NO (price will decrease)
     * 
     * Requirements:
     * - msg.value > 0 (must send HYPE)
     * - roundId must be universalRound or universalRound+1
     * - If roundId == universalRound: must be within first 5 minutes
     * - If roundId == universalRound+1: must be after 5 minutes (pre-market)
     * - Previous round must have a price (for current round)
     * 
     * Effects:
     * - Registers user in round if first time
     * - Updates market reserves
     * - Updates user share balances
     * - Distributes fees (60% protocol, 40% resolver)
     * 
     * @custom:reverts InvalidInput if side > 1
     * @custom:reverts InvalidRound if roundId is invalid or previous round has no price
     * @custom:reverts RoundExpired if current round trading window has closed
     * @custom:reverts RoundNotYetInitialised if trying to enter next round before pre-market
     * @custom:reverts SlippageReached if calculated shares < minAmountOut
     */
    function enterMarket(uint256 minAmountOut, uint256 marketId, uint256 roundId, uint256 side) external payable {
        if (!availableMarkets.contains(marketId)) revert InvalidInput();
        if(marketToDelistingRound[marketId] != 0 && marketToDelistingRound[marketId] <= roundId) revert InvalidInput();
        assembly {
            let rStart := sload(roundStart.slot)
            if gt(side, 1) {
                mstore(0x00, 0xb4fa3fb3) //InvalidInput()
                revert(0x1c, 0x04)
            }
            let universalRoundId := sload(universalRound.slot)
            // marketToRoundToPrice
            mstore(0x00, marketId)
            mstore(0x20, 9)
            let hash := keccak256(0, 0x40)
            mstore(0, sub(roundId, 1))
            mstore(0x20, hash)
            hash := keccak256(0, 0x40)
            if and(eq(universalRoundId, roundId), eq(sload(hash), 0)) {
                mstore(0x00, 0xa2b52a54) //InvalidRound()
                revert(0x1c, 0x04)
            }
            if or(gt(roundId, add(universalRoundId, 1)), lt(roundId, universalRoundId)) {
                mstore(0x00, 0xa2b52a54) //InvalidRound()
                revert(0x1c, 0x04)
            }
            if and(eq(roundId, universalRoundId), lt(add(rStart, 300), timestamp())) {
                mstore(0x00, 0x9e6d804f) //RoundExpired()
                revert(0x1c, 0x04)
            }
            if and(eq(roundId, add(universalRoundId, 1)), lt(timestamp(), add(rStart, 300))) {
                mstore(0x00, 0x5b903c71) //RoundNotYetInitialised()
                revert(0x1c, 0x04)
            }
            let amount := div(mul(callvalue(), 997), 1000)
            let totalFee := sub(callvalue(), amount)
            sstore(fees.slot, add(sload(fees.slot), div(mul(totalFee, 600), 1000))) //Deduct resolver fees from total fees

            // roundIdToResolverFees
            mstore(0x00, roundId)
            mstore(0x20, 16)
            hash := keccak256(0, 0x40)
            sstore(hash, add(sload(hash), sub(totalFee, div(mul(totalFee, 600), 1000))))

            // marketToRoundToTreasury
            mstore(0x00, marketId)
            mstore(0x20, 6)
            hash := keccak256(0, 0x40)
            mstore(0x20, hash)
            mstore(0, roundId)
            hash := keccak256(0, 0x40)
            sstore(hash, add(sload(hash), amount))

            //  userToRegisteredRound
            mstore(0x00, caller())
            mstore(0x20, 12)
            hash := keccak256(0x00, 0x40)
            mstore(0x00, marketId)
            mstore(0x20, hash)
            hash := keccak256(0x00, 0x40)
            mstore(0x00, roundId)
            mstore(0x20, hash)
            hash := keccak256(0x00, 0x40)
            if eq(sload(hash), 0) {
                sstore(hash, 1)
                // userToActiveRoundsPerMarket
                mstore(0x00, caller())
                mstore(0x20, 11)
                hash := keccak256(0, 0x40)
                mstore(0x00, marketId)
                mstore(0x20, hash)
                hash := keccak256(0, 0x40)
                let len := sload(hash)
                sstore(hash, add(len, 1))
                mstore(0x00, hash)
                hash := keccak256(0, 0x20)
                sstore(add(hash, len), roundId)
            }

            // marketToRoundToYesReserves
            mstore(0x00, marketId)
            mstore(0x20, 4)
            hash := keccak256(0, 0x40)
            mstore(0x20, hash)
            mstore(0, roundId)
            hash := keccak256(0, 0x40)
            let yesReserves := sload(hash)

            // marketToRoundToNoReserves
            mstore(0x00, marketId)
            mstore(0x20, 5)
            let noHash := keccak256(0, 0x40)
            mstore(0x20, noHash)
            mstore(0, roundId)
            noHash := keccak256(0, 0x40)
            let noReserves := sload(noHash)

            // _buyYes()
            if eq(side, 0) {
                let userPrimaryReserves := div(mul(amount, yesReserves), add(amount, noReserves))
                if lt(add(userPrimaryReserves, amount), minAmountOut) {
                    mstore(0x00, 0xa6d7690f) //SlippageReached()
                    revert(0x1c, 0x04)
                }

                sstore(hash, sub(yesReserves, userPrimaryReserves))
                sstore(noHash, add(noReserves, amount))

                // userToMarketToRoundToYesReserves
                mstore(0x00, caller())
                mstore(0x20, 7)
                hash := keccak256(0, 0x40)
                mstore(0x20, hash)
                mstore(0, marketId)
                hash := keccak256(0, 0x40)
                mstore(0x20, hash)
                mstore(0, roundId)
                hash := keccak256(0, 0x40)
                sstore(hash, add(sload(hash), add(userPrimaryReserves, amount)))

                // marketToRoundToOutYesShares
                mstore(0x00, marketId)
                mstore(0x20, 14)
                hash := keccak256(0, 0x40)
                mstore(0x20, hash)
                mstore(0, roundId)
                hash := keccak256(0, 0x40)
                sstore(hash, add(sload(hash), add(userPrimaryReserves, amount)))
                mstore(0x00, callvalue())
                mstore(0x20, side)
                mstore(0x40, add(userPrimaryReserves, amount))
                log4(0x00, 0x60, 0xafdcf9101f4dab5c3b6e53a3ec30d3e897f17b974edceb117d3c12d2d83b0fd9, marketId, roundId, caller())
                return(0,0)
            }
            // _buyNo()
            let userSecondaryReserves := div(mul(amount, noReserves), add(amount, yesReserves))
            if lt(add(userSecondaryReserves, amount), minAmountOut) {
                mstore(0x00, 0xa6d7690f) //SlippageReached()
                revert(0x1c, 0x04)
            }

            sstore(hash, add(yesReserves, amount))
            sstore(noHash, sub(noReserves, userSecondaryReserves))

            // userToMarketToRoundToNoReserves
            mstore(0x00, caller())
            mstore(0x20, 8)
            hash := keccak256(0, 0x40)
            mstore(0x20, hash)
            mstore(0, marketId)
            hash := keccak256(0, 0x40)
            mstore(0x20, hash)
            mstore(0, roundId)
            hash := keccak256(0, 0x40)
            sstore(hash, add(sload(hash), add(userSecondaryReserves, amount)))

            // marketToRoundToOutNoShares
            mstore(0x00, marketId)
            mstore(0x20, 15)
            hash := keccak256(0, 0x40)
            mstore(0x20, hash)
            mstore(0, roundId)
            hash := keccak256(0, 0x40)
            sstore(hash, add(sload(hash), add(userSecondaryReserves, amount)))
            mstore(0x00, callvalue())
            mstore(0x20, side)
            mstore(0x40, add(userSecondaryReserves, amount))
            log4(0x00, 0x60, 0xafdcf9101f4dab5c3b6e53a3ec30d3e897f17b974edceb117d3c12d2d83b0fd9, marketId, roundId, caller())
            return(0,0)
        }
    }

    /**
     * @notice Exit a market position by selling YES and NO shares
     * @dev Optionally swaps between YES/NO before redeeming. Deducts 0.3% exit fee
     * @param minNativeAmountOut Minimum HYPE expected after exit (slippage protection)
     * @param marketId Market identifier
     * @param roundId Round identifier (must be current or next round)
     * @param amountYes Amount of YES shares user wants to sell
     * @param amountNo Amount of NO shares user wants to sell
     * @param toBeExchanged Amount to swap between YES/NO to balance position before exit
     * 
     * Process:
     * 1. If toBeExchanged > 0: Swaps YES to NO or NO to YES (whichever is higher)
     * 2. Redeems equal amounts of YES and NO shares for HYPE
     * 3. Deducts 0.3% fee (60% protocol, 40% resolver)
     * 4. Transfers remaining HYPE to user
     * 
     * Requirements:
     * - roundId must be current round or next round
     * - If current round: must be within trading window (first 5 minutes)
     * - If next round: must be within pre-market trading window (second 5 minutes of current round)
     * - User must have sufficient YES and NO shares
     * 
     * @custom:reverts InvalidRound if roundId is out of valid range
     * @custom:reverts RoundExpired if current round trading window has closed
     * @custom:reverts SlippageReached if HYPE received < minNativeAmountOut
     * @custom:reverts InvalidOutput if HYPE transfer to user fails
     */
    function exitMarket(uint256 minNativeAmountOut, uint256 marketId, uint256 roundId, uint256 amountYes, uint256 amountNo, uint256 toBeExchanged) external {
        if(!availableMarkets.contains(marketId)) revert InvalidInput();
        uint256 amountOut;
        if (toBeExchanged > 0 ) {
            if (amountYes < amountNo) {
                amountOut = _sellNo(toBeExchanged, marketId, roundId);
                amountNo -= toBeExchanged;
                amountYes += amountOut;
            } else {
                amountOut = _sellYes(toBeExchanged,marketId, roundId);
                amountYes -= toBeExchanged;
                amountNo += amountOut;
            }
        }
        amountOut = amountYes > amountNo ? amountNo : amountYes;

        // @dev marketToRoundToYesReserves transient_slot 0
        // @dev marketToRoundToNoReserves transient_slot 1
        // @dev marketToRoundToTreasury transient_slot 2
        // @dev userToMarketToRoundToYesReserves transient_slot 3
        // @dev userToMarketToRoundToNoReserves transient_slot 4
        // @dev marketToRoundToOutYesShares transient_slot 5
        // @dev marketToRoundToOutNoShares transient_slot
        assembly {
            let localUniversalRound := sload(universalRound.slot)

            if or(lt(roundId, localUniversalRound), gt(roundId, add(localUniversalRound, 1))) {
                mstore(0x00, 0xa2b52a54) //InvalidRound()
                revert(0x1c, 0x04)
            }

            if and(eq(roundId, localUniversalRound), lt(add(sload(roundStart.slot), 300), timestamp())) {
                mstore(0x00, 0x9e6d804f) //RoundExpired()
                revert(0x1c, 0x04)
            }

            switch gt(toBeExchanged, 0)
            case 1 {
                // marketToRoundToTreasury DONE
                mstore(0x00, marketId)
                mstore(0x20, 6)
                let hash := keccak256(0, 0x40)
                mstore(0x20, hash)
                mstore(0, roundId)
                hash := keccak256(0, 0x40)
                sstore(hash, sub(tload(2), amountOut))
                tstore(2, 0)

                // userToMarketToRoundToYesReserves DONE
                mstore(0x00, caller())
                mstore(0x20, 7)
                hash := keccak256(0, 0x40)
                mstore(0x20, hash)
                mstore(0, marketId)
                hash := keccak256(0, 0x40)
                mstore(0x20, hash)
                mstore(0, roundId)
                hash := keccak256(0, 0x40)

                if lt(tload(3), amountOut) {
                    mstore(0x00, 0x7b9c8916) //InvalidReserves()
                    revert(0x1c, 0x04)
                }
                sstore(hash, sub(tload(3), amountOut))
                tstore(3, 0)

                // userToMarketToRoundToNoReserves DONE
                mstore(0x00, caller())
                mstore(0x20, 8)
                hash := keccak256(0, 0x40)
                mstore(0x20, hash)
                mstore(0, marketId)
                hash := keccak256(0, 0x40)
                mstore(0x20, hash)
                mstore(0, roundId)
                hash := keccak256(0, 0x40)

                if lt(tload(4), amountOut) {
                    mstore(0x00, 0x7b9c8916) //InvalidReserves()
                    revert(0x1c, 0x04)
                }
                sstore(hash, sub(tload(4), amountOut))
                tstore(4, 0)

                // marketToRoundToOutYesShares DONE
                mstore(0x00, marketId)
                mstore(0x20, 14)
                hash := keccak256(0, 0x40)
                mstore(0x20, hash)
                mstore(0, roundId)
                hash := keccak256(0, 0x40)
                sstore(hash, sub(tload(5), amountOut))
                tstore(5, 0)

                // marketToRoundToOutNoShares DONE
                mstore(0x00, marketId)
                mstore(0x20, 15)
                hash := keccak256(0, 0x40)
                mstore(0x20, hash)
                mstore(0, roundId)
                hash := keccak256(0, 0x40)
                sstore(hash, sub(tload(6), amountOut))
                tstore(6, 0)
            }
            case 0 {
                // marketToRoundToTreasury DONE
                mstore(0x00, marketId)
                mstore(0x20, 6)
                let hash := keccak256(0, 0x40)
                mstore(0x20, hash)
                mstore(0, roundId)
                hash := keccak256(0, 0x40)
                sstore(hash, sub(sload(hash), amountOut))

                // userToMarketToRoundToYesReserves DONE
                mstore(0x00, caller())
                mstore(0x20, 7)
                hash := keccak256(0, 0x40)
                mstore(0x20, hash)
                mstore(0, marketId)
                hash := keccak256(0, 0x40)
                mstore(0x20, hash)
                mstore(0, roundId)
                hash := keccak256(0, 0x40)
                let state := sload(hash)
                if lt(state, amountOut) {
                    mstore(0x00, 0x7b9c8916) //InvalidReserves()
                    revert(0x1c, 0x04)
                }
                sstore(hash, sub(state, amountOut))

                // userToMarketToRoundToNoReserves DONE
                mstore(0x00, caller())
                mstore(0x20, 8)
                hash := keccak256(0, 0x40)
                mstore(0x20, hash)
                mstore(0, marketId)
                hash := keccak256(0, 0x40)
                mstore(0x20, hash)
                mstore(0, roundId)
                hash := keccak256(0, 0x40)
                state := sload(hash)
                if lt(state, amountOut) {
                   mstore(0x00, 0x7b9c8916) //InvalidReserves()
                   revert(0x1c, 0x04)
                }
                sstore(hash, sub(state, amountOut))

                // marketToRoundToOutYesShares DONE
                mstore(0x00, marketId)
                mstore(0x20, 14)
                hash := keccak256(0, 0x40)
                mstore(0x20, hash)
                mstore(0, roundId)
                hash := keccak256(0, 0x40)
                sstore(hash, sub(sload(hash), amountOut))

                // marketToRoundToOutNoShares DONE
                mstore(0x00, marketId)
                mstore(0x20, 15)
                hash := keccak256(0, 0x40)
                mstore(0x20, hash)
                mstore(0, roundId)
                hash := keccak256(0, 0x40)
                sstore(hash, sub(sload(hash), amountOut))
            }
            let amountOutAfterFee := div(mul(amountOut, 997), 1000)
            let totalFee := sub(amountOut, amountOutAfterFee)
            sstore(fees.slot, add(sload(fees.slot), div(mul(totalFee, 600), 1000))) //Deduct resolver fees from total fees

            // roundIdToResolverFees
            mstore(0x00, roundId)
            mstore(0x20, 16)
            let hash := keccak256(0, 0x40)
            sstore(hash, add(sload(hash), sub(totalFee, div(mul(totalFee, 600), 1000))))
            if lt(amountOutAfterFee, minNativeAmountOut) {
                mstore(0x00, 0xa6d7690f) //SlippageReached()
                revert(0x1c, 0x04)
            }
            mstore(0x00, amountYes)
            mstore(0x20, amountNo)
            mstore(0x40, amountOutAfterFee)
            log4(0x00, 0x60, 0x4c686a53bc9329e91f0d0d94d821505fd2c0aef3c09a94ea360d98c0dfb9dee4, marketId, roundId, caller())
            if iszero(
                call(gas(), caller(), amountOutAfterFee, 0, 0, 0, 0)
            ) {
                mstore(0x00, 0x98f73609) //InvalidOutput()
                revert(0x1c, 0x04)
            }

        }
    }

    /**
     * @notice Resolves all markets for the current round and starts a new round
     * @dev Can be called by anyone after 10 minutes. Caller receives resolver fees as incentive
     * 
     * Process:
     * 1. Validates 10 minutes (600 seconds) have passed since round start
     * 2. For each market:
     *    - Fetches current price from oracle
     *    - Compares with previous round's price
     *    - Sets result: 1 if price increased (YES wins), 2 if decreased (NO wins)
     *    - If no winners, adds treasury to protocol fees
     *    - Initializes reserves for round+2 (425 HYPE each)
     * 3. Increments universalRound
     * 4. Updates roundStart to current timestamp
     * 5. Transfers accumulated resolver fees to caller
     * 
     * Fee Distribution:
     * - Resolver receives 40% of all trading fees from the round
     * - Protocol receives 60% of all trading fees
     * 
     * @custom:reverts InvalidTimestamp if called before 10 minutes elapsed
     * @custom:reverts RoundResolved if round already resolved
     * @custom:reverts OracleError if oracle price fetch fails
     * @custom:reverts InvalidOutput if fee transfer to resolver fails
     */
    function resolveMarkets() external {
        assembly {
            if lt(timestamp(), add(sload(roundStart.slot), 600)) {
                mstore(0x00, 0xb7d09497) //InvalidTimestamp()
                revert(0x1c, 0x04)
            }
        }
        uint256 uRound = universalRound;
        uint256 len = availableMarkets.length();
        for(uint i=0; i<len; i++){
            uint256 marketId = availableMarkets.at(i);
            // get price from oracle
            uint256 currentPrice = _oraclePx(marketId);
            assembly {
                // marketToRoundToResult
                mstore(0x00, marketId)
                mstore(0x20, 10)
                let hash := keccak256(0x00, 0x40)
                mstore(0x00, uRound)
                mstore(0x20, hash)
                let resultHash := keccak256(0x00, 0x40)

                if gt(sload(resultHash), 0) {
                    mstore(0x00, 0xfd29af2c) //RoundResolved()
                    revert(0x1c, 0x04)
                }

                // marketToRoundToPrice currentRound -1
                mstore(0x00, marketId)
                mstore(0x20, 9)
                hash := keccak256(0x00, 0x40)
                mstore(0x00, sub(uRound, 1))
                mstore(0x20, hash)
                hash := keccak256(0x00, 0x40)
                let lastPrice := sload(hash)
                // marketToRoundToPrice currentRound
                mstore(0x00, uRound)
                hash := keccak256(0x00, 0x40)
                sstore(hash, currentPrice)

                if gt(lastPrice, 0) {
                    mstore(0x00, marketId)
                    mstore(0x20, 6)
                    hash := keccak256(0, 0x40)
                    mstore(0x20, hash)
                    mstore(0, uRound)
                    hash := keccak256(0, 0x40)
                    let treasury := sload(hash)
                    switch gt(currentPrice, lastPrice)
                    case 1 {
                        sstore(resultHash, 1)
                        // If there are no winners then add market treasury to fees
                        mstore(0x00, marketId)
                        mstore(0x20, 14)
                        hash := keccak256(0, 0x40)
                        mstore(0x20, hash)
                        mstore(0, uRound)
                        hash := keccak256(0, 0x40)
                        if eq(sload(hash), 0) {
                            sstore(fees.slot, add(sload(fees.slot), treasury))
                        }
                    }
                    case 0 {
                        sstore(resultHash, 2)
                        // If there are no winners then add market treasury to fees
                        mstore(0x00, marketId)
                        mstore(0x20, 15)
                        hash := keccak256(0, 0x40)
                        mstore(0x20, hash)
                        mstore(0, uRound)
                        hash := keccak256(0, 0x40)
                        if eq(sload(hash), 0) {
                            sstore(fees.slot, add(sload(fees.slot), treasury))
                        }
                    }
                }

                // marketToRoundToYesReserves
                mstore(0x00, marketId)
                mstore(0x20, 4)
                hash := keccak256(0, 0x40)
                mstore(0x20, hash)
                mstore(0, add(uRound, 2))
                hash := keccak256(0, 0x40)
                sstore(hash, 425000000000000000000)

                // marketToRoundToNoReserves
                mstore(0x00, marketId)
                mstore(0x20, 5)
                hash := keccak256(0, 0x40)
                mstore(0x20, hash)
                mstore(0, add(uRound, 2))
                hash := keccak256(0, 0x40)
                sstore(hash, 425000000000000000000)
            }
        }
        assembly {
            mstore(0x00, sload(universalRound.slot))
            mstore(0x20, 16)
            let hash := keccak256(0, 0x40)
            let roundFees := sload(hash)
            sstore(universalRound.slot, add(uRound, 1))
            sstore(roundStart.slot, timestamp())
            if iszero(
                call(gas(), caller(), roundFees, 0, 0, 0, 0)
            ) {
                mstore(0x00, 0x98f73609) //InvalidOutput()
                revert(0x1c, 0x04)
            }
            mstore(0x00, roundFees)
            log3(0x00, 0x20, 0xa4151f6c29291b1556b1872bc36e5304d55092b1703f6226eefdb53250765c71, uRound, caller())
        }
    }

    /**
     * @notice Claims winnings from resolved rounds for a specific market (max 25 rounds)
     * @dev Processes up to 25 rounds per call to avoid gas limits. Call multiple times if needed
     * @param marketId Market identifier to claim winnings from
     * @dev Unresolved RoundIds will deterministically be placed on either roundIds storage slot 0, 1 or total_len-1, total_len-2 after an iteration
     * 
     * Process:
     * 1. Retrieves user's pending rounds for the market
     * 2. Processes up to 25 rounds:
     *    - Checks if round is resolved
     *    - Calculates user's share of treasury based on winning shares
     *    - Transfers winnings to user
     *    - Marks round as redeemed
     *    - Removes from pending list if resolved
     * 3. Reorganizes pending rounds array
     * 
     * Payout Formula:
     * - userPayout = (userWinningShares * marketTreasury) / totalWinningShares
     * 
     * @custom:reverts AlreadyClaimed if user already claimed winnings for a round
     * @custom:reverts InvalidOutput if HYPE transfer fails
     */
    function redeemRoundsPerMarketIdCapped(uint256 marketId) external {
        assembly {
            mstore(0x00, caller())
            mstore(0x20, 11)
            let hash := keccak256(0, 0x40)
            mstore(0x00, marketId)
            mstore(0x20, hash)
            let roundHashLen := keccak256(0, 0x40)
            let totalLen := sload(roundHashLen)
            let len := totalLen
            mstore(0x00, roundHashLen)
            let itemHash := keccak256(0, 0x20)
            if gt(len, 25) {
                len := 25
            }
            for {let i := 0} lt(i, len) {i := add(i, 1)} {
                let roundId := sload(add(itemHash, i))
                sstore(add(itemHash, i), 0) //clear roundId

                // userToRedeemedMarketRound
                mstore(0x00, caller())
                mstore(0x20, 13)
                hash := keccak256(0, 0x40)
                mstore(0, marketId)
                mstore(0x20, hash)
                hash := keccak256(0, 0x40)
                mstore(0, roundId)
                mstore(0x20, hash)
                let resultHash := keccak256(0, 0x40)

                if gt(sload(resultHash), 0) {
                    mstore(0x00, 0x646cf558) // AlreadyClaimed()
                    revert(0x1c, 0x04)
                }

                // marketToRoundToResult
                mstore(0x00, marketId)
                mstore(0x20, 10)
                hash := keccak256(0x00, 0x40)
                mstore(0x00, roundId)
                mstore(0x20, hash)
                hash := keccak256(0x00, 0x40)

                let userBet := 0
                let winningBets := 1
                let result := sload(hash)
                switch result
                case 1 {
                    // userToRedeemedMarketRound
                    sstore(resultHash, 1)

                    // userToMarketToRoundToYesReserves
                    mstore(0x00, caller())
                    mstore(0x20, 7)
                    hash := keccak256(0, 0x40)
                    mstore(0, marketId)
                    mstore(0x20, hash)
                    hash := keccak256(0, 0x40)
                    mstore(0, roundId)
                    mstore(0x20, hash)
                    hash := keccak256(0, 0x40)
                    userBet := sload(hash)

                    // marketToRoundToOutYesShares
                    mstore(0x00, marketId)
                    mstore(0x20, 14)
                    hash := keccak256(0, 0x40)
                    mstore(0, roundId)
                    mstore(0x20, hash)
                    hash := keccak256(0, 0x40)
                    winningBets := sload(hash)
                }
                case 2 {
                    // userToRedeemedMarketRound
                    sstore(resultHash, 1)

                    // userToMarketToRoundToNoReserves
                    mstore(0x00, caller())
                    mstore(0x20, 8)
                    hash := keccak256(0, 0x40)
                    mstore(0, marketId)
                    mstore(0x20, hash)
                    hash := keccak256(0, 0x40)
                    mstore(0, roundId)
                    mstore(0x20, hash)
                    hash := keccak256(0, 0x40)
                    userBet := sload(hash)

                    // marketToRoundToOutNoShares
                    mstore(0x00, marketId)
                    mstore(0x20, 15)
                    hash := keccak256(0, 0x40)
                    mstore(0, roundId)
                    mstore(0x20, hash)
                    hash := keccak256(0, 0x40)
                    winningBets := sload(hash)
                }
                default {
                    tstore(i, roundId)
                }

                if gt(sload(resultHash), 0) {
                    // marketToRoundToTreasury
                    mstore(0x00, marketId)
                    mstore(0x20, 6)
                    hash := keccak256(0, 0x40)
                    mstore(0, roundId)
                    mstore(0x20, hash)
                    hash := keccak256(0, 0x40)

                    let amountOut := div(mul(userBet, sload(hash)), winningBets)

                    mstore(0x00, result)
                    mstore(0x20, amountOut)
                    log4(0x00, 0x40, 0x3f63856e2d8c431941e15ac15a28d4201c2838a61987308f61a9d5d01aac4839, marketId, roundId, caller())

                    if iszero(call(gas(), caller(), amountOut, 0, 0, 0, 0)) {
                        mstore(0x00, 0x98f73609) //InvalidOutput()
                        revert(0x1c, 0x04)
                    }
                }
            }
            let movingLen := sub(totalLen, len)
            if gt(movingLen, 25) {
                movingLen := 25
            }
            let newLen := sub(totalLen, len)
            for {let i := 0} lt(i, movingLen) {i := add(i, 1)} {
                sstore(add(itemHash, i), sload(add(itemHash, sub(totalLen, add(i, 1)))))
                if gt(tload(i), 0) {
                    sstore(add(itemHash, newLen), tload(i))
                    tstore(i, 0)
                    newLen := add(newLen, 1)
                }
            }
            if eq(movingLen, 0 ) {
                //fallback if we need to index the whole window when processed assets are less than the page
                for {let i := 0} lt(i, 25) {i := add(i, 1)} {
                    if gt(tload(i), 0) {
                        sstore(add(itemHash, newLen), tload(i))
                        tstore(i, 0)
                        newLen := add(newLen, 1)
                    }
                }
            }
            sstore(roundHashLen, newLen)
        }
    }

    /**
     * @notice Claims winnings from ALL pending rounds for a specific market (unbounded)
     * @dev WARNING: May run out of gas if user has many pending rounds. Use capped version for safety
     * @param marketId Market identifier to claim winnings from
     * @dev Unresolved RoundIds will deterministically be on either transient slot 0, 1 or total_len-1, total_len-2
     * 
     * Process:
     * - Same as redeemRoundsPerMarketIdCapped but processes ALL pending rounds
     * - No 25-round limit
     * 
     * Gas Considerations:
     * - Each round costs ~60k gas
     * - Block gas limit is ~2M
     * - Safe to process ~25 rounds per call
     * - Use capped version if unsure
     * 
     * @custom:reverts AlreadyClaimed if user already claimed winnings for a round
     * @custom:reverts InvalidOutput if HYPE transfer fails
     */
    function redeemPendingRoundsPerMarketId(uint256 marketId) external {
        assembly {
            mstore(0x00, caller())
            mstore(0x20, 11)
            let hash := keccak256(0, 0x40)
            mstore(0x00, marketId)
            mstore(0x20, hash)
            let roundHashLen := keccak256(0, 0x40)
            let len := sload(roundHashLen)
            mstore(0x00, roundHashLen)
            let itemHash := keccak256(0, 0x20)
            for {let i := 0} lt(i, len) {i := add(i, 1)} {
                let roundId := sload(add(itemHash, i))
                sstore(add(itemHash, i), 0) //clear roundId

                // userToRedeemedMarketRound
                mstore(0x00, caller())
                mstore(0x20, 13)
                hash := keccak256(0, 0x40)
                mstore(0, marketId)
                mstore(0x20, hash)
                hash := keccak256(0, 0x40)
                mstore(0, roundId)
                mstore(0x20, hash)
                let resultHash := keccak256(0, 0x40)

                if gt(sload(resultHash), 0) {
                    mstore(0x00, 0x646cf558) // AlreadyClaimed()
                    revert(0x1c, 0x04)
                }

                // marketToRoundToResult
                mstore(0x00, marketId)
                mstore(0x20, 10)
                hash := keccak256(0x00, 0x40)
                mstore(0x00, roundId)
                mstore(0x20, hash)
                hash := keccak256(0x00, 0x40)
                let userBet := 0
                let winningBets := 1
                let result := sload(hash)
                switch result
                case 1 {
                    // userToRedeemedMarketRound
                    sstore(resultHash, 1)

                    // userToMarketToRoundToYesReserves
                    mstore(0x00, caller())
                    mstore(0x20, 7)
                    hash := keccak256(0, 0x40)
                    mstore(0, marketId)
                    mstore(0x20, hash)
                    hash := keccak256(0, 0x40)
                    mstore(0, roundId)
                    mstore(0x20, hash)
                    hash := keccak256(0, 0x40)
                    userBet := sload(hash)

                    // marketToRoundToOutYesShares
                    mstore(0x00, marketId)
                    mstore(0x20, 14)
                    hash := keccak256(0, 0x40)
                    mstore(0, roundId)
                    mstore(0x20, hash)
                    hash := keccak256(0, 0x40)
                    winningBets := sload(hash)
                }
                case 2 {
                    // userToRedeemedMarketRound
                    sstore(resultHash, 1)

                    // userToMarketToRoundToNoReserves
                    mstore(0x00, caller())
                    mstore(0x20, 8)
                    hash := keccak256(0, 0x40)
                    mstore(0, marketId)
                    mstore(0x20, hash)
                    hash := keccak256(0, 0x40)
                    mstore(0, roundId)
                    mstore(0x20, hash)
                    hash := keccak256(0, 0x40)
                    userBet := sload(hash)

                    // marketToRoundToOutNoShares
                    mstore(0x00, marketId)
                    mstore(0x20, 15)
                    hash := keccak256(0, 0x40)
                    mstore(0, roundId)
                    mstore(0x20, hash)
                    hash := keccak256(0, 0x40)
                    winningBets := sload(hash)
                }
                default {
                    tstore(i, roundId)
                }

                if gt(sload(resultHash), 0) {
                    // marketToRoundToTreasury
                    mstore(0x00, marketId)
                    mstore(0x20, 6)
                    hash := keccak256(0, 0x40)
                    mstore(0, roundId)
                    mstore(0x20, hash)
                    hash := keccak256(0, 0x40)

                    let amountOut := div(mul(userBet, sload(hash)), winningBets)

                    mstore(0x00, result)
                    mstore(0x20, amountOut)
                    log4(0x00, 0x40, 0x3f63856e2d8c431941e15ac15a28d4201c2838a61987308f61a9d5d01aac4839, marketId, roundId, caller())

                    if iszero(
                        call(gas(), caller(), amountOut, 0, 0, 0, 0)
                    ) {
                        mstore(0x00, 0x98f73609) //InvalidOutput()
                        revert(0x1c, 0x04)
                    }
                }
            }
            let newLen := 0
            if gt(tload(0), 0) {
                sstore(add(itemHash, newLen), tload(0))
                tstore(0, 0)
                newLen := add(newLen, 1)
            }
            if gt(tload(1), 0) {
                sstore(add(itemHash, newLen), tload(1))
                tstore(1, 0)
                newLen := add(newLen, 1)
            }
            if and(gt(tload(sub(len, 1)), 0), gt(len, 0)) {
                sstore(add(itemHash, newLen), tload(sub(len, 1)))
                tstore(sub(len, 1), 0)
                newLen := add(newLen, 1)
            }
            if and(gt(tload(sub(len, 2)), 0), gt(len, 1)) {
                sstore(add(itemHash, newLen), tload(sub(len, 2)))
                tstore(sub(len, 2), 0)
                newLen := add(newLen, 1)
            }
            sstore(roundHashLen, newLen)
        }
    }

    /**
     * @notice Withdraws accumulated protocol fees to admin
     * @dev Only admin can call. Transfers all accumulated fees and resets to 0
     * 
     * Fee Sources:
     * - 60% of all entry fees (0.3% of entry amount)
     * - 60% of all exit fees (0.3% of exit amount)
     * - Treasury from rounds with no winners
     * 
     * @custom:reverts Require fails if HYPE transfer to admin fails
     */
    function claimFees() external {
        uint256 feesToClaim = fees;
        fees = 0;
        require(payable(admin).send(feesToClaim));
    }

    // Internal functions
    /**
     * @notice Fetches current price from oracle for a given market
     * @dev Calls precompiled oracle contract at address 0x807
     * @param index Market index to fetch price for
     * @return price Current oracle price for the market
     * 
     * @custom:reverts OracleError if oracle call fails
     */
    function _oraclePx(uint256 index) internal view returns (uint256 price) {
        address oracle = 0x0000000000000000000000000000000000000807;
        assembly {
            mstore(0, index)
            if iszero(staticcall(gas(), oracle, 0x00, 0x20, 0x00, 0x20)) {
                mstore(0x00, 0xb41b6cb1) // OracleError()
                revert(0x1c, 0x04)
            }
            price := mload(0)
        }
      }

    /**
     * @notice Internal function to sell YES shares for NO shares
     * @dev Uses AMM formula: s = p_amount * S / (P + p_amount)
     * @param amount Amount of YES shares to sell
     * @param marketId Market identifier
     * @param currentRound Round identifier
     * @return userSecondaryReserves Amount of NO shares received
     * 
     * Effects:
     * - Increases YES reserves by amount
     * - Decreases NO reserves by userSecondaryReserves
     * - Updates user balances in transient storage
     * - Updates outstanding shares in transient storage
     */
    function _sellYes(uint256 amount, uint256 marketId, uint256 currentRound) internal returns(uint256 userSecondaryReserves) {
        assembly {

            // marketToRoundToYesReserves DONE
            mstore(0x00, marketId)
            mstore(0x20, 4)
            let hash := keccak256(0, 0x40)
            mstore(0, currentRound)
            mstore(0x20, hash)
            hash := keccak256(0, 0x40)
            let yesReserves := sload(hash)
            sstore(hash, add(yesReserves, amount))

            // marketToRoundToNoReserves DONE
            mstore(0x00, marketId)
            mstore(0x20, 5)
            hash := keccak256(0, 0x40)
            mstore(0x20, hash)
            mstore(0, currentRound)
            hash := keccak256(0, 0x40)
            let noReserves := sload(hash)
            // s = p_amount * S / (P + p_amount)
            userSecondaryReserves := div(mul(amount, noReserves), add(amount, yesReserves))
            sstore(hash, sub(noReserves, userSecondaryReserves))

            // marketToRoundToTreasury DONE
            mstore(0x00, marketId)
            mstore(0x20, 6)
            hash := keccak256(0, 0x40)
            mstore(0x20, hash)
            mstore(0, currentRound)
            hash := keccak256(0, 0x40)
            tstore(2, sload(hash))

            // userToMarketToRoundToYesReserves DONE
            mstore(0x00, caller())
            mstore(0x20, 7)
            hash := keccak256(0, 0x40)
            mstore(0x20, hash)
            mstore(0, marketId)
            hash := keccak256(0, 0x40)
            mstore(0x20, hash)
            mstore(0, currentRound)
            hash := keccak256(0, 0x40)
            let state := sload(hash)
            if lt(state, amount) {
               mstore(0x00, 0x7b9c8916) //InvalidReserves()
               revert(0x1c, 0x04)
            }
            tstore(3, sub(state, amount))

            // userToMarketToRoundToNoReserves DONE
            mstore(0x00, caller())
            mstore(0x20, 8)
            hash := keccak256(0, 0x40)
            mstore(0x20, hash)
            mstore(0, marketId)
            hash := keccak256(0, 0x40)
            mstore(0x20, hash)
            mstore(0, currentRound)
            hash := keccak256(0, 0x40)
            tstore(4, add(sload(hash), userSecondaryReserves))

            // marketToRoundToOutYesShares DONE
            mstore(0x00, marketId)
            mstore(0x20, 14)
            hash := keccak256(0, 0x40)
            mstore(0x20, hash)
            mstore(0, currentRound)
            hash := keccak256(0, 0x40)
            tstore(5, sub(sload(hash), amount))

            // marketToRoundToOutNoShares DONE
            mstore(0x00, marketId)
            mstore(0x20, 15)
            hash := keccak256(0, 0x40)
            mstore(0x20, hash)
            mstore(0, currentRound)
            hash := keccak256(0, 0x40)
            tstore(6, add(sload(hash), userSecondaryReserves))
        }
    }

    /**
     * @notice Internal function to sell NO shares for YES shares
     * @dev Uses AMM formula: p = s_amount * P / (S + s_amount)
     * @param amount Amount of NO shares to sell
     * @param marketId Market identifier
     * @param currentRound Round identifier
     * @return userPrimaryReserves Amount of YES shares received
     * 
     * Effects:
     * - Increases NO reserves by amount
     * - Decreases YES reserves by userPrimaryReserves
     * - Updates user balances in transient storage
     * - Updates outstanding shares in transient storage
     */
    function _sellNo(uint256 amount, uint256 marketId, uint256 currentRound) internal returns(uint256 userPrimaryReserves) {
        assembly {
            // marketToRoundToNoReserves DONE
            mstore(0x00, marketId)
            mstore(0x20, 5)
            let hash := keccak256(0, 0x40)
            mstore(0, currentRound)
            mstore(0x20, hash)
            hash := keccak256(0, 0x40)
            let noReserves := sload(hash)
            sstore(hash, add(noReserves, amount))

            // marketToRoundToYesReserves DONE
            mstore(0x00, marketId)
            mstore(0x20, 4)
            hash := keccak256(0, 0x40)
            mstore(0, currentRound)
            mstore(0x20, hash)
            hash := keccak256(0, 0x40)
            let yesReserves := sload(hash)
            // p = s_amount * P / (S + s_amount)
            userPrimaryReserves := div(mul(amount, yesReserves), add(amount, noReserves))
            sstore(hash, sub(yesReserves, userPrimaryReserves))

            // marketToRoundToTreasury DONE
            mstore(0x00, marketId)
            mstore(0x20, 6)
            hash := keccak256(0, 0x40)
            mstore(0x20, hash)
            mstore(0, currentRound)
            hash := keccak256(0, 0x40)
            tstore(2, sload(hash))

            // userToMarketToRoundToYesReserves DONE
            mstore(0x00, caller())
            mstore(0x20, 7)
            hash := keccak256(0, 0x40)
            mstore(0x20, hash)
            mstore(0, marketId)
            hash := keccak256(0, 0x40)
            mstore(0x20, hash)
            mstore(0, currentRound)
            hash := keccak256(0, 0x40)
            tstore(3, add(sload(hash), userPrimaryReserves))

            // userToMarketToRoundToNoReserves DONE
            mstore(0x00, caller())
            mstore(0x20, 8)
            hash := keccak256(0, 0x40)
            mstore(0x20, hash)
            mstore(0, marketId)
            hash := keccak256(0, 0x40)
            mstore(0x20, hash)
            mstore(0, currentRound)
            hash := keccak256(0, 0x40)
            let state := sload(hash)
            if lt(state, amount) {
                mstore(0x00, 0x7b9c8916) //InvalidReserves()
                revert(0x1c, 0x04)
            }
            tstore(4, sub(state, amount))

            // marketToRoundToOutYesShares DONE
            mstore(0x00, marketId)
            mstore(0x20, 14)
            hash := keccak256(0, 0x40)
            mstore(0x20, hash)
            mstore(0, currentRound)
            hash := keccak256(0, 0x40)
            tstore(5, add(sload(hash), userPrimaryReserves))

            // marketToRoundToOutNoShares DONE
            mstore(0x00, marketId)
            mstore(0x20, 15)
            hash := keccak256(0, 0x40)
            mstore(0x20, hash)
            mstore(0, currentRound)
            hash := keccak256(0, 0x40)
            tstore(6, sub(sload(hash), amount))
        }
    }

    //MARKET INFO VIEW FUNCTIONS
    /**
     * @notice Get market data for all markets in the current round
     * @return marketData Array of MarketData structs for all available markets
     */
    function currentRoundInfo() external view returns(MarketData[] memory marketData) {
        uint256 len = availableMarkets.length();
        marketData = new MarketData[](len);
        uint256 roundId = universalRound;
        uint256 currentRoundStart = roundStart;
        for(uint i=0; i<len; i++) {
            uint256 marketId = availableMarkets.at(i);
            uint256 currentPrice = _oraclePx(marketId);
            marketData[i] = MarketData({
                marketId: marketId,
                roundId: roundId,
                roundStart: currentRoundStart,
                yesReserves: marketToRoundToYesReserves[marketId][roundId],
                noReserves: marketToRoundToNoReserves[marketId][roundId],
                marketTreasury: marketToRoundToTreasury[marketId][roundId],
                lastPrice: marketToRoundToPrice[marketId][roundId-1],
                currentPrice: currentPrice,
                result: marketToRoundToResult[marketId][roundId],
                outYesReserves: marketToRoundToOutYesShares[marketId][roundId],
                outNoReserves: marketToRoundToOutNoShares[marketId][roundId]
            });
        }
    }


    //MARKET INFO VIEW FUNCTIONS
    /**
     * @notice Get market data for all markets in the current and next round
     * @return roundId Current round's number
     * @return marketDataCurrent Array of MarketData structs for all available markets for active round
     * @return marketDataFuture Array of MarketData structs for all available markets for next round
     */
    function currentAndFutureRoundInfo() external view returns(uint256 roundId, MarketDataWithHistory[] memory marketDataCurrent, MarketDataWithHistory[] memory marketDataFuture) {
        uint256 len = availableMarkets.length();
        roundId = universalRound;
        uint256 historyLen = roundId > 10 ? 10 : roundId-1;
        marketDataCurrent = new MarketDataWithHistory[](len);
        marketDataFuture = new MarketDataWithHistory[](len);
        uint256 futureRound = roundId + 1;
        uint256 currentRoundStart = roundStart;
        for(uint i=0; i<len; i++) {
            uint256[] memory history = new uint256[](historyLen);
            uint256 marketId = availableMarkets.at(i);
            uint256 currentPrice = _oraclePx(marketId);
            for(uint j=0; j<historyLen; j++) {
                history[j] = marketToRoundToResult[marketId][roundId-j-1];
            }
            marketDataCurrent[i] = MarketDataWithHistory({
                marketId: marketId,
                roundId: roundId,
                roundStart: currentRoundStart,
                yesReserves: marketToRoundToYesReserves[marketId][roundId],
                noReserves: marketToRoundToNoReserves[marketId][roundId],
                marketTreasury: marketToRoundToTreasury[marketId][roundId],
                lastPrice: marketToRoundToPrice[marketId][roundId-1],
                currentPrice: currentPrice,
                result: marketToRoundToResult[marketId][roundId],
                outYesReserves: marketToRoundToOutYesShares[marketId][roundId],
                outNoReserves: marketToRoundToOutNoShares[marketId][roundId],
                delistingRound: marketToDelistingRound[marketId],
                history: history
            });
            marketDataFuture[i] = MarketDataWithHistory({
                marketId: marketId,
                roundId: futureRound,
                roundStart: currentRoundStart,
                yesReserves: marketToRoundToYesReserves[marketId][futureRound],
                noReserves: marketToRoundToNoReserves[marketId][futureRound],
                marketTreasury: marketToRoundToTreasury[marketId][futureRound],
                lastPrice: marketToRoundToPrice[marketId][roundId],
                currentPrice: currentPrice,
                result: marketToRoundToResult[marketId][futureRound],
                outYesReserves: marketToRoundToOutYesShares[marketId][futureRound],
                outNoReserves: marketToRoundToOutNoShares[marketId][futureRound],
                delistingRound: marketToDelistingRound[marketId],
                history: history
            });
            delete history;
        }
    }

    /**
     * @notice Get market data for all markets in a specific round
     * @param roundId Round identifier to query
     * @return marketData Array of MarketData structs for all markets in the round
     */
    function inputRoundInfo(uint256 roundId) external view returns(MarketData[] memory marketData) {
        uint256 len = availableMarkets.length();
        marketData = new MarketData[](len);
        uint256 currentRoundStart = roundStart;
        for(uint i=0; i<len; i++) {
            uint256 marketId = availableMarkets.at(i);
            uint256 cPrice = marketToRoundToPrice[marketId][roundId];
            uint256 currentPrice = cPrice == 0 ? _oraclePx(marketId): cPrice;
            marketData[i] = MarketData({
                marketId: marketId,
                roundId: roundId,
                roundStart: currentRoundStart,
                yesReserves: marketToRoundToYesReserves[marketId][roundId],
                noReserves: marketToRoundToNoReserves[marketId][roundId],
                marketTreasury: marketToRoundToTreasury[marketId][roundId],
                lastPrice: marketToRoundToPrice[marketId][roundId-1],
                currentPrice: currentPrice,
                result: marketToRoundToResult[marketId][roundId],
                outYesReserves: marketToRoundToOutYesShares[marketId][roundId],
                outNoReserves: marketToRoundToOutNoShares[marketId][roundId]
            });
        }
    }

    /**
     * @notice Get market data for a specific market in the current round
     * @param marketId Market identifier to query
     * @return marketData MarketData struct for the specified market
     */
    function currentSingleMarketRoundInfo(uint256 marketId) external view returns(MarketData memory marketData) {
        uint256 roundId = universalRound;
        uint256 currentRoundStart = roundStart;
        uint256 currentPrice = _oraclePx(marketId);
        marketData = MarketData({
            marketId: marketId,
            roundId: roundId,
            roundStart: currentRoundStart,
            yesReserves: marketToRoundToYesReserves[marketId][roundId],
            noReserves: marketToRoundToNoReserves[marketId][roundId],
            marketTreasury: marketToRoundToTreasury[marketId][roundId],
            lastPrice: marketToRoundToPrice[marketId][roundId-1],
            currentPrice: currentPrice,
            result: marketToRoundToResult[marketId][roundId],
            outYesReserves: marketToRoundToOutYesShares[marketId][roundId],
            outNoReserves: marketToRoundToOutNoShares[marketId][roundId]
        });
    }

    /**
     * @notice Get market data for a specific market in a specific round
     * @param marketId Market identifier to query
     * @param roundId Round identifier to query
     * @return marketData MarketData struct for the specified market and round
     */
    function inputSingleMarketRoundInfo(uint256 marketId, uint256 roundId) external view returns(MarketDataWithHistory memory marketData) {
        uint256 currentRoundStart = roundStart;
        uint256 cPrice = marketToRoundToPrice[marketId][roundId];
        uint256 currentPrice = cPrice == 0 ? _oraclePx(marketId): cPrice;
        uint256 historyLen = roundId > 10 ? 10 : roundId-1;
        uint256[] memory history = new uint256[](historyLen);
        for(uint j=0; j<historyLen; j++) {
            history[j] = marketToRoundToResult[marketId][roundId-j-1];
        }
        marketData = MarketDataWithHistory({
            marketId: marketId,
            roundId: roundId,
            roundStart: currentRoundStart,
            yesReserves: marketToRoundToYesReserves[marketId][roundId],
            noReserves: marketToRoundToNoReserves[marketId][roundId],
            marketTreasury: marketToRoundToTreasury[marketId][roundId],
            lastPrice: marketToRoundToPrice[marketId][roundId-1],
            currentPrice: currentPrice,
            result: marketToRoundToResult[marketId][roundId],
            outYesReserves: marketToRoundToOutYesShares[marketId][roundId],
            outNoReserves: marketToRoundToOutNoShares[marketId][roundId],
            delistingRound: marketToDelistingRound[marketId],
            history: history
        });
    }

    /**
     * @notice Get market history for a specific market
     * @param marketId Market identifier to query
     * @return marketData MarketData struct for the specified market and round
     */
    function inputMarketRoundHistory(uint256 marketId) external view returns(MarketHistory[] memory marketData) {
        uint256 roundId = universalRound;
        uint256 historyLen = roundId > 150 ? 150 : roundId-1;
        uint256 index = roundId-historyLen;
        marketData = new MarketHistory[](historyLen);
        for(uint j=0; j<historyLen; j++) {
            marketData[j] = MarketHistory({
                marketId: marketId,
                roundId: index + j,
                openPrice: marketToRoundToPrice[marketId][index - 1+j],
                closePrice: marketToRoundToPrice[marketId][index + j],
                result: marketToRoundToResult[marketId][index + j],
                outYesReserves: marketToRoundToOutYesShares[marketId][index+j],
                outNoReserves: marketToRoundToOutNoShares[marketId][index+j]
            });
        }
    }

    /**
     * @notice Check if current round can be resolved and get resolver fees
     * @return isResolvable True if 10 minutes have passed and round can be resolved
     * @return secondsLeft Seconds remaining until round can be resolved (0 if resolvable)
     * @return currentRoundFees Accumulated resolver fees for current round (40% of trading fees)
     */
    function checkResolutionStatus() external view returns(bool isResolvable, uint256 secondsLeft, uint256 currentRoundFees) {
        isResolvable = block.timestamp >= roundStart + 600;
        secondsLeft = block.timestamp < roundStart + 600 ? roundStart + 600 - block.timestamp : 0;
        currentRoundFees = roundIdToResolverFees[universalRound];
    }

    //USER INFO VIEW FUNCTIONS
    /**
     * @notice Get all unclaimed round IDs for a user in a specific market
     * @param user User address to query
     * @param marketId Market identifier
     * @return roundIds Array of round IDs where user has unclaimed positions
     */
    function userUnclaimedRoundsPerMarketId(address user, uint256 marketId) external view returns (uint256[] memory roundIds) {
        return userToActiveRoundsPerMarket[user][marketId];
    }

    /**
     * @notice Get unclaimed round IDs with pagination (500 per page)
     * @param user User address to query
     * @param marketId Market identifier
     * @param page Page number (0-indexed)
     * @return total Total number of unclaimed rounds
     * @return roundIds Array of round IDs for the requested page (max 500)
     */
    function userUnclaimedRoundsPerMarketIdWithPage(address user, uint256 marketId, uint256 page) external view returns (uint256 total, uint256[] memory roundIds) {
        total = userToActiveRoundsPerMarket[user][marketId].length;
        uint256 pageSize = 500;
        uint256 startIndex = page * pageSize;

        if (startIndex >= total) {
            roundIds = new uint256[](0);
            return (total, roundIds);
        }

        uint256 remaining = total - startIndex;
        uint256 length = remaining < pageSize ? remaining : pageSize;
        roundIds = new uint256[](length);

        for (uint256 i = 0; i < length; i++) {
            roundIds[i] = userToActiveRoundsPerMarket[user][marketId][startIndex + i];
        }

        return (total, roundIds);
    }

    /**
     * @notice Get detailed data for unclaimed rounds with pagination (100 per page)
     * @param user User address to query
     * @param marketId Market identifier
     * @param page Page number (0-indexed)
     * @return total Total number of unclaimed rounds
     * @return userData Array of UserData structs for the requested page (max 100)
     */
    function userUnclaimedRoundsDataPerMarketId(address user, uint256 marketId, uint256 page) external view returns(uint256 total, UserData[] memory userData){
        total = userToActiveRoundsPerMarket[user][marketId].length;
        uint256 pageSize = 100;
        uint256 startIndex = page * pageSize;
        if (startIndex >= total) {
            userData = new UserData[](0);
            return (total, userData);
        }

        uint256 remaining = total - startIndex;
        uint256 length = remaining < pageSize ? remaining : pageSize;
        userData = new UserData[](length);
        for(uint i=0; i<length;i++) {
            uint256 roundId = userToActiveRoundsPerMarket[user][marketId][startIndex + i];
            userData[i] = UserData({
                marketId: marketId,
                roundId: roundId,
                result: marketToRoundToResult[marketId][roundId],
                outYesReserves: marketToRoundToOutYesShares[marketId][roundId],
                outNoReserves: marketToRoundToOutNoShares[marketId][roundId],
                userYesReserves: userToMarketToRoundToYesReserves[user][marketId][roundId],
                userNoReserves: userToMarketToRoundToNoReserves[user][marketId][roundId],
                treasury: marketToRoundToTreasury[marketId][roundId],
                userRedeemed: userToRedeemedMarketRound[user][marketId][roundId]
            });
        }
    }

    /**
     * @notice Get unclaimed rounds across all markets for a user
     * @param user User address to query
     * @return roundsPerMarket Array of UserToRoundsPerMarket structs for all markets
     */
    function userToUnclaimedRounds(address user) external view returns(UserToRoundsPerMarket[] memory roundsPerMarket) {
        uint256 len = availableMarkets.length();
        roundsPerMarket = new UserToRoundsPerMarket[](len);
        for(uint i=0; i<len;i++) {
            uint256 marketId = availableMarkets.at(i);
            roundsPerMarket[i] = UserToRoundsPerMarket({
                marketId: marketId,
                roundIds: userToActiveRoundsPerMarket[user][marketId]
            });
        }
    }

    /**
     * @notice Get user data for all markets in the current round
     * @param user User address to query
     * @return userData Array of UserData structs for all markets in current round
     */
    function userDataPerCurrentRoundId(address user) external view returns(UserData[] memory userData){
        uint256 len = availableMarkets.length();
        userData = new UserData[](len);
        uint256 roundId = universalRound;
        for(uint i=0; i<len;i++) {
            uint256 marketId = availableMarkets.at(i);
            userData[i] = UserData({
                marketId: marketId,
                roundId: roundId,
                result: marketToRoundToResult[marketId][roundId],
                outYesReserves: marketToRoundToOutYesShares[marketId][roundId],
                outNoReserves: marketToRoundToOutNoShares[marketId][roundId],
                userYesReserves: userToMarketToRoundToYesReserves[user][marketId][roundId],
                userNoReserves: userToMarketToRoundToNoReserves[user][marketId][roundId],
                treasury: marketToRoundToTreasury[marketId][roundId],
                userRedeemed: userToRedeemedMarketRound[user][marketId][roundId]
            });
        }
    }

    /**
     * @notice Get user data for a specific market in the current round
     * @param user User address to query
     * @param marketId Market identifier
     * @return userData UserData struct for the specified market in current round
     */
    function userDataPerMarketAndCurrentRoundId(address user, uint256 marketId) external view returns(UserData memory userData){
        uint256 roundId = universalRound;
        userData = UserData({
            marketId: marketId,
            roundId: roundId,
            result: marketToRoundToResult[marketId][roundId],
            outYesReserves: marketToRoundToOutYesShares[marketId][roundId],
            outNoReserves: marketToRoundToOutNoShares[marketId][roundId],
            userYesReserves: userToMarketToRoundToYesReserves[user][marketId][roundId],
            userNoReserves: userToMarketToRoundToNoReserves[user][marketId][roundId],
            treasury: marketToRoundToTreasury[marketId][roundId],
            userRedeemed: userToRedeemedMarketRound[user][marketId][roundId]
        });
    }

    /**
     * @notice Get user data for all markets in a specific round
     * @param user User address to query
     * @param roundId Round identifier
     * @return userData Array of UserData structs for all markets in the round
     */
    function userDataPerRoundId(address user, uint256 roundId) external view returns(UserData[] memory userData){
        uint256 len = availableMarkets.length();
        userData = new UserData[](len);
        for(uint i=0; i<len;i++) {
            uint256 marketId = availableMarkets.at(i);
            userData[i] = UserData({
                marketId: marketId,
                roundId: roundId,
                result: marketToRoundToResult[marketId][roundId],
                outYesReserves: marketToRoundToOutYesShares[marketId][roundId],
                outNoReserves: marketToRoundToOutNoShares[marketId][roundId],
                userYesReserves: userToMarketToRoundToYesReserves[user][marketId][roundId],
                userNoReserves: userToMarketToRoundToNoReserves[user][marketId][roundId],
                treasury: marketToRoundToTreasury[marketId][roundId],
                userRedeemed: userToRedeemedMarketRound[user][marketId][roundId]
            });
        }
    }

    /**
     * @notice Get user data for a specific market and round
     * @param user User address to query
     * @param marketId Market identifier
     * @param roundId Round identifier
     * @return userData UserData struct for the specified market and round
     */
    function userDataPerMarketIdAndRoundId(address user, uint256 marketId, uint256 roundId) external view returns(UserData memory userData){
        userData = UserData({
            marketId: marketId,
            roundId: roundId,
            result: marketToRoundToResult[marketId][roundId],
            outYesReserves: marketToRoundToOutYesShares[marketId][roundId],
            outNoReserves: marketToRoundToOutNoShares[marketId][roundId],
            userYesReserves: userToMarketToRoundToYesReserves[user][marketId][roundId],
            userNoReserves: userToMarketToRoundToNoReserves[user][marketId][roundId],
            treasury: marketToRoundToTreasury[marketId][roundId],
            userRedeemed: userToRedeemedMarketRound[user][marketId][roundId]
        });
    }

    /**
     * @notice Get user data for a specific market across multiple rounds
     * @param user User address to query
     * @param marketId Market identifier
     * @param roundIds Array of round identifiers
     * @return userData Array of UserData structs for the specified rounds
     */
    function userDataPerMarketIdAndRoundIds(address user, uint256 marketId, uint256[] memory roundIds) external view returns(UserData[] memory userData){
        uint256 len = roundIds.length;
        userData = new UserData[](len);
        for(uint i=0; i<len;i++) {
            uint256 roundId = roundIds[i];
            userData[i] = UserData({
                marketId: marketId,
                roundId: roundId,
                result: marketToRoundToResult[marketId][roundId],
                outYesReserves: marketToRoundToOutYesShares[marketId][roundId],
                outNoReserves: marketToRoundToOutNoShares[marketId][roundId],
                userYesReserves: userToMarketToRoundToYesReserves[user][marketId][roundId],
                userNoReserves: userToMarketToRoundToNoReserves[user][marketId][roundId],
                treasury: marketToRoundToTreasury[marketId][roundId],
                userRedeemed: userToRedeemedMarketRound[user][marketId][roundId]
            });
        }
    }

    /**
     * @notice Calculate expected shares for a given input amount
     * @dev Applies 0.3% fee before calculation. Used for price quotes
     * @param amountIn Amount of HYPE to spend
     * @param marketId Market identifier
     * @param roundId Round identifier
     * @param side 0 for YES, 1 for NO
     * @return amountOut Expected shares to receive (after fee)
     * 
     * Formula:
     * - amountAfterFee = amountIn * 997 / 1000
     * - If YES: amountOut = (amountAfterFee * yesReserves) / (amountAfterFee + noReserves) + amountAfterFee
     * - If NO: amountOut = (amountAfterFee * noReserves) / (amountAfterFee + yesReserves) + amountAfterFee
     */
    function getAmountOut(uint256 amountIn, uint256 marketId, uint256 roundId, uint256 side) external view returns(uint256 amountOut) {
        uint256 yesShares = marketToRoundToYesReserves[marketId][roundId];
        uint256 noShares = marketToRoundToNoReserves[marketId][roundId];
        amountIn = amountIn * 997/1000;
        if (side == 0) {
            amountOut = ((amountIn * yesShares) / (amountIn + noShares)) + amountIn;
        } else {
            amountOut = ((amountIn * noShares) / (amountIn + yesShares)) + amountIn;
        }
    }

    function getAllAvailableMarkets() external view returns(uint256[] memory) {
        return availableMarkets.values();
    }

    function getAllMarkets() external view returns(uint256[] memory) {
        return allMarkets.values();
    }

    function getBothMarkets() external view returns(uint256[] memory, uint256[] memory) {
        return (availableMarkets.values(), allMarkets.values());
    }


}

File 2 of 2 : EnumerableSetLib.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

// This file is auto-generated.

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

/// @dev An enumerable address set in storage.
struct AddressSet {
    uint256 _spacer;
}

/// @dev An enumerable bytes32 set in storage.
struct Bytes32Set {
    uint256 _spacer;
}

/// @dev An enumerable uint256 set in storage.
struct Uint256Set {
    uint256 _spacer;
}

/// @dev An enumerable int256 set in storage.
struct Int256Set {
    uint256 _spacer;
}

/// @dev An enumerable uint8 set in storage. Useful for enums.
struct Uint8Set {
    uint256 data;
}

using EnumerableSetLib for AddressSet global;
using EnumerableSetLib for Bytes32Set global;
using EnumerableSetLib for Uint256Set global;
using EnumerableSetLib for Int256Set global;
using EnumerableSetLib for Uint8Set global;

/// @notice Library for managing enumerable sets in storage.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/g/EnumerableSetLib.sol)
///
/// @dev Note:
/// In many applications, the number of elements in an enumerable set is small.
/// This enumerable set implementation avoids storing the length and indices
/// for up to 3 elements. Once the length exceeds 3 for the first time, the length
/// and indices will be initialized. The amortized cost of adding elements is O(1).
///
/// The AddressSet implementation packs the length with the 0th entry.
///
/// All enumerable sets except Uint8Set use a pop and swap mechanism to remove elements.
/// This means that the iteration order of elements can change between element removals.
library EnumerableSetLib {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The index must be less than the length.
    error IndexOutOfBounds();

    /// @dev The value cannot be the zero sentinel.
    error ValueIsZeroSentinel();

    /// @dev Cannot accommodate a new unique value with the capacity.
    error ExceedsCapacity();

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

    /// @dev The index to represent a value that does not exist.
    uint256 internal constant NOT_FOUND = type(uint256).max;

    /// @dev A sentinel value to denote the zero value in storage.
    /// No elements can be equal to this value.
    /// `uint72(bytes9(keccak256(bytes("_ZERO_SENTINEL"))))`.
    uint256 private constant _ZERO_SENTINEL = 0xfbb67fda52d4bfb8bf;

    /// @dev The storage layout is given by:
    /// ```
    ///     mstore(0x04, _ENUMERABLE_ADDRESS_SET_SLOT_SEED)
    ///     mstore(0x00, set.slot)
    ///     let rootSlot := keccak256(0x00, 0x24)
    ///     mstore(0x20, rootSlot)
    ///     mstore(0x00, shr(96, shl(96, value)))
    ///     let positionSlot := keccak256(0x00, 0x40)
    ///     let valueSlot := add(rootSlot, sload(positionSlot))
    ///     let valueInStorage := shr(96, sload(valueSlot))
    ///     let lazyLength := shr(160, shl(160, sload(rootSlot)))
    /// ```
    uint256 private constant _ENUMERABLE_ADDRESS_SET_SLOT_SEED = 0x978aab92;

    /// @dev The storage layout is given by:
    /// ```
    ///     mstore(0x04, _ENUMERABLE_WORD_SET_SLOT_SEED)
    ///     mstore(0x00, set.slot)
    ///     let rootSlot := keccak256(0x00, 0x24)
    ///     mstore(0x20, rootSlot)
    ///     mstore(0x00, value)
    ///     let positionSlot := keccak256(0x00, 0x40)
    ///     let valueSlot := add(rootSlot, sload(positionSlot))
    ///     let valueInStorage := sload(valueSlot)
    ///     let lazyLength := sload(not(rootSlot))
    /// ```
    uint256 private constant _ENUMERABLE_WORD_SET_SLOT_SEED = 0x18fb5864;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     GETTERS / SETTERS                      */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the number of elements in the set.
    function length(AddressSet storage set) internal view returns (uint256 result) {
        bytes32 rootSlot = _rootSlot(set);
        /// @solidity memory-safe-assembly
        assembly {
            let rootPacked := sload(rootSlot)
            let n := shr(160, shl(160, rootPacked))
            result := shr(1, n)
            for {} iszero(or(iszero(shr(96, rootPacked)), n)) {} {
                result := 1
                if iszero(sload(add(rootSlot, result))) { break }
                result := 2
                if iszero(sload(add(rootSlot, result))) { break }
                result := 3
                break
            }
        }
    }

    /// @dev Returns the number of elements in the set.
    function length(Bytes32Set storage set) internal view returns (uint256 result) {
        bytes32 rootSlot = _rootSlot(set);
        /// @solidity memory-safe-assembly
        assembly {
            let n := sload(not(rootSlot))
            result := shr(1, n)
            for {} iszero(n) {} {
                result := 0
                if iszero(sload(add(rootSlot, result))) { break }
                result := 1
                if iszero(sload(add(rootSlot, result))) { break }
                result := 2
                if iszero(sload(add(rootSlot, result))) { break }
                result := 3
                break
            }
        }
    }

    /// @dev Returns the number of elements in the set.
    function length(Uint256Set storage set) internal view returns (uint256 result) {
        result = length(_toBytes32Set(set));
    }

    /// @dev Returns the number of elements in the set.
    function length(Int256Set storage set) internal view returns (uint256 result) {
        result = length(_toBytes32Set(set));
    }

    /// @dev Returns the number of elements in the set.
    function length(Uint8Set storage set) internal view returns (uint256 result) {
        /// @solidity memory-safe-assembly
        assembly {
            for { let packed := sload(set.slot) } packed { result := add(1, result) } {
                packed := xor(packed, and(packed, add(1, not(packed))))
            }
        }
    }

    /// @dev Returns whether `value` is in the set.
    function contains(AddressSet storage set, address value) internal view returns (bool result) {
        bytes32 rootSlot = _rootSlot(set);
        /// @solidity memory-safe-assembly
        assembly {
            value := shr(96, shl(96, value))
            if eq(value, _ZERO_SENTINEL) {
                mstore(0x00, 0xf5a267f1) // `ValueIsZeroSentinel()`.
                revert(0x1c, 0x04)
            }
            if iszero(value) { value := _ZERO_SENTINEL }
            let rootPacked := sload(rootSlot)
            for {} 1 {} {
                if iszero(shr(160, shl(160, rootPacked))) {
                    result := 1
                    if eq(shr(96, rootPacked), value) { break }
                    if eq(shr(96, sload(add(rootSlot, 1))), value) { break }
                    if eq(shr(96, sload(add(rootSlot, 2))), value) { break }
                    result := 0
                    break
                }
                mstore(0x20, rootSlot)
                mstore(0x00, value)
                result := iszero(iszero(sload(keccak256(0x00, 0x40))))
                break
            }
        }
    }

    /// @dev Returns whether `value` is in the set.
    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool result) {
        bytes32 rootSlot = _rootSlot(set);
        /// @solidity memory-safe-assembly
        assembly {
            if eq(value, _ZERO_SENTINEL) {
                mstore(0x00, 0xf5a267f1) // `ValueIsZeroSentinel()`.
                revert(0x1c, 0x04)
            }
            if iszero(value) { value := _ZERO_SENTINEL }
            for {} 1 {} {
                if iszero(sload(not(rootSlot))) {
                    result := 1
                    if eq(sload(rootSlot), value) { break }
                    if eq(sload(add(rootSlot, 1)), value) { break }
                    if eq(sload(add(rootSlot, 2)), value) { break }
                    result := 0
                    break
                }
                mstore(0x20, rootSlot)
                mstore(0x00, value)
                result := iszero(iszero(sload(keccak256(0x00, 0x40))))
                break
            }
        }
    }

    /// @dev Returns whether `value` is in the set.
    function contains(Uint256Set storage set, uint256 value) internal view returns (bool result) {
        result = contains(_toBytes32Set(set), bytes32(value));
    }

    /// @dev Returns whether `value` is in the set.
    function contains(Int256Set storage set, int256 value) internal view returns (bool result) {
        result = contains(_toBytes32Set(set), bytes32(uint256(value)));
    }

    /// @dev Returns whether `value` is in the set.
    function contains(Uint8Set storage set, uint8 value) internal view returns (bool result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := and(1, shr(and(0xff, value), sload(set.slot)))
        }
    }

    /// @dev Adds `value` to the set. Returns whether `value` was not in the set.
    function add(AddressSet storage set, address value) internal returns (bool result) {
        bytes32 rootSlot = _rootSlot(set);
        /// @solidity memory-safe-assembly
        assembly {
            value := shr(96, shl(96, value))
            if eq(value, _ZERO_SENTINEL) {
                mstore(0x00, 0xf5a267f1) // `ValueIsZeroSentinel()`.
                revert(0x1c, 0x04)
            }
            if iszero(value) { value := _ZERO_SENTINEL }
            let rootPacked := sload(rootSlot)
            for { let n := shr(160, shl(160, rootPacked)) } 1 {} {
                mstore(0x20, rootSlot)
                if iszero(n) {
                    let v0 := shr(96, rootPacked)
                    if iszero(v0) {
                        sstore(rootSlot, shl(96, value))
                        result := 1
                        break
                    }
                    if eq(v0, value) { break }
                    let v1 := shr(96, sload(add(rootSlot, 1)))
                    if iszero(v1) {
                        sstore(add(rootSlot, 1), shl(96, value))
                        result := 1
                        break
                    }
                    if eq(v1, value) { break }
                    let v2 := shr(96, sload(add(rootSlot, 2)))
                    if iszero(v2) {
                        sstore(add(rootSlot, 2), shl(96, value))
                        result := 1
                        break
                    }
                    if eq(v2, value) { break }
                    mstore(0x00, v0)
                    sstore(keccak256(0x00, 0x40), 1)
                    mstore(0x00, v1)
                    sstore(keccak256(0x00, 0x40), 2)
                    mstore(0x00, v2)
                    sstore(keccak256(0x00, 0x40), 3)
                    rootPacked := or(rootPacked, 7)
                    n := 7
                }
                mstore(0x00, value)
                let p := keccak256(0x00, 0x40)
                if iszero(sload(p)) {
                    n := shr(1, n)
                    result := 1
                    sstore(p, add(1, n))
                    if iszero(n) {
                        sstore(rootSlot, or(3, shl(96, value)))
                        break
                    }
                    sstore(add(rootSlot, n), shl(96, value))
                    sstore(rootSlot, add(2, rootPacked))
                    break
                }
                break
            }
        }
    }

    /// @dev Adds `value` to the set. Returns whether `value` was not in the set.
    function add(Bytes32Set storage set, bytes32 value) internal returns (bool result) {
        bytes32 rootSlot = _rootSlot(set);
        /// @solidity memory-safe-assembly
        assembly {
            if eq(value, _ZERO_SENTINEL) {
                mstore(0x00, 0xf5a267f1) // `ValueIsZeroSentinel()`.
                revert(0x1c, 0x04)
            }
            if iszero(value) { value := _ZERO_SENTINEL }
            for { let n := sload(not(rootSlot)) } 1 {} {
                mstore(0x20, rootSlot)
                if iszero(n) {
                    let v0 := sload(rootSlot)
                    if iszero(v0) {
                        sstore(rootSlot, value)
                        result := 1
                        break
                    }
                    if eq(v0, value) { break }
                    let v1 := sload(add(rootSlot, 1))
                    if iszero(v1) {
                        sstore(add(rootSlot, 1), value)
                        result := 1
                        break
                    }
                    if eq(v1, value) { break }
                    let v2 := sload(add(rootSlot, 2))
                    if iszero(v2) {
                        sstore(add(rootSlot, 2), value)
                        result := 1
                        break
                    }
                    if eq(v2, value) { break }
                    mstore(0x00, v0)
                    sstore(keccak256(0x00, 0x40), 1)
                    mstore(0x00, v1)
                    sstore(keccak256(0x00, 0x40), 2)
                    mstore(0x00, v2)
                    sstore(keccak256(0x00, 0x40), 3)
                    n := 7
                }
                mstore(0x00, value)
                let p := keccak256(0x00, 0x40)
                if iszero(sload(p)) {
                    n := shr(1, n)
                    sstore(add(rootSlot, n), value)
                    sstore(p, add(1, n))
                    sstore(not(rootSlot), or(1, shl(1, add(1, n))))
                    result := 1
                    break
                }
                break
            }
        }
    }

    /// @dev Adds `value` to the set. Returns whether `value` was not in the set.
    function add(Uint256Set storage set, uint256 value) internal returns (bool result) {
        result = add(_toBytes32Set(set), bytes32(value));
    }

    /// @dev Adds `value` to the set. Returns whether `value` was not in the set.
    function add(Int256Set storage set, int256 value) internal returns (bool result) {
        result = add(_toBytes32Set(set), bytes32(uint256(value)));
    }

    /// @dev Adds `value` to the set. Returns whether `value` was not in the set.
    function add(Uint8Set storage set, uint8 value) internal returns (bool result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := sload(set.slot)
            let mask := shl(and(0xff, value), 1)
            sstore(set.slot, or(result, mask))
            result := iszero(and(result, mask))
        }
    }

    /// @dev Adds `value` to the set. Returns whether `value` was not in the set.
    /// Reverts if the set grows bigger than the custom on-the-fly capacity `cap`.
    function add(AddressSet storage set, address value, uint256 cap)
        internal
        returns (bool result)
    {
        if (result = add(set, value)) if (length(set) > cap) revert ExceedsCapacity();
    }

    /// @dev Adds `value` to the set. Returns whether `value` was not in the set.
    /// Reverts if the set grows bigger than the custom on-the-fly capacity `cap`.
    function add(Bytes32Set storage set, bytes32 value, uint256 cap)
        internal
        returns (bool result)
    {
        if (result = add(set, value)) if (length(set) > cap) revert ExceedsCapacity();
    }

    /// @dev Adds `value` to the set. Returns whether `value` was not in the set.
    /// Reverts if the set grows bigger than the custom on-the-fly capacity `cap`.
    function add(Uint256Set storage set, uint256 value, uint256 cap)
        internal
        returns (bool result)
    {
        if (result = add(set, value)) if (length(set) > cap) revert ExceedsCapacity();
    }

    /// @dev Adds `value` to the set. Returns whether `value` was not in the set.
    /// Reverts if the set grows bigger than the custom on-the-fly capacity `cap`.
    function add(Int256Set storage set, int256 value, uint256 cap) internal returns (bool result) {
        if (result = add(set, value)) if (length(set) > cap) revert ExceedsCapacity();
    }

    /// @dev Adds `value` to the set. Returns whether `value` was not in the set.
    /// Reverts if the set grows bigger than the custom on-the-fly capacity `cap`.
    function add(Uint8Set storage set, uint8 value, uint256 cap) internal returns (bool result) {
        if (result = add(set, value)) if (length(set) > cap) revert ExceedsCapacity();
    }

    /// @dev Removes `value` from the set. Returns whether `value` was in the set.
    function remove(AddressSet storage set, address value) internal returns (bool result) {
        bytes32 rootSlot = _rootSlot(set);
        /// @solidity memory-safe-assembly
        assembly {
            value := shr(96, shl(96, value))
            if eq(value, _ZERO_SENTINEL) {
                mstore(0x00, 0xf5a267f1) // `ValueIsZeroSentinel()`.
                revert(0x1c, 0x04)
            }
            if iszero(value) { value := _ZERO_SENTINEL }
            let rootPacked := sload(rootSlot)
            for { let n := shr(160, shl(160, rootPacked)) } 1 {} {
                if iszero(n) {
                    result := 1
                    if eq(shr(96, rootPacked), value) {
                        sstore(rootSlot, sload(add(rootSlot, 1)))
                        sstore(add(rootSlot, 1), sload(add(rootSlot, 2)))
                        sstore(add(rootSlot, 2), 0)
                        break
                    }
                    if eq(shr(96, sload(add(rootSlot, 1))), value) {
                        sstore(add(rootSlot, 1), sload(add(rootSlot, 2)))
                        sstore(add(rootSlot, 2), 0)
                        break
                    }
                    if eq(shr(96, sload(add(rootSlot, 2))), value) {
                        sstore(add(rootSlot, 2), 0)
                        break
                    }
                    result := 0
                    break
                }
                mstore(0x20, rootSlot)
                mstore(0x00, value)
                let p := keccak256(0x00, 0x40)
                let position := sload(p)
                if iszero(position) { break }
                n := sub(shr(1, n), 1)
                if iszero(eq(sub(position, 1), n)) {
                    let lastValue := shr(96, sload(add(rootSlot, n)))
                    sstore(add(rootSlot, sub(position, 1)), shl(96, lastValue))
                    mstore(0x00, lastValue)
                    sstore(keccak256(0x00, 0x40), position)
                }
                sstore(rootSlot, or(shl(96, shr(96, sload(rootSlot))), or(shl(1, n), 1)))
                sstore(p, 0)
                result := 1
                break
            }
        }
    }

    /// @dev Removes `value` from the set. Returns whether `value` was in the set.
    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool result) {
        bytes32 rootSlot = _rootSlot(set);
        /// @solidity memory-safe-assembly
        assembly {
            if eq(value, _ZERO_SENTINEL) {
                mstore(0x00, 0xf5a267f1) // `ValueIsZeroSentinel()`.
                revert(0x1c, 0x04)
            }
            if iszero(value) { value := _ZERO_SENTINEL }
            for { let n := sload(not(rootSlot)) } 1 {} {
                if iszero(n) {
                    result := 1
                    if eq(sload(rootSlot), value) {
                        sstore(rootSlot, sload(add(rootSlot, 1)))
                        sstore(add(rootSlot, 1), sload(add(rootSlot, 2)))
                        sstore(add(rootSlot, 2), 0)
                        break
                    }
                    if eq(sload(add(rootSlot, 1)), value) {
                        sstore(add(rootSlot, 1), sload(add(rootSlot, 2)))
                        sstore(add(rootSlot, 2), 0)
                        break
                    }
                    if eq(sload(add(rootSlot, 2)), value) {
                        sstore(add(rootSlot, 2), 0)
                        break
                    }
                    result := 0
                    break
                }
                mstore(0x20, rootSlot)
                mstore(0x00, value)
                let p := keccak256(0x00, 0x40)
                let position := sload(p)
                if iszero(position) { break }
                n := sub(shr(1, n), 1)
                if iszero(eq(sub(position, 1), n)) {
                    let lastValue := sload(add(rootSlot, n))
                    sstore(add(rootSlot, sub(position, 1)), lastValue)
                    mstore(0x00, lastValue)
                    sstore(keccak256(0x00, 0x40), position)
                }
                sstore(not(rootSlot), or(shl(1, n), 1))
                sstore(p, 0)
                result := 1
                break
            }
        }
    }

    /// @dev Removes `value` from the set. Returns whether `value` was in the set.
    function remove(Uint256Set storage set, uint256 value) internal returns (bool result) {
        result = remove(_toBytes32Set(set), bytes32(value));
    }

    /// @dev Removes `value` from the set. Returns whether `value` was in the set.
    function remove(Int256Set storage set, int256 value) internal returns (bool result) {
        result = remove(_toBytes32Set(set), bytes32(uint256(value)));
    }

    /// @dev Removes `value` from the set. Returns whether `value` was in the set.
    function remove(Uint8Set storage set, uint8 value) internal returns (bool result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := sload(set.slot)
            let mask := shl(and(0xff, value), 1)
            sstore(set.slot, and(result, not(mask)))
            result := iszero(iszero(and(result, mask)))
        }
    }

    /// @dev Shorthand for `isAdd ? set.add(value, cap) : set.remove(value)`.
    function update(AddressSet storage set, address value, bool isAdd, uint256 cap)
        internal
        returns (bool)
    {
        return isAdd ? add(set, value, cap) : remove(set, value);
    }

    /// @dev Shorthand for `isAdd ? set.add(value, cap) : set.remove(value)`.
    function update(Bytes32Set storage set, bytes32 value, bool isAdd, uint256 cap)
        internal
        returns (bool)
    {
        return isAdd ? add(set, value, cap) : remove(set, value);
    }

    /// @dev Shorthand for `isAdd ? set.add(value, cap) : set.remove(value)`.
    function update(Uint256Set storage set, uint256 value, bool isAdd, uint256 cap)
        internal
        returns (bool)
    {
        return isAdd ? add(set, value, cap) : remove(set, value);
    }

    /// @dev Shorthand for `isAdd ? set.add(value, cap) : set.remove(value)`.
    function update(Int256Set storage set, int256 value, bool isAdd, uint256 cap)
        internal
        returns (bool)
    {
        return isAdd ? add(set, value, cap) : remove(set, value);
    }

    /// @dev Shorthand for `isAdd ? set.add(value, cap) : set.remove(value)`.
    function update(Uint8Set storage set, uint8 value, bool isAdd, uint256 cap)
        internal
        returns (bool)
    {
        return isAdd ? add(set, value, cap) : remove(set, value);
    }

    /// @dev Returns all of the values in the set.
    /// Note: This can consume more gas than the block gas limit for large sets.
    function values(AddressSet storage set) internal view returns (address[] memory result) {
        bytes32 rootSlot = _rootSlot(set);
        /// @solidity memory-safe-assembly
        assembly {
            let zs := _ZERO_SENTINEL
            let rootPacked := sload(rootSlot)
            let n := shr(160, shl(160, rootPacked))
            result := mload(0x40)
            let o := add(0x20, result)
            let v := shr(96, rootPacked)
            mstore(o, mul(v, iszero(eq(v, zs))))
            for {} 1 {} {
                if iszero(n) {
                    if v {
                        n := 1
                        v := shr(96, sload(add(rootSlot, n)))
                        if v {
                            n := 2
                            mstore(add(o, 0x20), mul(v, iszero(eq(v, zs))))
                            v := shr(96, sload(add(rootSlot, n)))
                            if v {
                                n := 3
                                mstore(add(o, 0x40), mul(v, iszero(eq(v, zs))))
                            }
                        }
                    }
                    break
                }
                n := shr(1, n)
                for { let i := 1 } lt(i, n) { i := add(i, 1) } {
                    v := shr(96, sload(add(rootSlot, i)))
                    mstore(add(o, shl(5, i)), mul(v, iszero(eq(v, zs))))
                }
                break
            }
            mstore(result, n)
            mstore(0x40, add(o, shl(5, n)))
        }
    }

    /// @dev Returns all of the values in the set.
    /// Note: This can consume more gas than the block gas limit for large sets.
    function values(Bytes32Set storage set) internal view returns (bytes32[] memory result) {
        bytes32 rootSlot = _rootSlot(set);
        /// @solidity memory-safe-assembly
        assembly {
            let zs := _ZERO_SENTINEL
            let n := sload(not(rootSlot))
            result := mload(0x40)
            let o := add(0x20, result)
            for {} 1 {} {
                if iszero(n) {
                    let v := sload(rootSlot)
                    if v {
                        n := 1
                        mstore(o, mul(v, iszero(eq(v, zs))))
                        v := sload(add(rootSlot, n))
                        if v {
                            n := 2
                            mstore(add(o, 0x20), mul(v, iszero(eq(v, zs))))
                            v := sload(add(rootSlot, n))
                            if v {
                                n := 3
                                mstore(add(o, 0x40), mul(v, iszero(eq(v, zs))))
                            }
                        }
                    }
                    break
                }
                n := shr(1, n)
                for { let i := 0 } lt(i, n) { i := add(i, 1) } {
                    let v := sload(add(rootSlot, i))
                    mstore(add(o, shl(5, i)), mul(v, iszero(eq(v, zs))))
                }
                break
            }
            mstore(result, n)
            mstore(0x40, add(o, shl(5, n)))
        }
    }

    /// @dev Returns all of the values in the set.
    /// Note: This can consume more gas than the block gas limit for large sets.
    function values(Uint256Set storage set) internal view returns (uint256[] memory result) {
        result = _toUints(values(_toBytes32Set(set)));
    }

    /// @dev Returns all of the values in the set.
    /// Note: This can consume more gas than the block gas limit for large sets.
    function values(Int256Set storage set) internal view returns (int256[] memory result) {
        result = _toInts(values(_toBytes32Set(set)));
    }

    /// @dev Returns all of the values in the set.
    function values(Uint8Set storage set) internal view returns (uint8[] memory result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := mload(0x40)
            let ptr := add(result, 0x20)
            let o := 0
            for { let packed := sload(set.slot) } packed {} {
                if iszero(and(packed, 0xffff)) {
                    o := add(o, 16)
                    packed := shr(16, packed)
                    continue
                }
                mstore(ptr, o)
                ptr := add(ptr, shl(5, and(packed, 1)))
                o := add(o, 1)
                packed := shr(1, packed)
            }
            mstore(result, shr(5, sub(ptr, add(result, 0x20))))
            mstore(0x40, ptr)
        }
    }

    /// @dev Returns the element at index `i` in the set. Reverts if `i` is out-of-bounds.
    function at(AddressSet storage set, uint256 i) internal view returns (address result) {
        bytes32 rootSlot = _rootSlot(set);
        /// @solidity memory-safe-assembly
        assembly {
            result := shr(96, sload(add(rootSlot, i)))
            result := mul(result, iszero(eq(result, _ZERO_SENTINEL)))
        }
        if (i >= length(set)) revert IndexOutOfBounds();
    }

    /// @dev Returns the element at index `i` in the set. Reverts if `i` is out-of-bounds.
    function at(Bytes32Set storage set, uint256 i) internal view returns (bytes32 result) {
        result = _rootSlot(set);
        /// @solidity memory-safe-assembly
        assembly {
            result := sload(add(result, i))
            result := mul(result, iszero(eq(result, _ZERO_SENTINEL)))
        }
        if (i >= length(set)) revert IndexOutOfBounds();
    }

    /// @dev Returns the element at index `i` in the set. Reverts if `i` is out-of-bounds.
    function at(Uint256Set storage set, uint256 i) internal view returns (uint256 result) {
        result = uint256(at(_toBytes32Set(set), i));
    }

    /// @dev Returns the element at index `i` in the set. Reverts if `i` is out-of-bounds.
    function at(Int256Set storage set, uint256 i) internal view returns (int256 result) {
        result = int256(uint256(at(_toBytes32Set(set), i)));
    }

    /// @dev Returns the element at index `i` in the set. Reverts if `i` is out-of-bounds.
    function at(Uint8Set storage set, uint256 i) internal view returns (uint8 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let packed := sload(set.slot)
            for {} 1 {
                mstore(0x00, 0x4e23d035) // `IndexOutOfBounds()`.
                revert(0x1c, 0x04)
            } {
                if iszero(lt(i, 256)) { continue }
                for { let j := 0 } iszero(eq(i, j)) {} {
                    packed := xor(packed, and(packed, add(1, not(packed))))
                    j := add(j, 1)
                }
                if iszero(packed) { continue }
                break
            }
            // Find first set subroutine, optimized for smaller bytecode size.
            let x := and(packed, add(1, not(packed)))
            let r := shl(7, iszero(iszero(shr(128, x))))
            r := or(r, shl(6, iszero(iszero(shr(64, shr(r, x))))))
            r := or(r, shl(5, lt(0xffffffff, shr(r, x))))
            // For the lower 5 bits of the result, use a De Bruijn lookup.
            // forgefmt: disable-next-item
            result := or(r, byte(and(div(0xd76453e0, shr(r, x)), 0x1f),
                0x001f0d1e100c1d070f090b19131c1706010e11080a1a141802121b1503160405))
        }
    }

    /// @dev Returns the index of `value`. Returns `NOT_FOUND` if the value does not exist.
    function indexOf(AddressSet storage set, address value)
        internal
        view
        returns (uint256 result)
    {
        result = NOT_FOUND;
        if (uint160(value) == _ZERO_SENTINEL) return result;
        bytes32 rootSlot = _rootSlot(set);
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(value) { value := _ZERO_SENTINEL }
            result := not(0)
            let rootPacked := sload(rootSlot)
            for {} 1 {} {
                if iszero(shr(160, shl(160, rootPacked))) {
                    if eq(shr(96, rootPacked), value) {
                        result := 0
                        break
                    }
                    if eq(shr(96, sload(add(rootSlot, 1))), value) {
                        result := 1
                        break
                    }
                    if eq(shr(96, sload(add(rootSlot, 2))), value) {
                        result := 2
                        break
                    }
                    break
                }
                mstore(0x20, rootSlot)
                mstore(0x00, value)
                result := sub(sload(keccak256(0x00, 0x40)), 1)
                break
            }
        }
    }

    /// @dev Returns the index of `value`. Returns `NOT_FOUND` if the value does not exist.
    function indexOf(Bytes32Set storage set, bytes32 value)
        internal
        view
        returns (uint256 result)
    {
        result = NOT_FOUND;
        if (uint256(value) == _ZERO_SENTINEL) return result;
        bytes32 rootSlot = _rootSlot(set);
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(value) { value := _ZERO_SENTINEL }
            for {} 1 {} {
                if iszero(sload(not(rootSlot))) {
                    if eq(sload(rootSlot), value) {
                        result := 0
                        break
                    }
                    if eq(sload(add(rootSlot, 1)), value) {
                        result := 1
                        break
                    }
                    if eq(sload(add(rootSlot, 2)), value) {
                        result := 2
                        break
                    }
                    break
                }
                mstore(0x20, rootSlot)
                mstore(0x00, value)
                result := sub(sload(keccak256(0x00, 0x40)), 1)
                break
            }
        }
    }

    /// @dev Returns the index of `value`. Returns `NOT_FOUND` if the value does not exist.
    function indexOf(Uint256Set storage set, uint256 i) internal view returns (uint256 result) {
        result = indexOf(_toBytes32Set(set), bytes32(i));
    }

    /// @dev Returns the index of `value`. Returns `NOT_FOUND` if the value does not exist.
    function indexOf(Int256Set storage set, int256 i) internal view returns (uint256 result) {
        result = indexOf(_toBytes32Set(set), bytes32(uint256(i)));
    }

    /// @dev Returns the index of `value`. Returns `NOT_FOUND` if the value does not exist.
    function indexOf(Uint8Set storage set, uint8 value) internal view returns (uint256 result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := not(0)
            let packed := sload(set.slot)
            let m := shl(and(0xff, value), 1)
            if and(packed, m) {
                result := 0
                for { let p := and(packed, sub(m, 1)) } p {} {
                    p := xor(p, and(p, add(1, not(p))))
                    result := add(result, 1)
                }
            }
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      PRIVATE HELPERS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the root slot.
    function _rootSlot(AddressSet storage s) private pure returns (bytes32 r) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x04, _ENUMERABLE_ADDRESS_SET_SLOT_SEED)
            mstore(0x00, s.slot)
            r := keccak256(0x00, 0x24)
        }
    }

    /// @dev Returns the root slot.
    function _rootSlot(Bytes32Set storage s) private pure returns (bytes32 r) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x04, _ENUMERABLE_WORD_SET_SLOT_SEED)
            mstore(0x00, s.slot)
            r := keccak256(0x00, 0x24)
        }
    }

    /// @dev Casts to a Bytes32Set.
    function _toBytes32Set(Uint256Set storage s) private pure returns (Bytes32Set storage c) {
        /// @solidity memory-safe-assembly
        assembly {
            c.slot := s.slot
        }
    }

    /// @dev Casts to a Bytes32Set.
    function _toBytes32Set(Int256Set storage s) private pure returns (Bytes32Set storage c) {
        /// @solidity memory-safe-assembly
        assembly {
            c.slot := s.slot
        }
    }

    /// @dev Casts to a uint256 array.
    function _toUints(bytes32[] memory a) private pure returns (uint256[] memory c) {
        /// @solidity memory-safe-assembly
        assembly {
            c := a
        }
    }

    /// @dev Casts to a int256 array.
    function _toInts(bytes32[] memory a) private pure returns (int256[] memory c) {
        /// @solidity memory-safe-assembly
        assembly {
            c := a
        }
    }
}

Settings
{
  "evmVersion": "cancun",
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "remappings": [
    "project/:solady/=npm/[email protected]/"
  ]
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"uint256[]","name":"initMarketIds","type":"uint256[]"},{"internalType":"address","name":"_admin","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyClaimed","type":"error"},{"inputs":[],"name":"IndexOutOfBounds","type":"error"},{"inputs":[],"name":"InvalidInput","type":"error"},{"inputs":[],"name":"InvalidOutput","type":"error"},{"inputs":[],"name":"InvalidReserves","type":"error"},{"inputs":[],"name":"InvalidRound","type":"error"},{"inputs":[],"name":"InvalidTimestamp","type":"error"},{"inputs":[],"name":"NotAuthorised","type":"error"},{"inputs":[],"name":"OracleError","type":"error"},{"inputs":[],"name":"RoundExpired","type":"error"},{"inputs":[],"name":"RoundNotYetInitialised","type":"error"},{"inputs":[],"name":"RoundResolved","type":"error"},{"inputs":[],"name":"SlippageReached","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"MarketId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"RoundId","type":"uint256"},{"indexed":true,"internalType":"address","name":"User","type":"address"},{"indexed":false,"internalType":"uint256","name":"AmountIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"Side","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"AmountOut","type":"uint256"}],"name":"MarketEnter","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"MarketId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"RoundId","type":"uint256"},{"indexed":true,"internalType":"address","name":"User","type":"address"},{"indexed":false,"internalType":"uint256","name":"AmountInA","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"AmountInB","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"AmountOut","type":"uint256"}],"name":"MarketExit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"MarketId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"RoundId","type":"uint256"},{"indexed":true,"internalType":"address","name":"User","type":"address"},{"indexed":false,"internalType":"uint256","name":"Result","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"AmountOut","type":"uint256"}],"name":"MarketRedeem","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"RoundId","type":"uint256"},{"indexed":true,"internalType":"address","name":"Resolver","type":"address"},{"indexed":false,"internalType":"uint256","name":"Fees","type":"uint256"}],"name":"RoundResolvedBy","type":"event"},{"inputs":[],"name":"checkResolutionStatus","outputs":[{"internalType":"bool","name":"isResolvable","type":"bool"},{"internalType":"uint256","name":"secondsLeft","type":"uint256"},{"internalType":"uint256","name":"currentRoundFees","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"currentAndFutureRoundInfo","outputs":[{"internalType":"uint256","name":"roundId","type":"uint256"},{"components":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"roundId","type":"uint256"},{"internalType":"uint256","name":"roundStart","type":"uint256"},{"internalType":"uint256","name":"marketTreasury","type":"uint256"},{"internalType":"uint256","name":"yesReserves","type":"uint256"},{"internalType":"uint256","name":"noReserves","type":"uint256"},{"internalType":"uint256","name":"outYesReserves","type":"uint256"},{"internalType":"uint256","name":"outNoReserves","type":"uint256"},{"internalType":"uint256","name":"lastPrice","type":"uint256"},{"internalType":"uint256","name":"currentPrice","type":"uint256"},{"internalType":"uint256","name":"result","type":"uint256"},{"internalType":"uint256","name":"delistingRound","type":"uint256"},{"internalType":"uint256[]","name":"history","type":"uint256[]"}],"internalType":"struct MarketMakerAMM.MarketDataWithHistory[]","name":"marketDataCurrent","type":"tuple[]"},{"components":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"roundId","type":"uint256"},{"internalType":"uint256","name":"roundStart","type":"uint256"},{"internalType":"uint256","name":"marketTreasury","type":"uint256"},{"internalType":"uint256","name":"yesReserves","type":"uint256"},{"internalType":"uint256","name":"noReserves","type":"uint256"},{"internalType":"uint256","name":"outYesReserves","type":"uint256"},{"internalType":"uint256","name":"outNoReserves","type":"uint256"},{"internalType":"uint256","name":"lastPrice","type":"uint256"},{"internalType":"uint256","name":"currentPrice","type":"uint256"},{"internalType":"uint256","name":"result","type":"uint256"},{"internalType":"uint256","name":"delistingRound","type":"uint256"},{"internalType":"uint256[]","name":"history","type":"uint256[]"}],"internalType":"struct MarketMakerAMM.MarketDataWithHistory[]","name":"marketDataFuture","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentRoundInfo","outputs":[{"components":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"roundId","type":"uint256"},{"internalType":"uint256","name":"roundStart","type":"uint256"},{"internalType":"uint256","name":"marketTreasury","type":"uint256"},{"internalType":"uint256","name":"yesReserves","type":"uint256"},{"internalType":"uint256","name":"noReserves","type":"uint256"},{"internalType":"uint256","name":"outYesReserves","type":"uint256"},{"internalType":"uint256","name":"outNoReserves","type":"uint256"},{"internalType":"uint256","name":"lastPrice","type":"uint256"},{"internalType":"uint256","name":"currentPrice","type":"uint256"},{"internalType":"uint256","name":"result","type":"uint256"}],"internalType":"struct MarketMakerAMM.MarketData[]","name":"marketData","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"marketId","type":"uint256"}],"name":"currentSingleMarketRoundInfo","outputs":[{"components":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"roundId","type":"uint256"},{"internalType":"uint256","name":"roundStart","type":"uint256"},{"internalType":"uint256","name":"marketTreasury","type":"uint256"},{"internalType":"uint256","name":"yesReserves","type":"uint256"},{"internalType":"uint256","name":"noReserves","type":"uint256"},{"internalType":"uint256","name":"outYesReserves","type":"uint256"},{"internalType":"uint256","name":"outNoReserves","type":"uint256"},{"internalType":"uint256","name":"lastPrice","type":"uint256"},{"internalType":"uint256","name":"currentPrice","type":"uint256"},{"internalType":"uint256","name":"result","type":"uint256"}],"internalType":"struct MarketMakerAMM.MarketData","name":"marketData","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"delistMarket","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"minAmountOut","type":"uint256"},{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"roundId","type":"uint256"},{"internalType":"uint256","name":"side","type":"uint256"}],"name":"enterMarket","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"minNativeAmountOut","type":"uint256"},{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"roundId","type":"uint256"},{"internalType":"uint256","name":"amountYes","type":"uint256"},{"internalType":"uint256","name":"amountNo","type":"uint256"},{"internalType":"uint256","name":"toBeExchanged","type":"uint256"}],"name":"exitMarket","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllAvailableMarkets","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllMarkets","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"roundId","type":"uint256"},{"internalType":"uint256","name":"side","type":"uint256"}],"name":"getAmountOut","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBothMarkets","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"marketId","type":"uint256"}],"name":"inputMarketRoundHistory","outputs":[{"components":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"roundId","type":"uint256"},{"internalType":"uint256","name":"outYesReserves","type":"uint256"},{"internalType":"uint256","name":"outNoReserves","type":"uint256"},{"internalType":"uint256","name":"openPrice","type":"uint256"},{"internalType":"uint256","name":"closePrice","type":"uint256"},{"internalType":"uint256","name":"result","type":"uint256"}],"internalType":"struct MarketMakerAMM.MarketHistory[]","name":"marketData","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"roundId","type":"uint256"}],"name":"inputRoundInfo","outputs":[{"components":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"roundId","type":"uint256"},{"internalType":"uint256","name":"roundStart","type":"uint256"},{"internalType":"uint256","name":"marketTreasury","type":"uint256"},{"internalType":"uint256","name":"yesReserves","type":"uint256"},{"internalType":"uint256","name":"noReserves","type":"uint256"},{"internalType":"uint256","name":"outYesReserves","type":"uint256"},{"internalType":"uint256","name":"outNoReserves","type":"uint256"},{"internalType":"uint256","name":"lastPrice","type":"uint256"},{"internalType":"uint256","name":"currentPrice","type":"uint256"},{"internalType":"uint256","name":"result","type":"uint256"}],"internalType":"struct MarketMakerAMM.MarketData[]","name":"marketData","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"roundId","type":"uint256"}],"name":"inputSingleMarketRoundInfo","outputs":[{"components":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"roundId","type":"uint256"},{"internalType":"uint256","name":"roundStart","type":"uint256"},{"internalType":"uint256","name":"marketTreasury","type":"uint256"},{"internalType":"uint256","name":"yesReserves","type":"uint256"},{"internalType":"uint256","name":"noReserves","type":"uint256"},{"internalType":"uint256","name":"outYesReserves","type":"uint256"},{"internalType":"uint256","name":"outNoReserves","type":"uint256"},{"internalType":"uint256","name":"lastPrice","type":"uint256"},{"internalType":"uint256","name":"currentPrice","type":"uint256"},{"internalType":"uint256","name":"result","type":"uint256"},{"internalType":"uint256","name":"delistingRound","type":"uint256"},{"internalType":"uint256[]","name":"history","type":"uint256[]"}],"internalType":"struct MarketMakerAMM.MarketDataWithHistory","name":"marketData","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"marketId","type":"uint256"}],"name":"marketToDelistingRound","outputs":[{"internalType":"uint256","name":"delistRound","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"putMarketOnDelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"marketId","type":"uint256"}],"name":"redeemPendingRoundsPerMarketId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"marketId","type":"uint256"}],"name":"redeemRoundsPerMarketIdCapped","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"registerMarket","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"resolveMarkets","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"roundStart","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"universalRound","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newAdmin","type":"address"}],"name":"updateAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"userDataPerCurrentRoundId","outputs":[{"components":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"roundId","type":"uint256"},{"internalType":"uint256","name":"result","type":"uint256"},{"internalType":"uint256","name":"outYesReserves","type":"uint256"},{"internalType":"uint256","name":"outNoReserves","type":"uint256"},{"internalType":"uint256","name":"userYesReserves","type":"uint256"},{"internalType":"uint256","name":"userNoReserves","type":"uint256"},{"internalType":"uint256","name":"treasury","type":"uint256"},{"internalType":"uint256","name":"userRedeemed","type":"uint256"}],"internalType":"struct MarketMakerAMM.UserData[]","name":"userData","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"marketId","type":"uint256"}],"name":"userDataPerMarketAndCurrentRoundId","outputs":[{"components":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"roundId","type":"uint256"},{"internalType":"uint256","name":"result","type":"uint256"},{"internalType":"uint256","name":"outYesReserves","type":"uint256"},{"internalType":"uint256","name":"outNoReserves","type":"uint256"},{"internalType":"uint256","name":"userYesReserves","type":"uint256"},{"internalType":"uint256","name":"userNoReserves","type":"uint256"},{"internalType":"uint256","name":"treasury","type":"uint256"},{"internalType":"uint256","name":"userRedeemed","type":"uint256"}],"internalType":"struct MarketMakerAMM.UserData","name":"userData","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"roundId","type":"uint256"}],"name":"userDataPerMarketIdAndRoundId","outputs":[{"components":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"roundId","type":"uint256"},{"internalType":"uint256","name":"result","type":"uint256"},{"internalType":"uint256","name":"outYesReserves","type":"uint256"},{"internalType":"uint256","name":"outNoReserves","type":"uint256"},{"internalType":"uint256","name":"userYesReserves","type":"uint256"},{"internalType":"uint256","name":"userNoReserves","type":"uint256"},{"internalType":"uint256","name":"treasury","type":"uint256"},{"internalType":"uint256","name":"userRedeemed","type":"uint256"}],"internalType":"struct MarketMakerAMM.UserData","name":"userData","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256[]","name":"roundIds","type":"uint256[]"}],"name":"userDataPerMarketIdAndRoundIds","outputs":[{"components":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"roundId","type":"uint256"},{"internalType":"uint256","name":"result","type":"uint256"},{"internalType":"uint256","name":"outYesReserves","type":"uint256"},{"internalType":"uint256","name":"outNoReserves","type":"uint256"},{"internalType":"uint256","name":"userYesReserves","type":"uint256"},{"internalType":"uint256","name":"userNoReserves","type":"uint256"},{"internalType":"uint256","name":"treasury","type":"uint256"},{"internalType":"uint256","name":"userRedeemed","type":"uint256"}],"internalType":"struct MarketMakerAMM.UserData[]","name":"userData","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"roundId","type":"uint256"}],"name":"userDataPerRoundId","outputs":[{"components":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"roundId","type":"uint256"},{"internalType":"uint256","name":"result","type":"uint256"},{"internalType":"uint256","name":"outYesReserves","type":"uint256"},{"internalType":"uint256","name":"outNoReserves","type":"uint256"},{"internalType":"uint256","name":"userYesReserves","type":"uint256"},{"internalType":"uint256","name":"userNoReserves","type":"uint256"},{"internalType":"uint256","name":"treasury","type":"uint256"},{"internalType":"uint256","name":"userRedeemed","type":"uint256"}],"internalType":"struct MarketMakerAMM.UserData[]","name":"userData","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"userToUnclaimedRounds","outputs":[{"components":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256[]","name":"roundIds","type":"uint256[]"}],"internalType":"struct MarketMakerAMM.UserToRoundsPerMarket[]","name":"roundsPerMarket","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"page","type":"uint256"}],"name":"userUnclaimedRoundsDataPerMarketId","outputs":[{"internalType":"uint256","name":"total","type":"uint256"},{"components":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"roundId","type":"uint256"},{"internalType":"uint256","name":"result","type":"uint256"},{"internalType":"uint256","name":"outYesReserves","type":"uint256"},{"internalType":"uint256","name":"outNoReserves","type":"uint256"},{"internalType":"uint256","name":"userYesReserves","type":"uint256"},{"internalType":"uint256","name":"userNoReserves","type":"uint256"},{"internalType":"uint256","name":"treasury","type":"uint256"},{"internalType":"uint256","name":"userRedeemed","type":"uint256"}],"internalType":"struct MarketMakerAMM.UserData[]","name":"userData","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"marketId","type":"uint256"}],"name":"userUnclaimedRoundsPerMarketId","outputs":[{"internalType":"uint256[]","name":"roundIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"page","type":"uint256"}],"name":"userUnclaimedRoundsPerMarketIdWithPage","outputs":[{"internalType":"uint256","name":"total","type":"uint256"},{"internalType":"uint256[]","name":"roundIds","type":"uint256[]"}],"stateMutability":"view","type":"function"}]

608060405234801561000f575f5ffd5b506040516161f93803806161f983398181016040528101906100319190610582565b5f825190505f5f90505b81811015610188575f848281518110610057576100566105dc565b5b60200260200101519050610070816101ee60201b60201c565b60095f8381526020019081526020015f205f5f81526020019081526020015f20819055506100a881601261021c60201b90919060201c565b506100bd81601361021c60201b90919060201c565b5068170a0f5040e504000060045f8381526020019081526020015f205f600181526020019081526020015f208190555068170a0f5040e504000060055f8381526020019081526020015f205f600181526020019081526020015f208190555068170a0f5040e504000060045f8381526020019081526020015f205f600281526020019081526020015f208190555068170a0f5040e504000060055f8381526020019081526020015f205f600281526020019081526020015f208190555050808060010191505061003b565b5060025f81548092919061019b90610636565b919050555042600381905550815f5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505061067d565b5f5f6108079050825f5260205f60205f845afa6102125763b41b6cb15f526004601cfd5b5f51915050919050565b5f61023d61022f8461024560201b60201c565b835f1b61024e60201b60201c565b905092915050565b5f819050919050565b5f5f61025f8461037d60201b60201c565b905068fbb67fda52d4bfb8bf830361027e5763f5a267f15f526004601cfd5b826102905768fbb67fda52d4bfb8bf92505b80195460011561037557816020528061033e578154806102b7578483556001935050610375565b8481036102c45750610375565b6001830154806102df57856001850155600194505050610375565b8581036102ed575050610375565b6002840154806103095786600286015560019550505050610375565b86810361031857505050610375565b825f52600160405f2055815f52600260405f2055805f52600360405f2055600793505050505b835f5260405f208054610373578160011c915084828401558160010181558160010160011b6001178319556001935050610375565b505b505092915050565b5f6318fb5864600452815f5260245f209050919050565b5f604051905090565b5f5ffd5b5f5ffd5b5f5ffd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6103ef826103a9565b810181811067ffffffffffffffff8211171561040e5761040d6103b9565b5b80604052505050565b5f610420610394565b905061042c82826103e6565b919050565b5f67ffffffffffffffff82111561044b5761044a6103b9565b5b602082029050602081019050919050565b5f5ffd5b5f819050919050565b61047281610460565b811461047c575f5ffd5b50565b5f8151905061048d81610469565b92915050565b5f6104a56104a084610431565b610417565b905080838252602082019050602084028301858111156104c8576104c761045c565b5b835b818110156104f157806104dd888261047f565b8452602084019350506020810190506104ca565b5050509392505050565b5f82601f83011261050f5761050e6103a5565b5b815161051f848260208601610493565b91505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61055182610528565b9050919050565b61056181610547565b811461056b575f5ffd5b50565b5f8151905061057c81610558565b92915050565b5f5f604083850312156105985761059761039d565b5b5f83015167ffffffffffffffff8111156105b5576105b46103a1565b5b6105c1858286016104fb565b92505060206105d28582860161056e565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61064082610460565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361067257610671610609565b5b600182019050919050565b615b6f8061068a5f395ff3fe6080604052600436106101f7575f3560e01c80636fd981fe1161010c578063cd1031161161009f578063e512bb601161006e578063e512bb601461076e578063eba83e8d146107aa578063ed9e4ab4146107e6578063edaa019f1461080e578063f22cc0fd14610836576101f7565b8063cd103116146106c7578063d294f093146106f3578063df95b5da14610709578063e2f273bd14610746576101f7565b8063b7445245116100db578063b7445245146105fb578063c2c34cae14610626578063c37524651461064e578063c6b8a8d91461068a576101f7565b80636fd981fe146105555780639af1d35a1461056b578063a624a0dc14610595578063b0772d0b146105d1576101f7565b806340435c081161018f57806357473f0b1161015e57806357473f0b146104515780635769132c1461048d57806357ae4da4146104c95780635c9519e5146104f15780635f71acf41461052d576101f7565b806340435c081461037157806344fd7a49146103ad57806349390388146103d957806352707d8c14610415576101f7565b80632fbdb49a116101cb5780632fbdb49a146102c557806334e9f0ae146102ef5780633f33529e1461032b5780634036585214610347576101f7565b80628f8b35146101fb57806311067eb014610225578063168ffc5f14610261578063193fb23414610289575b5f5ffd5b348015610206575f5ffd5b5061020f610860565b60405161021c9190614a26565b60405180910390f35b348015610230575f5ffd5b5061024b60048036038101906102469190614a81565b610a6d565b6040516102589190614be0565b60405180910390f35b34801561026c575f5ffd5b5061028760048036038101906102829190614a81565b610c5c565b005b348015610294575f5ffd5b506102af60048036038101906102aa9190614c5a565b610ed2565b6040516102bc9190614d40565b60405180910390f35b3480156102d0575f5ffd5b506102d9610f75565b6040516102e69190614d40565b60405180910390f35b3480156102fa575f5ffd5b5061031560048036038101906103109190614d60565b610f86565b6040516103229190614f20565b60405180910390f35b61034560048036038101906103409190614f40565b611212565b005b348015610352575f5ffd5b5061035b6115d9565b6040516103689190614fb3565b60405180910390f35b34801561037c575f5ffd5b506103976004803603810190610392919061511c565b6115df565b6040516103a491906152e6565b60405180910390f35b3480156103b8575f5ffd5b506103c161186d565b6040516103d093929190615320565b60405180910390f35b3480156103e4575f5ffd5b506103ff60048036038101906103fa9190614c5a565b6118da565b60405161040c919061540a565b60405180910390f35b348015610420575f5ffd5b5061043b60048036038101906104369190614f40565b611ac2565b6040516104489190614fb3565b60405180910390f35b34801561045c575f5ffd5b5061047760048036038101906104729190614a81565b611b9d565b6040516104849190614a26565b60405180910390f35b348015610498575f5ffd5b506104b360048036038101906104ae9190614a81565b611dd8565b6040516104c09190614fb3565b60405180910390f35b3480156104d4575f5ffd5b506104ef60048036038101906104ea9190614a81565b611ded565b005b3480156104fc575f5ffd5b5061051760048036038101906105129190615424565b611ee3565b6040516105249190615544565b60405180910390f35b348015610538575f5ffd5b50610553600480360381019061054e9190614a81565b61204c565b005b348015610560575f5ffd5b506105696121b8565b005b348015610576575f5ffd5b5061057f6123df565b60405161058c9190614fb3565b60405180910390f35b3480156105a0575f5ffd5b506105bb60048036038101906105b69190614c5a565b6123e5565b6040516105c891906152e6565b60405180910390f35b3480156105dc575f5ffd5b506105e5612673565b6040516105f29190614d40565b60405180910390f35b348015610606575f5ffd5b5061060f612684565b60405161061d929190615564565b60405180910390f35b348015610631575f5ffd5b5061064c60048036038101906106479190614a81565b6126a3565b005b348015610659575f5ffd5b50610674600480360381019061066f9190615424565b6127dd565b60405161068191906152e6565b60405180910390f35b348015610695575f5ffd5b506106b060048036038101906106ab9190615599565b612a71565b6040516106be9291906155e9565b60405180910390f35b3480156106d2575f5ffd5b506106db612c59565b6040516106ea939291906157e8565b60405180910390f35b3480156106fe575f5ffd5b50610707613137565b005b348015610714575f5ffd5b5061072f600480360381019061072a9190615599565b6131a3565b60405161073d92919061582b565b60405180910390f35b348015610751575f5ffd5b5061076c60048036038101906107679190615424565b613574565b005b348015610779575f5ffd5b50610794600480360381019061078f9190614a81565b61363b565b6040516107a19190615938565b60405180910390f35b3480156107b5575f5ffd5b506107d060048036038101906107cb9190615599565b61379d565b6040516107dd919061540a565b60405180910390f35b3480156107f1575f5ffd5b5061080c60048036038101906108079190614a81565b61397f565b005b348015610819575f5ffd5b50610834600480360381019061082f9190615952565b613bdf565b005b348015610841575f5ffd5b5061084a613f98565b6040516108579190614fb3565b60405180910390f35b60605f61086d6012613f9e565b90508067ffffffffffffffff81111561088957610888614fe0565b5b6040519080825280602002602001820160405280156108c257816020015b6108af614749565b8152602001906001900390816108a75790505b5091505f60025490505f60035490505f5f90505b83811015610a66575f6108f3826012613fb790919063ffffffff16565b90505f6108ff82613fd4565b905060405180610160016040528083815260200186815260200185815260200160065f8581526020019081526020015f205f8881526020019081526020015f2054815260200160045f8581526020019081526020015f205f8881526020019081526020015f2054815260200160055f8581526020019081526020015f205f8881526020019081526020015f20548152602001600e5f8581526020019081526020015f205f8881526020019081526020015f20548152602001600f5f8581526020019081526020015f205f8881526020019081526020015f2054815260200160095f8581526020019081526020015f205f6001896109fc9190615a08565b81526020019081526020015f20548152602001828152602001600a5f8581526020019081526020015f205f8881526020019081526020015f2054815250878481518110610a4c57610a4b615a3b565b5b6020026020010181905250505080806001019150506108d6565b5050505090565b60605f60025490505f60968211610a9057600182610a8b9190615a08565b610a93565b60965b90505f8183610aa29190615a08565b90508167ffffffffffffffff811115610abe57610abd614fe0565b5b604051908082528060200260200182016040528015610af757816020015b610ae4614798565b815260200190600190039081610adc5790505b5093505f5f90505b82811015610c53576040518060e001604052808781526020018284610b249190615a68565b8152602001600e5f8981526020019081526020015f205f8486610b479190615a68565b81526020019081526020015f20548152602001600f5f8981526020019081526020015f205f8486610b789190615a68565b81526020019081526020015f2054815260200160095f8981526020019081526020015f205f84600187610bab9190615a08565b610bb59190615a68565b81526020019081526020015f2054815260200160095f8981526020019081526020015f205f8486610be69190615a68565b81526020019081526020015f20548152602001600a5f8981526020019081526020015f205f8486610c179190615a68565b81526020019081526020015f2054815250858281518110610c3b57610c3a615a3b565b5b60200260200101819052508080600101915050610aff565b50505050919050565b335f52600b60205260405f20815f528060205260405f20805480825f5260205f206019821115610c8b57601991505b5f5b82811015610e3c57808201545f82840155335f52600d60205260405f209650875f528660205260405f209650805f528660205260405f205f81541115610cda5763646cf5585f526004601cfd5b885f52600a60205260405f209750815f528760205260405f2097505f600189548060018114610d135760028114610d675785875d610db7565b60018555335f52600760205260405f209b508c5f528b60205260405f209b50855f528b60205260405f209b508b5493508c5f52600e60205260405f209b50855f528b60205260405f209b508b549250610db7565b60018555335f52600860205260405f209b508c5f528b60205260405f209b50855f528b60205260405f209b508b5493508c5f52600f60205260405f209b50855f528b60205260405f209b508b5492505b505f84541115610e2c578b5f52600660205260405f209a50845f528a60205260405f209a50818b54840204815f528060205233868e7f3f63856e2d8c431941e15ac15a28d4201c2838a61987308f61a9d5d01aac483960405fa45f5f5f5f84335af1610e2a576398f736095f526004601cfd5b505b5050505050600181019050610c8d565b508183036019811115610e4e57601990505b8284035f5b82811015610e8c57600181018603840154818501555f815c1115610e8157805c828501555f815d6001820191505b600181019050610e53565b505f8203610ec5575f5b6019811015610ec3575f815c1115610eb857805c828501555f815d6001820191505b600181019050610e96565b505b8086555050505050505050565b6060600b5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f20805480602002602001604051908101604052809291908181526020018280548015610f6857602002820191905f5260205f20905b815481526020019060010190808311610f54575b5050505050905092915050565b6060610f816012614002565b905090565b610f8e6147ce565b5f60035490505f60095f8681526020019081526020015f205f8581526020019081526020015f205490505f5f8214610fc65781610fd0565b610fcf86613fd4565b5b90505f600a8611610fed57600186610fe89190615a08565b610ff0565b600a5b90505f8167ffffffffffffffff81111561100d5761100c614fe0565b5b60405190808252806020026020018201604052801561103b5781602001602082028036833780820191505090505b5090505f5f90505b828110156110af57600a5f8a81526020019081526020015f205f6001838b61106b9190615a08565b6110759190615a08565b81526020019081526020015f205482828151811061109657611095615a3b565b5b6020026020010181815250508080600101915050611043565b50604051806101a0016040528089815260200188815260200186815260200160065f8b81526020019081526020015f205f8a81526020019081526020015f2054815260200160045f8b81526020019081526020015f205f8a81526020019081526020015f2054815260200160055f8b81526020019081526020015f205f8a81526020019081526020015f20548152602001600e5f8b81526020019081526020015f205f8a81526020019081526020015f20548152602001600f5f8b81526020019081526020015f205f8a81526020019081526020015f2054815260200160095f8b81526020019081526020015f205f60018b6111ab9190615a08565b81526020019081526020015f20548152602001848152602001600a5f8b81526020019081526020015f205f8a81526020019081526020015f2054815260200160115f8b81526020019081526020015f20548152602001828152509550505050505092915050565b61122683601261402490919063ffffffff16565b61125c576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60115f8581526020019081526020015f20541415801561128e57508160115f8581526020019081526020015f205411155b156112c5576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60035460018211156112de5763b4fa3fb35f526004601cfd5b600254845f52600960205260405f20600185035f528060205260405f2090505f81541485831416156113175763a2b52a545f526004601cfd5b81851060018301861117156113335763a2b52a545f526004601cfd5b4261012c840110828614161561135057639e6d804f5f526004601cfd5b61012c83014210600183018614161561137057635b903c715f526004601cfd5b6103e86103e53402048034036103e861025882020460015401600155865f52601060205260405f2092506103e861025882020481038354018355875f52600660205260405f20925082602052865f5260405f209250818354018355335f52600c60205260405f209250875f528260205260405f209250865f528260205260405f2092505f8354036114325760018355335f52600b60205260405f209250875f528260205260405f2092508254600181018455835f5260205f2093508781850155505b875f52600460205260405f20925082602052865f5260405f2092508254885f52600560205260405f2080602052885f5260405f20905080545f890361152557808501838602048c868201101561148f5763a6d7690f5f526004601cfd5b80840387558582018355335f52600760205260405f209650866020528b5f5260405f209650866020528a5f5260405f20965085810187540187558b5f52600e60205260405f209650866020528a5f5260405f2096508581018754018755345f5289602052858101604052338b8d7fafdcf9101f4dab5c3b6e53a3ec30d3e897f17b974edceb117d3c12d2d83b0fd960605fa45f5ff35b828501818602048c86820110156115435763a6d7690f5f526004601cfd5b85840187558082038355335f52600860205260405f209650866020528b5f5260405f209650866020528a5f5260405f20965085810187540187558b5f52600f60205260405f209650866020528a5f5260405f2096508581018754018755345f5289602052858101604052338b8d7fafdcf9101f4dab5c3b6e53a3ec30d3e897f17b974edceb117d3c12d2d83b0fd960605fa45f5ff35b60035481565b60605f825190508067ffffffffffffffff811115611600576115ff614fe0565b5b60405190808252806020026020018201604052801561163957816020015b61162661482a565b81526020019060019003908161161e5790505b5091505f5f90505b81811015611864575f84828151811061165d5761165c615a3b565b5b60200260200101519050604051806101200160405280878152602001828152602001600a5f8981526020019081526020015f205f8481526020019081526020015f20548152602001600e5f8981526020019081526020015f205f8481526020019081526020015f20548152602001600f5f8981526020019081526020015f205f8481526020019081526020015f2054815260200160075f8a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8981526020019081526020015f205f8481526020019081526020015f2054815260200160085f8a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8981526020019081526020015f205f8481526020019081526020015f2054815260200160065f8981526020019081526020015f205f8481526020019081526020015f20548152602001600d5f8a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8981526020019081526020015f205f8481526020019081526020015f205481525084838151811061184b5761184a615a3b565b5b6020026020010181905250508080600101915050611641565b50509392505050565b5f5f5f6102586003546118809190615a68565b42101592506102586003546118959190615a68565b42106118a1575f6118bd565b426102586003546118b29190615a68565b6118bc9190615a08565b5b915060105f60025481526020019081526020015f20549050909192565b6118e261482a565b5f6002549050604051806101200160405280848152602001828152602001600a5f8681526020019081526020015f205f8481526020019081526020015f20548152602001600e5f8681526020019081526020015f205f8481526020019081526020015f20548152602001600f5f8681526020019081526020015f205f8481526020019081526020015f2054815260200160075f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8681526020019081526020015f205f8481526020019081526020015f2054815260200160085f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8681526020019081526020015f205f8481526020019081526020015f2054815260200160065f8681526020019081526020015f205f8481526020019081526020015f20548152602001600d5f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8681526020019081526020015f205f8481526020019081526020015f205481525091505092915050565b5f5f60045f8681526020019081526020015f205f8581526020019081526020015f205490505f60055f8781526020019081526020015f205f8681526020019081526020015f205490506103e86103e588611b1c9190615a9b565b611b269190615b09565b96505f8403611b6357868188611b3c9190615a68565b8389611b489190615a9b565b611b529190615b09565b611b5c9190615a68565b9250611b93565b868288611b709190615a68565b8289611b7c9190615a9b565b611b869190615b09565b611b909190615a68565b92505b5050949350505050565b60605f611baa6012613f9e565b90508067ffffffffffffffff811115611bc657611bc5614fe0565b5b604051908082528060200260200182016040528015611bff57816020015b611bec614749565b815260200190600190039081611be45790505b5091505f60035490505f5f90505b82811015611dd0575f611c2a826012613fb790919063ffffffff16565b90505f60095f8381526020019081526020015f205f8881526020019081526020015f205490505f5f8214611c5e5781611c68565b611c6783613fd4565b5b905060405180610160016040528084815260200189815260200186815260200160065f8681526020019081526020015f205f8b81526020019081526020015f2054815260200160045f8681526020019081526020015f205f8b81526020019081526020015f2054815260200160055f8681526020019081526020015f205f8b81526020019081526020015f20548152602001600e5f8681526020019081526020015f205f8b81526020019081526020015f20548152602001600f5f8681526020019081526020015f205f8b81526020019081526020015f2054815260200160095f8681526020019081526020015f205f60018c611d659190615a08565b81526020019081526020015f20548152602001828152602001600a5f8681526020019081526020015f205f8b81526020019081526020015f2054815250878581518110611db557611db4615a3b565b5b60200260200101819052505050508080600101915050611c0d565b505050919050565b6011602052805f5260405f205f915090505481565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611e72576040517f1648fd0100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611e8681601261402490919063ffffffff16565b611ebc576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6005600254611ecb9190615a68565b60115f8381526020019081526020015f208190555050565b60605f611ef06012613f9e565b90508067ffffffffffffffff811115611f0c57611f0b614fe0565b5b604051908082528060200260200182016040528015611f4557816020015b611f3261486d565b815260200190600190039081611f2a5790505b5091505f5f90505b81811015612045575f611f6a826012613fb790919063ffffffff16565b90506040518060400160405280828152602001600b5f8873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f2080548060200260200160405190810160405280929190818152602001828054801561201157602002820191905f5260205f20905b815481526020019060010190808311611ffd575b505050505081525084838151811061202c5761202b615a3b565b5b6020026020010181905250508080600101915050611f4d565b5050919050565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146120d1576040517f1648fd0100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60115f8381526020019081526020015f20819055506120fb81601261404190919063ffffffff16565b612131576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61214581601361404190919063ffffffff16565b505f60016002546121569190615a68565b905068170a0f5040e504000060045f8481526020019081526020015f205f8381526020019081526020015f208190555068170a0f5040e504000060055f8481526020019081526020015f205f8381526020019081526020015f20819055505050565b610258600354014210156121d35763b7d094975f526004601cfd5b5f60025490505f6121e46012613f9e565b90505f5f90505b8181101561237a575f612208826012613fb790919063ffffffff16565b90505f61221482613fd4565b9050815f52600a60205260405f20855f528060205260405f205f815411156122435763fd29af2c5f526004601cfd5b835f52600960205260405f209150600187035f528160205260405f2091508154875f5260405f2092508383555f81111561231457845f52600660205260405f20925082602052875f5260405f2092508254818511600181146122ab575f81146122e057612311565b60018455865f52600e60205260405f20945084602052895f5260405f2094505f8554036122db5781600154016001555b612311565b60028455865f52600f60205260405f20945084602052895f5260405f2094505f8554036123105781600154016001555b5b50505b845f52600460205260405f20925082602052600288015f5260405f20925068170a0f5040e50400008355845f52600560205260405f20925082602052600288015f5260405f20925068170a0f5040e50400008355505050505080806001019150506121eb565b506002545f52601060205260405f20805460018401600255426003555f5f5f5f84335af16123af576398f736095f526004601cfd5b805f5233847fa4151f6c29291b1556b1872bc36e5304d55092b1703f6226eefdb53250765c7160205fa350505050565b60015481565b60605f6123f26012613f9e565b90508067ffffffffffffffff81111561240e5761240d614fe0565b5b60405190808252806020026020018201604052801561244757816020015b61243461482a565b81526020019060019003908161242c5790505b5091505f5f90505b8181101561266b575f61246c826012613fb790919063ffffffff16565b9050604051806101200160405280828152602001868152602001600a5f8481526020019081526020015f205f8881526020019081526020015f20548152602001600e5f8481526020019081526020015f205f8881526020019081526020015f20548152602001600f5f8481526020019081526020015f205f8881526020019081526020015f2054815260200160075f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205f8881526020019081526020015f2054815260200160085f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205f8881526020019081526020015f2054815260200160065f8481526020019081526020015f205f8881526020019081526020015f20548152602001600d5f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205f8881526020019081526020015f205481525084838151811061265257612651615a3b565b5b602002602001018190525050808060010191505061244f565b505092915050565b606061267f6013614002565b905090565b6060806126916012614002565b61269b6013614002565b915091509091565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612728576040517f1648fd0100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60115f8381526020019081526020015f20541480612759575060025460115f8381526020019081526020015f2054115b15612790576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6127a481601261405e90919063ffffffff16565b6127da576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b60605f6127ea6012613f9e565b90508067ffffffffffffffff81111561280657612805614fe0565b5b60405190808252806020026020018201604052801561283f57816020015b61282c61482a565b8152602001906001900390816128245790505b5091505f60025490505f5f90505b82811015612a69575f61286a826012613fb790919063ffffffff16565b9050604051806101200160405280828152602001848152602001600a5f8481526020019081526020015f205f8681526020019081526020015f20548152602001600e5f8481526020019081526020015f205f8681526020019081526020015f20548152602001600f5f8481526020019081526020015f205f8681526020019081526020015f2054815260200160075f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205f8681526020019081526020015f2054815260200160085f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205f8681526020019081526020015f2054815260200160065f8481526020019081526020015f205f8681526020019081526020015f20548152602001600d5f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205f8681526020019081526020015f2054815250858381518110612a5057612a4f615a3b565b5b602002602001018190525050808060010191505061284d565b505050919050565b5f6060600b5f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8581526020019081526020015f208054905091505f6101f490505f8185612ad99190615a9b565b9050838110612b34575f67ffffffffffffffff811115612afc57612afb614fe0565b5b604051908082528060200260200182016040528015612b2a5781602001602082028036833780820191505090505b5092505050612c51565b5f8185612b419190615a08565b90505f838210612b515783612b53565b815b90508067ffffffffffffffff811115612b6f57612b6e614fe0565b5b604051908082528060200260200182016040528015612b9d5781602001602082028036833780820191505090505b5094505f5f90505b81811015612c4b57600b5f8b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8a81526020019081526020015f208185612c059190615a68565b81548110612c1657612c15615a3b565b5b905f5260205f200154868281518110612c3257612c31615a3b565b5b6020026020010181815250508080600101915050612ba5565b50505050505b935093915050565b5f6060805f612c686012613f9e565b905060025493505f600a8511612c8a57600185612c859190615a08565b612c8d565b600a5b90508167ffffffffffffffff811115612ca957612ca8614fe0565b5b604051908082528060200260200182016040528015612ce257816020015b612ccf6147ce565b815260200190600190039081612cc75790505b5093508167ffffffffffffffff811115612cff57612cfe614fe0565b5b604051908082528060200260200182016040528015612d3857816020015b612d256147ce565b815260200190600190039081612d1d5790505b5092505f600186612d499190615a68565b90505f60035490505f5f90505b8481101561312d575f8467ffffffffffffffff811115612d7957612d78614fe0565b5b604051908082528060200260200182016040528015612da75781602001602082028036833780820191505090505b5090505f612dbf836012613fb790919063ffffffff16565b90505f612dcb82613fd4565b90505f5f90505b87811015612e3e57600a5f8481526020019081526020015f205f6001838f612dfa9190615a08565b612e049190615a08565b81526020019081526020015f2054848281518110612e2557612e24615a3b565b5b6020026020010181815250508080600101915050612dd2565b50604051806101a001604052808381526020018c815260200186815260200160065f8581526020019081526020015f205f8e81526020019081526020015f2054815260200160045f8581526020019081526020015f205f8e81526020019081526020015f2054815260200160055f8581526020019081526020015f205f8e81526020019081526020015f20548152602001600e5f8581526020019081526020015f205f8e81526020019081526020015f20548152602001600f5f8581526020019081526020015f205f8e81526020019081526020015f2054815260200160095f8581526020019081526020015f205f60018f612f3a9190615a08565b81526020019081526020015f20548152602001828152602001600a5f8581526020019081526020015f205f8e81526020019081526020015f2054815260200160115f8581526020019081526020015f20548152602001848152508a8581518110612fa757612fa6615a3b565b5b6020026020010181905250604051806101a0016040528083815260200187815260200186815260200160065f8581526020019081526020015f205f8981526020019081526020015f2054815260200160045f8581526020019081526020015f205f8981526020019081526020015f2054815260200160055f8581526020019081526020015f205f8981526020019081526020015f20548152602001600e5f8581526020019081526020015f205f8981526020019081526020015f20548152602001600f5f8581526020019081526020015f205f8981526020019081526020015f2054815260200160095f8581526020019081526020015f205f8e81526020019081526020015f20548152602001828152602001600a5f8581526020019081526020015f205f8981526020019081526020015f2054815260200160115f8581526020019081526020015f205481526020018481525089858151811061310e5761310d615a3b565b5b6020026020010181905250606092505050508080600101915050612d56565b5050505050909192565b5f60015490505f6001819055505f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc8290811502906040515f60405180830381858888f193505050506131a0575f5ffd5b50565b5f6060600b5f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8581526020019081526020015f208054905091505f606490505f818561320a9190615a9b565b9050838110613270575f67ffffffffffffffff81111561322d5761322c614fe0565b5b60405190808252806020026020018201604052801561326657816020015b61325361482a565b81526020019060019003908161324b5790505b509250505061356c565b5f818561327d9190615a08565b90505f83821061328d578361328f565b815b90508067ffffffffffffffff8111156132ab576132aa614fe0565b5b6040519080825280602002602001820160405280156132e457816020015b6132d161482a565b8152602001906001900390816132c95790505b5094505f5f90505b81811015613566575f600b5f8c73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8b81526020019081526020015f20828661334d9190615a68565b8154811061335e5761335d615a3b565b5b905f5260205f20015490506040518061012001604052808b8152602001828152602001600a5f8d81526020019081526020015f205f8481526020019081526020015f20548152602001600e5f8d81526020019081526020015f205f8481526020019081526020015f20548152602001600f5f8d81526020019081526020015f205f8481526020019081526020015f2054815260200160075f8e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8d81526020019081526020015f205f8481526020019081526020015f2054815260200160085f8e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8d81526020019081526020015f205f8481526020019081526020015f2054815260200160065f8d81526020019081526020015f205f8481526020019081526020015f20548152602001600d5f8e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8d81526020019081526020015f205f8481526020019081526020015f205481525087838151811061354d5761354c615a3b565b5b60200260200101819052505080806001019150506132ec565b50505050505b935093915050565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146135f9576040517f1648fd0100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805f5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b613643614749565b5f60025490505f60035490505f61365985613fd4565b905060405180610160016040528086815260200184815260200183815260200160065f8881526020019081526020015f205f8681526020019081526020015f2054815260200160045f8881526020019081526020015f205f8681526020019081526020015f2054815260200160055f8881526020019081526020015f205f8681526020019081526020015f20548152602001600e5f8881526020019081526020015f205f8681526020019081526020015f20548152602001600f5f8881526020019081526020015f205f8681526020019081526020015f2054815260200160095f8881526020019081526020015f205f6001876137569190615a08565b81526020019081526020015f20548152602001828152602001600a5f8881526020019081526020015f205f8681526020019081526020015f20548152509350505050919050565b6137a561482a565b604051806101200160405280848152602001838152602001600a5f8681526020019081526020015f205f8581526020019081526020015f20548152602001600e5f8681526020019081526020015f205f8581526020019081526020015f20548152602001600f5f8681526020019081526020015f205f8581526020019081526020015f2054815260200160075f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8681526020019081526020015f205f8581526020019081526020015f2054815260200160085f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8681526020019081526020015f205f8581526020019081526020015f2054815260200160065f8681526020019081526020015f205f8581526020019081526020015f20548152602001600d5f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8681526020019081526020015f205f8581526020019081526020015f205481525090509392505050565b335f52600b60205260405f20815f528060205260405f208054815f5260205f205f5b82811015613b5057808201545f82840155335f52600d60205260405f209550865f528560205260405f209550805f528560205260405f205f815411156139ee5763646cf5585f526004601cfd5b875f52600a60205260405f209650815f528660205260405f2096505f600188548060018114613a275760028114613a7b5785875d613acb565b60018555335f52600760205260405f209a508b5f528a60205260405f209a50855f528a60205260405f209a508a5493508b5f52600e60205260405f209a50855f528a60205260405f209a508a549250613acb565b60018555335f52600860205260405f209a508b5f528a60205260405f209a50855f528a60205260405f209a508a5493508b5f52600f60205260405f209a50855f528a60205260405f209a508a5492505b505f84541115613b40578a5f52600660205260405f209950845f528960205260405f209950818a54840204815f528060205233868d7f3f63856e2d8c431941e15ac15a28d4201c2838a61987308f61a9d5d01aac483960405fa45f5f5f5f84335af1613b3e576398f736095f526004601cfd5b505b50505050506001810190506139a1565b505f5f5f5c1115613b6b575f5c818301555f5f5d6001810190505b5f60015c1115613b875760015c818301555f60015d6001810190505b5f83115f600185035c111615613bad57600183035c818301555f600184035d6001810190505b600183115f600285035c111615613bd457600283035c818301555f600284035d6001810190505b808455505050505050565b613bf385601261402490919063ffffffff16565b613c29576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5f821115613c935782841015613c6857613c4582878761407b565b90508183613c539190615a08565b92508084613c619190615a68565b9350613c92565b613c738287876141aa565b90508184613c819190615a08565b93508083613c8f9190615a68565b92505b5b828411613ca05783613ca2565b825b90506002546001810186118187101715613cc35763a2b52a545f526004601cfd5b4261012c60035401108187141615613ce257639e6d804f5f526004601cfd5b5f831160018114613cf9575f8114613e0357613ef1565b875f52600660205260405f2080602052875f5260405f2090508360025c0381555f60025d335f52600760205260405f20905080602052885f5260405f20905080602052875f5260405f2090508360035c1015613d5c57637b9c89165f526004601cfd5b8360035c0381555f60035d335f52600860205260405f20905080602052885f5260405f20905080602052875f5260405f2090508360045c1015613da657637b9c89165f526004601cfd5b8360045c0381555f60045d885f52600e60205260405f20905080602052875f5260405f2090508360055c0381555f60055d885f52600f60205260405f20905080602052875f5260405f2090508360065c0381555f60065d50613ef1565b875f52600660205260405f2080602052875f5260405f209050838154038155335f52600760205260405f20905080602052885f5260405f20905080602052875f5260405f209050805484811015613e6157637b9c89165f526004601cfd5b8481038255335f52600860205260405f20915081602052895f5260405f20915081602052885f5260405f2091508154905084811015613ea757637b9c89165f526004601cfd5b8481038255895f52600e60205260405f20915081602052885f5260405f209150848254038255895f52600f60205260405f20915081602052885f5260405f20915084825403825550505b506103e86103e58302048083036103e861025882020460015401600155875f52601060205260405f206103e8610258830204820381540181558a831015613f3f5763a6d7690f5f526004601cfd5b875f52866020528260405233898b7f4c686a53bc9329e91f0d0d94d821505fd2c0aef3c09a94ea360d98c0dfb9dee460605fa45f5f5f5f86335af1613f8b576398f736095f526004601cfd5b5050505050505050505050565b60025481565b5f613fb0613fab836142d9565b6142e2565b9050919050565b5f613fca613fc4846142d9565b8361432f565b5f1c905092915050565b5f5f6108079050825f5260205f60205f845afa613ff85763b41b6cb15f526004601cfd5b5f51915050919050565b606061401d614018614013846142d9565b614399565b614460565b9050919050565b5f614039614031846142d9565b835f1b61446a565b905092915050565b5f61405661404e846142d9565b835f1b6144f9565b905092915050565b5f61407361406b846142d9565b835f1b614622565b905092915050565b5f825f52600560205260405f20825f528060205260405f20905080548581018255845f52600460205260405f209150835f528160205260405f20915081548187018188020493508381038355855f52600660205260405f20925082602052845f5260405f209250825460025d335f52600760205260405f20925082602052855f5260405f20925082602052845f5260405f2092508383540160035d335f52600860205260405f20925082602052855f5260405f20925082602052845f5260405f20925082548781101561415557637b9c89165f526004601cfd5b87810360045d865f52600e60205260405f20935083602052855f5260405f2093508484540160055d865f52600f60205260405f20935083602052855f5260405f2093508784540360065d505050509392505050565b5f825f52600460205260405f20825f528060205260405f20905080548581018255845f52600560205260405f20915081602052835f5260405f20915081548187018188020493508381038355855f52600660205260405f20925082602052845f5260405f209250825460025d335f52600760205260405f20925082602052855f5260405f20925082602052845f5260405f20925082548781101561425557637b9c89165f526004601cfd5b87810360035d335f52600860205260405f20935083602052865f5260405f20935083602052855f5260405f2093508484540160045d865f52600e60205260405f20935083602052855f5260405f2093508784540360055d865f52600f60205260405f20935083602052855f5260405f2093508484540160065d505050509392505050565b5f819050919050565b5f5f6142ed83614732565b90508019548060011c925080614328575f92508282015415614328576001925082820154156143285760029250828201541561432857600392505b5050919050565b5f61433983614732565b905081810154905068fbb67fda52d4bfb8bf8114158102905061435b836142e2565b8210614393576040517f4e23d03500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b92915050565b60605f6143a583614732565b905068fbb67fda52d4bfb8bf81195460405193508360200160011561444b578161441c5783548015614416576001925083811415810282528285015490508015614415576002925083811415810260208301528285015490508015614414576003925083811415810260408301525b5b5b5061444b565b8160011c91505f5b8281101561444957808501548481141581028260051b84015250600181019050614424565b505b8185528160051b810160405250505050919050565b6060819050919050565b5f5f61447584614732565b905068fbb67fda52d4bfb8bf83036144945763f5a267f15f526004601cfd5b826144a65768fbb67fda52d4bfb8bf92505b6001156144f2578019546144e1576001915082815403156144f25782600182015403156144f25782600282015403156144f2575f91506144f2565b80602052825f5260405f2054151591505b5092915050565b5f5f61450484614732565b905068fbb67fda52d4bfb8bf83036145235763f5a267f15f526004601cfd5b826145355768fbb67fda52d4bfb8bf92505b80195460011561461a5781602052806145e35781548061455c57848355600193505061461a565b848103614569575061461a565b6001830154806145845785600185015560019450505061461a565b85810361459257505061461a565b6002840154806145ae578660028601556001955050505061461a565b8681036145bd5750505061461a565b825f52600160405f2055815f52600260405f2055805f52600360405f2055600793505050505b835f5260405f208054614618578160011c915084828401558160010181558160010160011b600117831955600193505061461a565b505b505092915050565b5f5f61462d84614732565b905068fbb67fda52d4bfb8bf830361464c5763f5a267f15f526004601cfd5b8261465e5768fbb67fda52d4bfb8bf92505b80195460011561472a57806146d35760019250838254036146955760018201548255600282015460018301555f600283015561472a565b836001830154036146b557600282015460018301555f600283015561472a565b836002830154036146cb575f600283015561472a565b5f925061472a565b81602052835f5260405f208054806146ec57505061472a565b60018360011c03925082600182031461471657828401548060018303860155805f528160405f2055505b60018360011b178419555f82556001945050505b505092915050565b5f6318fb5864600452815f5260245f209050919050565b6040518061016001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b6040518060e001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b604051806101a001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f8152602001606081525090565b6040518061012001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b60405180604001604052805f8152602001606081525090565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f819050919050565b6148c1816148af565b82525050565b61016082015f8201516148dc5f8501826148b8565b5060208201516148ef60208501826148b8565b50604082015161490260408501826148b8565b50606082015161491560608501826148b8565b50608082015161492860808501826148b8565b5060a082015161493b60a08501826148b8565b5060c082015161494e60c08501826148b8565b5060e082015161496160e08501826148b8565b506101008201516149766101008501826148b8565b5061012082015161498b6101208501826148b8565b506101408201516149a06101408501826148b8565b50505050565b5f6149b183836148c7565b6101608301905092915050565b5f602082019050919050565b5f6149d482614886565b6149de8185614890565b93506149e9836148a0565b805f5b83811015614a19578151614a0088826149a6565b9750614a0b836149be565b9250506001810190506149ec565b5085935050505092915050565b5f6020820190508181035f830152614a3e81846149ca565b905092915050565b5f604051905090565b5f5ffd5b5f5ffd5b614a60816148af565b8114614a6a575f5ffd5b50565b5f81359050614a7b81614a57565b92915050565b5f60208284031215614a9657614a95614a4f565b5b5f614aa384828501614a6d565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b60e082015f820151614ae95f8501826148b8565b506020820151614afc60208501826148b8565b506040820151614b0f60408501826148b8565b506060820151614b2260608501826148b8565b506080820151614b3560808501826148b8565b5060a0820151614b4860a08501826148b8565b5060c0820151614b5b60c08501826148b8565b50505050565b5f614b6c8383614ad5565b60e08301905092915050565b5f602082019050919050565b5f614b8e82614aac565b614b988185614ab6565b9350614ba383614ac6565b805f5b83811015614bd3578151614bba8882614b61565b9750614bc583614b78565b925050600181019050614ba6565b5085935050505092915050565b5f6020820190508181035f830152614bf88184614b84565b905092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f614c2982614c00565b9050919050565b614c3981614c1f565b8114614c43575f5ffd5b50565b5f81359050614c5481614c30565b92915050565b5f5f60408385031215614c7057614c6f614a4f565b5b5f614c7d85828601614c46565b9250506020614c8e85828601614a6d565b9150509250929050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f614ccc83836148b8565b60208301905092915050565b5f602082019050919050565b5f614cee82614c98565b614cf88185614ca2565b9350614d0383614cb2565b805f5b83811015614d33578151614d1a8882614cc1565b9750614d2583614cd8565b925050600181019050614d06565b5085935050505092915050565b5f6020820190508181035f830152614d588184614ce4565b905092915050565b5f5f60408385031215614d7657614d75614a4f565b5b5f614d8385828601614a6d565b9250506020614d9485828601614a6d565b9150509250929050565b5f82825260208201905092915050565b5f614db882614c98565b614dc28185614d9e565b9350614dcd83614cb2565b805f5b83811015614dfd578151614de48882614cc1565b9750614def83614cd8565b925050600181019050614dd0565b5085935050505092915050565b5f6101a083015f830151614e205f8601826148b8565b506020830151614e3360208601826148b8565b506040830151614e4660408601826148b8565b506060830151614e5960608601826148b8565b506080830151614e6c60808601826148b8565b5060a0830151614e7f60a08601826148b8565b5060c0830151614e9260c08601826148b8565b5060e0830151614ea560e08601826148b8565b50610100830151614eba6101008601826148b8565b50610120830151614ecf6101208601826148b8565b50610140830151614ee46101408601826148b8565b50610160830151614ef96101608601826148b8565b50610180830151848203610180860152614f138282614dae565b9150508091505092915050565b5f6020820190508181035f830152614f388184614e0a565b905092915050565b5f5f5f5f60808587031215614f5857614f57614a4f565b5b5f614f6587828801614a6d565b9450506020614f7687828801614a6d565b9350506040614f8787828801614a6d565b9250506060614f9887828801614a6d565b91505092959194509250565b614fad816148af565b82525050565b5f602082019050614fc65f830184614fa4565b92915050565b5f5ffd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b61501682614fd0565b810181811067ffffffffffffffff8211171561503557615034614fe0565b5b80604052505050565b5f615047614a46565b9050615053828261500d565b919050565b5f67ffffffffffffffff82111561507257615071614fe0565b5b602082029050602081019050919050565b5f5ffd5b5f61509961509484615058565b61503e565b905080838252602082019050602084028301858111156150bc576150bb615083565b5b835b818110156150e557806150d18882614a6d565b8452602084019350506020810190506150be565b5050509392505050565b5f82601f83011261510357615102614fcc565b5b8135615113848260208601615087565b91505092915050565b5f5f5f6060848603121561513357615132614a4f565b5b5f61514086828701614c46565b935050602061515186828701614a6d565b925050604084013567ffffffffffffffff81111561517257615171614a53565b5b61517e868287016150ef565b9150509250925092565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b61012082015f8201516151c65f8501826148b8565b5060208201516151d960208501826148b8565b5060408201516151ec60408501826148b8565b5060608201516151ff60608501826148b8565b50608082015161521260808501826148b8565b5060a082015161522560a08501826148b8565b5060c082015161523860c08501826148b8565b5060e082015161524b60e08501826148b8565b506101008201516152606101008501826148b8565b50505050565b5f61527183836151b1565b6101208301905092915050565b5f602082019050919050565b5f61529482615188565b61529e8185615192565b93506152a9836151a2565b805f5b838110156152d95781516152c08882615266565b97506152cb8361527e565b9250506001810190506152ac565b5085935050505092915050565b5f6020820190508181035f8301526152fe818461528a565b905092915050565b5f8115159050919050565b61531a81615306565b82525050565b5f6060820190506153335f830186615311565b6153406020830185614fa4565b61534d6040830184614fa4565b949350505050565b61012082015f82015161536a5f8501826148b8565b50602082015161537d60208501826148b8565b50604082015161539060408501826148b8565b5060608201516153a360608501826148b8565b5060808201516153b660808501826148b8565b5060a08201516153c960a08501826148b8565b5060c08201516153dc60c08501826148b8565b5060e08201516153ef60e08501826148b8565b506101008201516154046101008501826148b8565b50505050565b5f6101208201905061541e5f830184615355565b92915050565b5f6020828403121561543957615438614a4f565b5b5f61544684828501614c46565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f604083015f83015161548d5f8601826148b8565b50602083015184820360208601526154a58282614dae565b9150508091505092915050565b5f6154bd8383615478565b905092915050565b5f602082019050919050565b5f6154db8261544f565b6154e58185615459565b9350836020820285016154f785615469565b805f5b85811015615532578484038952815161551385826154b2565b945061551e836154c5565b925060208a019950506001810190506154fa565b50829750879550505050505092915050565b5f6020820190508181035f83015261555c81846154d1565b905092915050565b5f6040820190508181035f83015261557c8185614ce4565b905081810360208301526155908184614ce4565b90509392505050565b5f5f5f606084860312156155b0576155af614a4f565b5b5f6155bd86828701614c46565b93505060206155ce86828701614a6d565b92505060406155df86828701614a6d565b9150509250925092565b5f6040820190506155fc5f830185614fa4565b818103602083015261560e8184614ce4565b90509392505050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f6101a083015f8301516156565f8601826148b8565b50602083015161566960208601826148b8565b50604083015161567c60408601826148b8565b50606083015161568f60608601826148b8565b5060808301516156a260808601826148b8565b5060a08301516156b560a08601826148b8565b5060c08301516156c860c08601826148b8565b5060e08301516156db60e08601826148b8565b506101008301516156f06101008601826148b8565b506101208301516157056101208601826148b8565b5061014083015161571a6101408601826148b8565b5061016083015161572f6101608601826148b8565b506101808301518482036101808601526157498282614dae565b9150508091505092915050565b5f6157618383615640565b905092915050565b5f602082019050919050565b5f61577f82615617565b6157898185615621565b93508360208202850161579b85615631565b805f5b858110156157d657848403895281516157b78582615756565b94506157c283615769565b925060208a0199505060018101905061579e565b50829750879550505050505092915050565b5f6060820190506157fb5f830186614fa4565b818103602083015261580d8185615775565b905081810360408301526158218184615775565b9050949350505050565b5f60408201905061583e5f830185614fa4565b8181036020830152615850818461528a565b90509392505050565b61016082015f82015161586e5f8501826148b8565b50602082015161588160208501826148b8565b50604082015161589460408501826148b8565b5060608201516158a760608501826148b8565b5060808201516158ba60808501826148b8565b5060a08201516158cd60a08501826148b8565b5060c08201516158e060c08501826148b8565b5060e08201516158f360e08501826148b8565b506101008201516159086101008501826148b8565b5061012082015161591d6101208501826148b8565b506101408201516159326101408501826148b8565b50505050565b5f6101608201905061594c5f830184615859565b92915050565b5f5f5f5f5f5f60c0878903121561596c5761596b614a4f565b5b5f61597989828a01614a6d565b965050602061598a89828a01614a6d565b955050604061599b89828a01614a6d565b94505060606159ac89828a01614a6d565b93505060806159bd89828a01614a6d565b92505060a06159ce89828a01614a6d565b9150509295509295509295565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f615a12826148af565b9150615a1d836148af565b9250828203905081811115615a3557615a346159db565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f615a72826148af565b9150615a7d836148af565b9250828201905080821115615a9557615a946159db565b5b92915050565b5f615aa5826148af565b9150615ab0836148af565b9250828202615abe816148af565b91508282048414831517615ad557615ad46159db565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f615b13826148af565b9150615b1e836148af565b925082615b2e57615b2d615adc565b5b82820490509291505056fea2646970667358221220137ad95f047d8f6117acaa283c77bac9e6c7dfbcf68da0151429aa2025d06b5164736f6c634300081c003300000000000000000000000000000000000000000000000000000000000000400000000000000000000000002a007eb889ddf2be3f3bda225734c1873bf1ea420000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000009f

Deployed Bytecode

0x6080604052600436106101f7575f3560e01c80636fd981fe1161010c578063cd1031161161009f578063e512bb601161006e578063e512bb601461076e578063eba83e8d146107aa578063ed9e4ab4146107e6578063edaa019f1461080e578063f22cc0fd14610836576101f7565b8063cd103116146106c7578063d294f093146106f3578063df95b5da14610709578063e2f273bd14610746576101f7565b8063b7445245116100db578063b7445245146105fb578063c2c34cae14610626578063c37524651461064e578063c6b8a8d91461068a576101f7565b80636fd981fe146105555780639af1d35a1461056b578063a624a0dc14610595578063b0772d0b146105d1576101f7565b806340435c081161018f57806357473f0b1161015e57806357473f0b146104515780635769132c1461048d57806357ae4da4146104c95780635c9519e5146104f15780635f71acf41461052d576101f7565b806340435c081461037157806344fd7a49146103ad57806349390388146103d957806352707d8c14610415576101f7565b80632fbdb49a116101cb5780632fbdb49a146102c557806334e9f0ae146102ef5780633f33529e1461032b5780634036585214610347576101f7565b80628f8b35146101fb57806311067eb014610225578063168ffc5f14610261578063193fb23414610289575b5f5ffd5b348015610206575f5ffd5b5061020f610860565b60405161021c9190614a26565b60405180910390f35b348015610230575f5ffd5b5061024b60048036038101906102469190614a81565b610a6d565b6040516102589190614be0565b60405180910390f35b34801561026c575f5ffd5b5061028760048036038101906102829190614a81565b610c5c565b005b348015610294575f5ffd5b506102af60048036038101906102aa9190614c5a565b610ed2565b6040516102bc9190614d40565b60405180910390f35b3480156102d0575f5ffd5b506102d9610f75565b6040516102e69190614d40565b60405180910390f35b3480156102fa575f5ffd5b5061031560048036038101906103109190614d60565b610f86565b6040516103229190614f20565b60405180910390f35b61034560048036038101906103409190614f40565b611212565b005b348015610352575f5ffd5b5061035b6115d9565b6040516103689190614fb3565b60405180910390f35b34801561037c575f5ffd5b506103976004803603810190610392919061511c565b6115df565b6040516103a491906152e6565b60405180910390f35b3480156103b8575f5ffd5b506103c161186d565b6040516103d093929190615320565b60405180910390f35b3480156103e4575f5ffd5b506103ff60048036038101906103fa9190614c5a565b6118da565b60405161040c919061540a565b60405180910390f35b348015610420575f5ffd5b5061043b60048036038101906104369190614f40565b611ac2565b6040516104489190614fb3565b60405180910390f35b34801561045c575f5ffd5b5061047760048036038101906104729190614a81565b611b9d565b6040516104849190614a26565b60405180910390f35b348015610498575f5ffd5b506104b360048036038101906104ae9190614a81565b611dd8565b6040516104c09190614fb3565b60405180910390f35b3480156104d4575f5ffd5b506104ef60048036038101906104ea9190614a81565b611ded565b005b3480156104fc575f5ffd5b5061051760048036038101906105129190615424565b611ee3565b6040516105249190615544565b60405180910390f35b348015610538575f5ffd5b50610553600480360381019061054e9190614a81565b61204c565b005b348015610560575f5ffd5b506105696121b8565b005b348015610576575f5ffd5b5061057f6123df565b60405161058c9190614fb3565b60405180910390f35b3480156105a0575f5ffd5b506105bb60048036038101906105b69190614c5a565b6123e5565b6040516105c891906152e6565b60405180910390f35b3480156105dc575f5ffd5b506105e5612673565b6040516105f29190614d40565b60405180910390f35b348015610606575f5ffd5b5061060f612684565b60405161061d929190615564565b60405180910390f35b348015610631575f5ffd5b5061064c60048036038101906106479190614a81565b6126a3565b005b348015610659575f5ffd5b50610674600480360381019061066f9190615424565b6127dd565b60405161068191906152e6565b60405180910390f35b348015610695575f5ffd5b506106b060048036038101906106ab9190615599565b612a71565b6040516106be9291906155e9565b60405180910390f35b3480156106d2575f5ffd5b506106db612c59565b6040516106ea939291906157e8565b60405180910390f35b3480156106fe575f5ffd5b50610707613137565b005b348015610714575f5ffd5b5061072f600480360381019061072a9190615599565b6131a3565b60405161073d92919061582b565b60405180910390f35b348015610751575f5ffd5b5061076c60048036038101906107679190615424565b613574565b005b348015610779575f5ffd5b50610794600480360381019061078f9190614a81565b61363b565b6040516107a19190615938565b60405180910390f35b3480156107b5575f5ffd5b506107d060048036038101906107cb9190615599565b61379d565b6040516107dd919061540a565b60405180910390f35b3480156107f1575f5ffd5b5061080c60048036038101906108079190614a81565b61397f565b005b348015610819575f5ffd5b50610834600480360381019061082f9190615952565b613bdf565b005b348015610841575f5ffd5b5061084a613f98565b6040516108579190614fb3565b60405180910390f35b60605f61086d6012613f9e565b90508067ffffffffffffffff81111561088957610888614fe0565b5b6040519080825280602002602001820160405280156108c257816020015b6108af614749565b8152602001906001900390816108a75790505b5091505f60025490505f60035490505f5f90505b83811015610a66575f6108f3826012613fb790919063ffffffff16565b90505f6108ff82613fd4565b905060405180610160016040528083815260200186815260200185815260200160065f8581526020019081526020015f205f8881526020019081526020015f2054815260200160045f8581526020019081526020015f205f8881526020019081526020015f2054815260200160055f8581526020019081526020015f205f8881526020019081526020015f20548152602001600e5f8581526020019081526020015f205f8881526020019081526020015f20548152602001600f5f8581526020019081526020015f205f8881526020019081526020015f2054815260200160095f8581526020019081526020015f205f6001896109fc9190615a08565b81526020019081526020015f20548152602001828152602001600a5f8581526020019081526020015f205f8881526020019081526020015f2054815250878481518110610a4c57610a4b615a3b565b5b6020026020010181905250505080806001019150506108d6565b5050505090565b60605f60025490505f60968211610a9057600182610a8b9190615a08565b610a93565b60965b90505f8183610aa29190615a08565b90508167ffffffffffffffff811115610abe57610abd614fe0565b5b604051908082528060200260200182016040528015610af757816020015b610ae4614798565b815260200190600190039081610adc5790505b5093505f5f90505b82811015610c53576040518060e001604052808781526020018284610b249190615a68565b8152602001600e5f8981526020019081526020015f205f8486610b479190615a68565b81526020019081526020015f20548152602001600f5f8981526020019081526020015f205f8486610b789190615a68565b81526020019081526020015f2054815260200160095f8981526020019081526020015f205f84600187610bab9190615a08565b610bb59190615a68565b81526020019081526020015f2054815260200160095f8981526020019081526020015f205f8486610be69190615a68565b81526020019081526020015f20548152602001600a5f8981526020019081526020015f205f8486610c179190615a68565b81526020019081526020015f2054815250858281518110610c3b57610c3a615a3b565b5b60200260200101819052508080600101915050610aff565b50505050919050565b335f52600b60205260405f20815f528060205260405f20805480825f5260205f206019821115610c8b57601991505b5f5b82811015610e3c57808201545f82840155335f52600d60205260405f209650875f528660205260405f209650805f528660205260405f205f81541115610cda5763646cf5585f526004601cfd5b885f52600a60205260405f209750815f528760205260405f2097505f600189548060018114610d135760028114610d675785875d610db7565b60018555335f52600760205260405f209b508c5f528b60205260405f209b50855f528b60205260405f209b508b5493508c5f52600e60205260405f209b50855f528b60205260405f209b508b549250610db7565b60018555335f52600860205260405f209b508c5f528b60205260405f209b50855f528b60205260405f209b508b5493508c5f52600f60205260405f209b50855f528b60205260405f209b508b5492505b505f84541115610e2c578b5f52600660205260405f209a50845f528a60205260405f209a50818b54840204815f528060205233868e7f3f63856e2d8c431941e15ac15a28d4201c2838a61987308f61a9d5d01aac483960405fa45f5f5f5f84335af1610e2a576398f736095f526004601cfd5b505b5050505050600181019050610c8d565b508183036019811115610e4e57601990505b8284035f5b82811015610e8c57600181018603840154818501555f815c1115610e8157805c828501555f815d6001820191505b600181019050610e53565b505f8203610ec5575f5b6019811015610ec3575f815c1115610eb857805c828501555f815d6001820191505b600181019050610e96565b505b8086555050505050505050565b6060600b5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f20805480602002602001604051908101604052809291908181526020018280548015610f6857602002820191905f5260205f20905b815481526020019060010190808311610f54575b5050505050905092915050565b6060610f816012614002565b905090565b610f8e6147ce565b5f60035490505f60095f8681526020019081526020015f205f8581526020019081526020015f205490505f5f8214610fc65781610fd0565b610fcf86613fd4565b5b90505f600a8611610fed57600186610fe89190615a08565b610ff0565b600a5b90505f8167ffffffffffffffff81111561100d5761100c614fe0565b5b60405190808252806020026020018201604052801561103b5781602001602082028036833780820191505090505b5090505f5f90505b828110156110af57600a5f8a81526020019081526020015f205f6001838b61106b9190615a08565b6110759190615a08565b81526020019081526020015f205482828151811061109657611095615a3b565b5b6020026020010181815250508080600101915050611043565b50604051806101a0016040528089815260200188815260200186815260200160065f8b81526020019081526020015f205f8a81526020019081526020015f2054815260200160045f8b81526020019081526020015f205f8a81526020019081526020015f2054815260200160055f8b81526020019081526020015f205f8a81526020019081526020015f20548152602001600e5f8b81526020019081526020015f205f8a81526020019081526020015f20548152602001600f5f8b81526020019081526020015f205f8a81526020019081526020015f2054815260200160095f8b81526020019081526020015f205f60018b6111ab9190615a08565b81526020019081526020015f20548152602001848152602001600a5f8b81526020019081526020015f205f8a81526020019081526020015f2054815260200160115f8b81526020019081526020015f20548152602001828152509550505050505092915050565b61122683601261402490919063ffffffff16565b61125c576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60115f8581526020019081526020015f20541415801561128e57508160115f8581526020019081526020015f205411155b156112c5576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60035460018211156112de5763b4fa3fb35f526004601cfd5b600254845f52600960205260405f20600185035f528060205260405f2090505f81541485831416156113175763a2b52a545f526004601cfd5b81851060018301861117156113335763a2b52a545f526004601cfd5b4261012c840110828614161561135057639e6d804f5f526004601cfd5b61012c83014210600183018614161561137057635b903c715f526004601cfd5b6103e86103e53402048034036103e861025882020460015401600155865f52601060205260405f2092506103e861025882020481038354018355875f52600660205260405f20925082602052865f5260405f209250818354018355335f52600c60205260405f209250875f528260205260405f209250865f528260205260405f2092505f8354036114325760018355335f52600b60205260405f209250875f528260205260405f2092508254600181018455835f5260205f2093508781850155505b875f52600460205260405f20925082602052865f5260405f2092508254885f52600560205260405f2080602052885f5260405f20905080545f890361152557808501838602048c868201101561148f5763a6d7690f5f526004601cfd5b80840387558582018355335f52600760205260405f209650866020528b5f5260405f209650866020528a5f5260405f20965085810187540187558b5f52600e60205260405f209650866020528a5f5260405f2096508581018754018755345f5289602052858101604052338b8d7fafdcf9101f4dab5c3b6e53a3ec30d3e897f17b974edceb117d3c12d2d83b0fd960605fa45f5ff35b828501818602048c86820110156115435763a6d7690f5f526004601cfd5b85840187558082038355335f52600860205260405f209650866020528b5f5260405f209650866020528a5f5260405f20965085810187540187558b5f52600f60205260405f209650866020528a5f5260405f2096508581018754018755345f5289602052858101604052338b8d7fafdcf9101f4dab5c3b6e53a3ec30d3e897f17b974edceb117d3c12d2d83b0fd960605fa45f5ff35b60035481565b60605f825190508067ffffffffffffffff811115611600576115ff614fe0565b5b60405190808252806020026020018201604052801561163957816020015b61162661482a565b81526020019060019003908161161e5790505b5091505f5f90505b81811015611864575f84828151811061165d5761165c615a3b565b5b60200260200101519050604051806101200160405280878152602001828152602001600a5f8981526020019081526020015f205f8481526020019081526020015f20548152602001600e5f8981526020019081526020015f205f8481526020019081526020015f20548152602001600f5f8981526020019081526020015f205f8481526020019081526020015f2054815260200160075f8a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8981526020019081526020015f205f8481526020019081526020015f2054815260200160085f8a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8981526020019081526020015f205f8481526020019081526020015f2054815260200160065f8981526020019081526020015f205f8481526020019081526020015f20548152602001600d5f8a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8981526020019081526020015f205f8481526020019081526020015f205481525084838151811061184b5761184a615a3b565b5b6020026020010181905250508080600101915050611641565b50509392505050565b5f5f5f6102586003546118809190615a68565b42101592506102586003546118959190615a68565b42106118a1575f6118bd565b426102586003546118b29190615a68565b6118bc9190615a08565b5b915060105f60025481526020019081526020015f20549050909192565b6118e261482a565b5f6002549050604051806101200160405280848152602001828152602001600a5f8681526020019081526020015f205f8481526020019081526020015f20548152602001600e5f8681526020019081526020015f205f8481526020019081526020015f20548152602001600f5f8681526020019081526020015f205f8481526020019081526020015f2054815260200160075f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8681526020019081526020015f205f8481526020019081526020015f2054815260200160085f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8681526020019081526020015f205f8481526020019081526020015f2054815260200160065f8681526020019081526020015f205f8481526020019081526020015f20548152602001600d5f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8681526020019081526020015f205f8481526020019081526020015f205481525091505092915050565b5f5f60045f8681526020019081526020015f205f8581526020019081526020015f205490505f60055f8781526020019081526020015f205f8681526020019081526020015f205490506103e86103e588611b1c9190615a9b565b611b269190615b09565b96505f8403611b6357868188611b3c9190615a68565b8389611b489190615a9b565b611b529190615b09565b611b5c9190615a68565b9250611b93565b868288611b709190615a68565b8289611b7c9190615a9b565b611b869190615b09565b611b909190615a68565b92505b5050949350505050565b60605f611baa6012613f9e565b90508067ffffffffffffffff811115611bc657611bc5614fe0565b5b604051908082528060200260200182016040528015611bff57816020015b611bec614749565b815260200190600190039081611be45790505b5091505f60035490505f5f90505b82811015611dd0575f611c2a826012613fb790919063ffffffff16565b90505f60095f8381526020019081526020015f205f8881526020019081526020015f205490505f5f8214611c5e5781611c68565b611c6783613fd4565b5b905060405180610160016040528084815260200189815260200186815260200160065f8681526020019081526020015f205f8b81526020019081526020015f2054815260200160045f8681526020019081526020015f205f8b81526020019081526020015f2054815260200160055f8681526020019081526020015f205f8b81526020019081526020015f20548152602001600e5f8681526020019081526020015f205f8b81526020019081526020015f20548152602001600f5f8681526020019081526020015f205f8b81526020019081526020015f2054815260200160095f8681526020019081526020015f205f60018c611d659190615a08565b81526020019081526020015f20548152602001828152602001600a5f8681526020019081526020015f205f8b81526020019081526020015f2054815250878581518110611db557611db4615a3b565b5b60200260200101819052505050508080600101915050611c0d565b505050919050565b6011602052805f5260405f205f915090505481565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611e72576040517f1648fd0100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611e8681601261402490919063ffffffff16565b611ebc576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6005600254611ecb9190615a68565b60115f8381526020019081526020015f208190555050565b60605f611ef06012613f9e565b90508067ffffffffffffffff811115611f0c57611f0b614fe0565b5b604051908082528060200260200182016040528015611f4557816020015b611f3261486d565b815260200190600190039081611f2a5790505b5091505f5f90505b81811015612045575f611f6a826012613fb790919063ffffffff16565b90506040518060400160405280828152602001600b5f8873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f2080548060200260200160405190810160405280929190818152602001828054801561201157602002820191905f5260205f20905b815481526020019060010190808311611ffd575b505050505081525084838151811061202c5761202b615a3b565b5b6020026020010181905250508080600101915050611f4d565b5050919050565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146120d1576040517f1648fd0100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60115f8381526020019081526020015f20819055506120fb81601261404190919063ffffffff16565b612131576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61214581601361404190919063ffffffff16565b505f60016002546121569190615a68565b905068170a0f5040e504000060045f8481526020019081526020015f205f8381526020019081526020015f208190555068170a0f5040e504000060055f8481526020019081526020015f205f8381526020019081526020015f20819055505050565b610258600354014210156121d35763b7d094975f526004601cfd5b5f60025490505f6121e46012613f9e565b90505f5f90505b8181101561237a575f612208826012613fb790919063ffffffff16565b90505f61221482613fd4565b9050815f52600a60205260405f20855f528060205260405f205f815411156122435763fd29af2c5f526004601cfd5b835f52600960205260405f209150600187035f528160205260405f2091508154875f5260405f2092508383555f81111561231457845f52600660205260405f20925082602052875f5260405f2092508254818511600181146122ab575f81146122e057612311565b60018455865f52600e60205260405f20945084602052895f5260405f2094505f8554036122db5781600154016001555b612311565b60028455865f52600f60205260405f20945084602052895f5260405f2094505f8554036123105781600154016001555b5b50505b845f52600460205260405f20925082602052600288015f5260405f20925068170a0f5040e50400008355845f52600560205260405f20925082602052600288015f5260405f20925068170a0f5040e50400008355505050505080806001019150506121eb565b506002545f52601060205260405f20805460018401600255426003555f5f5f5f84335af16123af576398f736095f526004601cfd5b805f5233847fa4151f6c29291b1556b1872bc36e5304d55092b1703f6226eefdb53250765c7160205fa350505050565b60015481565b60605f6123f26012613f9e565b90508067ffffffffffffffff81111561240e5761240d614fe0565b5b60405190808252806020026020018201604052801561244757816020015b61243461482a565b81526020019060019003908161242c5790505b5091505f5f90505b8181101561266b575f61246c826012613fb790919063ffffffff16565b9050604051806101200160405280828152602001868152602001600a5f8481526020019081526020015f205f8881526020019081526020015f20548152602001600e5f8481526020019081526020015f205f8881526020019081526020015f20548152602001600f5f8481526020019081526020015f205f8881526020019081526020015f2054815260200160075f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205f8881526020019081526020015f2054815260200160085f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205f8881526020019081526020015f2054815260200160065f8481526020019081526020015f205f8881526020019081526020015f20548152602001600d5f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205f8881526020019081526020015f205481525084838151811061265257612651615a3b565b5b602002602001018190525050808060010191505061244f565b505092915050565b606061267f6013614002565b905090565b6060806126916012614002565b61269b6013614002565b915091509091565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612728576040517f1648fd0100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60115f8381526020019081526020015f20541480612759575060025460115f8381526020019081526020015f2054115b15612790576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6127a481601261405e90919063ffffffff16565b6127da576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b60605f6127ea6012613f9e565b90508067ffffffffffffffff81111561280657612805614fe0565b5b60405190808252806020026020018201604052801561283f57816020015b61282c61482a565b8152602001906001900390816128245790505b5091505f60025490505f5f90505b82811015612a69575f61286a826012613fb790919063ffffffff16565b9050604051806101200160405280828152602001848152602001600a5f8481526020019081526020015f205f8681526020019081526020015f20548152602001600e5f8481526020019081526020015f205f8681526020019081526020015f20548152602001600f5f8481526020019081526020015f205f8681526020019081526020015f2054815260200160075f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205f8681526020019081526020015f2054815260200160085f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205f8681526020019081526020015f2054815260200160065f8481526020019081526020015f205f8681526020019081526020015f20548152602001600d5f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205f8681526020019081526020015f2054815250858381518110612a5057612a4f615a3b565b5b602002602001018190525050808060010191505061284d565b505050919050565b5f6060600b5f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8581526020019081526020015f208054905091505f6101f490505f8185612ad99190615a9b565b9050838110612b34575f67ffffffffffffffff811115612afc57612afb614fe0565b5b604051908082528060200260200182016040528015612b2a5781602001602082028036833780820191505090505b5092505050612c51565b5f8185612b419190615a08565b90505f838210612b515783612b53565b815b90508067ffffffffffffffff811115612b6f57612b6e614fe0565b5b604051908082528060200260200182016040528015612b9d5781602001602082028036833780820191505090505b5094505f5f90505b81811015612c4b57600b5f8b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8a81526020019081526020015f208185612c059190615a68565b81548110612c1657612c15615a3b565b5b905f5260205f200154868281518110612c3257612c31615a3b565b5b6020026020010181815250508080600101915050612ba5565b50505050505b935093915050565b5f6060805f612c686012613f9e565b905060025493505f600a8511612c8a57600185612c859190615a08565b612c8d565b600a5b90508167ffffffffffffffff811115612ca957612ca8614fe0565b5b604051908082528060200260200182016040528015612ce257816020015b612ccf6147ce565b815260200190600190039081612cc75790505b5093508167ffffffffffffffff811115612cff57612cfe614fe0565b5b604051908082528060200260200182016040528015612d3857816020015b612d256147ce565b815260200190600190039081612d1d5790505b5092505f600186612d499190615a68565b90505f60035490505f5f90505b8481101561312d575f8467ffffffffffffffff811115612d7957612d78614fe0565b5b604051908082528060200260200182016040528015612da75781602001602082028036833780820191505090505b5090505f612dbf836012613fb790919063ffffffff16565b90505f612dcb82613fd4565b90505f5f90505b87811015612e3e57600a5f8481526020019081526020015f205f6001838f612dfa9190615a08565b612e049190615a08565b81526020019081526020015f2054848281518110612e2557612e24615a3b565b5b6020026020010181815250508080600101915050612dd2565b50604051806101a001604052808381526020018c815260200186815260200160065f8581526020019081526020015f205f8e81526020019081526020015f2054815260200160045f8581526020019081526020015f205f8e81526020019081526020015f2054815260200160055f8581526020019081526020015f205f8e81526020019081526020015f20548152602001600e5f8581526020019081526020015f205f8e81526020019081526020015f20548152602001600f5f8581526020019081526020015f205f8e81526020019081526020015f2054815260200160095f8581526020019081526020015f205f60018f612f3a9190615a08565b81526020019081526020015f20548152602001828152602001600a5f8581526020019081526020015f205f8e81526020019081526020015f2054815260200160115f8581526020019081526020015f20548152602001848152508a8581518110612fa757612fa6615a3b565b5b6020026020010181905250604051806101a0016040528083815260200187815260200186815260200160065f8581526020019081526020015f205f8981526020019081526020015f2054815260200160045f8581526020019081526020015f205f8981526020019081526020015f2054815260200160055f8581526020019081526020015f205f8981526020019081526020015f20548152602001600e5f8581526020019081526020015f205f8981526020019081526020015f20548152602001600f5f8581526020019081526020015f205f8981526020019081526020015f2054815260200160095f8581526020019081526020015f205f8e81526020019081526020015f20548152602001828152602001600a5f8581526020019081526020015f205f8981526020019081526020015f2054815260200160115f8581526020019081526020015f205481526020018481525089858151811061310e5761310d615a3b565b5b6020026020010181905250606092505050508080600101915050612d56565b5050505050909192565b5f60015490505f6001819055505f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc8290811502906040515f60405180830381858888f193505050506131a0575f5ffd5b50565b5f6060600b5f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8581526020019081526020015f208054905091505f606490505f818561320a9190615a9b565b9050838110613270575f67ffffffffffffffff81111561322d5761322c614fe0565b5b60405190808252806020026020018201604052801561326657816020015b61325361482a565b81526020019060019003908161324b5790505b509250505061356c565b5f818561327d9190615a08565b90505f83821061328d578361328f565b815b90508067ffffffffffffffff8111156132ab576132aa614fe0565b5b6040519080825280602002602001820160405280156132e457816020015b6132d161482a565b8152602001906001900390816132c95790505b5094505f5f90505b81811015613566575f600b5f8c73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8b81526020019081526020015f20828661334d9190615a68565b8154811061335e5761335d615a3b565b5b905f5260205f20015490506040518061012001604052808b8152602001828152602001600a5f8d81526020019081526020015f205f8481526020019081526020015f20548152602001600e5f8d81526020019081526020015f205f8481526020019081526020015f20548152602001600f5f8d81526020019081526020015f205f8481526020019081526020015f2054815260200160075f8e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8d81526020019081526020015f205f8481526020019081526020015f2054815260200160085f8e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8d81526020019081526020015f205f8481526020019081526020015f2054815260200160065f8d81526020019081526020015f205f8481526020019081526020015f20548152602001600d5f8e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8d81526020019081526020015f205f8481526020019081526020015f205481525087838151811061354d5761354c615a3b565b5b60200260200101819052505080806001019150506132ec565b50505050505b935093915050565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146135f9576040517f1648fd0100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805f5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b613643614749565b5f60025490505f60035490505f61365985613fd4565b905060405180610160016040528086815260200184815260200183815260200160065f8881526020019081526020015f205f8681526020019081526020015f2054815260200160045f8881526020019081526020015f205f8681526020019081526020015f2054815260200160055f8881526020019081526020015f205f8681526020019081526020015f20548152602001600e5f8881526020019081526020015f205f8681526020019081526020015f20548152602001600f5f8881526020019081526020015f205f8681526020019081526020015f2054815260200160095f8881526020019081526020015f205f6001876137569190615a08565b81526020019081526020015f20548152602001828152602001600a5f8881526020019081526020015f205f8681526020019081526020015f20548152509350505050919050565b6137a561482a565b604051806101200160405280848152602001838152602001600a5f8681526020019081526020015f205f8581526020019081526020015f20548152602001600e5f8681526020019081526020015f205f8581526020019081526020015f20548152602001600f5f8681526020019081526020015f205f8581526020019081526020015f2054815260200160075f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8681526020019081526020015f205f8581526020019081526020015f2054815260200160085f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8681526020019081526020015f205f8581526020019081526020015f2054815260200160065f8681526020019081526020015f205f8581526020019081526020015f20548152602001600d5f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8681526020019081526020015f205f8581526020019081526020015f205481525090509392505050565b335f52600b60205260405f20815f528060205260405f208054815f5260205f205f5b82811015613b5057808201545f82840155335f52600d60205260405f209550865f528560205260405f209550805f528560205260405f205f815411156139ee5763646cf5585f526004601cfd5b875f52600a60205260405f209650815f528660205260405f2096505f600188548060018114613a275760028114613a7b5785875d613acb565b60018555335f52600760205260405f209a508b5f528a60205260405f209a50855f528a60205260405f209a508a5493508b5f52600e60205260405f209a50855f528a60205260405f209a508a549250613acb565b60018555335f52600860205260405f209a508b5f528a60205260405f209a50855f528a60205260405f209a508a5493508b5f52600f60205260405f209a50855f528a60205260405f209a508a5492505b505f84541115613b40578a5f52600660205260405f209950845f528960205260405f209950818a54840204815f528060205233868d7f3f63856e2d8c431941e15ac15a28d4201c2838a61987308f61a9d5d01aac483960405fa45f5f5f5f84335af1613b3e576398f736095f526004601cfd5b505b50505050506001810190506139a1565b505f5f5f5c1115613b6b575f5c818301555f5f5d6001810190505b5f60015c1115613b875760015c818301555f60015d6001810190505b5f83115f600185035c111615613bad57600183035c818301555f600184035d6001810190505b600183115f600285035c111615613bd457600283035c818301555f600284035d6001810190505b808455505050505050565b613bf385601261402490919063ffffffff16565b613c29576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5f821115613c935782841015613c6857613c4582878761407b565b90508183613c539190615a08565b92508084613c619190615a68565b9350613c92565b613c738287876141aa565b90508184613c819190615a08565b93508083613c8f9190615a68565b92505b5b828411613ca05783613ca2565b825b90506002546001810186118187101715613cc35763a2b52a545f526004601cfd5b4261012c60035401108187141615613ce257639e6d804f5f526004601cfd5b5f831160018114613cf9575f8114613e0357613ef1565b875f52600660205260405f2080602052875f5260405f2090508360025c0381555f60025d335f52600760205260405f20905080602052885f5260405f20905080602052875f5260405f2090508360035c1015613d5c57637b9c89165f526004601cfd5b8360035c0381555f60035d335f52600860205260405f20905080602052885f5260405f20905080602052875f5260405f2090508360045c1015613da657637b9c89165f526004601cfd5b8360045c0381555f60045d885f52600e60205260405f20905080602052875f5260405f2090508360055c0381555f60055d885f52600f60205260405f20905080602052875f5260405f2090508360065c0381555f60065d50613ef1565b875f52600660205260405f2080602052875f5260405f209050838154038155335f52600760205260405f20905080602052885f5260405f20905080602052875f5260405f209050805484811015613e6157637b9c89165f526004601cfd5b8481038255335f52600860205260405f20915081602052895f5260405f20915081602052885f5260405f2091508154905084811015613ea757637b9c89165f526004601cfd5b8481038255895f52600e60205260405f20915081602052885f5260405f209150848254038255895f52600f60205260405f20915081602052885f5260405f20915084825403825550505b506103e86103e58302048083036103e861025882020460015401600155875f52601060205260405f206103e8610258830204820381540181558a831015613f3f5763a6d7690f5f526004601cfd5b875f52866020528260405233898b7f4c686a53bc9329e91f0d0d94d821505fd2c0aef3c09a94ea360d98c0dfb9dee460605fa45f5f5f5f86335af1613f8b576398f736095f526004601cfd5b5050505050505050505050565b60025481565b5f613fb0613fab836142d9565b6142e2565b9050919050565b5f613fca613fc4846142d9565b8361432f565b5f1c905092915050565b5f5f6108079050825f5260205f60205f845afa613ff85763b41b6cb15f526004601cfd5b5f51915050919050565b606061401d614018614013846142d9565b614399565b614460565b9050919050565b5f614039614031846142d9565b835f1b61446a565b905092915050565b5f61405661404e846142d9565b835f1b6144f9565b905092915050565b5f61407361406b846142d9565b835f1b614622565b905092915050565b5f825f52600560205260405f20825f528060205260405f20905080548581018255845f52600460205260405f209150835f528160205260405f20915081548187018188020493508381038355855f52600660205260405f20925082602052845f5260405f209250825460025d335f52600760205260405f20925082602052855f5260405f20925082602052845f5260405f2092508383540160035d335f52600860205260405f20925082602052855f5260405f20925082602052845f5260405f20925082548781101561415557637b9c89165f526004601cfd5b87810360045d865f52600e60205260405f20935083602052855f5260405f2093508484540160055d865f52600f60205260405f20935083602052855f5260405f2093508784540360065d505050509392505050565b5f825f52600460205260405f20825f528060205260405f20905080548581018255845f52600560205260405f20915081602052835f5260405f20915081548187018188020493508381038355855f52600660205260405f20925082602052845f5260405f209250825460025d335f52600760205260405f20925082602052855f5260405f20925082602052845f5260405f20925082548781101561425557637b9c89165f526004601cfd5b87810360035d335f52600860205260405f20935083602052865f5260405f20935083602052855f5260405f2093508484540160045d865f52600e60205260405f20935083602052855f5260405f2093508784540360055d865f52600f60205260405f20935083602052855f5260405f2093508484540160065d505050509392505050565b5f819050919050565b5f5f6142ed83614732565b90508019548060011c925080614328575f92508282015415614328576001925082820154156143285760029250828201541561432857600392505b5050919050565b5f61433983614732565b905081810154905068fbb67fda52d4bfb8bf8114158102905061435b836142e2565b8210614393576040517f4e23d03500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b92915050565b60605f6143a583614732565b905068fbb67fda52d4bfb8bf81195460405193508360200160011561444b578161441c5783548015614416576001925083811415810282528285015490508015614415576002925083811415810260208301528285015490508015614414576003925083811415810260408301525b5b5b5061444b565b8160011c91505f5b8281101561444957808501548481141581028260051b84015250600181019050614424565b505b8185528160051b810160405250505050919050565b6060819050919050565b5f5f61447584614732565b905068fbb67fda52d4bfb8bf83036144945763f5a267f15f526004601cfd5b826144a65768fbb67fda52d4bfb8bf92505b6001156144f2578019546144e1576001915082815403156144f25782600182015403156144f25782600282015403156144f2575f91506144f2565b80602052825f5260405f2054151591505b5092915050565b5f5f61450484614732565b905068fbb67fda52d4bfb8bf83036145235763f5a267f15f526004601cfd5b826145355768fbb67fda52d4bfb8bf92505b80195460011561461a5781602052806145e35781548061455c57848355600193505061461a565b848103614569575061461a565b6001830154806145845785600185015560019450505061461a565b85810361459257505061461a565b6002840154806145ae578660028601556001955050505061461a565b8681036145bd5750505061461a565b825f52600160405f2055815f52600260405f2055805f52600360405f2055600793505050505b835f5260405f208054614618578160011c915084828401558160010181558160010160011b600117831955600193505061461a565b505b505092915050565b5f5f61462d84614732565b905068fbb67fda52d4bfb8bf830361464c5763f5a267f15f526004601cfd5b8261465e5768fbb67fda52d4bfb8bf92505b80195460011561472a57806146d35760019250838254036146955760018201548255600282015460018301555f600283015561472a565b836001830154036146b557600282015460018301555f600283015561472a565b836002830154036146cb575f600283015561472a565b5f925061472a565b81602052835f5260405f208054806146ec57505061472a565b60018360011c03925082600182031461471657828401548060018303860155805f528160405f2055505b60018360011b178419555f82556001945050505b505092915050565b5f6318fb5864600452815f5260245f209050919050565b6040518061016001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b6040518060e001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b604051806101a001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f8152602001606081525090565b6040518061012001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b60405180604001604052805f8152602001606081525090565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f819050919050565b6148c1816148af565b82525050565b61016082015f8201516148dc5f8501826148b8565b5060208201516148ef60208501826148b8565b50604082015161490260408501826148b8565b50606082015161491560608501826148b8565b50608082015161492860808501826148b8565b5060a082015161493b60a08501826148b8565b5060c082015161494e60c08501826148b8565b5060e082015161496160e08501826148b8565b506101008201516149766101008501826148b8565b5061012082015161498b6101208501826148b8565b506101408201516149a06101408501826148b8565b50505050565b5f6149b183836148c7565b6101608301905092915050565b5f602082019050919050565b5f6149d482614886565b6149de8185614890565b93506149e9836148a0565b805f5b83811015614a19578151614a0088826149a6565b9750614a0b836149be565b9250506001810190506149ec565b5085935050505092915050565b5f6020820190508181035f830152614a3e81846149ca565b905092915050565b5f604051905090565b5f5ffd5b5f5ffd5b614a60816148af565b8114614a6a575f5ffd5b50565b5f81359050614a7b81614a57565b92915050565b5f60208284031215614a9657614a95614a4f565b5b5f614aa384828501614a6d565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b60e082015f820151614ae95f8501826148b8565b506020820151614afc60208501826148b8565b506040820151614b0f60408501826148b8565b506060820151614b2260608501826148b8565b506080820151614b3560808501826148b8565b5060a0820151614b4860a08501826148b8565b5060c0820151614b5b60c08501826148b8565b50505050565b5f614b6c8383614ad5565b60e08301905092915050565b5f602082019050919050565b5f614b8e82614aac565b614b988185614ab6565b9350614ba383614ac6565b805f5b83811015614bd3578151614bba8882614b61565b9750614bc583614b78565b925050600181019050614ba6565b5085935050505092915050565b5f6020820190508181035f830152614bf88184614b84565b905092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f614c2982614c00565b9050919050565b614c3981614c1f565b8114614c43575f5ffd5b50565b5f81359050614c5481614c30565b92915050565b5f5f60408385031215614c7057614c6f614a4f565b5b5f614c7d85828601614c46565b9250506020614c8e85828601614a6d565b9150509250929050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f614ccc83836148b8565b60208301905092915050565b5f602082019050919050565b5f614cee82614c98565b614cf88185614ca2565b9350614d0383614cb2565b805f5b83811015614d33578151614d1a8882614cc1565b9750614d2583614cd8565b925050600181019050614d06565b5085935050505092915050565b5f6020820190508181035f830152614d588184614ce4565b905092915050565b5f5f60408385031215614d7657614d75614a4f565b5b5f614d8385828601614a6d565b9250506020614d9485828601614a6d565b9150509250929050565b5f82825260208201905092915050565b5f614db882614c98565b614dc28185614d9e565b9350614dcd83614cb2565b805f5b83811015614dfd578151614de48882614cc1565b9750614def83614cd8565b925050600181019050614dd0565b5085935050505092915050565b5f6101a083015f830151614e205f8601826148b8565b506020830151614e3360208601826148b8565b506040830151614e4660408601826148b8565b506060830151614e5960608601826148b8565b506080830151614e6c60808601826148b8565b5060a0830151614e7f60a08601826148b8565b5060c0830151614e9260c08601826148b8565b5060e0830151614ea560e08601826148b8565b50610100830151614eba6101008601826148b8565b50610120830151614ecf6101208601826148b8565b50610140830151614ee46101408601826148b8565b50610160830151614ef96101608601826148b8565b50610180830151848203610180860152614f138282614dae565b9150508091505092915050565b5f6020820190508181035f830152614f388184614e0a565b905092915050565b5f5f5f5f60808587031215614f5857614f57614a4f565b5b5f614f6587828801614a6d565b9450506020614f7687828801614a6d565b9350506040614f8787828801614a6d565b9250506060614f9887828801614a6d565b91505092959194509250565b614fad816148af565b82525050565b5f602082019050614fc65f830184614fa4565b92915050565b5f5ffd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b61501682614fd0565b810181811067ffffffffffffffff8211171561503557615034614fe0565b5b80604052505050565b5f615047614a46565b9050615053828261500d565b919050565b5f67ffffffffffffffff82111561507257615071614fe0565b5b602082029050602081019050919050565b5f5ffd5b5f61509961509484615058565b61503e565b905080838252602082019050602084028301858111156150bc576150bb615083565b5b835b818110156150e557806150d18882614a6d565b8452602084019350506020810190506150be565b5050509392505050565b5f82601f83011261510357615102614fcc565b5b8135615113848260208601615087565b91505092915050565b5f5f5f6060848603121561513357615132614a4f565b5b5f61514086828701614c46565b935050602061515186828701614a6d565b925050604084013567ffffffffffffffff81111561517257615171614a53565b5b61517e868287016150ef565b9150509250925092565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b61012082015f8201516151c65f8501826148b8565b5060208201516151d960208501826148b8565b5060408201516151ec60408501826148b8565b5060608201516151ff60608501826148b8565b50608082015161521260808501826148b8565b5060a082015161522560a08501826148b8565b5060c082015161523860c08501826148b8565b5060e082015161524b60e08501826148b8565b506101008201516152606101008501826148b8565b50505050565b5f61527183836151b1565b6101208301905092915050565b5f602082019050919050565b5f61529482615188565b61529e8185615192565b93506152a9836151a2565b805f5b838110156152d95781516152c08882615266565b97506152cb8361527e565b9250506001810190506152ac565b5085935050505092915050565b5f6020820190508181035f8301526152fe818461528a565b905092915050565b5f8115159050919050565b61531a81615306565b82525050565b5f6060820190506153335f830186615311565b6153406020830185614fa4565b61534d6040830184614fa4565b949350505050565b61012082015f82015161536a5f8501826148b8565b50602082015161537d60208501826148b8565b50604082015161539060408501826148b8565b5060608201516153a360608501826148b8565b5060808201516153b660808501826148b8565b5060a08201516153c960a08501826148b8565b5060c08201516153dc60c08501826148b8565b5060e08201516153ef60e08501826148b8565b506101008201516154046101008501826148b8565b50505050565b5f6101208201905061541e5f830184615355565b92915050565b5f6020828403121561543957615438614a4f565b5b5f61544684828501614c46565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f604083015f83015161548d5f8601826148b8565b50602083015184820360208601526154a58282614dae565b9150508091505092915050565b5f6154bd8383615478565b905092915050565b5f602082019050919050565b5f6154db8261544f565b6154e58185615459565b9350836020820285016154f785615469565b805f5b85811015615532578484038952815161551385826154b2565b945061551e836154c5565b925060208a019950506001810190506154fa565b50829750879550505050505092915050565b5f6020820190508181035f83015261555c81846154d1565b905092915050565b5f6040820190508181035f83015261557c8185614ce4565b905081810360208301526155908184614ce4565b90509392505050565b5f5f5f606084860312156155b0576155af614a4f565b5b5f6155bd86828701614c46565b93505060206155ce86828701614a6d565b92505060406155df86828701614a6d565b9150509250925092565b5f6040820190506155fc5f830185614fa4565b818103602083015261560e8184614ce4565b90509392505050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f6101a083015f8301516156565f8601826148b8565b50602083015161566960208601826148b8565b50604083015161567c60408601826148b8565b50606083015161568f60608601826148b8565b5060808301516156a260808601826148b8565b5060a08301516156b560a08601826148b8565b5060c08301516156c860c08601826148b8565b5060e08301516156db60e08601826148b8565b506101008301516156f06101008601826148b8565b506101208301516157056101208601826148b8565b5061014083015161571a6101408601826148b8565b5061016083015161572f6101608601826148b8565b506101808301518482036101808601526157498282614dae565b9150508091505092915050565b5f6157618383615640565b905092915050565b5f602082019050919050565b5f61577f82615617565b6157898185615621565b93508360208202850161579b85615631565b805f5b858110156157d657848403895281516157b78582615756565b94506157c283615769565b925060208a0199505060018101905061579e565b50829750879550505050505092915050565b5f6060820190506157fb5f830186614fa4565b818103602083015261580d8185615775565b905081810360408301526158218184615775565b9050949350505050565b5f60408201905061583e5f830185614fa4565b8181036020830152615850818461528a565b90509392505050565b61016082015f82015161586e5f8501826148b8565b50602082015161588160208501826148b8565b50604082015161589460408501826148b8565b5060608201516158a760608501826148b8565b5060808201516158ba60808501826148b8565b5060a08201516158cd60a08501826148b8565b5060c08201516158e060c08501826148b8565b5060e08201516158f360e08501826148b8565b506101008201516159086101008501826148b8565b5061012082015161591d6101208501826148b8565b506101408201516159326101408501826148b8565b50505050565b5f6101608201905061594c5f830184615859565b92915050565b5f5f5f5f5f5f60c0878903121561596c5761596b614a4f565b5b5f61597989828a01614a6d565b965050602061598a89828a01614a6d565b955050604061599b89828a01614a6d565b94505060606159ac89828a01614a6d565b93505060806159bd89828a01614a6d565b92505060a06159ce89828a01614a6d565b9150509295509295509295565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f615a12826148af565b9150615a1d836148af565b9250828203905081811115615a3557615a346159db565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f615a72826148af565b9150615a7d836148af565b9250828201905080821115615a9557615a946159db565b5b92915050565b5f615aa5826148af565b9150615ab0836148af565b9250828202615abe816148af565b91508282048414831517615ad557615ad46159db565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f615b13826148af565b9150615b1e836148af565b925082615b2e57615b2d615adc565b5b82820490509291505056fea2646970667358221220137ad95f047d8f6117acaa283c77bac9e6c7dfbcf68da0151429aa2025d06b5164736f6c634300081c0033

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

00000000000000000000000000000000000000000000000000000000000000400000000000000000000000002a007eb889ddf2be3f3bda225734c1873bf1ea420000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000009f

-----Decoded View---------------
Arg [0] : initMarketIds (uint256[]): 0,1,5,159
Arg [1] : _admin (address): 0x2A007Eb889Ddf2bE3f3bdA225734c1873BF1EA42

-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [1] : 0000000000000000000000002a007eb889ddf2be3f3bda225734c1873bf1ea42
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000004
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000005
Arg [6] : 000000000000000000000000000000000000000000000000000000000000009f


Block Transaction Gas Used Reward
view all blocks ##produced##

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ 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.