false
true
0

Contract Address Details

0x06905DaD75b31274D0Fe526EC8289a6532265EC3

Contract Name
VestingMulticall
Creator
0xa8667e–664f18 at 0x1a03ac–050fd0
Balance
0 PLS ( )
Tokens
Fetching tokens...
Transactions
Fetching transactions...
Transfers
Fetching transfers...
Gas Used
Fetching gas used...
Last Balance Update
25855366
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
Contract name:
VestingMulticall




Optimization enabled
true
Compiler version
v0.8.20+commit.a1b79de6




Optimization runs
200
EVM Version
shanghai




Verified at
2026-01-18T07:41:28.818836Z

Constructor Arguments

0x0000000000000000000000006fabb568bb71041d92b4e541eb99eba3598c5a21

Arg [0] (address) : 0x6fabb568bb71041d92b4e541eb99eba3598c5a21

              

src/constants/contracts/viewcaVest.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

interface ICryptoForAll {
    function thisDay() external view returns (uint256);
    function vesting(
        address user,
        uint256 day
    )
        external
        view
        returns (
            uint256 vestTime,
            uint256 amount,
            uint256 claimed,
            uint256 lastUpdate,
            uint256 collected
        );
    function calcVestingEmission(
        address user,
        uint256 day
    ) external view returns (uint256);
    function readVestingEmission(
        address user,
        uint256 day
    ) external view returns (uint256);
    function auctionEntry_thatDay(uint256 day) external view returns (uint256);
    function buyBackAndBuildDone(uint256 day) external view returns (bool);
    function mapMemberAuction(
        address user,
        uint256 day
    )
        external
        view
        returns (uint256 memberAuctionValue, bool hasChangedShareToToken);
    function calculateTokenPerShareOnDay(
        uint256 day
    ) external view returns (uint256);
    function oneDay() external view returns (uint256);
    function auctionPeriod() external view returns (uint256);
}

contract VestingMulticall {
    // Combine related data to reduce stack variables
    struct VestingData {
        uint256 day;
        uint256 amount;
        uint256 claimed;
        uint256 vestTime;
        uint256 lastUpdate;
        uint256 collected;
        bool isValid;
    }

    struct UserVestingData {
        uint256 totalDays;
        VestingData[] vestingDetails;
    }

    struct AuctionData {
        uint256 day;
        uint256 userDeposit;
        uint256 totalDeposits;
        bool hasChangedShareToToken;
        bool buyBackAndBuildDone;
        uint256 tokenPerShare;
        uint256 pendingEmission;
    }

    address public owner;
    ICryptoForAll public cryptoForAll;

    modifier onlyOwner() {
        require(msg.sender == owner, "Not owner");
        _;
    }

    constructor(address _cryptoForAll) {
        owner = msg.sender;
        cryptoForAll = ICryptoForAll(_cryptoForAll);
    }

    function setCryptoForAll(address _cryptoForAll) external onlyOwner {
        cryptoForAll = ICryptoForAll(_cryptoForAll);
    }

    /**
     * @notice Get all vesting data for a user in a single call
     * @param user Address of the user
     * @param startDay First day to fetch (usually 1)
     * @param endDay Last day to fetch (can be current day)
     * @return A struct containing all vesting data for the specified days
     */
    function getUserVestingStats(
        address user,
        uint256 startDay,
        uint256 endDay
    ) external view returns (UserVestingData memory) {
        require(startDay > 0, "Start day must be greater than 0");

        // Limit end day to the current day
        uint256 currentDay = cryptoForAll.thisDay();
        if (endDay > currentDay) {
            endDay = currentDay;
        }

        // First pass: count valid entries
        uint256 validCount = 0;
        for (uint256 day = startDay; day <= endDay; day++) {
            (uint256 vestTime, , , , ) = cryptoForAll.vesting(user, day);
            if (vestTime > 0) {
                validCount++;
            }
        }

        // Create result with proper size
        UserVestingData memory userData = UserVestingData({
            totalDays: validCount,
            vestingDetails: new VestingData[](validCount)
        });

        // Only if we have valid entries, populate the array
        if (validCount > 0) {
            uint256 index = 0;
            for (
                uint256 day = startDay;
                day <= endDay && index < validCount;
                day++
            ) {
                (
                    uint256 vestTime,
                    uint256 amount,
                    uint256 claimed,
                    uint256 lastUpdate,
                    uint256 collected
                ) = cryptoForAll.vesting(user, day);

                if (vestTime > 0) {
                    // Split into two operations to reduce stack depth
                    userData.vestingDetails[index].day = day;
                    userData.vestingDetails[index].amount = amount;
                    userData.vestingDetails[index].claimed = cryptoForAll
                        .calcVestingEmission(user, day);
                    userData.vestingDetails[index].vestTime = vestTime;
                    userData.vestingDetails[index].lastUpdate = lastUpdate;
                    userData.vestingDetails[index].collected = collected;
                    userData.vestingDetails[index].isValid = true;

                    index++;
                }
            }
        }

        return userData;
    }

    /**
     * @notice Get vesting data for specific days (for pagination)
     * @param user Address of the user
     * @param _days Array of days to fetch data for
     * @return Array of VestingData for the specified days
     */
    function getVestingDataForDays(
        address user,
        uint256[] calldata _days
    ) external view returns (VestingData[] memory) {
        VestingData[] memory results = new VestingData[](_days.length);

        for (uint256 i = 0; i < _days.length; i++) {
            uint256 day = _days[i];
            // Get vesting data - split into multiple statements
            (
                uint256 vestTime,
                uint256 amount,
                uint256 claimed,
                uint256 lastUpdate,
                uint256 collected
            ) = cryptoForAll.vesting(user, day);

            // Populate data fields one by one to reduce stack usage
            results[i].day = day;
            results[i].amount = amount;
            results[i].vestTime = vestTime;
            results[i].lastUpdate = lastUpdate;
            results[i].collected = collected;
            results[i].isValid = vestTime > 0;

            // Only calculate emission if there's a valid vesting
            if (vestTime > 0) {
                results[i].claimed = cryptoForAll.calcVestingEmission(
                    user,
                    day
                );
            } else {
                results[i].claimed = 0;
            }
        }

        return results;
    }

    /**
     * @notice Get auction data for a user within a range of days
     * @param user Address of the user
     * @param startDay First day to fetch
     * @param endDay Last day to fetch
     * @return Array of AuctionData for the specified days
     */
    function getUserAuctionData(
        address user,
        uint256 startDay,
        uint256 endDay
    ) external view returns (AuctionData[] memory) {
        require(startDay > 0, "Start day must be greater than 0");

        // Validate input
        uint256 currentDay = cryptoForAll.thisDay();
        if (endDay > currentDay) {
            endDay = currentDay;
        }

        uint256 daysCount = endDay - startDay + 1;
        AuctionData[] memory auctionData = new AuctionData[](daysCount);

        // Process each day
        for (uint256 i = 0; i < daysCount; i++) {
            uint256 day = startDay + i;

            // Split data gathering into multiple statements
            (
                uint256 memberAuctionValue,
                bool hasChangedShareToToken
            ) = cryptoForAll.mapMemberAuction(user, day);

            // Populate data fields one by one
            auctionData[i].day = day;
            auctionData[i].userDeposit = memberAuctionValue;
            auctionData[i].totalDeposits = cryptoForAll.auctionEntry_thatDay(
                day
            );
            auctionData[i].hasChangedShareToToken = hasChangedShareToToken;
            auctionData[i].buyBackAndBuildDone = cryptoForAll
                .buyBackAndBuildDone(day);
            auctionData[i].tokenPerShare = cryptoForAll
                .calculateTokenPerShareOnDay(day);

            // Only calculate emission if shares were changed to tokens
            if (hasChangedShareToToken) {
                auctionData[i].pendingEmission = cryptoForAll
                    .calcVestingEmission(user, day);
            } else {
                auctionData[i].pendingEmission = 0;
            }
        }

        return auctionData;
    }

    /**
     * @notice Get the current vesting day
     * @return Current day from the CryptoForAll contract
     */
    function getCurrentDay() external view returns (uint256) {
        return cryptoForAll.thisDay();
    }

    /**
     * @notice Count how many valid vesting entries a user has
     * @param user Address of the user
     * @return Total count of valid vesting entries
     */
    function countUserVestingEntries(
        address user
    ) external view returns (uint256) {
        uint256 currentDay = cryptoForAll.thisDay();
        uint256 count = 0;

        for (uint256 day = 1; day <= currentDay; day++) {
            (uint256 vestTime, , , , ) = cryptoForAll.vesting(user, day);
            if (vestTime > 0) {
                count++;
            }
        }

        return count;
    }

    /**
     * @notice Get vesting data for a specific page (with pagination)
     * @param user Address of the user
     * @param pageSize Number of items per page
     * @param pageNumber Page number (starting from 1)
     * @return Array of VestingData for the specified page and total pages
     */
    function getVestingDataPaginated(
        address user,
        uint256 pageSize,
        uint256 pageNumber
    ) external view returns (VestingData[] memory, uint256) {
        require(pageNumber > 0, "Page number must be greater than 0");
        require(pageSize > 0, "Page size must be greater than 0");

        // First collect valid days (reducing local vars by using more memory)
        uint256[] memory validDays = _collectValidDays(user);
        uint256 validCount = 0;

        // Count valid days (separate loop to reduce stack)
        for (uint256 i = 0; i < validDays.length; i++) {
            if (validDays[i] > 0) validCount++;
            else break; // We stored days sequentially, so first 0 means end
        }

        // Early return if no data
        if (validCount == 0) {
            return (new VestingData[](0), 0);
        }

        // Calculate pagination parameters
        uint256 totalPages = (validCount + pageSize - 1) / pageSize; // Ceiling division
        pageNumber = pageNumber > totalPages ? totalPages : pageNumber;

        uint256 startIndex = (pageNumber - 1) * pageSize;
        uint256 itemsToFetch = pageSize;
        if (startIndex + itemsToFetch > validCount) {
            itemsToFetch = validCount - startIndex;
        }

        // Create and populate result
        VestingData[] memory results = new VestingData[](itemsToFetch);
        for (uint256 i = 0; i < itemsToFetch; i++) {
            _populateVestingData(results, i, user, validDays[startIndex + i]);
        }

        return (results, totalPages);
    }

    /**
     * @notice Helper function to collect valid days with vesting data
     * @param user User address to check
     * @return Array of day numbers with valid vesting data (0 means no data)
     */
    function _collectValidDays(
        address user
    ) private view returns (uint256[] memory) {
        uint256 currentDay = cryptoForAll.thisDay();
        uint256[] memory _days = new uint256[](currentDay);
        uint256 count = 0;

        for (uint256 day = 1; day <= currentDay; day++) {
            (uint256 vestTime, , , , ) = cryptoForAll.vesting(user, day);
            if (vestTime > 0) {
                _days[count] = day;
                count++;
            }
        }

        return _days;
    }

    /**
     * @notice Helper function to populate vesting data (reduces stack usage)
     * @param results Array to populate
     * @param index Index in the array
     * @param user User address
     * @param day Day to fetch data for
     */
    function _populateVestingData(
        VestingData[] memory results,
        uint256 index,
        address user,
        uint256 day
    ) private view {
        // Get vesting data
        (
            uint256 vestTime,
            uint256 amount,
            uint256 claimed,
            uint256 lastUpdate,
            uint256 collected
        ) = cryptoForAll.vesting(user, day);

        // Populate struct fields one by one
        results[index].day = day;
        results[index].amount = amount;
        results[index].vestTime = vestTime;
        results[index].lastUpdate = lastUpdate;
        results[index].collected = collected;
        results[index].isValid = true;
        results[index].claimed = cryptoForAll.calcVestingEmission(user, day);
    }

    /**
     * @notice Get important contract constants in a single call
     * @return oneDay Period of one day in seconds
     * @return auctionPeriod Total auction period in seconds
     * @return currentDay Current day number
     */
    function getContractConstants()
        external
        view
        returns (uint256 oneDay, uint256 auctionPeriod, uint256 currentDay)
    {
        return (
            cryptoForAll.oneDay(),
            cryptoForAll.auctionPeriod(),
            cryptoForAll.thisDay()
        );
    }
}
        

Compiler Settings

{"viaIR":true,"remappings":["forge-std/=lib/forge-std/src/"],"outputSelection":{"*":{"*":["*"],"":["*"]}},"optimizer":{"runs":200,"enabled":true},"metadata":{"useLiteralContent":false,"bytecodeHash":"ipfs","appendCBOR":true},"libraries":{},"evmVersion":"shanghai"}
              

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_cryptoForAll","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"countUserVestingEntries","inputs":[{"type":"address","name":"user","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract ICryptoForAll"}],"name":"cryptoForAll","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"oneDay","internalType":"uint256"},{"type":"uint256","name":"auctionPeriod","internalType":"uint256"},{"type":"uint256","name":"currentDay","internalType":"uint256"}],"name":"getContractConstants","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getCurrentDay","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple[]","name":"","internalType":"struct VestingMulticall.AuctionData[]","components":[{"type":"uint256","name":"day","internalType":"uint256"},{"type":"uint256","name":"userDeposit","internalType":"uint256"},{"type":"uint256","name":"totalDeposits","internalType":"uint256"},{"type":"bool","name":"hasChangedShareToToken","internalType":"bool"},{"type":"bool","name":"buyBackAndBuildDone","internalType":"bool"},{"type":"uint256","name":"tokenPerShare","internalType":"uint256"},{"type":"uint256","name":"pendingEmission","internalType":"uint256"}]}],"name":"getUserAuctionData","inputs":[{"type":"address","name":"user","internalType":"address"},{"type":"uint256","name":"startDay","internalType":"uint256"},{"type":"uint256","name":"endDay","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct VestingMulticall.UserVestingData","components":[{"type":"uint256","name":"totalDays","internalType":"uint256"},{"type":"tuple[]","name":"vestingDetails","internalType":"struct VestingMulticall.VestingData[]","components":[{"type":"uint256","name":"day","internalType":"uint256"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint256","name":"claimed","internalType":"uint256"},{"type":"uint256","name":"vestTime","internalType":"uint256"},{"type":"uint256","name":"lastUpdate","internalType":"uint256"},{"type":"uint256","name":"collected","internalType":"uint256"},{"type":"bool","name":"isValid","internalType":"bool"}]}]}],"name":"getUserVestingStats","inputs":[{"type":"address","name":"user","internalType":"address"},{"type":"uint256","name":"startDay","internalType":"uint256"},{"type":"uint256","name":"endDay","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple[]","name":"","internalType":"struct VestingMulticall.VestingData[]","components":[{"type":"uint256","name":"day","internalType":"uint256"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint256","name":"claimed","internalType":"uint256"},{"type":"uint256","name":"vestTime","internalType":"uint256"},{"type":"uint256","name":"lastUpdate","internalType":"uint256"},{"type":"uint256","name":"collected","internalType":"uint256"},{"type":"bool","name":"isValid","internalType":"bool"}]}],"name":"getVestingDataForDays","inputs":[{"type":"address","name":"user","internalType":"address"},{"type":"uint256[]","name":"_days","internalType":"uint256[]"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple[]","name":"","internalType":"struct VestingMulticall.VestingData[]","components":[{"type":"uint256","name":"day","internalType":"uint256"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint256","name":"claimed","internalType":"uint256"},{"type":"uint256","name":"vestTime","internalType":"uint256"},{"type":"uint256","name":"lastUpdate","internalType":"uint256"},{"type":"uint256","name":"collected","internalType":"uint256"},{"type":"bool","name":"isValid","internalType":"bool"}]},{"type":"uint256","name":"","internalType":"uint256"}],"name":"getVestingDataPaginated","inputs":[{"type":"address","name":"user","internalType":"address"},{"type":"uint256","name":"pageSize","internalType":"uint256"},{"type":"uint256","name":"pageNumber","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setCryptoForAll","inputs":[{"type":"address","name":"_cryptoForAll","internalType":"address"}]}]
              

Contract Creation Code

0x60803461007857601f61168b38819003918201601f19168301916001600160401b0383118484101761007c5780849260209460405283398101031261007857516001600160a01b038116908190036100785760018060a01b031933815f5416175f5560015416176001556040516115fa90816100918239f35b5f80fd5b634e487b7160e01b5f52604160045260245ffdfe6080806040526004361015610012575f80fd5b60e05f35811c9182633c11abb414610d56575081633e6968b614610cd65781634844e11014610c5b57816351c1e94d146107fe5750806355ab7b45146105f15780638da5cb5b146105ca5780638e98465e14610498578063ad6f2efe14610470578063e6bfd81f146104385763e7b4a0731461008c575f80fd5b3461030f5761009a36610e81565b91908290606060206040516100ae81610f30565b5f815201526100be811515610f82565b60015460405163bf627bf560e01b81526001600160a01b039091169490602081600481895afa90811561031b575f91610406575b508091116103fe575b505f93815b83811115610377575061011285611062565b946040519561012087610f30565b818752602087015280610190575b50505050506040518091602082526020606083019180518285015201519060408084015281518091526020608084019201905f5b818110610170575050500390f35b9193509160206101836001928651610eab565b9401910191849392610162565b5f9592939495935b858111158061036e575b1561035d5760405163143ee5b960e01b81526001600160a01b03881660048201526024810182905260a081604481875afa801561031b575f915f80915f93610326575b50836101fe575b505050506101f990610fcd565b610198565b846102118a60208b9c97989c01516110b1565b5152602061022285828b01516110b1565b510152604051638f10aca760e01b81526001600160a01b038b166004820152602481018990526020816044818a5afa90811561031b575f916102db575b50906101f994849392604061027b6102d19760208d01516110b1565b510152606061028e8560208c01516110b1565b51015260806102a18460208b01516110b1565b51015260a06102b48360208a01516110b1565b510152600160c06102c98360208a01516110b1565b510152610fcd565b94905f80806101ec565b93929190506020843d602011610313575b816102f960209383610f60565b8101031261030f579251919290916101f961025f565b5f80fd5b3d91506102ec565b6040513d5f823e3d90fd5b9250505061034c915060a03d60a011610356575b6103448183610f60565b810190610fdb565b915090915f6101e5565b503d61033a565b505050925050505f8080808061012e565b508185106101a2565b60405163143ee5b960e01b81526001600160a01b03861660048201526024810182905260a0908181604481875afa91821561031b575f926103dd575b50506103c8575b6103c390610fcd565b610100565b946103d56103c391610fcd565b9590506103ba565b6103f39250803d10610356576103448183610f60565b505050505f806103b3565b91505f6100fb565b90506020813d602011610430575b8161042160209383610f60565b8101031261030f57515f6100f2565b3d9150610414565b3461030f5761046661045261044c36610e81565b91611100565b604051928392604084526040840190610ef4565b9060208301520390f35b3461030f575f36600319011261030f576001546040516001600160a01b039091168152602090f35b3461030f575f36600319011261030f57600154604051634bd9351b60e01b81526001600160a01b039091169060208082600481865afa91821561031b575f9261059b575b506040516301999f8b60e31b8152928184600481845afa93841561031b575f9461056c575b5092816004946040519586809263bf627bf560e01b82525afa91821561031b575f9261053c575b606094506040519384528301526040820152f35b80925084813d8311610565575b6105538183610f60565b8101031261030f576060935191610528565b503d610549565b93508184813d8311610594575b6105838183610f60565b8101031261030f5792519281610501565b503d610579565b9080925081813d83116105c3575b6105b38183610f60565b8101031261030f575190836104dc565b503d6105a9565b3461030f575f36600319011261030f575f546040516001600160a01b039091168152602090f35b3461030f57604036600319011261030f5761060a610e6b565b602480359067ffffffffffffffff80831161030f573660238401121561030f57826004013590811161030f57600591368183851b8601011161030f57610651829392611062565b60015490946001600160a01b03909116925f5b85811061068557604051602080825281906106819082018a610ef4565b0390f35b60405163143ee5b960e01b81526001600160a01b038916600482015281831b840185013560248201819052919060a080826044818b5afa801561031b575f915f93858d5f925f956107c7575b5081818a6106e460809561070c956110b1565b5152602098896106f484846110b1565b51015287606061070484846110b1565b5101526110b1565b510152610719858d6110b1565b51015215158060c061072b858d6110b1565b510152156107b457604051638f10aca760e01b81526001600160a01b038b166004820152602481019390935280836044818a5afa90811561031b575f91610784575b5061077f925060406102c9838b6110b1565b610664565b905082813d83116107ad575b61079a8183610f60565b8101031261030f5761077f91518a61076d565b503d610790565b5061077f91505f60406102c9838b6110b1565b90945061070c96506107eb91955060809250833d8511610356576103448183610f60565b92985092969195929391929190506106d1565b3461030f5761080c36610e81565b929091908361081c841515610f82565b60019260018060a01b038454169160405163bf627bf560e01b81526020978882600481885afa801561031b5788925f91610c26575b50806108639411610c1e575b506110d9565b91848301809311610c0a5761087b8397969597611002565b946108896040519687610f60565b838652601f1961089885611002565b015f5b818110610bed5750505f5b84811061093457505050505060405193838594850190808652845180925280604087019501935f905b8382106108dc5787870388f35b85518051885280840151888501526040808201519089015260608082015115159089015260808082015115159089015260a0808201519089015260c090810151908801528897509586019594820194908401906108cf565b61094281839a98999a6110e6565b6040805163262cffef60e11b81526001600160a01b0387166004820152602481018390529192919081604481885afa90811561031b575f905f92610bad575b508361098d848d6110b1565b51528b61099a848d6110b1565b510152604051635ccbff4160e11b815260048101849052602491908c8184818a5afa90811561031b578c85915f93610b7b575b506040916109da916110b1565b51015260606109e9848d6110b1565b51821515910152604051631585119960e01b8152600481018590528c8184818a5afa90811561031b578c85915f93610b3a575b50608091610a29916110b1565b510190151590528b6040518093633a52bedd60e01b825286600483015281895afa801561031b57838c8e945f93610b04575b5060a091610a68916110b1565b51015215610af157604051638f10aca760e01b81526001600160a01b0387166004820152602481019390935282604481875afa801561031b575f90610ac2575b610ab9925060c06102c9838c6110b1565b979695976108a6565b508982813d8311610aea575b610ad88183610f60565b8101031261030f57610ab99151610aa8565b503d610ace565b50610ab991505f60c06102c9838c6110b1565b949250505082813d8311610b33575b610b1d8183610f60565b8101031261030f5790518b9190838c60a0610a5b565b503d610b13565b925050508c81813d8311610b74575b610b538183610f60565b8101031261030f576080610a2985610b6b8f946110f3565b93915091610a1c565b503d610b49565b925050508c81813d8311610ba6575b610b948183610f60565b8101031261030f5751838c60406109cd565b503d610b8a565b9150506040813d604011610be5575b81610bc960409383610f60565b8101031261030f57610bde8b825192016110f3565b908c610981565b3d9150610bbc565b9780999798610bfa61101a565b82828c010152019897969861089b565b634e487b7160e01b5f52601160045260245ffd5b90508961085d565b8093508a8092503d8311610c54575b610c3f8183610f60565b8101031261030f579051879190610863610851565b503d610c35565b3461030f57602036600319011261030f57610c74610e6b565b5f546001600160a01b03919082163303610ca557166bffffffffffffffffffffffff60a01b60015416176001555f80f35b60405162461bcd60e51b81526020600482015260096024820152682737ba1037bbb732b960b91b6044820152606490fd5b3461030f575f36600319011261030f5760015460405163bf627bf560e01b815290602090829060049082906001600160a01b03165afa801561031b575f90610d24575b602090604051908152f35b506020813d8211610d4e575b81610d3d60209383610f60565b8101031261030f5760209051610d19565b3d9150610d30565b3461030f5760208060031936011261030f57610d70610e6b565b60015463bf627bf560e01b84526001600160a01b03168284600481845afa93841561031b575f94610e3c575b505f9160015b85811115610db557505050604051908152f35b60405163143ee5b960e01b81526001600160a01b03831660048201526024810182905260a0908181604481885afa91821561031b575f92610e1b575b5050610e06575b610e0190610fcd565b610da2565b92610e13610e0191610fcd565b939050610df8565b610e319250803d10610356576103448183610f60565b505050508780610df1565b9093508281813d8311610e64575b610e548183610f60565b8101031261030f57519284610d9c565b503d610e4a565b600435906001600160a01b038216820361030f57565b606090600319011261030f576004356001600160a01b038116810361030f57906024359060443590565b9060c060e092805183526020810151602084015260408101516040840152606081015160608401526080810151608084015260a081015160a08401520151151560c08201520190565b9081518082526020808093019301915f5b828110610f13575050505090565b9091929382610f256001928751610eab565b950193929101610f05565b6040810190811067ffffffffffffffff821117610f4c57604052565b634e487b7160e01b5f52604160045260245ffd5b90601f8019910116810190811067ffffffffffffffff821117610f4c57604052565b15610f8957565b606460405162461bcd60e51b815260206004820152602060248201527f537461727420646179206d7573742062652067726561746572207468616e20306044820152fd5b5f198114610c0a5760010190565b908160a091031261030f578051916020820151916040810151916080606083015192015190565b67ffffffffffffffff8111610f4c5760051b60200190565b6040519060e0820182811067ffffffffffffffff821117610f4c576040528160c05f918281528260208201528260408201528260608201528260808201528260a08201520152565b9061106c82611002565b6110796040519182610f60565b828152809261108a601f1991611002565b01905f5b82811061109a57505050565b6020906110a561101a565b8282850101520161108e565b80518210156110c55760209160051b010190565b634e487b7160e01b5f52603260045260245ffd5b91908203918211610c0a57565b91908201809211610c0a57565b5190811515820361030f57565b90929192831561157457801561153057600180546040805163bf627bf560e01b81529460209391926001600160a01b031690600485888281865afa978815611526575f986114f7575b5061115388611002565b976111608651998a610f60565b808952601f1961116f82611002565b0136888b01375f855b8281111561144d575050505f978489905b611414575b5088156113d35761119f888a6110e6565b5f1999908a81019081116113c0578990049b8c8111156113ba57508b995b8a01998a116113a757888a0299808b048a14901517156113a757808a916111e48b846110e6565b11611394575b50506111f588611062565b985f5b89811061120d57505050505050505050509190565b61122061121a82846110e6565b846110b1565b51885163143ee5b960e01b81526001600160a01b0387168682019081526020810183905260a09081908390819060400103818c5afa91821561138a5760c08f868f95916112be928f95966112f299975f8081928295611361575b508a61128688886110b1565b51528b61129388886110b1565b51015260606112a287876110b1565b51015260806112b186866110b1565b51015261070484846110b1565b5101528a51638f10aca760e01b81526001600160a01b03891688820190815260208101929092529283918291604090910190565b03818a5afa9081156113575790898d93925f9261131d575b506102c983611318956110b1565b6111f8565b809394508c8092503d8311611350575b6113378183610f60565b8101031261134d5750518b9190896102c961130a565b80fd5b503d61132d565b89513d5f823e3d90fd5b925050508161137d9293503d8411610356576103448183610f60565b949390929091505f61127a565b8b513d5f823e3d90fd5b61139f9299506110d9565b96885f6111ea565b601183634e487b7160e01b5f525260245ffd5b996111bd565b601184634e487b7160e01b5f525260245ffd5b509650505050915092935080519283019183831067ffffffffffffffff8411176114015750525f8152905f90565b604190634e487b7160e01b5f525260245ffd5b9881518a1015611447576114288a836110b1565b51156114475761144161143b8792610fcd565b9a610fcd565b90611189565b9861118e565b875163143ee5b960e01b81526001600160a01b0386168582019081526020810183905260a0919082908290819060400103818b5afa9182156114ed57908d92915f926114cc575b50506114aa575b506114a590610fcd565b611178565b82826114bd6114a594956114c3946110b1565b52610fcd565b9190508a61149b565b6114e29250803d10610356576103448183610f60565b505050505f80611494565b8a513d5f823e3d90fd5b90978682813d831161151f575b61150e8183610f60565b8101031261134d575051965f611149565b503d611504565b85513d5f823e3d90fd5b606460405162461bcd60e51b815260206004820152602060248201527f506167652073697a65206d7573742062652067726561746572207468616e20306044820152fd5b60405162461bcd60e51b815260206004820152602260248201527f50616765206e756d626572206d7573742062652067726561746572207468616e604482015261020360f41b6064820152608490fdfea26469706673582212206f898f816534106cbcb8062f454279cb0e0753fa590028aa359b3ab4dc3cf26d64736f6c634300081400330000000000000000000000006fabb568bb71041d92b4e541eb99eba3598c5a21

Deployed ByteCode

0x6080806040526004361015610012575f80fd5b60e05f35811c9182633c11abb414610d56575081633e6968b614610cd65781634844e11014610c5b57816351c1e94d146107fe5750806355ab7b45146105f15780638da5cb5b146105ca5780638e98465e14610498578063ad6f2efe14610470578063e6bfd81f146104385763e7b4a0731461008c575f80fd5b3461030f5761009a36610e81565b91908290606060206040516100ae81610f30565b5f815201526100be811515610f82565b60015460405163bf627bf560e01b81526001600160a01b039091169490602081600481895afa90811561031b575f91610406575b508091116103fe575b505f93815b83811115610377575061011285611062565b946040519561012087610f30565b818752602087015280610190575b50505050506040518091602082526020606083019180518285015201519060408084015281518091526020608084019201905f5b818110610170575050500390f35b9193509160206101836001928651610eab565b9401910191849392610162565b5f9592939495935b858111158061036e575b1561035d5760405163143ee5b960e01b81526001600160a01b03881660048201526024810182905260a081604481875afa801561031b575f915f80915f93610326575b50836101fe575b505050506101f990610fcd565b610198565b846102118a60208b9c97989c01516110b1565b5152602061022285828b01516110b1565b510152604051638f10aca760e01b81526001600160a01b038b166004820152602481018990526020816044818a5afa90811561031b575f916102db575b50906101f994849392604061027b6102d19760208d01516110b1565b510152606061028e8560208c01516110b1565b51015260806102a18460208b01516110b1565b51015260a06102b48360208a01516110b1565b510152600160c06102c98360208a01516110b1565b510152610fcd565b94905f80806101ec565b93929190506020843d602011610313575b816102f960209383610f60565b8101031261030f579251919290916101f961025f565b5f80fd5b3d91506102ec565b6040513d5f823e3d90fd5b9250505061034c915060a03d60a011610356575b6103448183610f60565b810190610fdb565b915090915f6101e5565b503d61033a565b505050925050505f8080808061012e565b508185106101a2565b60405163143ee5b960e01b81526001600160a01b03861660048201526024810182905260a0908181604481875afa91821561031b575f926103dd575b50506103c8575b6103c390610fcd565b610100565b946103d56103c391610fcd565b9590506103ba565b6103f39250803d10610356576103448183610f60565b505050505f806103b3565b91505f6100fb565b90506020813d602011610430575b8161042160209383610f60565b8101031261030f57515f6100f2565b3d9150610414565b3461030f5761046661045261044c36610e81565b91611100565b604051928392604084526040840190610ef4565b9060208301520390f35b3461030f575f36600319011261030f576001546040516001600160a01b039091168152602090f35b3461030f575f36600319011261030f57600154604051634bd9351b60e01b81526001600160a01b039091169060208082600481865afa91821561031b575f9261059b575b506040516301999f8b60e31b8152928184600481845afa93841561031b575f9461056c575b5092816004946040519586809263bf627bf560e01b82525afa91821561031b575f9261053c575b606094506040519384528301526040820152f35b80925084813d8311610565575b6105538183610f60565b8101031261030f576060935191610528565b503d610549565b93508184813d8311610594575b6105838183610f60565b8101031261030f5792519281610501565b503d610579565b9080925081813d83116105c3575b6105b38183610f60565b8101031261030f575190836104dc565b503d6105a9565b3461030f575f36600319011261030f575f546040516001600160a01b039091168152602090f35b3461030f57604036600319011261030f5761060a610e6b565b602480359067ffffffffffffffff80831161030f573660238401121561030f57826004013590811161030f57600591368183851b8601011161030f57610651829392611062565b60015490946001600160a01b03909116925f5b85811061068557604051602080825281906106819082018a610ef4565b0390f35b60405163143ee5b960e01b81526001600160a01b038916600482015281831b840185013560248201819052919060a080826044818b5afa801561031b575f915f93858d5f925f956107c7575b5081818a6106e460809561070c956110b1565b5152602098896106f484846110b1565b51015287606061070484846110b1565b5101526110b1565b510152610719858d6110b1565b51015215158060c061072b858d6110b1565b510152156107b457604051638f10aca760e01b81526001600160a01b038b166004820152602481019390935280836044818a5afa90811561031b575f91610784575b5061077f925060406102c9838b6110b1565b610664565b905082813d83116107ad575b61079a8183610f60565b8101031261030f5761077f91518a61076d565b503d610790565b5061077f91505f60406102c9838b6110b1565b90945061070c96506107eb91955060809250833d8511610356576103448183610f60565b92985092969195929391929190506106d1565b3461030f5761080c36610e81565b929091908361081c841515610f82565b60019260018060a01b038454169160405163bf627bf560e01b81526020978882600481885afa801561031b5788925f91610c26575b50806108639411610c1e575b506110d9565b91848301809311610c0a5761087b8397969597611002565b946108896040519687610f60565b838652601f1961089885611002565b015f5b818110610bed5750505f5b84811061093457505050505060405193838594850190808652845180925280604087019501935f905b8382106108dc5787870388f35b85518051885280840151888501526040808201519089015260608082015115159089015260808082015115159089015260a0808201519089015260c090810151908801528897509586019594820194908401906108cf565b61094281839a98999a6110e6565b6040805163262cffef60e11b81526001600160a01b0387166004820152602481018390529192919081604481885afa90811561031b575f905f92610bad575b508361098d848d6110b1565b51528b61099a848d6110b1565b510152604051635ccbff4160e11b815260048101849052602491908c8184818a5afa90811561031b578c85915f93610b7b575b506040916109da916110b1565b51015260606109e9848d6110b1565b51821515910152604051631585119960e01b8152600481018590528c8184818a5afa90811561031b578c85915f93610b3a575b50608091610a29916110b1565b510190151590528b6040518093633a52bedd60e01b825286600483015281895afa801561031b57838c8e945f93610b04575b5060a091610a68916110b1565b51015215610af157604051638f10aca760e01b81526001600160a01b0387166004820152602481019390935282604481875afa801561031b575f90610ac2575b610ab9925060c06102c9838c6110b1565b979695976108a6565b508982813d8311610aea575b610ad88183610f60565b8101031261030f57610ab99151610aa8565b503d610ace565b50610ab991505f60c06102c9838c6110b1565b949250505082813d8311610b33575b610b1d8183610f60565b8101031261030f5790518b9190838c60a0610a5b565b503d610b13565b925050508c81813d8311610b74575b610b538183610f60565b8101031261030f576080610a2985610b6b8f946110f3565b93915091610a1c565b503d610b49565b925050508c81813d8311610ba6575b610b948183610f60565b8101031261030f5751838c60406109cd565b503d610b8a565b9150506040813d604011610be5575b81610bc960409383610f60565b8101031261030f57610bde8b825192016110f3565b908c610981565b3d9150610bbc565b9780999798610bfa61101a565b82828c010152019897969861089b565b634e487b7160e01b5f52601160045260245ffd5b90508961085d565b8093508a8092503d8311610c54575b610c3f8183610f60565b8101031261030f579051879190610863610851565b503d610c35565b3461030f57602036600319011261030f57610c74610e6b565b5f546001600160a01b03919082163303610ca557166bffffffffffffffffffffffff60a01b60015416176001555f80f35b60405162461bcd60e51b81526020600482015260096024820152682737ba1037bbb732b960b91b6044820152606490fd5b3461030f575f36600319011261030f5760015460405163bf627bf560e01b815290602090829060049082906001600160a01b03165afa801561031b575f90610d24575b602090604051908152f35b506020813d8211610d4e575b81610d3d60209383610f60565b8101031261030f5760209051610d19565b3d9150610d30565b3461030f5760208060031936011261030f57610d70610e6b565b60015463bf627bf560e01b84526001600160a01b03168284600481845afa93841561031b575f94610e3c575b505f9160015b85811115610db557505050604051908152f35b60405163143ee5b960e01b81526001600160a01b03831660048201526024810182905260a0908181604481885afa91821561031b575f92610e1b575b5050610e06575b610e0190610fcd565b610da2565b92610e13610e0191610fcd565b939050610df8565b610e319250803d10610356576103448183610f60565b505050508780610df1565b9093508281813d8311610e64575b610e548183610f60565b8101031261030f57519284610d9c565b503d610e4a565b600435906001600160a01b038216820361030f57565b606090600319011261030f576004356001600160a01b038116810361030f57906024359060443590565b9060c060e092805183526020810151602084015260408101516040840152606081015160608401526080810151608084015260a081015160a08401520151151560c08201520190565b9081518082526020808093019301915f5b828110610f13575050505090565b9091929382610f256001928751610eab565b950193929101610f05565b6040810190811067ffffffffffffffff821117610f4c57604052565b634e487b7160e01b5f52604160045260245ffd5b90601f8019910116810190811067ffffffffffffffff821117610f4c57604052565b15610f8957565b606460405162461bcd60e51b815260206004820152602060248201527f537461727420646179206d7573742062652067726561746572207468616e20306044820152fd5b5f198114610c0a5760010190565b908160a091031261030f578051916020820151916040810151916080606083015192015190565b67ffffffffffffffff8111610f4c5760051b60200190565b6040519060e0820182811067ffffffffffffffff821117610f4c576040528160c05f918281528260208201528260408201528260608201528260808201528260a08201520152565b9061106c82611002565b6110796040519182610f60565b828152809261108a601f1991611002565b01905f5b82811061109a57505050565b6020906110a561101a565b8282850101520161108e565b80518210156110c55760209160051b010190565b634e487b7160e01b5f52603260045260245ffd5b91908203918211610c0a57565b91908201809211610c0a57565b5190811515820361030f57565b90929192831561157457801561153057600180546040805163bf627bf560e01b81529460209391926001600160a01b031690600485888281865afa978815611526575f986114f7575b5061115388611002565b976111608651998a610f60565b808952601f1961116f82611002565b0136888b01375f855b8281111561144d575050505f978489905b611414575b5088156113d35761119f888a6110e6565b5f1999908a81019081116113c0578990049b8c8111156113ba57508b995b8a01998a116113a757888a0299808b048a14901517156113a757808a916111e48b846110e6565b11611394575b50506111f588611062565b985f5b89811061120d57505050505050505050509190565b61122061121a82846110e6565b846110b1565b51885163143ee5b960e01b81526001600160a01b0387168682019081526020810183905260a09081908390819060400103818c5afa91821561138a5760c08f868f95916112be928f95966112f299975f8081928295611361575b508a61128688886110b1565b51528b61129388886110b1565b51015260606112a287876110b1565b51015260806112b186866110b1565b51015261070484846110b1565b5101528a51638f10aca760e01b81526001600160a01b03891688820190815260208101929092529283918291604090910190565b03818a5afa9081156113575790898d93925f9261131d575b506102c983611318956110b1565b6111f8565b809394508c8092503d8311611350575b6113378183610f60565b8101031261134d5750518b9190896102c961130a565b80fd5b503d61132d565b89513d5f823e3d90fd5b925050508161137d9293503d8411610356576103448183610f60565b949390929091505f61127a565b8b513d5f823e3d90fd5b61139f9299506110d9565b96885f6111ea565b601183634e487b7160e01b5f525260245ffd5b996111bd565b601184634e487b7160e01b5f525260245ffd5b509650505050915092935080519283019183831067ffffffffffffffff8411176114015750525f8152905f90565b604190634e487b7160e01b5f525260245ffd5b9881518a1015611447576114288a836110b1565b51156114475761144161143b8792610fcd565b9a610fcd565b90611189565b9861118e565b875163143ee5b960e01b81526001600160a01b0386168582019081526020810183905260a0919082908290819060400103818b5afa9182156114ed57908d92915f926114cc575b50506114aa575b506114a590610fcd565b611178565b82826114bd6114a594956114c3946110b1565b52610fcd565b9190508a61149b565b6114e29250803d10610356576103448183610f60565b505050505f80611494565b8a513d5f823e3d90fd5b90978682813d831161151f575b61150e8183610f60565b8101031261134d575051965f611149565b503d611504565b85513d5f823e3d90fd5b606460405162461bcd60e51b815260206004820152602060248201527f506167652073697a65206d7573742062652067726561746572207468616e20306044820152fd5b60405162461bcd60e51b815260206004820152602260248201527f50616765206e756d626572206d7573742062652067726561746572207468616e604482015261020360f41b6064820152608490fdfea26469706673582212206f898f816534106cbcb8062f454279cb0e0753fa590028aa359b3ab4dc3cf26d64736f6c63430008140033