Contract 0xCf3667dfEFa12790D98e4C57E2ADdac40a5292B4

  Note: Our ETH balance display is temporarily unavailable. Please check back later.

Contract Overview

Balance:
Txn Hash Method
Block
From
To
Value
0xd4b6b0f3a43773375bc81d9c8cbd378790b81a8e60903387ebb993aa3e19d3d50x60806040179766902023-11-30 21:57:28175 days 16 hrs ago0xd866b2332d4383c1bf719732177e2d9109c99dbc IN  Create: ParlayVerifier0 ETH0.0000000426370.00001
[ Download CSV Export 
Parent Txn Hash Block From To Value
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
ParlayVerifier

Compiler Version
v0.8.4+commit.c7e474f2

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 11 : ParlayVerifier.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

// interfaces
import "../../interfaces/IParlayMarketsAMM.sol";
import "../../interfaces/ISportsAMM.sol";
// import "../../interfaces/IParlayMarketData.sol";
import "../../interfaces/ISportPositionalMarket.sol";
import "../../interfaces/IParlayPolicy.sol";

contract ParlayVerifier {
    uint private constant ONE = 1e18;
    uint private constant ONE_PERCENT = 1e16;

    uint private constant TAG_F1 = 9445;
    uint private constant TAG_MOTOGP = 9497;
    uint private constant TAG_GOLF = 100121;
    uint private constant TAG_NUMBER_SPREAD = 10001;
    uint private constant TAG_NUMBER_TOTAL = 10002;
    uint private constant DOUBLE_CHANCE_TAG = 10003;
    uint private constant PLAYER_PROPS_TAG = 10010;

    struct InitialQuoteParameters {
        address[] sportMarkets;
        uint[] positions;
        uint totalSUSDToPay;
        uint parlaySize;
        uint defaultONE;
        uint[] sgpFees;
        ISportsAMM sportsAMM;
        address parlayAMM;
    }

    struct VerifyMarket {
        address[] sportMarkets;
        uint[] positions;
        ISportsAMM sportsAMM;
        address parlayAMM;
        uint defaultONE;
    }

    struct CachedMarket {
        bytes32 gameId;
        uint gameCounter;
    }

    struct CheckSGP {
        address[] sportMarkets;
        uint[] positions;
        uint[] tag1;
        uint[] tag2;
        IParlayPolicy parlayPolicy;
        uint defaultONE;
    }

    /// @notice Verifying if given parlay is able to be created given the policies in state
    /// @param params VerifyMarket parameters
    /// @return eligible if the parlay can be created
    /// @return odds the odds for each position
    /// @return sgpFees the fees applied per position in case of SameGameParlay
    function _verifyMarkets(VerifyMarket memory params)
        internal
        view
        returns (
            bool eligible,
            uint[] memory odds,
            uint[] memory sgpFees
        )
    {
        eligible = true;
        uint[] memory tags1;
        uint[] memory tags2;
        IParlayPolicy parlayPolicy = IParlayPolicy(IParlayMarketsAMM(params.parlayAMM).parlayPolicy());
        (tags1, tags2) = _obtainAllTags(params.sportMarkets);
        (odds, sgpFees) = _checkSGPAndGetOdds(
            CheckSGP(params.sportMarkets, params.positions, tags1, tags2, parlayPolicy, params.defaultONE)
        );
    }

    /// @notice Obtain all the tags for each position and calculate unique ones
    /// @param sportMarkets the sport markets for the parlay
    /// @return tag1 all the tags 1 per market
    /// @return tag2 all the tags 2 per market
    function _obtainAllTags(address[] memory sportMarkets) internal view returns (uint[] memory tag1, uint[] memory tag2) {
        tag1 = new uint[](sportMarkets.length);
        tag2 = new uint[](sportMarkets.length);
        address sportMarket;
        for (uint i = 0; i < sportMarkets.length; i++) {
            // 1. Get all tags for a sport market (tag1, tag2)
            sportMarket = sportMarkets[i];
            tag1[i] = ISportPositionalMarket(sportMarket).tags(0);
            tag2[i] = ISportPositionalMarket(sportMarket).getTagsLength() > 1
                ? ISportPositionalMarket(sportMarket).tags(1)
                : 0;
            for (uint j = 0; j < i; j++) {
                if (sportMarkets[i] == sportMarkets[j]) {
                    revert("SameTeamOnParlay");
                }
            }
        }
    }

    /// @notice Check the names, check if any markets are SGPs, obtain odds and apply fees if needed
    /// @param params all the parameters to calculate the fees and odds per position
    /// @return odds all the odds per position
    /// @return sgpFees all the fees per position
    function _checkSGPAndGetOdds(CheckSGP memory params) internal view returns (uint[] memory odds, uint[] memory sgpFees) {
        odds = new uint[](params.sportMarkets.length);
        sgpFees = new uint[](odds.length);
        bool[] memory alreadyInSGP = new bool[](sgpFees.length);
        for (uint i = 0; i < params.sportMarkets.length; i++) {
            for (uint j = 0; j < i; j++) {
                if (params.sportMarkets[j] != params.sportMarkets[i]) {
                    if (!alreadyInSGP[j] && params.tag1[j] == params.tag1[i] && (params.tag2[i] > 0 || params.tag2[j] > 0)) {
                        address parentI = address(ISportPositionalMarket(params.sportMarkets[i]).parentMarket());
                        address parentJ = address(ISportPositionalMarket(params.sportMarkets[j]).parentMarket());
                        if (
                            (params.tag2[j] > 0 && parentJ == params.sportMarkets[i]) ||
                            (params.tag2[i] > 0 && parentI == params.sportMarkets[j]) ||
                            // the following line is for totals + spreads or totals + playerProps
                            (params.tag2[i] > 0 && params.tag2[j] > 0 && parentI == parentJ)
                        ) {
                            uint sgpFee = params.parlayPolicy.getSgpFeePerCombination(
                                IParlayPolicy.SGPData(
                                    params.tag1[i],
                                    params.tag2[i],
                                    params.tag2[j],
                                    params.positions[i],
                                    params.positions[j]
                                )
                            );
                            if (params.tag2[j] == PLAYER_PROPS_TAG && params.tag2[i] == PLAYER_PROPS_TAG) {
                                // check if the markets are elibible props markets
                                if (
                                    !params.parlayPolicy.areEligiblePropsMarkets(
                                        params.sportMarkets[i],
                                        params.sportMarkets[j],
                                        params.tag1[i]
                                    )
                                ) {
                                    revert("InvalidPlayerProps");
                                }
                            } else if (sgpFee == 0) {
                                revert("SameTeamOnParlay");
                            } else {
                                alreadyInSGP[i] = true;
                                alreadyInSGP[j] = true;
                                if (params.tag2[j] > 0) {
                                    (odds[i], odds[j], sgpFees[i], sgpFees[j]) = _getSGPSingleOdds(
                                        params.parlayPolicy.getMarketDefaultOdds(
                                            params.sportMarkets[i],
                                            params.positions[i]
                                        ),
                                        params.parlayPolicy.getMarketDefaultOdds(
                                            params.sportMarkets[j],
                                            params.positions[j]
                                        ),
                                        params.positions[j],
                                        sgpFee,
                                        params.parlayPolicy.getChildMarketTotalLine(params.sportMarkets[j]),
                                        params.defaultONE
                                    );
                                } else {
                                    (odds[j], odds[i], sgpFees[j], sgpFees[i]) = _getSGPSingleOdds(
                                        params.parlayPolicy.getMarketDefaultOdds(
                                            params.sportMarkets[j],
                                            params.positions[j]
                                        ),
                                        params.parlayPolicy.getMarketDefaultOdds(
                                            params.sportMarkets[i],
                                            params.positions[i]
                                        ),
                                        params.positions[i],
                                        sgpFee,
                                        params.parlayPolicy.getChildMarketTotalLine(params.sportMarkets[i]),
                                        params.defaultONE
                                    );
                                }
                            }
                        }
                    }
                } else {
                    revert("SameTeamOnParlay");
                }
            }
            if (odds[i] == 0) {
                odds[i] = params.parlayPolicy.getMarketDefaultOdds(params.sportMarkets[i], params.positions[i]);
            }
        }
    }

    function getSPGOdds(
        uint odds1,
        uint odds2,
        uint position2,
        uint sgpFee,
        uint totalsLine,
        uint defaultONE
    )
        external
        pure
        returns (
            uint resultOdds1,
            uint resultOdds2,
            uint sgpFee1,
            uint sgpFee2
        )
    {
        (resultOdds1, resultOdds2, sgpFee1, sgpFee2) = _getSGPSingleOdds(
            odds1,
            odds2,
            position2,
            sgpFee,
            totalsLine,
            defaultONE
        );
    }

    /// @notice Calculate the sgpFees for the positions of two sport markets, given their odds and default sgpfee
    /// @param odds1 the odd of position 1 (usually the moneyline odd)
    /// @param odds2 the odd of position 2 (usually the totals/spreads odd)
    /// @param sgpFee the default sgp fee
    /// @return resultOdds1 the odd1
    /// @return resultOdds2 the odd2
    /// @return sgpFee1 the fee for position 1 or odd1
    /// @return sgpFee2 the fee for position 2 or odd2
    function _getSGPSingleOdds(
        uint odds1,
        uint odds2,
        uint position2,
        uint sgpFee,
        uint totalsLine,
        uint defaultONE
    )
        internal
        pure
        returns (
            uint resultOdds1,
            uint resultOdds2,
            uint sgpFee1,
            uint sgpFee2
        )
    {
        resultOdds1 = odds1;
        resultOdds2 = odds2;

        odds1 = odds1 * defaultONE;
        odds2 = odds2 * defaultONE;

        if (odds1 > 0 && odds2 > 0) {
            if (totalsLine == 2) {
                sgpFee2 = sgpFee;
            } else if (totalsLine == 250) {
                if (position2 == 0) {
                    if (odds1 < (6 * ONE_PERCENT) && odds2 < (70 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee - (ONE - sgpFee);
                    } else if (odds1 >= (99 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee + ((ONE - sgpFee) - 1 * ONE_PERCENT);
                    } else if (odds1 >= (96 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee + ((ONE - sgpFee) * 90 * ONE_PERCENT) / ONE;
                    } else if (odds1 >= (93 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee + ((ONE - sgpFee) * 75 * ONE_PERCENT) / ONE;
                    } else if (odds1 >= (90 * ONE_PERCENT) && odds2 >= (65 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee + ((ONE - sgpFee) * 90 * ONE_PERCENT) / ONE;
                    } else if (odds1 >= (83 * ONE_PERCENT) && odds2 >= (98 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee + (5 * ONE_PERCENT);
                    } else if (odds1 >= (83 * ONE_PERCENT) && odds2 >= (52 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee + ((ONE - sgpFee) * 30 * ONE_PERCENT) / ONE;
                    } else if (odds1 >= (80 * ONE_PERCENT) && odds2 >= (74 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee + ((ONE - sgpFee) * 20 * ONE_PERCENT) / ONE;
                    } else if (odds1 >= (80 * ONE_PERCENT) && odds2 >= (70 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee + ((ONE - sgpFee) * 50 * ONE_PERCENT) / ONE;
                    } else if (odds1 >= (80 * ONE_PERCENT) && odds2 >= (60 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee + ((ONE - sgpFee) * 30 * ONE_PERCENT) / ONE;
                    } else if (odds1 >= (80 * ONE_PERCENT) && odds2 >= (50 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee + ((ONE - sgpFee) * 90 * ONE_PERCENT) / ONE;
                    } else if (odds2 >= (60 * ONE_PERCENT) && odds1 <= (10 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee;
                    } else if (odds2 >= (55 * ONE_PERCENT) && odds1 <= (19 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee - ((ONE - sgpFee) * 70 * ONE_PERCENT) / ONE;
                    } else if (odds2 >= (55 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee - ((ONE - sgpFee) * 40 * ONE_PERCENT) / ONE;
                    } else if (odds2 >= (54 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee - ((ONE - sgpFee) * 70 * ONE_PERCENT) / ONE;
                    } else if (odds2 >= (52 * ONE_PERCENT)) {
                        if (odds1 <= (10 * ONE_PERCENT)) {
                            sgpFee2 = sgpFee - ((ONE - sgpFee) * 50 * ONE_PERCENT) / ONE;
                        } else if (odds1 <= (23 * ONE_PERCENT)) {
                            sgpFee2 = sgpFee - ((ONE - sgpFee) * 45 * ONE_PERCENT) / ONE;
                        } else if (odds1 <= (46 * ONE_PERCENT)) {
                            sgpFee2 = sgpFee + (((5 * ONE_PERCENT) * (ONE - odds1)) / ONE);
                        } else {
                            sgpFee2 = sgpFee;
                        }
                    } else if (odds2 >= (51 * ONE_PERCENT) && odds1 <= (20 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee - ((ONE - sgpFee) * 90 * ONE_PERCENT) / ONE;
                    } else if (odds2 >= (51 * ONE_PERCENT) && odds1 <= (25 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee - ((sgpFee * 10 * ONE_PERCENT) / ONE);
                    } else if (odds2 >= (50 * ONE_PERCENT)) {
                        if (odds1 < (10 * ONE_PERCENT)) {
                            sgpFee2 = ONE + odds1;
                        } else if (odds1 <= (21 * ONE_PERCENT)) {
                            sgpFee2 = sgpFee - ((ONE - sgpFee) * 90 * ONE_PERCENT) / ONE;
                        } else if (odds1 <= (23 * ONE_PERCENT)) {
                            sgpFee2 = sgpFee - ((ONE - sgpFee) * 30 * ONE_PERCENT) / ONE;
                        } else if (odds1 <= (56 * ONE_PERCENT)) {
                            sgpFee2 = sgpFee - ((ONE - sgpFee) * 70 * ONE_PERCENT) / ONE;
                        } else {
                            uint oddsDiff = odds2 > odds1 ? odds2 - odds1 : odds1 - odds2;
                            if (oddsDiff > 0) {
                                oddsDiff = (oddsDiff - (5 * ONE_PERCENT) / (90 * ONE_PERCENT));
                                oddsDiff = ((ONE - sgpFee) * oddsDiff) / ONE;
                                sgpFee2 = (sgpFee * (ONE + oddsDiff)) / ONE;
                            } else {
                                sgpFee2 = sgpFee;
                            }
                        }
                    } else if (odds2 >= (49 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee - ((ONE - sgpFee) * 70 * ONE_PERCENT) / ONE;
                    } else if (odds2 >= (48 * ONE_PERCENT) && odds1 <= (20 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee - ((ONE - sgpFee) * 30 * ONE_PERCENT) / ONE;
                    } else if (odds2 >= (48 * ONE_PERCENT) && odds1 <= (40 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee - ((ONE - sgpFee) * 20 * ONE_PERCENT) / ONE;
                    } else if (odds2 >= (48 * ONE_PERCENT) && odds1 <= (50 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee - ((ONE - sgpFee) * 40 * ONE_PERCENT) / ONE;
                    } else if (odds2 >= (48 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee;
                    } else if (odds2 >= (46 * ONE_PERCENT) && odds1 <= (43 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee - ((ONE - sgpFee) * 50 * ONE_PERCENT) / ONE;
                    } else if (odds2 >= (46 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee;
                    } else if (odds2 >= (43 * ONE_PERCENT)) {
                        if (odds1 <= (24 * ONE_PERCENT)) {
                            sgpFee2 = sgpFee - ((ONE - sgpFee) * 30 * ONE_PERCENT) / ONE;
                        } else if (odds2 <= (46 * ONE_PERCENT)) {
                            sgpFee2 = sgpFee > 5 * ONE_PERCENT ? sgpFee - (2 * ONE_PERCENT) : sgpFee;
                        } else {
                            uint oddsDiff = odds2 > odds1 ? odds2 - odds1 : odds1 - odds2;
                            if (oddsDiff > 0) {
                                oddsDiff = (oddsDiff - (5 * ONE_PERCENT) / (90 * ONE_PERCENT));
                                oddsDiff = ((ONE - sgpFee + (ONE - sgpFee) / 2) * oddsDiff) / ONE;

                                sgpFee2 = (sgpFee * (ONE + oddsDiff)) / ONE;
                            } else {
                                sgpFee2 = sgpFee;
                            }
                        }
                    } else if (odds2 >= (39 * ONE_PERCENT) && odds1 >= (43 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee - ((ONE - sgpFee) * 70 * ONE_PERCENT) / ONE;
                    } else if (odds2 >= (35 * ONE_PERCENT)) {
                        if (odds1 <= (46 * ONE_PERCENT)) {
                            sgpFee2 = sgpFee - (((ONE - sgpFee) * (ONE - odds1)) / ONE);
                        } else {
                            sgpFee2 = sgpFee > 5 * ONE_PERCENT ? sgpFee - (2 * ONE_PERCENT) : sgpFee;
                        }
                    } else if (odds2 < (35 * ONE_PERCENT)) {
                        if (odds1 <= (46 * ONE_PERCENT)) {
                            sgpFee2 = sgpFee + ((ONE - sgpFee) * 90 * ONE_PERCENT) / ONE;
                        } else {
                            sgpFee2 = sgpFee > 5 * ONE_PERCENT ? sgpFee - (2 * ONE_PERCENT) : sgpFee;
                        }
                    }
                } else {
                    if (odds2 >= (56 * ONE_PERCENT)) {
                        if (odds2 > (68 * ONE_PERCENT) && odds1 <= (15 * ONE_PERCENT)) {
                            sgpFee2 = sgpFee + ((ONE - sgpFee) * 50 * ONE_PERCENT) / ONE;
                        } else if (odds1 >= 76 * ONE_PERCENT) {
                            sgpFee2 = (ONE + (15 * ONE_PERCENT) + (odds1 * 15 * ONE_PERCENT) / ONE);
                        } else if (odds1 >= 60 * ONE_PERCENT) {
                            sgpFee2 = ONE + (ONE - sgpFee);
                        } else if (odds2 >= (58 * ONE_PERCENT) && odds1 <= (18 * ONE_PERCENT)) {
                            sgpFee2 = sgpFee + ((ONE - sgpFee) * 80 * ONE_PERCENT) / ONE;
                        } else if (odds2 >= (58 * ONE_PERCENT) && odds1 <= (32 * ONE_PERCENT)) {
                            sgpFee2 = sgpFee - ((ONE - sgpFee) * 70 * ONE_PERCENT) / ONE;
                        } else if (odds2 >= (55 * ONE_PERCENT) && odds1 >= (58 * ONE_PERCENT)) {
                            sgpFee2 = sgpFee;
                        } else if (odds2 >= (55 * ONE_PERCENT) && odds1 <= (18 * ONE_PERCENT)) {
                            sgpFee2 = sgpFee;
                        } else if (odds1 <= 35 * ONE_PERCENT && odds1 >= 30 * ONE_PERCENT) {
                            sgpFee2 = sgpFee;
                        } else if (odds1 <= 15 * ONE_PERCENT) {
                            sgpFee2 = sgpFee - ((ONE - sgpFee) * 50 * ONE_PERCENT) / ONE;
                        } else {
                            sgpFee2 = (ONE + (15 * ONE_PERCENT) + (odds1 * 10 * ONE_PERCENT) / ONE);
                        }
                    } else if (odds2 <= (32 * ONE_PERCENT) && odds1 >= (65 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee - (ONE - sgpFee);
                    } else if (odds2 <= (32 * ONE_PERCENT) && odds1 >= (85 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee - ((ONE - sgpFee) * 80 * ONE_PERCENT) / ONE;
                    } else if (odds2 <= (35 * ONE_PERCENT) && odds1 <= (125 * 1e15)) {
                        sgpFee2 = sgpFee - ((ONE - sgpFee) * 10 * ONE_PERCENT) / ONE;
                    } else if (odds2 <= (35 * ONE_PERCENT) && odds1 > (125 * 1e15) && odds1 <= (13 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee;
                    } else if (odds2 <= (35 * ONE_PERCENT) && odds1 <= (15 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee - ((ONE - sgpFee) * 20 * ONE_PERCENT) / ONE;
                    } else if (odds2 <= (35 * ONE_PERCENT) && odds1 <= (24 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee + ((ONE - sgpFee) * 30 * ONE_PERCENT) / ONE;
                    } else if (odds2 <= (37 * ONE_PERCENT) && odds1 <= (10 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee - (ONE - sgpFee);
                    } else if (odds2 <= (37 * ONE_PERCENT) && odds1 <= (16 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee + ((ONE - sgpFee) * 60 * ONE_PERCENT) / ONE;
                    } else if (odds2 <= (38 * ONE_PERCENT) && odds1 >= (80 * ONE_PERCENT)) {
                        sgpFee2 = ONE + (ONE - sgpFee + 5 * ONE_PERCENT);
                    } else if (odds2 <= (38 * ONE_PERCENT) && odds1 >= (70 * ONE_PERCENT)) {
                        sgpFee2 = ONE + (ONE - sgpFee + 10 * ONE_PERCENT);
                    } else if (odds2 <= (38 * ONE_PERCENT) && odds1 >= (66 * ONE_PERCENT)) {
                        sgpFee2 = ONE + (ONE - sgpFee + 25 * ONE_PERCENT);
                    } else if (odds2 <= (38 * ONE_PERCENT) && odds1 >= (50 * ONE_PERCENT)) {
                        sgpFee2 = ONE + (ONE - sgpFee + 5 * ONE_PERCENT);
                    } else if (odds2 <= (38 * ONE_PERCENT) && odds1 >= (25 * ONE_PERCENT)) {
                        sgpFee2 = ONE + (2 * (ONE - sgpFee));
                    } else if (odds2 <= (38 * ONE_PERCENT) && odds1 >= (23 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee - ((ONE - sgpFee) * 30 * ONE_PERCENT) / ONE;
                    } else if (odds2 <= (38 * ONE_PERCENT) && odds1 < (23 * ONE_PERCENT)) {
                        sgpFee2 = ONE + ((ONE - sgpFee) * 40 * ONE_PERCENT) / ONE;
                    } else if (odds2 <= (39 * ONE_PERCENT) && odds1 < (20 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee - (sgpFee * 20 * ONE_PERCENT) / ONE;
                    } else if (odds2 <= (40 * ONE_PERCENT) && odds1 <= (9 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee + ((ONE - sgpFee) * 80 * ONE_PERCENT) / ONE;
                    } else if (odds2 <= (40 * ONE_PERCENT) && odds1 <= (11 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee;
                    } else if (odds2 <= (40 * ONE_PERCENT) && odds1 <= (13 * ONE_PERCENT)) {
                        sgpFee2 = ONE + ((ONE - sgpFee) * 50 * ONE_PERCENT) / ONE;
                    } else if (odds2 <= (40 * ONE_PERCENT) && odds1 <= (14 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee + ((ONE - sgpFee) * 80 * ONE_PERCENT) / ONE;
                    } else if (odds2 <= (40 * ONE_PERCENT) && odds1 <= (30 * ONE_PERCENT)) {
                        sgpFee2 = ONE + (sgpFee * 30 * ONE_PERCENT) / ONE;
                    } else if (odds2 <= (40 * ONE_PERCENT) && odds1 <= (54 * ONE_PERCENT)) {
                        sgpFee2 = ONE + (sgpFee * 20 * ONE_PERCENT) / ONE;
                    } else if (odds2 <= (40 * ONE_PERCENT) && odds1 > (54 * ONE_PERCENT)) {
                        sgpFee2 = ONE + (ONE - sgpFee);
                    } else if (odds2 <= (43 * ONE_PERCENT) && odds1 <= (11 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee + ((ONE - sgpFee) * 50 * ONE_PERCENT) / ONE;
                    } else if (odds2 <= (43 * ONE_PERCENT) && odds1 <= (12 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee + ((ONE - sgpFee) * 75 * ONE_PERCENT) / ONE;
                    } else if (odds2 <= (43 * ONE_PERCENT) && odds1 <= (14 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee + (sgpFee * 20 * ONE_PERCENT) / ONE;
                    } else if (odds2 <= (43 * ONE_PERCENT) && odds1 <= (15 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee - (sgpFee * 30 * ONE_PERCENT) / ONE;
                    } else if (odds2 <= (43 * ONE_PERCENT) && odds1 <= (51 * ONE_PERCENT)) {
                        sgpFee2 = ONE + (ONE - sgpFee);
                    } else if (odds2 <= (44 * ONE_PERCENT) && odds1 >= (55 * ONE_PERCENT)) {
                        sgpFee2 = ONE + (sgpFee * 30 * ONE_PERCENT) / ONE;
                    } else if (odds2 <= (44 * ONE_PERCENT) && odds1 <= (55 * ONE_PERCENT)) {
                        sgpFee2 = ONE + (sgpFee * 30 * ONE_PERCENT) / ONE;
                    } else if (odds2 <= (45 * ONE_PERCENT) && odds1 >= (70 * ONE_PERCENT)) {
                        sgpFee2 = ONE + (2 * (ONE - sgpFee)) - ((ONE - sgpFee) * 40 * ONE_PERCENT) / ONE;
                    } else if (odds2 <= (45 * ONE_PERCENT) && odds1 >= (44 * ONE_PERCENT)) {
                        sgpFee2 = ONE + ((ONE - sgpFee) * 70 * ONE_PERCENT) / ONE;
                    } else if (odds2 <= (45 * ONE_PERCENT) && odds1 >= (40 * ONE_PERCENT)) {
                        sgpFee2 = ONE + ((ONE - sgpFee) * 10 * ONE_PERCENT) / ONE;
                    } else if (odds2 <= (45 * ONE_PERCENT) && odds1 >= (20 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee + ((ONE - sgpFee) * 80 * ONE_PERCENT) / ONE;
                    } else if (odds2 <= (45 * ONE_PERCENT) && odds1 < (20 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee + ((ONE - sgpFee) * 30 * ONE_PERCENT) / ONE;
                    } else if (odds2 <= (47 * ONE_PERCENT) && odds1 <= (17 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee + ((ONE - sgpFee) * 70 * ONE_PERCENT) / ONE;
                    } else if (odds2 <= (47 * ONE_PERCENT) && odds1 <= (23 * ONE_PERCENT)) {
                        sgpFee2 = ONE + ((ONE - sgpFee) * 8 * ONE_PERCENT) / ONE;
                    } else if (odds2 <= (48 * ONE_PERCENT) && odds1 <= (11 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee + ((ONE - sgpFee) * 80 * ONE_PERCENT) / ONE;
                    } else if (odds2 <= (48 * ONE_PERCENT) && odds1 <= (24 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee + (sgpFee * 20 * ONE_PERCENT) / ONE;
                    } else if (odds2 <= (49 * ONE_PERCENT) && odds1 <= (15 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee + ((ONE - sgpFee) * 30 * ONE_PERCENT) / ONE;
                    } else if (odds2 <= (49 * ONE_PERCENT) && odds1 <= (25 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee + ((ONE - sgpFee) * 80 * ONE_PERCENT) / ONE;
                    } else if (odds2 <= (49 * ONE_PERCENT) && odds1 <= (33 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee;
                    } else if (odds2 <= (50 * ONE_PERCENT) && odds1 <= (10 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee + ((ONE - sgpFee) * 50 * ONE_PERCENT) / ONE;
                    } else if (odds2 <= (50 * ONE_PERCENT) && odds1 <= (17 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee + ((ONE - sgpFee) * 35 * ONE_PERCENT) / ONE;
                    } else if (odds2 <= (50 * ONE_PERCENT) && odds1 <= (20 * ONE_PERCENT)) {
                        sgpFee2 = ONE + (ONE - sgpFee);
                    } else if (odds2 <= (50 * ONE_PERCENT) && odds1 <= (25 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee - (ONE - sgpFee) - (ONE - sgpFee);
                    } else if (odds2 <= (51 * ONE_PERCENT) && odds1 <= (24 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee;
                    } else if (odds2 <= (52 * ONE_PERCENT) && odds1 <= (10 * ONE_PERCENT)) {
                        sgpFee2 = ONE + ((ONE - sgpFee) * 35 * ONE_PERCENT) / ONE;
                    } else if (odds2 <= (52 * ONE_PERCENT) && odds1 <= (15 * ONE_PERCENT)) {
                        sgpFee2 = ONE + ((ONE - sgpFee) * 45 * ONE_PERCENT) / ONE;
                    } else if (odds2 <= (52 * ONE_PERCENT) && odds1 <= (24 * ONE_PERCENT)) {
                        sgpFee2 = ONE + ((ONE - sgpFee) * 35 * ONE_PERCENT) / ONE;
                    } else if (odds2 <= (52 * ONE_PERCENT) && odds1 > (72 * ONE_PERCENT)) {
                        sgpFee2 = ONE + ((ONE - sgpFee) * 35 * ONE_PERCENT) / ONE;
                    } else if (odds2 <= (53 * ONE_PERCENT) && odds1 <= (24 * ONE_PERCENT)) {
                        sgpFee2 = ONE + (sgpFee * 30 * ONE_PERCENT) / ONE;
                    } else if (odds2 <= (53 * ONE_PERCENT) && odds1 <= (40 * ONE_PERCENT)) {
                        sgpFee2 = ONE;
                    } else if (odds2 < (54 * ONE_PERCENT) && odds1 >= (74 * ONE_PERCENT)) {
                        sgpFee2 = ONE + (ONE - sgpFee);
                    } else if (odds2 < (54 * ONE_PERCENT) && odds1 >= (58 * ONE_PERCENT)) {
                        sgpFee2 = ONE + (ONE - sgpFee + 10 * ONE_PERCENT);
                    } else if (odds2 < (54 * ONE_PERCENT) && odds1 >= (24 * ONE_PERCENT)) {
                        sgpFee2 = ONE + (ONE - sgpFee);
                    } else if (odds2 < (54 * ONE_PERCENT) && odds1 < (24 * ONE_PERCENT)) {
                        sgpFee2 = sgpFee + ((ONE - sgpFee) * 30 * ONE_PERCENT) / ONE;
                    } else if (odds2 < (56 * ONE_PERCENT) && odds1 >= (82 * ONE_PERCENT)) {
                        sgpFee2 = ONE + ((ONE - sgpFee) * 50 * ONE_PERCENT) / ONE;
                    } else if (odds2 < (56 * ONE_PERCENT) && odds1 >= (40 * ONE_PERCENT)) {
                        sgpFee2 = ONE + (ONE - sgpFee);
                    } else if (odds2 < (56 * ONE_PERCENT) && odds1 >= (10 * ONE_PERCENT)) {
                        sgpFee2 = ONE + (ONE - sgpFee);
                    } else {
                        sgpFee2 = sgpFee;
                    }
                }
            } else {
                sgpFee2 = sgpFee;
            }
            if (sgpFee2 > 0) {
                uint totalQuote = (odds1 * odds2) / ONE;
                uint totalQuoteWSGP = ((totalQuote * ONE * ONE) / sgpFee2) / ONE;
                if (totalQuoteWSGP < (10 * ONE_PERCENT)) {
                    if (odds1 > (10 * ONE_PERCENT)) {
                        sgpFee2 = ((totalQuote * ONE * ONE) / (10 * ONE_PERCENT)) / ONE;
                    } else {
                        sgpFee2 = ((totalQuote * ONE * ONE) / (odds1 - ((odds1 * 10 * ONE_PERCENT) / ONE))) / ONE;
                    }
                } else if (totalQuoteWSGP > odds1 && odds1 < odds2) {
                    sgpFee2 = odds2 + (4 * 1e15);
                } else if (totalQuoteWSGP > odds2 && odds2 <= odds1) {
                    sgpFee2 = odds1 + (4 * 1e15);
                }
            }
        }
    }

    function calculateInitialQuotesForParlay(InitialQuoteParameters memory params)
        external
        view
        returns (
            uint totalQuote,
            uint totalBuyAmount,
            uint skewImpact,
            uint[] memory finalQuotes,
            uint[] memory amountsToBuy
        )
    {
        uint numOfMarkets = params.sportMarkets.length;
        uint inverseSum;
        bool eligible;
        amountsToBuy = new uint[](numOfMarkets);
        (eligible, finalQuotes, params.sgpFees) = _verifyMarkets(
            VerifyMarket(params.sportMarkets, params.positions, params.sportsAMM, params.parlayAMM, params.defaultONE)
        );
        if (eligible && numOfMarkets == params.positions.length && numOfMarkets > 0 && numOfMarkets <= params.parlaySize) {
            for (uint i = 0; i < numOfMarkets; i++) {
                if (params.positions[i] > 2) {
                    totalQuote = 0;
                    break;
                }
                if (finalQuotes.length == 0) {
                    totalQuote = 0;
                    break;
                }
                finalQuotes[i] = (params.defaultONE * finalQuotes[i]);
                if (params.sgpFees[i] > 0) {
                    finalQuotes[i] = ((finalQuotes[i] * ONE * ONE) / params.sgpFees[i]) / ONE;
                }
                totalQuote = totalQuote == 0 ? finalQuotes[i] : (totalQuote * finalQuotes[i]) / ONE;
            }
            if (totalQuote != 0) {
                if (totalQuote < IParlayMarketsAMM(params.parlayAMM).maxSupportedOdds()) {
                    totalQuote = IParlayMarketsAMM(params.parlayAMM).maxSupportedOdds();
                }
                totalBuyAmount = (params.totalSUSDToPay * ONE) / totalQuote;
                _calculateRisk(params.sportMarkets, (totalBuyAmount - params.totalSUSDToPay), params.sportsAMM.parlayAMM());
            }

            for (uint i = 0; i < numOfMarkets; i++) {
                //consider if this works well for Arbitrum at 6 decimals
                if (finalQuotes[i] > 0) {
                    amountsToBuy[i] = (ONE * params.totalSUSDToPay) / finalQuotes[i];
                }
            }
        }
    }

    function obtainSportsAMMPosition(uint _position) public pure returns (ISportsAMM.Position) {
        if (_position == 0) {
            return ISportsAMM.Position.Home;
        } else if (_position == 1) {
            return ISportsAMM.Position.Away;
        }
        return ISportsAMM.Position.Draw;
    }

    function _calculateRisk(
        address[] memory _sportMarkets,
        uint _sUSDInRisky,
        address _parlayAMM
    ) internal view returns (bool riskFree) {
        require(_checkRisk(_sportMarkets, _sUSDInRisky, _parlayAMM), "RiskPerComb exceeded");
        riskFree = true;
    }

    function _checkRisk(
        address[] memory _sportMarkets,
        uint _sUSDInRisk,
        address _parlayAMM
    ) internal view returns (bool riskFree) {
        if (_sportMarkets.length > 1 && _sportMarkets.length <= IParlayMarketsAMM(_parlayAMM).parlaySize()) {
            uint riskCombination = IParlayMarketsAMM(_parlayAMM).riskPerPackedGamesCombination(
                _calculateCombinationKey(_sportMarkets)
            );
            riskFree = (riskCombination + _sUSDInRisk) <= IParlayMarketsAMM(_parlayAMM).maxAllowedRiskPerCombination();
        }
    }

    function _calculateCombinationKey(address[] memory _sportMarkets) internal pure returns (bytes32) {
        address[] memory sortedAddresses = new address[](_sportMarkets.length);
        sortedAddresses = _sort(_sportMarkets);
        return keccak256(abi.encodePacked(sortedAddresses));
    }

    function _sort(address[] memory data) internal pure returns (address[] memory) {
        _quickSort(data, int(0), int(data.length - 1));
        return data;
    }

    function _quickSort(
        address[] memory arr,
        int left,
        int right
    ) internal pure {
        int i = left;
        int j = right;
        if (i == j) return;
        address pivot = arr[uint(left + (right - left) / 2)];
        while (i <= j) {
            while (arr[uint(i)] < pivot) i++;
            while (pivot < arr[uint(j)]) j--;
            if (i <= j) {
                (arr[uint(i)], arr[uint(j)]) = (arr[uint(j)], arr[uint(i)]);
                i++;
                j--;
            }
        }
        if (left < j) _quickSort(arr, left, j);
        if (i < right) _quickSort(arr, i, right);
    }

    function sort(address[] memory data) external pure returns (address[] memory) {
        _quickSort(data, int(0), int(data.length - 1));
        return data;
    }

    function calculateCombinationKey(address[] memory _sportMarkets) external pure returns (bytes32) {
        return _calculateCombinationKey(_sportMarkets);
    }
}

File 2 of 11 : IParlayMarketsAMM.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";

import "../SportMarkets/Parlay/ParlayVerifier.sol";

interface IParlayMarketsAMM {
    /* ========== VIEWS / VARIABLES ========== */

    function parlaySize() external view returns (uint);

    function sUSD() external view returns (IERC20Upgradeable);

    function sportsAmm() external view returns (address);

    function parlayPolicy() external view returns (address);

    function parlayAmmFee() external view returns (uint);

    function maxAllowedRiskPerCombination() external view returns (uint);

    function maxSupportedOdds() external view returns (uint);

    function getSgpFeePerCombination(
        uint tag1,
        uint tag2_1,
        uint tag2_2,
        uint position1,
        uint position2
    ) external view returns (uint sgpFee);

    function riskPerCombination(
        address _sportMarkets1,
        uint _position1,
        address _sportMarkets2,
        uint _position2,
        address _sportMarkets3,
        uint _position3,
        address _sportMarkets4,
        uint _position4
    ) external view returns (uint);

    function riskPerGameCombination(
        address _sportMarkets1,
        address _sportMarkets2,
        address _sportMarkets3,
        address _sportMarkets4,
        address _sportMarkets5,
        address _sportMarkets6,
        address _sportMarkets7,
        address _sportMarkets8
    ) external view returns (uint);

    function riskPerPackedGamesCombination(bytes32 gamesPacked) external view returns (uint);

    function isActiveParlay(address _parlayMarket) external view returns (bool isActiveParlayMarket);

    function exerciseParlay(address _parlayMarket) external;

    function triggerResolvedEvent(address _account, bool _userWon) external;

    function resolveParlay() external;

    function buyFromParlay(
        address[] calldata _sportMarkets,
        uint[] calldata _positions,
        uint _sUSDPaid,
        uint _additionalSlippage,
        uint _expectedPayout,
        address _differentRecepient
    ) external;

    function buyQuoteFromParlay(
        address[] calldata _sportMarkets,
        uint[] calldata _positions,
        uint _sUSDPaid
    )
        external
        view
        returns (
            uint sUSDAfterFees,
            uint totalBuyAmount,
            uint totalQuote,
            uint initialQuote,
            uint skewImpact,
            uint[] memory finalQuotes,
            uint[] memory amountsToBuy
        );

    function canCreateParlayMarket(
        address[] calldata _sportMarkets,
        uint[] calldata _positions,
        uint _sUSDToPay
    ) external view returns (bool canBeCreated);

    function numActiveParlayMarkets() external view returns (uint);

    function activeParlayMarkets(uint index, uint pageSize) external view returns (address[] memory);

    function parlayVerifier() external view returns (ParlayVerifier);

    function minUSDAmount() external view returns (uint);

    function maxSupportedAmount() external view returns (uint);

    function safeBoxImpact() external view returns (uint);
}

File 3 of 11 : ISportsAMM.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "../interfaces/ISportAMMRiskManager.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";

interface ISportsAMM {
    /* ========== VIEWS / VARIABLES ========== */

    enum Position {
        Home,
        Away,
        Draw
    }

    struct SellRequirements {
        address user;
        address market;
        Position position;
        uint amount;
        uint expectedPayout;
        uint additionalSlippage;
    }

    function theRundownConsumer() external view returns (address);

    function riskManager() external view returns (ISportAMMRiskManager riskManager);

    function getMarketDefaultOdds(address _market, bool isSell) external view returns (uint[] memory);

    function isMarketInAMMTrading(address _market) external view returns (bool);

    function isMarketForSportOnePositional(uint _tag) external view returns (bool);

    function availableToBuyFromAMM(address market, Position position) external view returns (uint _available);

    function parlayAMM() external view returns (address);

    function minSupportedOdds() external view returns (uint);

    function maxSupportedOdds() external view returns (uint);

    function minSupportedOddsPerSport(uint) external view returns (uint);

    function min_spread() external view returns (uint);

    function max_spread() external view returns (uint);

    function minimalTimeLeftToMaturity() external view returns (uint);

    function getSpentOnGame(address market) external view returns (uint);

    function safeBoxImpact() external view returns (uint);

    function manager() external view returns (address);

    function getLiquidityPool() external view returns (address);

    function sUSD() external view returns (IERC20Upgradeable);

    function buyFromAMM(
        address market,
        Position position,
        uint amount,
        uint expectedPayout,
        uint additionalSlippage
    ) external;

    function buyFromAmmQuote(
        address market,
        Position position,
        uint amount
    ) external view returns (uint);

    function buyFromAmmQuoteForParlayAMM(
        address market,
        Position position,
        uint amount
    ) external view returns (uint);

    function updateParlayVolume(address _account, uint _amount) external;

    function buyPriceImpact(
        address market,
        ISportsAMM.Position position,
        uint amount
    ) external view returns (int impact);

    function obtainOdds(address _market, ISportsAMM.Position _position) external view returns (uint oddsToReturn);

    function buyFromAmmQuoteWithDifferentCollateral(
        address market,
        ISportsAMM.Position position,
        uint amount,
        address collateral
    ) external view returns (uint collateralQuote, uint sUSDToPay);

    function availableToBuyFromAMMWithBaseOdds(
        address market,
        ISportsAMM.Position position,
        uint baseOdds,
        uint balance,
        bool useBalance
    ) external view returns (uint availableAmount);

    function floorBaseOdds(uint baseOdds, address market) external view returns (uint);
}

File 4 of 11 : ISportPositionalMarket.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.5.16;

import "../interfaces/IPositionalMarketManager.sol";
import "../interfaces/IPosition.sol";
import "../interfaces/IPriceFeed.sol";

interface ISportPositionalMarket {
    /* ========== TYPES ========== */

    enum Phase {
        Trading,
        Maturity,
        Expiry
    }
    enum Side {
        Cancelled,
        Home,
        Away,
        Draw
    }

    /* ========== VIEWS / VARIABLES ========== */

    function getOptions()
        external
        view
        returns (
            IPosition home,
            IPosition away,
            IPosition draw
        );

    function times() external view returns (uint maturity, uint destruction);

    function getGameDetails() external view returns (bytes32 gameId, string memory gameLabel);

    function getGameId() external view returns (bytes32);

    function deposited() external view returns (uint);

    function optionsCount() external view returns (uint);

    function creator() external view returns (address);

    function resolved() external view returns (bool);

    function cancelled() external view returns (bool);

    function paused() external view returns (bool);

    function phase() external view returns (Phase);

    function canResolve() external view returns (bool);

    function result() external view returns (Side);

    function isChild() external view returns (bool);

    function optionsInitialized() external view returns (bool);

    function tags(uint idx) external view returns (uint);

    function getTags() external view returns (uint tag1, uint tag2);

    function getTagsLength() external view returns (uint tagsLength);

    function getParentMarketPositions() external view returns (IPosition position1, IPosition position2);

    function getParentMarketPositionsUint() external view returns (uint position1, uint position2);

    function getStampedOdds()
        external
        view
        returns (
            uint,
            uint,
            uint
        );

    function balancesOf(address account)
        external
        view
        returns (
            uint home,
            uint away,
            uint draw
        );

    function totalSupplies()
        external
        view
        returns (
            uint home,
            uint away,
            uint draw
        );

    function isDoubleChance() external view returns (bool);

    function parentMarket() external view returns (ISportPositionalMarket);

    /* ========== MUTATIVE FUNCTIONS ========== */

    function setPaused(bool _paused) external;

    function updateDates(uint256 _maturity, uint256 _expiry) external;

    function mint(uint value) external;

    function exerciseOptions() external;

    function restoreInvalidOdds(
        uint _homeOdds,
        uint _awayOdds,
        uint _drawOdds
    ) external;
}

File 5 of 11 : IParlayPolicy.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IParlayPolicy {
    struct SGPData {
        uint tag1;
        uint tag2_1;
        uint tag2_2;
        uint position1;
        uint position2;
    }

    /* ========== VIEWS / VARIABLES ========== */
    function consumer() external view returns (address);

    function getSgpFeePerCombination(SGPData memory params) external view returns (uint sgpFee);

    function getMarketDefaultOdds(address _sportMarket, uint _position) external view returns (uint odd);

    function areEligiblePropsMarkets(
        address _childMarket1,
        address _childMarket2,
        uint _tag1
    ) external view returns (bool samePlayerDifferentProp);

    function getChildMarketTotalLine(address _sportMarket) external view returns (uint childTotalsLine);
}

File 6 of 11 : IERC20Upgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20Upgradeable {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

File 7 of 11 : ISportAMMRiskManager.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

interface ISportAMMRiskManager {
    function calculateCapToBeUsed(address _market) external view returns (uint toReturn);

    function isTotalSpendingLessThanTotalRisk(uint _totalSpent, address _market) external view returns (bool _isNotRisky);

    function isMarketForSportOnePositional(uint _tag) external view returns (bool);

    function isMarketForPlayerPropsOnePositional(uint _tag) external view returns (bool);

    function minSupportedOddsPerSport(uint tag) external view returns (uint);

    function minSpreadPerSport(uint tag1, uint tag2) external view returns (uint);

    function maxSpreadPerSport(uint tag) external view returns (uint);

    function getMinSpreadToUse(
        bool useDefaultMinSpread,
        address market,
        uint min_spread,
        uint min_spreadPerAddress
    ) external view returns (uint);

    function getMaxSpreadForMarket(address _market, uint max_spread) external view returns (uint);

    function getMinOddsForMarket(address _market, uint minSupportedOdds) external view returns (uint minOdds);

    function getCapAndMaxSpreadForMarket(address _market, uint max_spread) external view returns (uint, uint);

    function getCapMaxSpreadAndMinOddsForMarket(
        address _market,
        uint max_spread,
        uint minSupportedOdds
    )
        external
        view
        returns (
            uint cap,
            uint maxSpread,
            uint minOddsForMarket
        );
}

File 8 of 11 : IPositionalMarketManager.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.5.16;

import "../interfaces/IPositionalMarket.sol";

interface IPositionalMarketManager {
    /* ========== VIEWS / VARIABLES ========== */

    function durations() external view returns (uint expiryDuration, uint maxTimeToMaturity);

    function capitalRequirement() external view returns (uint);

    function marketCreationEnabled() external view returns (bool);

    function onlyAMMMintingAndBurning() external view returns (bool);

    function transformCollateral(uint value) external view returns (uint);

    function reverseTransformCollateral(uint value) external view returns (uint);

    function totalDeposited() external view returns (uint);

    function numActiveMarkets() external view returns (uint);

    function activeMarkets(uint index, uint pageSize) external view returns (address[] memory);

    function numMaturedMarkets() external view returns (uint);

    function maturedMarkets(uint index, uint pageSize) external view returns (address[] memory);

    function isActiveMarket(address candidate) external view returns (bool);

    function isKnownMarket(address candidate) external view returns (bool);

    function getThalesAMM() external view returns (address);

    /* ========== MUTATIVE FUNCTIONS ========== */

    function createMarket(
        bytes32 oracleKey,
        uint strikePrice,
        uint maturity,
        uint initialMint // initial sUSD to mint options for,
    ) external returns (IPositionalMarket);

    function resolveMarket(address market) external;

    function expireMarkets(address[] calldata market) external;

    function transferSusdTo(
        address sender,
        address receiver,
        uint amount
    ) external;
}

File 9 of 11 : IPosition.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.5.16;

import "./IPositionalMarket.sol";

interface IPosition {
    /* ========== VIEWS / VARIABLES ========== */

    function getBalanceOf(address account) external view returns (uint);

    function getTotalSupply() external view returns (uint);

    function exerciseWithAmount(address claimant, uint amount) external;
}

File 10 of 11 : IPriceFeed.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.5.16;

interface IPriceFeed {
    // Structs
    struct RateAndUpdatedTime {
        uint216 rate;
        uint40 time;
    }

    // Mutative functions
    function addAggregator(bytes32 currencyKey, address aggregatorAddress) external;

    function removeAggregator(bytes32 currencyKey) external;

    // Views

    function rateForCurrency(bytes32 currencyKey) external view returns (uint);

    function rateAndUpdatedTime(bytes32 currencyKey) external view returns (uint rate, uint time);

    function getRates() external view returns (uint[] memory);

    function getCurrencies() external view returns (bytes32[] memory);
}

File 11 of 11 : IPositionalMarket.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.5.16;

import "../interfaces/IPositionalMarketManager.sol";
import "../interfaces/IPosition.sol";
import "../interfaces/IPriceFeed.sol";

interface IPositionalMarket {
    /* ========== TYPES ========== */

    enum Phase {
        Trading,
        Maturity,
        Expiry
    }
    enum Side {
        Up,
        Down
    }

    /* ========== VIEWS / VARIABLES ========== */

    function getOptions() external view returns (IPosition up, IPosition down);

    function times() external view returns (uint maturity, uint destructino);

    function getOracleDetails()
        external
        view
        returns (
            bytes32 key,
            uint strikePrice,
            uint finalPrice
        );

    function fees() external view returns (uint poolFee, uint creatorFee);

    function deposited() external view returns (uint);

    function creator() external view returns (address);

    function resolved() external view returns (bool);

    function phase() external view returns (Phase);

    function oraclePrice() external view returns (uint);

    function oraclePriceAndTimestamp() external view returns (uint price, uint updatedAt);

    function canResolve() external view returns (bool);

    function result() external view returns (Side);

    function balancesOf(address account) external view returns (uint up, uint down);

    function totalSupplies() external view returns (uint up, uint down);

    function getMaximumBurnable(address account) external view returns (uint amount);

    /* ========== MUTATIVE FUNCTIONS ========== */

    function mint(uint value) external;

    function exerciseOptions() external returns (uint);

    function burnOptions(uint amount) external;

    function burnOptionsMaximum() external;
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract ABI

[{"inputs":[{"internalType":"address[]","name":"_sportMarkets","type":"address[]"}],"name":"calculateCombinationKey","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"components":[{"internalType":"address[]","name":"sportMarkets","type":"address[]"},{"internalType":"uint256[]","name":"positions","type":"uint256[]"},{"internalType":"uint256","name":"totalSUSDToPay","type":"uint256"},{"internalType":"uint256","name":"parlaySize","type":"uint256"},{"internalType":"uint256","name":"defaultONE","type":"uint256"},{"internalType":"uint256[]","name":"sgpFees","type":"uint256[]"},{"internalType":"contract ISportsAMM","name":"sportsAMM","type":"address"},{"internalType":"address","name":"parlayAMM","type":"address"}],"internalType":"struct ParlayVerifier.InitialQuoteParameters","name":"params","type":"tuple"}],"name":"calculateInitialQuotesForParlay","outputs":[{"internalType":"uint256","name":"totalQuote","type":"uint256"},{"internalType":"uint256","name":"totalBuyAmount","type":"uint256"},{"internalType":"uint256","name":"skewImpact","type":"uint256"},{"internalType":"uint256[]","name":"finalQuotes","type":"uint256[]"},{"internalType":"uint256[]","name":"amountsToBuy","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"odds1","type":"uint256"},{"internalType":"uint256","name":"odds2","type":"uint256"},{"internalType":"uint256","name":"position2","type":"uint256"},{"internalType":"uint256","name":"sgpFee","type":"uint256"},{"internalType":"uint256","name":"totalsLine","type":"uint256"},{"internalType":"uint256","name":"defaultONE","type":"uint256"}],"name":"getSPGOdds","outputs":[{"internalType":"uint256","name":"resultOdds1","type":"uint256"},{"internalType":"uint256","name":"resultOdds2","type":"uint256"},{"internalType":"uint256","name":"sgpFee1","type":"uint256"},{"internalType":"uint256","name":"sgpFee2","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"_position","type":"uint256"}],"name":"obtainSportsAMMPosition","outputs":[{"internalType":"enum ISportsAMM.Position","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address[]","name":"data","type":"address[]"}],"name":"sort","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"pure","type":"function"}]

608060405234801561001057600080fd5b50614c48806100206000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c8063128424a71461005c5780636517d1a414610085578063e7468c62146100a6578063e7fe0d37146100ca578063e835640f146100ea575b600080fd5b61006f61006a3660046146c3565b61011d565b60405161007c91906148f9565b60405180910390f35b6100986100933660046146c3565b61013c565b60405190815260200161007c565b6100b96100b436600461471e565b61014d565b60405161007c959493929190614998565b6100dd6100d836600461480e565b610701565b60405161007c9190614946565b6100fd6100f836600461483e565b610729565b60408051948552602085019390935291830152606082015260800161007c565b6060610138826000600185516101339190614b53565b610751565b5090565b600061014782610963565b92915050565b6000806000606080600086600001515190506000808267ffffffffffffffff81111561018957634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156101b2578160200160208202803683370190505b50935061020a6040518060a001604052808b6000015181526020018b6020015181526020018b60c001516001600160a01b031681526020018b60e001516001600160a01b031681526020018b608001518152506109f4565b60a08c015295509050808015610224575088602001515183145b80156102305750600083115b8015610240575088606001518311155b156106f55760005b8381101561047d5760028a60200151828151811061027657634e487b7160e01b600052603260045260246000fd5b6020026020010151111561028d576000985061047d565b855161029c576000985061047d565b8581815181106102bc57634e487b7160e01b600052603260045260246000fd5b60200260200101518a608001516102d39190614af5565b8682815181106102f357634e487b7160e01b600052603260045260246000fd5b60200260200101818152505060008a60a00151828151811061032557634e487b7160e01b600052603260045260246000fd5b602002602001015111156103ef57670de0b6b3a76400008a60a00151828151811061036057634e487b7160e01b600052603260045260246000fd5b6020026020010151670de0b6b3a76400008089858151811061039257634e487b7160e01b600052603260045260246000fd5b60200260200101516103a49190614af5565b6103ae9190614af5565b6103b89190614ae1565b6103c29190614ae1565b8682815181106103e257634e487b7160e01b600052603260045260246000fd5b6020026020010181815250505b881561044057670de0b6b3a764000086828151811061041e57634e487b7160e01b600052603260045260246000fd5b60200260200101518a6104319190614af5565b61043b9190614ae1565b610469565b85818151811061046057634e487b7160e01b600052603260045260246000fd5b60200260200101515b98508061047581614ba8565b915050610248565b50871561062f578860e001516001600160a01b031663e88698bf6040518163ffffffff1660e01b815260040160206040518083038186803b1580156104c157600080fd5b505afa1580156104d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104f99190614826565b881015610578578860e001516001600160a01b031663e88698bf6040518163ffffffff1660e01b815260040160206040518083038186803b15801561053d57600080fd5b505afa158015610551573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105759190614826565b97505b87670de0b6b3a76400008a604001516105919190614af5565b61059b9190614ae1565b895160408b015191985061062d916105b3908a614b53565b8b60c001516001600160a01b0316637d550e056040518163ffffffff1660e01b815260040160206040518083038186803b1580156105f057600080fd5b505afa158015610604573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061062891906146a7565b610ae5565b505b60005b838110156106f357600086828151811061065c57634e487b7160e01b600052603260045260246000fd5b602002602001015111156106e15785818151811061068a57634e487b7160e01b600052603260045260246000fd5b60200260200101518a60400151670de0b6b3a76400006106aa9190614af5565b6106b49190614ae1565b8582815181106106d457634e487b7160e01b600052603260045260246000fd5b6020026020010181815250505b806106eb81614ba8565b915050610632565b505b50505091939590929450565b60008161071057506000919050565b816001141561072157506001919050565b506002919050565b60008060008061073d8a8a8a8a8a8a610b44565b929d919c509a509098509650505050505050565b818180821415610762575050505050565b60008560026107718787614b14565b61077b9190614ab3565b6107859087614a5a565b815181106107a357634e487b7160e01b600052603260045260246000fd5b602002602001015190505b818313610935575b806001600160a01b03168684815181106107e057634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b03161015610809578261080181614b88565b9350506107b6565b85828151811061082957634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b0316816001600160a01b0316101561085c578161085481614b6a565b925050610809565b8183136109305785828151811061088357634e487b7160e01b600052603260045260246000fd5b60200260200101518684815181106108ab57634e487b7160e01b600052603260045260246000fd5b60200260200101518785815181106108d357634e487b7160e01b600052603260045260246000fd5b602002602001018885815181106108fa57634e487b7160e01b600052603260045260246000fd5b6001600160a01b039384166020918202929092010152911690528261091e81614b88565b935050818061092c90614b6a565b9250505b6107ae565b8185121561094857610948868684610751565b8383121561095b5761095b868486610751565b505050505050565b600080825167ffffffffffffffff81111561098e57634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156109b7578160200160208202803683370190505b5090506109c38361011d565b9050806040516020016109d691906148ba565b60405160208183030381529060405280519060200120915050919050565b600060608060019250606080600086606001516001600160a01b0316639e9d38c66040518163ffffffff1660e01b815260040160206040518083038186803b158015610a3f57600080fd5b505afa158015610a53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a7791906146a7565b9050610a868760000151612f4d565b8093508194505050610ad86040518060c001604052808960000151815260200189602001518152602001858152602001848152602001836001600160a01b0316815260200189608001518152506132b4565b9698909750945050505050565b6000610af2848484614427565b610b3a5760405162461bcd60e51b8152602060048201526014602482015273149a5cdad4195c90dbdb5888195e18d95959195960621b60448201526064015b60405180910390fd5b5060019392505050565b8585600080610b538585614af5565b9950610b5f858a614af5565b985060008a118015610b715750600089115b15612f40578560021415610b86575085612dd3565b8560fa1415612dd0578761177857610ba6662386f26fc100006006614af5565b8a108015610bc45750610bc1662386f26fc100006046614af5565b89105b15610bec57610bdb87670de0b6b3a7640000614b53565b610be59088614b53565b9050612dd3565b610bfe662386f26fc100006063614af5565b8a10610c3c57610c16662386f26fc100006001614af5565b610c2888670de0b6b3a7640000614b53565b610c329190614b53565b610be59088614a9b565b610c4e662386f26fc100006060614af5565b8a10610c8e57670de0b6b3a7640000662386f26fc10000610c6f8983614b53565b610c7a90605a614af5565b610c849190614af5565b610c329190614ae1565b610ca0662386f26fc10000605d614af5565b8a10610ccc57670de0b6b3a7640000662386f26fc10000610cc18983614b53565b610c7a90604b614af5565b610cde662386f26fc10000605a614af5565b8a10158015610cfe5750610cfa662386f26fc100006041614af5565b8910155b15610d1e57670de0b6b3a7640000662386f26fc10000610c6f8983614b53565b610d30662386f26fc100006053614af5565b8a10158015610d505750610d4c662386f26fc100006062614af5565b8910155b15610d6757610c32662386f26fc100006005614af5565b610d79662386f26fc100006053614af5565b8a10158015610d995750610d95662386f26fc100006034614af5565b8910155b15610dc457670de0b6b3a7640000662386f26fc10000610db98983614b53565b610c7a90601e614af5565b610dd6662386f26fc100006050614af5565b8a10158015610df65750610df2662386f26fc10000604a614af5565b8910155b15610e2157670de0b6b3a7640000662386f26fc10000610e168983614b53565b610c7a906014614af5565b610e33662386f26fc100006050614af5565b8a10158015610e535750610e4f662386f26fc100006046614af5565b8910155b15610e7e57670de0b6b3a7640000662386f26fc10000610e738983614b53565b610c7a906032614af5565b610e90662386f26fc100006050614af5565b8a10158015610eb05750610eac662386f26fc10000603c614af5565b8910155b15610ed057670de0b6b3a7640000662386f26fc10000610db98983614b53565b610ee2662386f26fc100006050614af5565b8a10158015610f025750610efe662386f26fc100006032614af5565b8910155b15610f2257670de0b6b3a7640000662386f26fc10000610c6f8983614b53565b610f34662386f26fc10000603c614af5565b8910158015610f545750610f50662386f26fc10000600a614af5565b8a11155b15610f60575085612dd3565b610f72662386f26fc100006037614af5565b8910158015610f925750610f8e662386f26fc100006013614af5565b8a11155b15610fd157670de0b6b3a7640000662386f26fc10000610fb28983614b53565b610fbd906046614af5565b610fc79190614af5565b610bdb9190614ae1565b610fe3662386f26fc100006037614af5565b891061100f57670de0b6b3a7640000662386f26fc100006110048983614b53565b610fbd906028614af5565b611021662386f26fc100006036614af5565b891061104257670de0b6b3a7640000662386f26fc10000610fb28983614b53565b611054662386f26fc100006034614af5565b891061111a5761106c662386f26fc10000600a614af5565b8a1161109857670de0b6b3a7640000662386f26fc1000061108d8983614b53565b610fbd906032614af5565b6110aa662386f26fc100006017614af5565b8a116110d657670de0b6b3a7640000662386f26fc100006110cb8983614b53565b610fbd90602d614af5565b6110e8662386f26fc10000602e614af5565b8a1161111357670de0b6b3a76400006111018b82614b53565b610c7a662386f26fc100006005614af5565b5085612dd3565b61112c662386f26fc100006033614af5565b891015801561114c5750611148662386f26fc100006014614af5565b8a11155b1561117757670de0b6b3a7640000662386f26fc1000061116c8983614b53565b610fbd90605a614af5565b611189662386f26fc100006033614af5565b89101580156111a957506111a5662386f26fc100006019614af5565b8a11155b156111ca57670de0b6b3a7640000662386f26fc10000610fbd89600a614af5565b6111dc662386f26fc100006032614af5565b8910611377576111f4662386f26fc10000600a614af5565b8a101561120d57610be58a670de0b6b3a7640000614a9b565b61121f662386f26fc100006015614af5565b8a1161124057670de0b6b3a7640000662386f26fc1000061116c8983614b53565b611252662386f26fc100006017614af5565b8a1161127e57670de0b6b3a7640000662386f26fc100006112738983614b53565b610fbd90601e614af5565b611290662386f26fc100006038614af5565b8a116112b157670de0b6b3a7640000662386f26fc10000610fb28983614b53565b60008a8a116112c9576112c48a8c614b53565b6112d3565b6112d38b8b614b53565b9050801561136d576112ed662386f26fc10000605a614af5565b6112ff662386f26fc100006005614af5565b6113099190614ae1565b6113139082614b53565b9050670de0b6b3a7640000816113298a83614b53565b6113339190614af5565b61133d9190614ae1565b9050670de0b6b3a76400006113528282614a9b565b61135c908a614af5565b6113669190614ae1565b9150611371565b8791505b50612dd3565b611389662386f26fc100006031614af5565b89106113aa57670de0b6b3a7640000662386f26fc10000610fb28983614b53565b6113bc662386f26fc100006030614af5565b89101580156113dc57506113d8662386f26fc100006014614af5565b8a11155b156113fc57670de0b6b3a7640000662386f26fc100006112738983614b53565b61140e662386f26fc100006030614af5565b891015801561142e575061142a662386f26fc100006028614af5565b8a11155b1561145957670de0b6b3a7640000662386f26fc1000061144e8983614b53565b610fbd906014614af5565b61146b662386f26fc100006030614af5565b891015801561148b5750611487662386f26fc100006032614af5565b8a11155b156114ab57670de0b6b3a7640000662386f26fc100006110048983614b53565b6114bd662386f26fc100006030614af5565b89106114ca575085612dd3565b6114dc662386f26fc10000602e614af5565b89101580156114fc57506114f8662386f26fc10000602b614af5565b8a11155b1561151c57670de0b6b3a7640000662386f26fc1000061108d8983614b53565b61152e662386f26fc10000602e614af5565b891061153b575085612dd3565b61154d662386f26fc10000602b614af5565b891061166e57611565662386f26fc100006018614af5565b8a1161158657670de0b6b3a7640000662386f26fc100006112738983614b53565b611598662386f26fc10000602e614af5565b89116115ce576115b0662386f26fc100006005614af5565b87116115bc5786610be5565b610bdb662386f26fc100006002614af5565b60008a8a116115e6576115e18a8c614b53565b6115f0565b6115f08b8b614b53565b9050801561136d5761160a662386f26fc10000605a614af5565b61161c662386f26fc100006005614af5565b6116269190614ae1565b6116309082614b53565b9050670de0b6b3a76400008160026116488b84614b53565b6116529190614ae1565b6116648b670de0b6b3a7640000614b53565b6113299190614a9b565b611680662386f26fc100006027614af5565b89101580156116a0575061169c662386f26fc10000602b614af5565b8a10155b156116c057670de0b6b3a7640000662386f26fc10000610fb28983614b53565b6116d2662386f26fc100006023614af5565b8910611727576116ea662386f26fc10000602e614af5565b8a1161171557670de0b6b3a76400006117038b82614b53565b610fbd89670de0b6b3a7640000614b53565b6115b0662386f26fc100006005614af5565b611739662386f26fc100006023614af5565b89101561177357611752662386f26fc10000602e614af5565b8a1161171557670de0b6b3a7640000662386f26fc10000610c6f8983614b53565b612dd3565b61178a662386f26fc100006038614af5565b8910611a4b576117a2662386f26fc100006044614af5565b891180156117c157506117bd662386f26fc10000600f614af5565b8a11155b156117e157670de0b6b3a7640000662386f26fc10000610e738983614b53565b6117f3662386f26fc10000604c614af5565b8a1061185757670de0b6b3a7640000662386f26fc100006118158c600f614af5565b61181f9190614af5565b6118299190614ae1565b61183b662386f26fc10000600f614af5565b61184d90670de0b6b3a7640000614a9b565b610be59190614a9b565b611869662386f26fc10000603c614af5565b8a106118935761188187670de0b6b3a7640000614b53565b610be590670de0b6b3a7640000614a9b565b6118a5662386f26fc10000603a614af5565b89101580156118c557506118c1662386f26fc100006012614af5565b8a11155b156118f057670de0b6b3a7640000662386f26fc100006118e58983614b53565b610c7a906050614af5565b611902662386f26fc10000603a614af5565b8910158015611922575061191e662386f26fc100006020614af5565b8a11155b1561194257670de0b6b3a7640000662386f26fc10000610fb28983614b53565b611954662386f26fc100006037614af5565b89101580156119745750611970662386f26fc10000603a614af5565b8a10155b15611980575085612dd3565b611992662386f26fc100006037614af5565b89101580156119b257506119ae662386f26fc100006012614af5565b8a11155b156119be575085612dd3565b6119d0662386f26fc100006023614af5565b8a111580156119f057506119ec662386f26fc10000601e614af5565b8a10155b156119fc575085612dd3565b611a0e662386f26fc10000600f614af5565b8a11611a2f57670de0b6b3a7640000662386f26fc1000061108d8983614b53565b670de0b6b3a7640000662386f26fc100006118158c600a614af5565b611a5d662386f26fc100006020614af5565b8911158015611a7d5750611a79662386f26fc100006041614af5565b8a10155b15611a9457610bdb87670de0b6b3a7640000614b53565b611aa6662386f26fc100006020614af5565b8911158015611ac65750611ac2662386f26fc100006055614af5565b8a10155b15611af157670de0b6b3a7640000662386f26fc10000611ae68983614b53565b610fbd906050614af5565b611b03662386f26fc100006023614af5565b8911158015611b1a57506701bc16d674ec80008a11155b15611b4557670de0b6b3a7640000662386f26fc10000611b3a8983614b53565b610fbd90600a614af5565b611b57662386f26fc100006023614af5565b8911158015611b6d57506701bc16d674ec80008a115b8015611b8a5750611b86662386f26fc10000600d614af5565b8a11155b15611b96575085612dd3565b611ba8662386f26fc100006023614af5565b8911158015611bc85750611bc4662386f26fc10000600f614af5565b8a11155b15611be857670de0b6b3a7640000662386f26fc1000061144e8983614b53565b611bfa662386f26fc100006023614af5565b8911158015611c1a5750611c16662386f26fc100006018614af5565b8a11155b15611c3a57670de0b6b3a7640000662386f26fc10000610db98983614b53565b611c4c662386f26fc100006025614af5565b8911158015611c6c5750611c68662386f26fc10000600a614af5565b8a11155b15611c8357610bdb87670de0b6b3a7640000614b53565b611c95662386f26fc100006025614af5565b8911158015611cb55750611cb1662386f26fc100006010614af5565b8a11155b15611ce057670de0b6b3a7640000662386f26fc10000611cd58983614b53565b610c7a90603c614af5565b611cf2662386f26fc100006026614af5565b8911158015611d125750611d0e662386f26fc100006050614af5565b8a10155b15611d4557611d29662386f26fc100006005614af5565b611d3b88670de0b6b3a7640000614b53565b6118819190614a9b565b611d57662386f26fc100006026614af5565b8911158015611d775750611d73662386f26fc100006046614af5565b8a10155b15611d8e57611d29662386f26fc10000600a614af5565b611da0662386f26fc100006026614af5565b8911158015611dc05750611dbc662386f26fc100006042614af5565b8a10155b15611dd757611d29662386f26fc100006019614af5565b611de9662386f26fc100006026614af5565b8911158015611e095750611e05662386f26fc100006032614af5565b8a10155b15611e2057611d29662386f26fc100006005614af5565b611e32662386f26fc100006026614af5565b8911158015611e525750611e4e662386f26fc100006019614af5565b8a10155b15611e7457611e6987670de0b6b3a7640000614b53565b611881906002614af5565b611e86662386f26fc100006026614af5565b8911158015611ea65750611ea2662386f26fc100006017614af5565b8a10155b15611ec657670de0b6b3a7640000662386f26fc100006112738983614b53565b611ed8662386f26fc100006026614af5565b8911158015611ef75750611ef4662386f26fc100006017614af5565b8a105b15611f3657670de0b6b3a7640000662386f26fc10000611f178983614b53565b611f22906028614af5565b611f2c9190614af5565b6118819190614ae1565b611f48662386f26fc100006027614af5565b8911158015611f675750611f64662386f26fc100006014614af5565b8a105b15611f8857670de0b6b3a7640000662386f26fc10000610fbd896014614af5565b611f9a662386f26fc100006028614af5565b8911158015611fba5750611fb6662386f26fc100006009614af5565b8a11155b15611fda57670de0b6b3a7640000662386f26fc100006118e58983614b53565b611fec662386f26fc100006028614af5565b891115801561200c5750612008662386f26fc10000600b614af5565b8a11155b15612018575085612dd3565b61202a662386f26fc100006028614af5565b891115801561204a5750612046662386f26fc10000600d614af5565b8a11155b1561207557670de0b6b3a7640000662386f26fc1000061206a8983614b53565b611f22906032614af5565b612087662386f26fc100006028614af5565b89111580156120a757506120a3662386f26fc10000600e614af5565b8a11155b156120c757670de0b6b3a7640000662386f26fc100006118e58983614b53565b6120d9662386f26fc100006028614af5565b89111580156120f957506120f5662386f26fc10000601e614af5565b8a11155b1561211a57670de0b6b3a7640000662386f26fc10000611f2289601e614af5565b61212c662386f26fc100006028614af5565b891115801561214c5750612148662386f26fc100006036614af5565b8a11155b1561216d57670de0b6b3a7640000662386f26fc10000611f22896014614af5565b61217f662386f26fc100006028614af5565b891115801561219e575061219b662386f26fc100006036614af5565b8a115b156121b55761188187670de0b6b3a7640000614b53565b6121c7662386f26fc10000602b614af5565b89111580156121e757506121e3662386f26fc10000600b614af5565b8a11155b1561220757670de0b6b3a7640000662386f26fc10000610e738983614b53565b612219662386f26fc10000602b614af5565b89111580156122395750612235662386f26fc10000600c614af5565b8a11155b1561225957670de0b6b3a7640000662386f26fc10000610cc18983614b53565b61226b662386f26fc10000602b614af5565b891115801561228b5750612287662386f26fc10000600e614af5565b8a11155b156122ac57670de0b6b3a7640000662386f26fc10000610c7a896014614af5565b6122be662386f26fc10000602b614af5565b89111580156122de57506122da662386f26fc10000600f614af5565b8a11155b156122ff57670de0b6b3a7640000662386f26fc10000610fbd89601e614af5565b612311662386f26fc10000602b614af5565b8911158015612331575061232d662386f26fc100006033614af5565b8a11155b156123485761188187670de0b6b3a7640000614b53565b61235a662386f26fc10000602c614af5565b891115801561237a5750612376662386f26fc100006037614af5565b8a10155b1561239b57670de0b6b3a7640000662386f26fc10000611f2289601e614af5565b6123ad662386f26fc10000602c614af5565b89111580156123cd57506123c9662386f26fc100006037614af5565b8a11155b156123ee57670de0b6b3a7640000662386f26fc10000611f2289601e614af5565b612400662386f26fc10000602d614af5565b8911158015612420575061241c662386f26fc100006046614af5565b8a10155b1561249857670de0b6b3a7640000662386f26fc100006124408983614b53565b61244b906028614af5565b6124559190614af5565b61245f9190614ae1565b61247188670de0b6b3a7640000614b53565b61247c906002614af5565b61248e90670de0b6b3a7640000614a9b565b610be59190614b53565b6124aa662386f26fc10000602d614af5565b89111580156124ca57506124c6662386f26fc10000602c614af5565b8a10155b156124f557670de0b6b3a7640000662386f26fc100006124ea8983614b53565b611f22906046614af5565b612507662386f26fc10000602d614af5565b89111580156125275750612523662386f26fc100006028614af5565b8a10155b1561255257670de0b6b3a7640000662386f26fc100006125478983614b53565b611f2290600a614af5565b612564662386f26fc10000602d614af5565b89111580156125845750612580662386f26fc100006014614af5565b8a10155b156125a457670de0b6b3a7640000662386f26fc100006118e58983614b53565b6125b6662386f26fc10000602d614af5565b89111580156125d557506125d2662386f26fc100006014614af5565b8a105b156125f557670de0b6b3a7640000662386f26fc10000610db98983614b53565b612607662386f26fc10000602f614af5565b89111580156126275750612623662386f26fc100006011614af5565b8a11155b1561265257670de0b6b3a7640000662386f26fc100006126478983614b53565b610c7a906046614af5565b612664662386f26fc10000602f614af5565b89111580156126845750612680662386f26fc100006017614af5565b8a11155b156126af57670de0b6b3a7640000662386f26fc100006126a48983614b53565b611f22906008614af5565b6126c1662386f26fc100006030614af5565b89111580156126e157506126dd662386f26fc10000600b614af5565b8a11155b1561270157670de0b6b3a7640000662386f26fc100006118e58983614b53565b612713662386f26fc100006030614af5565b8911158015612733575061272f662386f26fc100006018614af5565b8a11155b1561275457670de0b6b3a7640000662386f26fc10000610c7a896014614af5565b612766662386f26fc100006031614af5565b89111580156127865750612782662386f26fc10000600f614af5565b8a11155b156127a657670de0b6b3a7640000662386f26fc10000610db98983614b53565b6127b8662386f26fc100006031614af5565b89111580156127d857506127d4662386f26fc100006019614af5565b8a11155b156127f857670de0b6b3a7640000662386f26fc100006118e58983614b53565b61280a662386f26fc100006031614af5565b891115801561282a5750612826662386f26fc100006021614af5565b8a11155b15612836575085612dd3565b612848662386f26fc100006032614af5565b89111580156128685750612864662386f26fc10000600a614af5565b8a11155b1561288857670de0b6b3a7640000662386f26fc10000610e738983614b53565b61289a662386f26fc100006032614af5565b89111580156128ba57506128b6662386f26fc100006011614af5565b8a11155b156128e557670de0b6b3a7640000662386f26fc100006128da8983614b53565b610c7a906023614af5565b6128f7662386f26fc100006032614af5565b89111580156129175750612913662386f26fc100006014614af5565b8a11155b1561292e5761188187670de0b6b3a7640000614b53565b612940662386f26fc100006032614af5565b8911158015612960575061295c662386f26fc100006019614af5565b8a11155b156129935761297787670de0b6b3a7640000614b53565b61298988670de0b6b3a7640000614b53565b61248e9089614b53565b6129a5662386f26fc100006033614af5565b89111580156129c557506129c1662386f26fc100006018614af5565b8a11155b156129d1575085612dd3565b6129e3662386f26fc100006034614af5565b8911158015612a0357506129ff662386f26fc10000600a614af5565b8a11155b15612a2e57670de0b6b3a7640000662386f26fc10000612a238983614b53565b611f22906023614af5565b612a40662386f26fc100006034614af5565b8911158015612a605750612a5c662386f26fc10000600f614af5565b8a11155b15612a8b57670de0b6b3a7640000662386f26fc10000612a808983614b53565b611f2290602d614af5565b612a9d662386f26fc100006034614af5565b8911158015612abd5750612ab9662386f26fc100006018614af5565b8a11155b15612add57670de0b6b3a7640000662386f26fc10000612a238983614b53565b612aef662386f26fc100006034614af5565b8911158015612b0e5750612b0b662386f26fc100006048614af5565b8a115b15612b2e57670de0b6b3a7640000662386f26fc10000612a238983614b53565b612b40662386f26fc100006035614af5565b8911158015612b605750612b5c662386f26fc100006018614af5565b8a11155b15612b8157670de0b6b3a7640000662386f26fc10000611f2289601e614af5565b612b93662386f26fc100006035614af5565b8911158015612bb35750612baf662386f26fc100006028614af5565b8a11155b15612bc75750670de0b6b3a7640000612dd3565b612bd9662386f26fc100006036614af5565b89108015612bf85750612bf4662386f26fc10000604a614af5565b8a10155b15612c0f5761188187670de0b6b3a7640000614b53565b612c21662386f26fc100006036614af5565b89108015612c405750612c3c662386f26fc10000603a614af5565b8a10155b15612c5757611d29662386f26fc10000600a614af5565b612c69662386f26fc100006036614af5565b89108015612c885750612c84662386f26fc100006018614af5565b8a10155b15612c9f5761188187670de0b6b3a7640000614b53565b612cb1662386f26fc100006036614af5565b89108015612ccf5750612ccc662386f26fc100006018614af5565b8a105b15612cef57670de0b6b3a7640000662386f26fc10000610db98983614b53565b612d01662386f26fc100006038614af5565b89108015612d205750612d1c662386f26fc100006052614af5565b8a10155b15612d4057670de0b6b3a7640000662386f26fc1000061206a8983614b53565b612d52662386f26fc100006038614af5565b89108015612d715750612d6d662386f26fc100006028614af5565b8a10155b15612d885761188187670de0b6b3a7640000614b53565b612d9a662386f26fc100006038614af5565b89108015612db95750612db5662386f26fc10000600a614af5565b8a10155b156111135761188187670de0b6b3a7640000614b53565b50855b8015612f40576000670de0b6b3a7640000612dee8b8d614af5565b612df89190614ae1565b90506000670de0b6b3a76400008381612e118186614af5565b612e1b9190614af5565b612e259190614ae1565b612e2f9190614ae1565b9050612e43662386f26fc10000600a614af5565b811015612ef157612e5c662386f26fc10000600a614af5565b8c1115612eb657670de0b6b3a7640000612e7e662386f26fc10000600a614af5565b670de0b6b3a7640000612e918186614af5565b612e9b9190614af5565b612ea59190614ae1565b612eaf9190614ae1565b9250612f3d565b670de0b6b3a764000080662386f26fc10000612ed38f600a614af5565b612edd9190614af5565b612ee79190614ae1565b612e7e908e614b53565b8b81118015612eff57508a8c105b15612f1557612eaf8b660e35fa931a0000614a9b565b8a81118015612f2457508b8b11155b15612f3d57612f3a8c660e35fa931a0000614a9b565b92505b50505b9650965096509692505050565b606080825167ffffffffffffffff811115612f7857634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015612fa1578160200160208202803683370190505b509150825167ffffffffffffffff811115612fcc57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015612ff5578160200160208202803683370190505b5090506000805b84518110156132ad5784818151811061302557634e487b7160e01b600052603260045260246000fd5b60200260200101519150816001600160a01b03166320822abc60006040518263ffffffff1660e01b815260040161305e91815260200190565b60206040518083038186803b15801561307657600080fd5b505afa15801561308a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130ae9190614826565b8482815181106130ce57634e487b7160e01b600052603260045260246000fd5b6020026020010181815250506001826001600160a01b03166344f2723f6040518163ffffffff1660e01b815260040160206040518083038186803b15801561311557600080fd5b505afa158015613129573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061314d9190614826565b116131595760006131d1565b6040516308208aaf60e21b8152600160048201526001600160a01b038316906320822abc9060240160206040518083038186803b15801561319957600080fd5b505afa1580156131ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131d19190614826565b8382815181106131f157634e487b7160e01b600052603260045260246000fd5b60200260200101818152505060005b8181101561329a5785818151811061322857634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b031686838151811061325957634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b031614156132885760405162461bcd60e51b8152600401610b319061496e565b8061329281614ba8565b915050613200565b50806132a581614ba8565b915050612ffc565b5050915091565b60608082600001515167ffffffffffffffff8111156132e357634e487b7160e01b600052604160045260246000fd5b60405190808252806020026020018201604052801561330c578160200160208202803683370190505b509150815167ffffffffffffffff81111561333757634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015613360578160200160208202803683370190505b5090506000815167ffffffffffffffff81111561338d57634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156133b6578160200160208202803683370190505b50905060005b8451518110156132ad5760005b818110156142cb5785518051839081106133f357634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b03168660000151828151811061342857634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b0316146142a15782818151811061345e57634e487b7160e01b600052603260045260246000fd5b60200260200101511580156134c857508560400151828151811061349257634e487b7160e01b600052603260045260246000fd5b6020026020010151866040015182815181106134be57634e487b7160e01b600052603260045260246000fd5b6020026020010151145b801561353457506000866060015183815181106134f557634e487b7160e01b600052603260045260246000fd5b60200260200101511180613534575060008660600151828151811061352a57634e487b7160e01b600052603260045260246000fd5b6020026020010151115b1561429c5760008660000151838151811061355f57634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b031663d03ecc646040518163ffffffff1660e01b815260040160206040518083038186803b15801561359f57600080fd5b505afa1580156135b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135d791906146a7565b90506000876000015183815181106135ff57634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b031663d03ecc646040518163ffffffff1660e01b815260040160206040518083038186803b15801561363f57600080fd5b505afa158015613653573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061367791906146a7565b905060008860600151848151811061369f57634e487b7160e01b600052603260045260246000fd5b60200260200101511180156136ee575087518051859081106136d157634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b0316816001600160a01b0316145b80613769575060008860600151858151811061371a57634e487b7160e01b600052603260045260246000fd5b60200260200101511180156137695750875180518490811061374c57634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b0316826001600160a01b0316145b806137f2575060008860600151858151811061379557634e487b7160e01b600052603260045260246000fd5b60200260200101511180156137d557506000886060015184815181106137cb57634e487b7160e01b600052603260045260246000fd5b6020026020010151115b80156137f25750806001600160a01b0316826001600160a01b0316145b1561429957600088608001516001600160a01b031663ec748e396040518060a001604052808c60400151898151811061383b57634e487b7160e01b600052603260045260246000fd5b602002602001015181526020018c60600151898151811061386c57634e487b7160e01b600052603260045260246000fd5b602002602001015181526020018c60600151888151811061389d57634e487b7160e01b600052603260045260246000fd5b602002602001015181526020018c6020015189815181106138ce57634e487b7160e01b600052603260045260246000fd5b602002602001015181526020018c6020015188815181106138ff57634e487b7160e01b600052603260045260246000fd5b602090810291909101810151909152604080516001600160e01b031960e086901b16815283516004820152918301516024830152820151604482015260608201516064820152608090910151608482015260a40160206040518083038186803b15801561396b57600080fd5b505afa15801561397f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139a39190614826565b905061271a896060015185815181106139cc57634e487b7160e01b600052603260045260246000fd5b6020026020010151148015613a0d575061271a89606001518681518110613a0357634e487b7160e01b600052603260045260246000fd5b6020026020010151145b15613b775788608001516001600160a01b031663a2abdac58a600001518781518110613a4957634e487b7160e01b600052603260045260246000fd5b60200260200101518b600001518781518110613a7557634e487b7160e01b600052603260045260246000fd5b60200260200101518c604001518981518110613aa157634e487b7160e01b600052603260045260246000fd5b60209081029190910101516040516001600160e01b031960e086901b1681526001600160a01b039384166004820152929091166024830152604482015260640160206040518083038186803b158015613af957600080fd5b505afa158015613b0d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b3191906146fe565b613b725760405162461bcd60e51b8152602060048201526012602482015271496e76616c6964506c6179657250726f707360701b6044820152606401610b31565b614297565b80613b945760405162461bcd60e51b8152600401610b319061496e565b6001868681518110613bb657634e487b7160e01b600052603260045260246000fd5b6020026020010190151590811515815250506001868581518110613bea57634e487b7160e01b600052603260045260246000fd5b602002602001019015159081151581525050600089606001518581518110613c2257634e487b7160e01b600052603260045260246000fd5b60200260200101511115613fac57613efc89608001516001600160a01b03166340c5336c8b600001518881518110613c6a57634e487b7160e01b600052603260045260246000fd5b60200260200101518c602001518981518110613c9657634e487b7160e01b600052603260045260246000fd5b60200260200101516040518363ffffffff1660e01b8152600401613ccf9291906001600160a01b03929092168252602082015260400190565b60206040518083038186803b158015613ce757600080fd5b505afa158015613cfb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d1f9190614826565b8a608001516001600160a01b03166340c5336c8c600001518881518110613d5657634e487b7160e01b600052603260045260246000fd5b60200260200101518d602001518981518110613d8257634e487b7160e01b600052603260045260246000fd5b60200260200101516040518363ffffffff1660e01b8152600401613dbb9291906001600160a01b03929092168252602082015260400190565b60206040518083038186803b158015613dd357600080fd5b505afa158015613de7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e0b9190614826565b8b602001518781518110613e2f57634e487b7160e01b600052603260045260246000fd5b6020026020010151848d608001516001600160a01b031663699c2c608f600001518b81518110613e6f57634e487b7160e01b600052603260045260246000fd5b60200260200101516040518263ffffffff1660e01b8152600401613ea291906001600160a01b0391909116815260200190565b60206040518083038186803b158015613eba57600080fd5b505afa158015613ece573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ef29190614826565b8e60a00151610b44565b8b8981518110613f1c57634e487b7160e01b600052603260045260246000fd5b602002602001018c8981518110613f4357634e487b7160e01b600052603260045260246000fd5b602002602001018c8b81518110613f6a57634e487b7160e01b600052603260045260246000fd5b602002602001018d8b81518110613f9157634e487b7160e01b600052603260045260246000fd5b60209081029190910101939093529290915291905252614297565b6141eb89608001516001600160a01b03166340c5336c8b600001518781518110613fe657634e487b7160e01b600052603260045260246000fd5b60200260200101518c60200151888151811061401257634e487b7160e01b600052603260045260246000fd5b60200260200101516040518363ffffffff1660e01b815260040161404b9291906001600160a01b03929092168252602082015260400190565b60206040518083038186803b15801561406357600080fd5b505afa158015614077573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061409b9190614826565b8a608001516001600160a01b03166340c5336c8c6000015189815181106140d257634e487b7160e01b600052603260045260246000fd5b60200260200101518d602001518a815181106140fe57634e487b7160e01b600052603260045260246000fd5b60200260200101516040518363ffffffff1660e01b81526004016141379291906001600160a01b03929092168252602082015260400190565b60206040518083038186803b15801561414f57600080fd5b505afa158015614163573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141879190614826565b8b6020015188815181106141ab57634e487b7160e01b600052603260045260246000fd5b6020026020010151848d608001516001600160a01b031663699c2c608f600001518c81518110613e6f57634e487b7160e01b600052603260045260246000fd5b8b888151811061420b57634e487b7160e01b600052603260045260246000fd5b602002602001018c8a8151811061423257634e487b7160e01b600052603260045260246000fd5b602002602001018c8a8151811061425957634e487b7160e01b600052603260045260246000fd5b602002602001018d8c8151811061428057634e487b7160e01b600052603260045260246000fd5b602090810291909101019390935292909152919052525b505b50505b6142b9565b60405162461bcd60e51b8152600401610b319061496e565b806142c381614ba8565b9150506133c9565b508381815181106142ec57634e487b7160e01b600052603260045260246000fd5b6020026020010151600014156144155784608001516001600160a01b03166340c5336c8660000151838151811061433357634e487b7160e01b600052603260045260246000fd5b60200260200101518760200151848151811061435f57634e487b7160e01b600052603260045260246000fd5b60200260200101516040518363ffffffff1660e01b81526004016143989291906001600160a01b03929092168252602082015260400190565b60206040518083038186803b1580156143b057600080fd5b505afa1580156143c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143e89190614826565b84828151811061440857634e487b7160e01b600052603260045260246000fd5b6020026020010181815250505b8061441f81614ba8565b9150506133bc565b6000600184511180156144ab5750816001600160a01b031663734131936040518163ffffffff1660e01b815260040160206040518083038186803b15801561446e57600080fd5b505afa158015614482573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144a69190614826565b845111155b156145bb576000826001600160a01b03166396f8af9c6144ca87610963565b6040518263ffffffff1660e01b81526004016144e891815260200190565b60206040518083038186803b15801561450057600080fd5b505afa158015614514573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145389190614826565b9050826001600160a01b031663182605676040518163ffffffff1660e01b815260040160206040518083038186803b15801561457357600080fd5b505afa158015614587573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145ab9190614826565b6145b58583614a9b565b11159150505b9392505050565b80356145cd81614bfa565b919050565b600082601f8301126145e2578081fd5b813560206145f76145f283614a36565b614a05565b80838252828201915082860187848660051b8901011115614616578586fd5b855b8581101561463d57813561462b81614bfa565b84529284019290840190600101614618565b5090979650505050505050565b600082601f83011261465a578081fd5b8135602061466a6145f283614a36565b80838252828201915082860187848660051b8901011115614689578586fd5b855b8581101561463d5781358452928401929084019060010161468b565b6000602082840312156146b8578081fd5b81516145bb81614bfa565b6000602082840312156146d4578081fd5b813567ffffffffffffffff8111156146ea578182fd5b6146f6848285016145d2565b949350505050565b60006020828403121561470f578081fd5b815180151581146145bb578182fd5b60006020828403121561472f578081fd5b813567ffffffffffffffff80821115614746578283fd5b90830190610100828603121561475a578283fd5b6147626149db565b823582811115614770578485fd5b61477c878286016145d2565b825250602083013582811115614790578485fd5b61479c8782860161464a565b60208301525060408301356040820152606083013560608201526080830135608082015260a0830135828111156147d1578485fd5b6147dd8782860161464a565b60a0830152506147ef60c084016145c2565b60c082015261480060e084016145c2565b60e082015295945050505050565b60006020828403121561481f578081fd5b5035919050565b600060208284031215614837578081fd5b5051919050565b60008060008060008060c08789031215614856578182fd5b505084359660208601359650604086013595606081013595506080810135945060a0013592509050565b6000815180845260208085019450808401835b838110156148af57815187529582019590820190600101614893565b509495945050505050565b815160009082906020808601845b838110156148ed5781516001600160a01b0316855293820193908201906001016148c8565b50929695505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561493a5783516001600160a01b031683529284019291840191600101614915565b50909695505050505050565b602081016003831061496857634e487b7160e01b600052602160045260246000fd5b91905290565b60208082526010908201526f53616d655465616d4f6e5061726c617960801b604082015260600190565b85815284602082015283604082015260a0606082015260006149bd60a0830185614880565b82810360808401526149cf8185614880565b98975050505050505050565b604051610100810167ffffffffffffffff811182821017156149ff576149ff614be4565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715614a2e57614a2e614be4565b604052919050565b600067ffffffffffffffff821115614a5057614a50614be4565b5060051b60200190565b600080821280156001600160ff1b0384900385131615614a7c57614a7c614bb8565b600160ff1b8390038412811615614a9557614a95614bb8565b50500190565b60008219821115614aae57614aae614bb8565b500190565b600082614ac257614ac2614bce565b600160ff1b821460001984141615614adc57614adc614bb8565b500590565b600082614af057614af0614bce565b500490565b6000816000190483118215151615614b0f57614b0f614bb8565b500290565b60008083128015600160ff1b850184121615614b3257614b32614bb8565b6001600160ff1b0384018313811615614b4d57614b4d614bb8565b50500390565b600082821015614b6557614b65614bb8565b500390565b6000600160ff1b821415614b8057614b80614bb8565b506000190190565b60006001600160ff1b03821415614ba157614ba1614bb8565b5060010190565b6000600019821415614ba157614ba15b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114614c0f57600080fd5b5056fea2646970667358221220f9750e08dd601d0f0ff7f687464571722e5b38f3b8f2dc83916441328137af8764736f6c63430008040033

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106100575760003560e01c8063128424a71461005c5780636517d1a414610085578063e7468c62146100a6578063e7fe0d37146100ca578063e835640f146100ea575b600080fd5b61006f61006a3660046146c3565b61011d565b60405161007c91906148f9565b60405180910390f35b6100986100933660046146c3565b61013c565b60405190815260200161007c565b6100b96100b436600461471e565b61014d565b60405161007c959493929190614998565b6100dd6100d836600461480e565b610701565b60405161007c9190614946565b6100fd6100f836600461483e565b610729565b60408051948552602085019390935291830152606082015260800161007c565b6060610138826000600185516101339190614b53565b610751565b5090565b600061014782610963565b92915050565b6000806000606080600086600001515190506000808267ffffffffffffffff81111561018957634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156101b2578160200160208202803683370190505b50935061020a6040518060a001604052808b6000015181526020018b6020015181526020018b60c001516001600160a01b031681526020018b60e001516001600160a01b031681526020018b608001518152506109f4565b60a08c015295509050808015610224575088602001515183145b80156102305750600083115b8015610240575088606001518311155b156106f55760005b8381101561047d5760028a60200151828151811061027657634e487b7160e01b600052603260045260246000fd5b6020026020010151111561028d576000985061047d565b855161029c576000985061047d565b8581815181106102bc57634e487b7160e01b600052603260045260246000fd5b60200260200101518a608001516102d39190614af5565b8682815181106102f357634e487b7160e01b600052603260045260246000fd5b60200260200101818152505060008a60a00151828151811061032557634e487b7160e01b600052603260045260246000fd5b602002602001015111156103ef57670de0b6b3a76400008a60a00151828151811061036057634e487b7160e01b600052603260045260246000fd5b6020026020010151670de0b6b3a76400008089858151811061039257634e487b7160e01b600052603260045260246000fd5b60200260200101516103a49190614af5565b6103ae9190614af5565b6103b89190614ae1565b6103c29190614ae1565b8682815181106103e257634e487b7160e01b600052603260045260246000fd5b6020026020010181815250505b881561044057670de0b6b3a764000086828151811061041e57634e487b7160e01b600052603260045260246000fd5b60200260200101518a6104319190614af5565b61043b9190614ae1565b610469565b85818151811061046057634e487b7160e01b600052603260045260246000fd5b60200260200101515b98508061047581614ba8565b915050610248565b50871561062f578860e001516001600160a01b031663e88698bf6040518163ffffffff1660e01b815260040160206040518083038186803b1580156104c157600080fd5b505afa1580156104d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104f99190614826565b881015610578578860e001516001600160a01b031663e88698bf6040518163ffffffff1660e01b815260040160206040518083038186803b15801561053d57600080fd5b505afa158015610551573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105759190614826565b97505b87670de0b6b3a76400008a604001516105919190614af5565b61059b9190614ae1565b895160408b015191985061062d916105b3908a614b53565b8b60c001516001600160a01b0316637d550e056040518163ffffffff1660e01b815260040160206040518083038186803b1580156105f057600080fd5b505afa158015610604573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061062891906146a7565b610ae5565b505b60005b838110156106f357600086828151811061065c57634e487b7160e01b600052603260045260246000fd5b602002602001015111156106e15785818151811061068a57634e487b7160e01b600052603260045260246000fd5b60200260200101518a60400151670de0b6b3a76400006106aa9190614af5565b6106b49190614ae1565b8582815181106106d457634e487b7160e01b600052603260045260246000fd5b6020026020010181815250505b806106eb81614ba8565b915050610632565b505b50505091939590929450565b60008161071057506000919050565b816001141561072157506001919050565b506002919050565b60008060008061073d8a8a8a8a8a8a610b44565b929d919c509a509098509650505050505050565b818180821415610762575050505050565b60008560026107718787614b14565b61077b9190614ab3565b6107859087614a5a565b815181106107a357634e487b7160e01b600052603260045260246000fd5b602002602001015190505b818313610935575b806001600160a01b03168684815181106107e057634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b03161015610809578261080181614b88565b9350506107b6565b85828151811061082957634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b0316816001600160a01b0316101561085c578161085481614b6a565b925050610809565b8183136109305785828151811061088357634e487b7160e01b600052603260045260246000fd5b60200260200101518684815181106108ab57634e487b7160e01b600052603260045260246000fd5b60200260200101518785815181106108d357634e487b7160e01b600052603260045260246000fd5b602002602001018885815181106108fa57634e487b7160e01b600052603260045260246000fd5b6001600160a01b039384166020918202929092010152911690528261091e81614b88565b935050818061092c90614b6a565b9250505b6107ae565b8185121561094857610948868684610751565b8383121561095b5761095b868486610751565b505050505050565b600080825167ffffffffffffffff81111561098e57634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156109b7578160200160208202803683370190505b5090506109c38361011d565b9050806040516020016109d691906148ba565b60405160208183030381529060405280519060200120915050919050565b600060608060019250606080600086606001516001600160a01b0316639e9d38c66040518163ffffffff1660e01b815260040160206040518083038186803b158015610a3f57600080fd5b505afa158015610a53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a7791906146a7565b9050610a868760000151612f4d565b8093508194505050610ad86040518060c001604052808960000151815260200189602001518152602001858152602001848152602001836001600160a01b0316815260200189608001518152506132b4565b9698909750945050505050565b6000610af2848484614427565b610b3a5760405162461bcd60e51b8152602060048201526014602482015273149a5cdad4195c90dbdb5888195e18d95959195960621b60448201526064015b60405180910390fd5b5060019392505050565b8585600080610b538585614af5565b9950610b5f858a614af5565b985060008a118015610b715750600089115b15612f40578560021415610b86575085612dd3565b8560fa1415612dd0578761177857610ba6662386f26fc100006006614af5565b8a108015610bc45750610bc1662386f26fc100006046614af5565b89105b15610bec57610bdb87670de0b6b3a7640000614b53565b610be59088614b53565b9050612dd3565b610bfe662386f26fc100006063614af5565b8a10610c3c57610c16662386f26fc100006001614af5565b610c2888670de0b6b3a7640000614b53565b610c329190614b53565b610be59088614a9b565b610c4e662386f26fc100006060614af5565b8a10610c8e57670de0b6b3a7640000662386f26fc10000610c6f8983614b53565b610c7a90605a614af5565b610c849190614af5565b610c329190614ae1565b610ca0662386f26fc10000605d614af5565b8a10610ccc57670de0b6b3a7640000662386f26fc10000610cc18983614b53565b610c7a90604b614af5565b610cde662386f26fc10000605a614af5565b8a10158015610cfe5750610cfa662386f26fc100006041614af5565b8910155b15610d1e57670de0b6b3a7640000662386f26fc10000610c6f8983614b53565b610d30662386f26fc100006053614af5565b8a10158015610d505750610d4c662386f26fc100006062614af5565b8910155b15610d6757610c32662386f26fc100006005614af5565b610d79662386f26fc100006053614af5565b8a10158015610d995750610d95662386f26fc100006034614af5565b8910155b15610dc457670de0b6b3a7640000662386f26fc10000610db98983614b53565b610c7a90601e614af5565b610dd6662386f26fc100006050614af5565b8a10158015610df65750610df2662386f26fc10000604a614af5565b8910155b15610e2157670de0b6b3a7640000662386f26fc10000610e168983614b53565b610c7a906014614af5565b610e33662386f26fc100006050614af5565b8a10158015610e535750610e4f662386f26fc100006046614af5565b8910155b15610e7e57670de0b6b3a7640000662386f26fc10000610e738983614b53565b610c7a906032614af5565b610e90662386f26fc100006050614af5565b8a10158015610eb05750610eac662386f26fc10000603c614af5565b8910155b15610ed057670de0b6b3a7640000662386f26fc10000610db98983614b53565b610ee2662386f26fc100006050614af5565b8a10158015610f025750610efe662386f26fc100006032614af5565b8910155b15610f2257670de0b6b3a7640000662386f26fc10000610c6f8983614b53565b610f34662386f26fc10000603c614af5565b8910158015610f545750610f50662386f26fc10000600a614af5565b8a11155b15610f60575085612dd3565b610f72662386f26fc100006037614af5565b8910158015610f925750610f8e662386f26fc100006013614af5565b8a11155b15610fd157670de0b6b3a7640000662386f26fc10000610fb28983614b53565b610fbd906046614af5565b610fc79190614af5565b610bdb9190614ae1565b610fe3662386f26fc100006037614af5565b891061100f57670de0b6b3a7640000662386f26fc100006110048983614b53565b610fbd906028614af5565b611021662386f26fc100006036614af5565b891061104257670de0b6b3a7640000662386f26fc10000610fb28983614b53565b611054662386f26fc100006034614af5565b891061111a5761106c662386f26fc10000600a614af5565b8a1161109857670de0b6b3a7640000662386f26fc1000061108d8983614b53565b610fbd906032614af5565b6110aa662386f26fc100006017614af5565b8a116110d657670de0b6b3a7640000662386f26fc100006110cb8983614b53565b610fbd90602d614af5565b6110e8662386f26fc10000602e614af5565b8a1161111357670de0b6b3a76400006111018b82614b53565b610c7a662386f26fc100006005614af5565b5085612dd3565b61112c662386f26fc100006033614af5565b891015801561114c5750611148662386f26fc100006014614af5565b8a11155b1561117757670de0b6b3a7640000662386f26fc1000061116c8983614b53565b610fbd90605a614af5565b611189662386f26fc100006033614af5565b89101580156111a957506111a5662386f26fc100006019614af5565b8a11155b156111ca57670de0b6b3a7640000662386f26fc10000610fbd89600a614af5565b6111dc662386f26fc100006032614af5565b8910611377576111f4662386f26fc10000600a614af5565b8a101561120d57610be58a670de0b6b3a7640000614a9b565b61121f662386f26fc100006015614af5565b8a1161124057670de0b6b3a7640000662386f26fc1000061116c8983614b53565b611252662386f26fc100006017614af5565b8a1161127e57670de0b6b3a7640000662386f26fc100006112738983614b53565b610fbd90601e614af5565b611290662386f26fc100006038614af5565b8a116112b157670de0b6b3a7640000662386f26fc10000610fb28983614b53565b60008a8a116112c9576112c48a8c614b53565b6112d3565b6112d38b8b614b53565b9050801561136d576112ed662386f26fc10000605a614af5565b6112ff662386f26fc100006005614af5565b6113099190614ae1565b6113139082614b53565b9050670de0b6b3a7640000816113298a83614b53565b6113339190614af5565b61133d9190614ae1565b9050670de0b6b3a76400006113528282614a9b565b61135c908a614af5565b6113669190614ae1565b9150611371565b8791505b50612dd3565b611389662386f26fc100006031614af5565b89106113aa57670de0b6b3a7640000662386f26fc10000610fb28983614b53565b6113bc662386f26fc100006030614af5565b89101580156113dc57506113d8662386f26fc100006014614af5565b8a11155b156113fc57670de0b6b3a7640000662386f26fc100006112738983614b53565b61140e662386f26fc100006030614af5565b891015801561142e575061142a662386f26fc100006028614af5565b8a11155b1561145957670de0b6b3a7640000662386f26fc1000061144e8983614b53565b610fbd906014614af5565b61146b662386f26fc100006030614af5565b891015801561148b5750611487662386f26fc100006032614af5565b8a11155b156114ab57670de0b6b3a7640000662386f26fc100006110048983614b53565b6114bd662386f26fc100006030614af5565b89106114ca575085612dd3565b6114dc662386f26fc10000602e614af5565b89101580156114fc57506114f8662386f26fc10000602b614af5565b8a11155b1561151c57670de0b6b3a7640000662386f26fc1000061108d8983614b53565b61152e662386f26fc10000602e614af5565b891061153b575085612dd3565b61154d662386f26fc10000602b614af5565b891061166e57611565662386f26fc100006018614af5565b8a1161158657670de0b6b3a7640000662386f26fc100006112738983614b53565b611598662386f26fc10000602e614af5565b89116115ce576115b0662386f26fc100006005614af5565b87116115bc5786610be5565b610bdb662386f26fc100006002614af5565b60008a8a116115e6576115e18a8c614b53565b6115f0565b6115f08b8b614b53565b9050801561136d5761160a662386f26fc10000605a614af5565b61161c662386f26fc100006005614af5565b6116269190614ae1565b6116309082614b53565b9050670de0b6b3a76400008160026116488b84614b53565b6116529190614ae1565b6116648b670de0b6b3a7640000614b53565b6113299190614a9b565b611680662386f26fc100006027614af5565b89101580156116a0575061169c662386f26fc10000602b614af5565b8a10155b156116c057670de0b6b3a7640000662386f26fc10000610fb28983614b53565b6116d2662386f26fc100006023614af5565b8910611727576116ea662386f26fc10000602e614af5565b8a1161171557670de0b6b3a76400006117038b82614b53565b610fbd89670de0b6b3a7640000614b53565b6115b0662386f26fc100006005614af5565b611739662386f26fc100006023614af5565b89101561177357611752662386f26fc10000602e614af5565b8a1161171557670de0b6b3a7640000662386f26fc10000610c6f8983614b53565b612dd3565b61178a662386f26fc100006038614af5565b8910611a4b576117a2662386f26fc100006044614af5565b891180156117c157506117bd662386f26fc10000600f614af5565b8a11155b156117e157670de0b6b3a7640000662386f26fc10000610e738983614b53565b6117f3662386f26fc10000604c614af5565b8a1061185757670de0b6b3a7640000662386f26fc100006118158c600f614af5565b61181f9190614af5565b6118299190614ae1565b61183b662386f26fc10000600f614af5565b61184d90670de0b6b3a7640000614a9b565b610be59190614a9b565b611869662386f26fc10000603c614af5565b8a106118935761188187670de0b6b3a7640000614b53565b610be590670de0b6b3a7640000614a9b565b6118a5662386f26fc10000603a614af5565b89101580156118c557506118c1662386f26fc100006012614af5565b8a11155b156118f057670de0b6b3a7640000662386f26fc100006118e58983614b53565b610c7a906050614af5565b611902662386f26fc10000603a614af5565b8910158015611922575061191e662386f26fc100006020614af5565b8a11155b1561194257670de0b6b3a7640000662386f26fc10000610fb28983614b53565b611954662386f26fc100006037614af5565b89101580156119745750611970662386f26fc10000603a614af5565b8a10155b15611980575085612dd3565b611992662386f26fc100006037614af5565b89101580156119b257506119ae662386f26fc100006012614af5565b8a11155b156119be575085612dd3565b6119d0662386f26fc100006023614af5565b8a111580156119f057506119ec662386f26fc10000601e614af5565b8a10155b156119fc575085612dd3565b611a0e662386f26fc10000600f614af5565b8a11611a2f57670de0b6b3a7640000662386f26fc1000061108d8983614b53565b670de0b6b3a7640000662386f26fc100006118158c600a614af5565b611a5d662386f26fc100006020614af5565b8911158015611a7d5750611a79662386f26fc100006041614af5565b8a10155b15611a9457610bdb87670de0b6b3a7640000614b53565b611aa6662386f26fc100006020614af5565b8911158015611ac65750611ac2662386f26fc100006055614af5565b8a10155b15611af157670de0b6b3a7640000662386f26fc10000611ae68983614b53565b610fbd906050614af5565b611b03662386f26fc100006023614af5565b8911158015611b1a57506701bc16d674ec80008a11155b15611b4557670de0b6b3a7640000662386f26fc10000611b3a8983614b53565b610fbd90600a614af5565b611b57662386f26fc100006023614af5565b8911158015611b6d57506701bc16d674ec80008a115b8015611b8a5750611b86662386f26fc10000600d614af5565b8a11155b15611b96575085612dd3565b611ba8662386f26fc100006023614af5565b8911158015611bc85750611bc4662386f26fc10000600f614af5565b8a11155b15611be857670de0b6b3a7640000662386f26fc1000061144e8983614b53565b611bfa662386f26fc100006023614af5565b8911158015611c1a5750611c16662386f26fc100006018614af5565b8a11155b15611c3a57670de0b6b3a7640000662386f26fc10000610db98983614b53565b611c4c662386f26fc100006025614af5565b8911158015611c6c5750611c68662386f26fc10000600a614af5565b8a11155b15611c8357610bdb87670de0b6b3a7640000614b53565b611c95662386f26fc100006025614af5565b8911158015611cb55750611cb1662386f26fc100006010614af5565b8a11155b15611ce057670de0b6b3a7640000662386f26fc10000611cd58983614b53565b610c7a90603c614af5565b611cf2662386f26fc100006026614af5565b8911158015611d125750611d0e662386f26fc100006050614af5565b8a10155b15611d4557611d29662386f26fc100006005614af5565b611d3b88670de0b6b3a7640000614b53565b6118819190614a9b565b611d57662386f26fc100006026614af5565b8911158015611d775750611d73662386f26fc100006046614af5565b8a10155b15611d8e57611d29662386f26fc10000600a614af5565b611da0662386f26fc100006026614af5565b8911158015611dc05750611dbc662386f26fc100006042614af5565b8a10155b15611dd757611d29662386f26fc100006019614af5565b611de9662386f26fc100006026614af5565b8911158015611e095750611e05662386f26fc100006032614af5565b8a10155b15611e2057611d29662386f26fc100006005614af5565b611e32662386f26fc100006026614af5565b8911158015611e525750611e4e662386f26fc100006019614af5565b8a10155b15611e7457611e6987670de0b6b3a7640000614b53565b611881906002614af5565b611e86662386f26fc100006026614af5565b8911158015611ea65750611ea2662386f26fc100006017614af5565b8a10155b15611ec657670de0b6b3a7640000662386f26fc100006112738983614b53565b611ed8662386f26fc100006026614af5565b8911158015611ef75750611ef4662386f26fc100006017614af5565b8a105b15611f3657670de0b6b3a7640000662386f26fc10000611f178983614b53565b611f22906028614af5565b611f2c9190614af5565b6118819190614ae1565b611f48662386f26fc100006027614af5565b8911158015611f675750611f64662386f26fc100006014614af5565b8a105b15611f8857670de0b6b3a7640000662386f26fc10000610fbd896014614af5565b611f9a662386f26fc100006028614af5565b8911158015611fba5750611fb6662386f26fc100006009614af5565b8a11155b15611fda57670de0b6b3a7640000662386f26fc100006118e58983614b53565b611fec662386f26fc100006028614af5565b891115801561200c5750612008662386f26fc10000600b614af5565b8a11155b15612018575085612dd3565b61202a662386f26fc100006028614af5565b891115801561204a5750612046662386f26fc10000600d614af5565b8a11155b1561207557670de0b6b3a7640000662386f26fc1000061206a8983614b53565b611f22906032614af5565b612087662386f26fc100006028614af5565b89111580156120a757506120a3662386f26fc10000600e614af5565b8a11155b156120c757670de0b6b3a7640000662386f26fc100006118e58983614b53565b6120d9662386f26fc100006028614af5565b89111580156120f957506120f5662386f26fc10000601e614af5565b8a11155b1561211a57670de0b6b3a7640000662386f26fc10000611f2289601e614af5565b61212c662386f26fc100006028614af5565b891115801561214c5750612148662386f26fc100006036614af5565b8a11155b1561216d57670de0b6b3a7640000662386f26fc10000611f22896014614af5565b61217f662386f26fc100006028614af5565b891115801561219e575061219b662386f26fc100006036614af5565b8a115b156121b55761188187670de0b6b3a7640000614b53565b6121c7662386f26fc10000602b614af5565b89111580156121e757506121e3662386f26fc10000600b614af5565b8a11155b1561220757670de0b6b3a7640000662386f26fc10000610e738983614b53565b612219662386f26fc10000602b614af5565b89111580156122395750612235662386f26fc10000600c614af5565b8a11155b1561225957670de0b6b3a7640000662386f26fc10000610cc18983614b53565b61226b662386f26fc10000602b614af5565b891115801561228b5750612287662386f26fc10000600e614af5565b8a11155b156122ac57670de0b6b3a7640000662386f26fc10000610c7a896014614af5565b6122be662386f26fc10000602b614af5565b89111580156122de57506122da662386f26fc10000600f614af5565b8a11155b156122ff57670de0b6b3a7640000662386f26fc10000610fbd89601e614af5565b612311662386f26fc10000602b614af5565b8911158015612331575061232d662386f26fc100006033614af5565b8a11155b156123485761188187670de0b6b3a7640000614b53565b61235a662386f26fc10000602c614af5565b891115801561237a5750612376662386f26fc100006037614af5565b8a10155b1561239b57670de0b6b3a7640000662386f26fc10000611f2289601e614af5565b6123ad662386f26fc10000602c614af5565b89111580156123cd57506123c9662386f26fc100006037614af5565b8a11155b156123ee57670de0b6b3a7640000662386f26fc10000611f2289601e614af5565b612400662386f26fc10000602d614af5565b8911158015612420575061241c662386f26fc100006046614af5565b8a10155b1561249857670de0b6b3a7640000662386f26fc100006124408983614b53565b61244b906028614af5565b6124559190614af5565b61245f9190614ae1565b61247188670de0b6b3a7640000614b53565b61247c906002614af5565b61248e90670de0b6b3a7640000614a9b565b610be59190614b53565b6124aa662386f26fc10000602d614af5565b89111580156124ca57506124c6662386f26fc10000602c614af5565b8a10155b156124f557670de0b6b3a7640000662386f26fc100006124ea8983614b53565b611f22906046614af5565b612507662386f26fc10000602d614af5565b89111580156125275750612523662386f26fc100006028614af5565b8a10155b1561255257670de0b6b3a7640000662386f26fc100006125478983614b53565b611f2290600a614af5565b612564662386f26fc10000602d614af5565b89111580156125845750612580662386f26fc100006014614af5565b8a10155b156125a457670de0b6b3a7640000662386f26fc100006118e58983614b53565b6125b6662386f26fc10000602d614af5565b89111580156125d557506125d2662386f26fc100006014614af5565b8a105b156125f557670de0b6b3a7640000662386f26fc10000610db98983614b53565b612607662386f26fc10000602f614af5565b89111580156126275750612623662386f26fc100006011614af5565b8a11155b1561265257670de0b6b3a7640000662386f26fc100006126478983614b53565b610c7a906046614af5565b612664662386f26fc10000602f614af5565b89111580156126845750612680662386f26fc100006017614af5565b8a11155b156126af57670de0b6b3a7640000662386f26fc100006126a48983614b53565b611f22906008614af5565b6126c1662386f26fc100006030614af5565b89111580156126e157506126dd662386f26fc10000600b614af5565b8a11155b1561270157670de0b6b3a7640000662386f26fc100006118e58983614b53565b612713662386f26fc100006030614af5565b8911158015612733575061272f662386f26fc100006018614af5565b8a11155b1561275457670de0b6b3a7640000662386f26fc10000610c7a896014614af5565b612766662386f26fc100006031614af5565b89111580156127865750612782662386f26fc10000600f614af5565b8a11155b156127a657670de0b6b3a7640000662386f26fc10000610db98983614b53565b6127b8662386f26fc100006031614af5565b89111580156127d857506127d4662386f26fc100006019614af5565b8a11155b156127f857670de0b6b3a7640000662386f26fc100006118e58983614b53565b61280a662386f26fc100006031614af5565b891115801561282a5750612826662386f26fc100006021614af5565b8a11155b15612836575085612dd3565b612848662386f26fc100006032614af5565b89111580156128685750612864662386f26fc10000600a614af5565b8a11155b1561288857670de0b6b3a7640000662386f26fc10000610e738983614b53565b61289a662386f26fc100006032614af5565b89111580156128ba57506128b6662386f26fc100006011614af5565b8a11155b156128e557670de0b6b3a7640000662386f26fc100006128da8983614b53565b610c7a906023614af5565b6128f7662386f26fc100006032614af5565b89111580156129175750612913662386f26fc100006014614af5565b8a11155b1561292e5761188187670de0b6b3a7640000614b53565b612940662386f26fc100006032614af5565b8911158015612960575061295c662386f26fc100006019614af5565b8a11155b156129935761297787670de0b6b3a7640000614b53565b61298988670de0b6b3a7640000614b53565b61248e9089614b53565b6129a5662386f26fc100006033614af5565b89111580156129c557506129c1662386f26fc100006018614af5565b8a11155b156129d1575085612dd3565b6129e3662386f26fc100006034614af5565b8911158015612a0357506129ff662386f26fc10000600a614af5565b8a11155b15612a2e57670de0b6b3a7640000662386f26fc10000612a238983614b53565b611f22906023614af5565b612a40662386f26fc100006034614af5565b8911158015612a605750612a5c662386f26fc10000600f614af5565b8a11155b15612a8b57670de0b6b3a7640000662386f26fc10000612a808983614b53565b611f2290602d614af5565b612a9d662386f26fc100006034614af5565b8911158015612abd5750612ab9662386f26fc100006018614af5565b8a11155b15612add57670de0b6b3a7640000662386f26fc10000612a238983614b53565b612aef662386f26fc100006034614af5565b8911158015612b0e5750612b0b662386f26fc100006048614af5565b8a115b15612b2e57670de0b6b3a7640000662386f26fc10000612a238983614b53565b612b40662386f26fc100006035614af5565b8911158015612b605750612b5c662386f26fc100006018614af5565b8a11155b15612b8157670de0b6b3a7640000662386f26fc10000611f2289601e614af5565b612b93662386f26fc100006035614af5565b8911158015612bb35750612baf662386f26fc100006028614af5565b8a11155b15612bc75750670de0b6b3a7640000612dd3565b612bd9662386f26fc100006036614af5565b89108015612bf85750612bf4662386f26fc10000604a614af5565b8a10155b15612c0f5761188187670de0b6b3a7640000614b53565b612c21662386f26fc100006036614af5565b89108015612c405750612c3c662386f26fc10000603a614af5565b8a10155b15612c5757611d29662386f26fc10000600a614af5565b612c69662386f26fc100006036614af5565b89108015612c885750612c84662386f26fc100006018614af5565b8a10155b15612c9f5761188187670de0b6b3a7640000614b53565b612cb1662386f26fc100006036614af5565b89108015612ccf5750612ccc662386f26fc100006018614af5565b8a105b15612cef57670de0b6b3a7640000662386f26fc10000610db98983614b53565b612d01662386f26fc100006038614af5565b89108015612d205750612d1c662386f26fc100006052614af5565b8a10155b15612d4057670de0b6b3a7640000662386f26fc1000061206a8983614b53565b612d52662386f26fc100006038614af5565b89108015612d715750612d6d662386f26fc100006028614af5565b8a10155b15612d885761188187670de0b6b3a7640000614b53565b612d9a662386f26fc100006038614af5565b89108015612db95750612db5662386f26fc10000600a614af5565b8a10155b156111135761188187670de0b6b3a7640000614b53565b50855b8015612f40576000670de0b6b3a7640000612dee8b8d614af5565b612df89190614ae1565b90506000670de0b6b3a76400008381612e118186614af5565b612e1b9190614af5565b612e259190614ae1565b612e2f9190614ae1565b9050612e43662386f26fc10000600a614af5565b811015612ef157612e5c662386f26fc10000600a614af5565b8c1115612eb657670de0b6b3a7640000612e7e662386f26fc10000600a614af5565b670de0b6b3a7640000612e918186614af5565b612e9b9190614af5565b612ea59190614ae1565b612eaf9190614ae1565b9250612f3d565b670de0b6b3a764000080662386f26fc10000612ed38f600a614af5565b612edd9190614af5565b612ee79190614ae1565b612e7e908e614b53565b8b81118015612eff57508a8c105b15612f1557612eaf8b660e35fa931a0000614a9b565b8a81118015612f2457508b8b11155b15612f3d57612f3a8c660e35fa931a0000614a9b565b92505b50505b9650965096509692505050565b606080825167ffffffffffffffff811115612f7857634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015612fa1578160200160208202803683370190505b509150825167ffffffffffffffff811115612fcc57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015612ff5578160200160208202803683370190505b5090506000805b84518110156132ad5784818151811061302557634e487b7160e01b600052603260045260246000fd5b60200260200101519150816001600160a01b03166320822abc60006040518263ffffffff1660e01b815260040161305e91815260200190565b60206040518083038186803b15801561307657600080fd5b505afa15801561308a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130ae9190614826565b8482815181106130ce57634e487b7160e01b600052603260045260246000fd5b6020026020010181815250506001826001600160a01b03166344f2723f6040518163ffffffff1660e01b815260040160206040518083038186803b15801561311557600080fd5b505afa158015613129573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061314d9190614826565b116131595760006131d1565b6040516308208aaf60e21b8152600160048201526001600160a01b038316906320822abc9060240160206040518083038186803b15801561319957600080fd5b505afa1580156131ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131d19190614826565b8382815181106131f157634e487b7160e01b600052603260045260246000fd5b60200260200101818152505060005b8181101561329a5785818151811061322857634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b031686838151811061325957634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b031614156132885760405162461bcd60e51b8152600401610b319061496e565b8061329281614ba8565b915050613200565b50806132a581614ba8565b915050612ffc565b5050915091565b60608082600001515167ffffffffffffffff8111156132e357634e487b7160e01b600052604160045260246000fd5b60405190808252806020026020018201604052801561330c578160200160208202803683370190505b509150815167ffffffffffffffff81111561333757634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015613360578160200160208202803683370190505b5090506000815167ffffffffffffffff81111561338d57634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156133b6578160200160208202803683370190505b50905060005b8451518110156132ad5760005b818110156142cb5785518051839081106133f357634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b03168660000151828151811061342857634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b0316146142a15782818151811061345e57634e487b7160e01b600052603260045260246000fd5b60200260200101511580156134c857508560400151828151811061349257634e487b7160e01b600052603260045260246000fd5b6020026020010151866040015182815181106134be57634e487b7160e01b600052603260045260246000fd5b6020026020010151145b801561353457506000866060015183815181106134f557634e487b7160e01b600052603260045260246000fd5b60200260200101511180613534575060008660600151828151811061352a57634e487b7160e01b600052603260045260246000fd5b6020026020010151115b1561429c5760008660000151838151811061355f57634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b031663d03ecc646040518163ffffffff1660e01b815260040160206040518083038186803b15801561359f57600080fd5b505afa1580156135b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135d791906146a7565b90506000876000015183815181106135ff57634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b031663d03ecc646040518163ffffffff1660e01b815260040160206040518083038186803b15801561363f57600080fd5b505afa158015613653573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061367791906146a7565b905060008860600151848151811061369f57634e487b7160e01b600052603260045260246000fd5b60200260200101511180156136ee575087518051859081106136d157634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b0316816001600160a01b0316145b80613769575060008860600151858151811061371a57634e487b7160e01b600052603260045260246000fd5b60200260200101511180156137695750875180518490811061374c57634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b0316826001600160a01b0316145b806137f2575060008860600151858151811061379557634e487b7160e01b600052603260045260246000fd5b60200260200101511180156137d557506000886060015184815181106137cb57634e487b7160e01b600052603260045260246000fd5b6020026020010151115b80156137f25750806001600160a01b0316826001600160a01b0316145b1561429957600088608001516001600160a01b031663ec748e396040518060a001604052808c60400151898151811061383b57634e487b7160e01b600052603260045260246000fd5b602002602001015181526020018c60600151898151811061386c57634e487b7160e01b600052603260045260246000fd5b602002602001015181526020018c60600151888151811061389d57634e487b7160e01b600052603260045260246000fd5b602002602001015181526020018c6020015189815181106138ce57634e487b7160e01b600052603260045260246000fd5b602002602001015181526020018c6020015188815181106138ff57634e487b7160e01b600052603260045260246000fd5b602090810291909101810151909152604080516001600160e01b031960e086901b16815283516004820152918301516024830152820151604482015260608201516064820152608090910151608482015260a40160206040518083038186803b15801561396b57600080fd5b505afa15801561397f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139a39190614826565b905061271a896060015185815181106139cc57634e487b7160e01b600052603260045260246000fd5b6020026020010151148015613a0d575061271a89606001518681518110613a0357634e487b7160e01b600052603260045260246000fd5b6020026020010151145b15613b775788608001516001600160a01b031663a2abdac58a600001518781518110613a4957634e487b7160e01b600052603260045260246000fd5b60200260200101518b600001518781518110613a7557634e487b7160e01b600052603260045260246000fd5b60200260200101518c604001518981518110613aa157634e487b7160e01b600052603260045260246000fd5b60209081029190910101516040516001600160e01b031960e086901b1681526001600160a01b039384166004820152929091166024830152604482015260640160206040518083038186803b158015613af957600080fd5b505afa158015613b0d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b3191906146fe565b613b725760405162461bcd60e51b8152602060048201526012602482015271496e76616c6964506c6179657250726f707360701b6044820152606401610b31565b614297565b80613b945760405162461bcd60e51b8152600401610b319061496e565b6001868681518110613bb657634e487b7160e01b600052603260045260246000fd5b6020026020010190151590811515815250506001868581518110613bea57634e487b7160e01b600052603260045260246000fd5b602002602001019015159081151581525050600089606001518581518110613c2257634e487b7160e01b600052603260045260246000fd5b60200260200101511115613fac57613efc89608001516001600160a01b03166340c5336c8b600001518881518110613c6a57634e487b7160e01b600052603260045260246000fd5b60200260200101518c602001518981518110613c9657634e487b7160e01b600052603260045260246000fd5b60200260200101516040518363ffffffff1660e01b8152600401613ccf9291906001600160a01b03929092168252602082015260400190565b60206040518083038186803b158015613ce757600080fd5b505afa158015613cfb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d1f9190614826565b8a608001516001600160a01b03166340c5336c8c600001518881518110613d5657634e487b7160e01b600052603260045260246000fd5b60200260200101518d602001518981518110613d8257634e487b7160e01b600052603260045260246000fd5b60200260200101516040518363ffffffff1660e01b8152600401613dbb9291906001600160a01b03929092168252602082015260400190565b60206040518083038186803b158015613dd357600080fd5b505afa158015613de7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e0b9190614826565b8b602001518781518110613e2f57634e487b7160e01b600052603260045260246000fd5b6020026020010151848d608001516001600160a01b031663699c2c608f600001518b81518110613e6f57634e487b7160e01b600052603260045260246000fd5b60200260200101516040518263ffffffff1660e01b8152600401613ea291906001600160a01b0391909116815260200190565b60206040518083038186803b158015613eba57600080fd5b505afa158015613ece573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ef29190614826565b8e60a00151610b44565b8b8981518110613f1c57634e487b7160e01b600052603260045260246000fd5b602002602001018c8981518110613f4357634e487b7160e01b600052603260045260246000fd5b602002602001018c8b81518110613f6a57634e487b7160e01b600052603260045260246000fd5b602002602001018d8b81518110613f9157634e487b7160e01b600052603260045260246000fd5b60209081029190910101939093529290915291905252614297565b6141eb89608001516001600160a01b03166340c5336c8b600001518781518110613fe657634e487b7160e01b600052603260045260246000fd5b60200260200101518c60200151888151811061401257634e487b7160e01b600052603260045260246000fd5b60200260200101516040518363ffffffff1660e01b815260040161404b9291906001600160a01b03929092168252602082015260400190565b60206040518083038186803b15801561406357600080fd5b505afa158015614077573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061409b9190614826565b8a608001516001600160a01b03166340c5336c8c6000015189815181106140d257634e487b7160e01b600052603260045260246000fd5b60200260200101518d602001518a815181106140fe57634e487b7160e01b600052603260045260246000fd5b60200260200101516040518363ffffffff1660e01b81526004016141379291906001600160a01b03929092168252602082015260400190565b60206040518083038186803b15801561414f57600080fd5b505afa158015614163573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141879190614826565b8b6020015188815181106141ab57634e487b7160e01b600052603260045260246000fd5b6020026020010151848d608001516001600160a01b031663699c2c608f600001518c81518110613e6f57634e487b7160e01b600052603260045260246000fd5b8b888151811061420b57634e487b7160e01b600052603260045260246000fd5b602002602001018c8a8151811061423257634e487b7160e01b600052603260045260246000fd5b602002602001018c8a8151811061425957634e487b7160e01b600052603260045260246000fd5b602002602001018d8c8151811061428057634e487b7160e01b600052603260045260246000fd5b602090810291909101019390935292909152919052525b505b50505b6142b9565b60405162461bcd60e51b8152600401610b319061496e565b806142c381614ba8565b9150506133c9565b508381815181106142ec57634e487b7160e01b600052603260045260246000fd5b6020026020010151600014156144155784608001516001600160a01b03166340c5336c8660000151838151811061433357634e487b7160e01b600052603260045260246000fd5b60200260200101518760200151848151811061435f57634e487b7160e01b600052603260045260246000fd5b60200260200101516040518363ffffffff1660e01b81526004016143989291906001600160a01b03929092168252602082015260400190565b60206040518083038186803b1580156143b057600080fd5b505afa1580156143c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143e89190614826565b84828151811061440857634e487b7160e01b600052603260045260246000fd5b6020026020010181815250505b8061441f81614ba8565b9150506133bc565b6000600184511180156144ab5750816001600160a01b031663734131936040518163ffffffff1660e01b815260040160206040518083038186803b15801561446e57600080fd5b505afa158015614482573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144a69190614826565b845111155b156145bb576000826001600160a01b03166396f8af9c6144ca87610963565b6040518263ffffffff1660e01b81526004016144e891815260200190565b60206040518083038186803b15801561450057600080fd5b505afa158015614514573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145389190614826565b9050826001600160a01b031663182605676040518163ffffffff1660e01b815260040160206040518083038186803b15801561457357600080fd5b505afa158015614587573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145ab9190614826565b6145b58583614a9b565b11159150505b9392505050565b80356145cd81614bfa565b919050565b600082601f8301126145e2578081fd5b813560206145f76145f283614a36565b614a05565b80838252828201915082860187848660051b8901011115614616578586fd5b855b8581101561463d57813561462b81614bfa565b84529284019290840190600101614618565b5090979650505050505050565b600082601f83011261465a578081fd5b8135602061466a6145f283614a36565b80838252828201915082860187848660051b8901011115614689578586fd5b855b8581101561463d5781358452928401929084019060010161468b565b6000602082840312156146b8578081fd5b81516145bb81614bfa565b6000602082840312156146d4578081fd5b813567ffffffffffffffff8111156146ea578182fd5b6146f6848285016145d2565b949350505050565b60006020828403121561470f578081fd5b815180151581146145bb578182fd5b60006020828403121561472f578081fd5b813567ffffffffffffffff80821115614746578283fd5b90830190610100828603121561475a578283fd5b6147626149db565b823582811115614770578485fd5b61477c878286016145d2565b825250602083013582811115614790578485fd5b61479c8782860161464a565b60208301525060408301356040820152606083013560608201526080830135608082015260a0830135828111156147d1578485fd5b6147dd8782860161464a565b60a0830152506147ef60c084016145c2565b60c082015261480060e084016145c2565b60e082015295945050505050565b60006020828403121561481f578081fd5b5035919050565b600060208284031215614837578081fd5b5051919050565b60008060008060008060c08789031215614856578182fd5b505084359660208601359650604086013595606081013595506080810135945060a0013592509050565b6000815180845260208085019450808401835b838110156148af57815187529582019590820190600101614893565b509495945050505050565b815160009082906020808601845b838110156148ed5781516001600160a01b0316855293820193908201906001016148c8565b50929695505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561493a5783516001600160a01b031683529284019291840191600101614915565b50909695505050505050565b602081016003831061496857634e487b7160e01b600052602160045260246000fd5b91905290565b60208082526010908201526f53616d655465616d4f6e5061726c617960801b604082015260600190565b85815284602082015283604082015260a0606082015260006149bd60a0830185614880565b82810360808401526149cf8185614880565b98975050505050505050565b604051610100810167ffffffffffffffff811182821017156149ff576149ff614be4565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715614a2e57614a2e614be4565b604052919050565b600067ffffffffffffffff821115614a5057614a50614be4565b5060051b60200190565b600080821280156001600160ff1b0384900385131615614a7c57614a7c614bb8565b600160ff1b8390038412811615614a9557614a95614bb8565b50500190565b60008219821115614aae57614aae614bb8565b500190565b600082614ac257614ac2614bce565b600160ff1b821460001984141615614adc57614adc614bb8565b500590565b600082614af057614af0614bce565b500490565b6000816000190483118215151615614b0f57614b0f614bb8565b500290565b60008083128015600160ff1b850184121615614b3257614b32614bb8565b6001600160ff1b0384018313811615614b4d57614b4d614bb8565b50500390565b600082821015614b6557614b65614bb8565b500390565b6000600160ff1b821415614b8057614b80614bb8565b506000190190565b60006001600160ff1b03821415614ba157614ba1614bb8565b5060010190565b6000600019821415614ba157614ba15b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114614c0f57600080fd5b5056fea2646970667358221220f9750e08dd601d0f0ff7f687464571722e5b38f3b8f2dc83916441328137af8764736f6c63430008040033

Block Transaction Difficulty Gas Used Reward
Block Uncle Number Difficulty Gas Used Reward
Loading