BNB Price: $696.41 (-2.23%)
Gas: 1 GWei
 

Overview

BNB Balance

BNB Smart Chain LogoBNB Smart Chain LogoBNB Smart Chain Logo259.272764517740386609 BNB

BNB Value

$180,559.09 (@ $696.41/BNB)

Token Holdings

More Info

Private Name Tags

ContractCreator

GENESIS at txn GENESIS_0000000000000000000000000000000000001000

Multichain Info

Transaction Hash
Method
Block
From
To
Deposit453250692024-12-30 10:59:107 secs ago1735556350IN
BSC: Validator Set
0.02009337 BNB00
Deposit453250682024-12-30 10:59:0710 secs ago1735556347IN
BSC: Validator Set
0.01645475 BNB00
Deposit453250672024-12-30 10:59:0413 secs ago1735556344IN
BSC: Validator Set
0.0155492 BNB00
Deposit453250662024-12-30 10:59:0116 secs ago1735556341IN
BSC: Validator Set
0.01681084 BNB00
Deposit453250652024-12-30 10:58:5819 secs ago1735556338IN
BSC: Validator Set
0.02052249 BNB00
Deposit453250642024-12-30 10:58:5522 secs ago1735556335IN
BSC: Validator Set
0.01908659 BNB00
Deposit453250632024-12-30 10:58:5225 secs ago1735556332IN
BSC: Validator Set
0.02135745 BNB00
Deposit453250622024-12-30 10:58:4928 secs ago1735556329IN
BSC: Validator Set
0.01942206 BNB00
Deposit453250612024-12-30 10:58:4631 secs ago1735556326IN
BSC: Validator Set
0.01332149 BNB00
Deposit453250602024-12-30 10:58:4334 secs ago1735556323IN
BSC: Validator Set
0.01826178 BNB00
Deposit453250592024-12-30 10:58:4037 secs ago1735556320IN
BSC: Validator Set
0.02124022 BNB00
Deposit453250582024-12-30 10:58:3740 secs ago1735556317IN
BSC: Validator Set
0.01990376 BNB00
Deposit453250572024-12-30 10:58:3443 secs ago1735556314IN
BSC: Validator Set
0.01694823 BNB00
Deposit453250562024-12-30 10:58:3146 secs ago1735556311IN
BSC: Validator Set
0.02777693 BNB00
Deposit453250552024-12-30 10:58:2849 secs ago1735556308IN
BSC: Validator Set
0.02150812 BNB00
Deposit453250542024-12-30 10:58:2552 secs ago1735556305IN
BSC: Validator Set
0.01603294 BNB00
Deposit453250532024-12-30 10:58:2255 secs ago1735556302IN
BSC: Validator Set
0.01710958 BNB00
Deposit453250522024-12-30 10:58:1958 secs ago1735556299IN
BSC: Validator Set
0.01498764 BNB00
Deposit453250512024-12-30 10:58:161 min ago1735556296IN
BSC: Validator Set
0.0196872 BNB00
Deposit453250502024-12-30 10:58:131 min ago1735556293IN
BSC: Validator Set
0.01492721 BNB00
Deposit453250492024-12-30 10:58:101 min ago1735556290IN
BSC: Validator Set
0.01564162 BNB00
Deposit453250482024-12-30 10:58:071 min ago1735556287IN
BSC: Validator Set
0.02442585 BNB00
Deposit453250472024-12-30 10:58:041 min ago1735556284IN
BSC: Validator Set
0.02111183 BNB00
Deposit453250462024-12-30 10:58:011 min ago1735556281IN
BSC: Validator Set
0.01535476 BNB00
Deposit453250452024-12-30 10:57:581 min ago1735556278IN
BSC: Validator Set
0.01337155 BNB00
View all transactions

Latest 25 internal transactions (View All)

Parent Transaction Hash Block From To
453250652024-12-30 10:58:5819 secs ago1735556338
BSC: Validator Set
0.00205224 BNB
453250652024-12-30 10:58:5819 secs ago1735556338
BSC: Validator Set
0.00128265 BNB
453250642024-12-30 10:58:5522 secs ago1735556335
BSC: Validator Set
0.00190865 BNB
453250642024-12-30 10:58:5522 secs ago1735556335
BSC: Validator Set
0.00119291 BNB
453250632024-12-30 10:58:5225 secs ago1735556332
BSC: Validator Set
0.00213574 BNB
453250632024-12-30 10:58:5225 secs ago1735556332
BSC: Validator Set
0.00133484 BNB
453250622024-12-30 10:58:4928 secs ago1735556329
BSC: Validator Set
0.0019422 BNB
453250622024-12-30 10:58:4928 secs ago1735556329
BSC: Validator Set
0.00121387 BNB
453250612024-12-30 10:58:4631 secs ago1735556326
BSC: Validator Set
0.00133214 BNB
453250612024-12-30 10:58:4631 secs ago1735556326
BSC: Validator Set
0.00083259 BNB
453250602024-12-30 10:58:4334 secs ago1735556323
BSC: Validator Set
0.00182617 BNB
453250602024-12-30 10:58:4334 secs ago1735556323
BSC: Validator Set
0.00114136 BNB
453250592024-12-30 10:58:4037 secs ago1735556320
BSC: Validator Set
0.00212402 BNB
453250592024-12-30 10:58:4037 secs ago1735556320
BSC: Validator Set
0.00132751 BNB
453250582024-12-30 10:58:3740 secs ago1735556317
BSC: Validator Set
0.00199037 BNB
453250582024-12-30 10:58:3740 secs ago1735556317
BSC: Validator Set
0.00124398 BNB
453250572024-12-30 10:58:3443 secs ago1735556314
BSC: Validator Set
0.00169482 BNB
453250572024-12-30 10:58:3443 secs ago1735556314
BSC: Validator Set
0.00105926 BNB
453250562024-12-30 10:58:3146 secs ago1735556311
BSC: Validator Set
0.00277769 BNB
453250562024-12-30 10:58:3146 secs ago1735556311
BSC: Validator Set
0.00173605 BNB
453250552024-12-30 10:58:2849 secs ago1735556308
BSC: Validator Set
0.00215081 BNB
453250552024-12-30 10:58:2849 secs ago1735556308
BSC: Validator Set
0.00134425 BNB
453250542024-12-30 10:58:2552 secs ago1735556305
BSC: Validator Set
0.00160329 BNB
453250542024-12-30 10:58:2552 secs ago1735556305
BSC: Validator Set
0.00100205 BNB
453250532024-12-30 10:58:2255 secs ago1735556302
BSC: Validator Set
0.00171095 BNB
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Genesis Bytecode Match Only)

Contract Name:
BSCValidatorSet

Compiler Version
v0.6.4+commit.1dca32f3

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity)

/**
 *Submitted for verification at BscScan.com on 2020-09-02
*/

pragma solidity =0.6.4;
pragma experimental ABIEncoderV2;

// contracts/interface/IApplication.sol

interface IApplication {
    /**
     * @dev Handle syn package
     */
    function handleSynPackage(
        uint8 channelId,
        bytes calldata msgBytes
    ) external returns (bytes memory responsePayload);

    /**
     * @dev Handle ack package
     */
    function handleAckPackage(uint8 channelId, bytes calldata msgBytes) external;

    /**
     * @dev Handle fail ack package
     */
    function handleFailAckPackage(uint8 channelId, bytes calldata msgBytes) external;
}

// contracts/interface/IBSCValidatorSet.sol

interface IBSCValidatorSet {
    function misdemeanor(address validator) external;
    function felony(address validator) external;
    function isCurrentValidator(address validator) external view returns (bool);
    function getLivingValidators() external view returns (address[] memory, bytes[] memory);
    function getMiningValidators() external view returns (address[] memory, bytes[] memory);
    function isMonitoredForMaliciousVote(bytes calldata voteAddr) external view returns (bool);
}

// contracts/interface/ILightClient.sol

interface ILightClient {
    function isHeaderSynced(uint64 height) external view returns (bool);

    function getAppHash(uint64 height) external view returns (bytes32);

    function getSubmitter(uint64 height) external view returns (address payable);
}

// contracts/interface/IParamSubscriber.sol

interface IParamSubscriber {
    function updateParam(string calldata key, bytes calldata value) external;
}

// contracts/interface/IRelayerHub.sol

interface IRelayerHub {
    function isRelayer(address sender) external view returns (bool);
}

// contracts/interface/ISlashIndicator.sol

interface ISlashIndicator {
    function clean() external;
    function downtimeSlash(address validator, uint256 count) external;
    function sendFelonyPackage(address validator) external;
    function getSlashThresholds() external view returns (uint256, uint256);
}

// contracts/interface/IStakeHub.sol

interface IStakeHub {
    function downtimeSlash(address validator) external;
    function maliciousVoteSlash(bytes calldata voteAddress) external;
    function doubleSignSlash(address validator) external;
    function voteToOperator(bytes calldata voteAddress) external view returns (address);
    function consensusToOperator(address validator) external view returns (address);
    function getValidatorConsensusAddress(address validator) external view returns (address);
    function getValidatorCreditContract(address validator) external view returns (address);
    function getValidatorVoteAddress(address validator) external view returns (bytes memory);
    function maxElectedValidators() external view returns (uint256);
    function distributeReward(address validator) external payable;
}

// contracts/interface/ISystemReward.sol

interface ISystemReward {
    function claimRewards(address payable to, uint256 amount) external returns (uint256 actualAmount);
}

// contracts/interface/ITokenHub.sol

interface ITokenHub {
    function getMiniRelayFee() external view returns (uint256);

    function getContractAddrByBEP2Symbol(bytes32 bep2Symbol) external view returns (address);

    function getBep2SymbolByContractAddr(address contractAddr) external view returns (bytes32);

    function bindToken(bytes32 bep2Symbol, address contractAddr, uint256 decimals) external;

    function unbindToken(bytes32 bep2Symbol, address contractAddr) external;

    function transferOut(
        address contractAddr,
        address recipient,
        uint256 amount,
        uint64 expireTime
    ) external payable returns (bool);

    function recoverBCAsset(bytes32 tokenSymbol, address recipient, uint256 amount) external;
    function cancelTokenRecoverLock(bytes32 tokenSymbol, address attacker) external;

    /* solium-disable-next-line */
    function batchTransferOutBNB(
        address[] calldata recipientAddrs,
        uint256[] calldata amounts,
        address[] calldata refundAddrs,
        uint64 expireTime
    ) external payable returns (bool);

    function withdrawStakingBNB(uint256 amount) external returns (bool);

    function cancelTransferIn(address tokenAddress, address attacker) external;
}

// contracts/lib/BytesLib.sol
/*
 * @title Solidity Bytes Arrays Utils
 * @author Gonçalo Sá <[email protected]>
 * Copyright (c) 2016-2020 zpouladzade/Seriality
 * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.
 *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.
 */

library BytesLib {
    function concat(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bytes memory) {
        bytes memory tempBytes;

        assembly {
            // Get a location of some free memory and store it in tempBytes as
            // Solidity does for memory variables.
            tempBytes := mload(0x40)

            // Store the length of the first bytes array at the beginning of
            // the memory for tempBytes.
            let length := mload(_preBytes)
            mstore(tempBytes, length)

            // Maintain a memory counter for the current write location in the
            // temp bytes array by adding the 32 bytes for the array length to
            // the starting location.
            let mc := add(tempBytes, 0x20)
            // Stop copying when the memory counter reaches the length of the
            // first bytes array.
            let end := add(mc, length)

            for {
                // Initialize a copy counter to the start of the _preBytes data,
                // 32 bytes into its memory.
                let cc := add(_preBytes, 0x20)
            } lt(mc, end) {
                // Increase both counters by 32 bytes each iteration.
                mc := add(mc, 0x20)
                cc := add(cc, 0x20)
            } {
                // Write the _preBytes data into the tempBytes memory 32 bytes
                // at a time.
                mstore(mc, mload(cc))
            }

            // Add the length of _postBytes to the current length of tempBytes
            // and store it as the new length in the first 32 bytes of the
            // tempBytes memory.
            length := mload(_postBytes)
            mstore(tempBytes, add(length, mload(tempBytes)))

            // Move the memory counter back from a multiple of 0x20 to the
            // actual end of the _preBytes data.
            mc := end
            // Stop copying when the memory counter reaches the new combined
            // length of the arrays.
            end := add(mc, length)

            for { let cc := add(_postBytes, 0x20) } lt(mc, end) {
                mc := add(mc, 0x20)
                cc := add(cc, 0x20)
            } { mstore(mc, mload(cc)) }

            // Update the free-memory pointer by padding our last write location
            // to 32 bytes: add 31 bytes to the end of tempBytes to move to the
            // next 32 byte block, then round down to the nearest multiple of
            // 32. If the sum of the length of the two arrays is zero then add
            // one before rounding down to leave a blank 32 bytes (the length block with 0).
            mstore(
                0x40,
                and(
                    add(add(end, iszero(add(length, mload(_preBytes)))), 31),
                    not(31) // Round down to the nearest 32 bytes.
                )
            )
        }

        return tempBytes;
    }

    function concatStorage(bytes storage _preBytes, bytes memory _postBytes) internal {
        assembly {
            // Read the first 32 bytes of _preBytes storage, which is the length
            // of the array. (We don't need to use the offset into the slot
            // because arrays use the entire slot.)
            let fslot := sload(_preBytes_slot)
            // Arrays of 31 bytes or less have an even value in their slot,
            // while longer arrays have an odd value. The actual length is
            // the slot divided by two for odd values, and the lowest order
            // byte divided by two for even values.
            // If the slot is even, bitwise and the slot with 255 and divide by
            // two to get the length. If the slot is odd, bitwise and the slot
            // with -1 and divide by two.
            let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)
            let mlength := mload(_postBytes)
            let newlength := add(slength, mlength)
            // slength can contain both the length and contents of the array
            // if length < 32 bytes so let's prepare for that
            // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage
            switch add(lt(slength, 32), lt(newlength, 32))
            case 2 {
                // Since the new array still fits in the slot, we just need to
                // update the contents of the slot.
                // uint256(bytes_storage) = uint256(bytes_storage) + uint256(bytes_memory) + new_length
                sstore(
                    _preBytes_slot,
                    // all the modifications to the slot are inside this
                    // next block
                    add(
                        // we can just add to the slot contents because the
                        // bytes we want to change are the LSBs
                        fslot,
                        add(
                            mul(
                                div(
                                    // load the bytes from memory
                                    mload(add(_postBytes, 0x20)),
                                    // zero all bytes to the right
                                    exp(0x100, sub(32, mlength))
                                ),
                                // and now shift left the number of bytes to
                                // leave space for the length in the slot
                                exp(0x100, sub(32, newlength))
                            ),
                            // increase length by the double of the memory
                            // bytes length
                            mul(mlength, 2)
                        )
                    )
                )
            }
            case 1 {
                // The stored value fits in the slot, but the combined value
                // will exceed it.
                // get the keccak hash to get the contents of the array
                mstore(0x0, _preBytes_slot)
                let sc := add(keccak256(0x0, 0x20), div(slength, 32))

                // save new length
                sstore(_preBytes_slot, add(mul(newlength, 2), 1))

                // The contents of the _postBytes array start 32 bytes into
                // the structure. Our first read should obtain the `submod`
                // bytes that can fit into the unused space in the last word
                // of the stored array. To get this, we read 32 bytes starting
                // from `submod`, so the data we read overlaps with the array
                // contents by `submod` bytes. Masking the lowest-order
                // `submod` bytes allows us to add that value directly to the
                // stored value.

                let submod := sub(32, slength)
                let mc := add(_postBytes, submod)
                let end := add(_postBytes, mlength)
                let mask := sub(exp(0x100, submod), 1)

                sstore(
                    sc,
                    add(
                        and(fslot, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00),
                        and(mload(mc), mask)
                    )
                )

                for {
                    mc := add(mc, 0x20)
                    sc := add(sc, 1)
                } lt(mc, end) {
                    sc := add(sc, 1)
                    mc := add(mc, 0x20)
                } { sstore(sc, mload(mc)) }

                mask := exp(0x100, sub(mc, end))

                sstore(sc, mul(div(mload(mc), mask), mask))
            }
            default {
                // get the keccak hash to get the contents of the array
                mstore(0x0, _preBytes_slot)
                // Start copying to the last used word of the stored array.
                let sc := add(keccak256(0x0, 0x20), div(slength, 32))

                // save new length
                sstore(_preBytes_slot, add(mul(newlength, 2), 1))

                // Copy over the first `submod` bytes of the new data as in
                // case 1 above.
                let slengthmod := mod(slength, 32)
                let mlengthmod := mod(mlength, 32)
                let submod := sub(32, slengthmod)
                let mc := add(_postBytes, submod)
                let end := add(_postBytes, mlength)
                let mask := sub(exp(0x100, submod), 1)

                sstore(sc, add(sload(sc), and(mload(mc), mask)))

                for {
                    sc := add(sc, 1)
                    mc := add(mc, 0x20)
                } lt(mc, end) {
                    sc := add(sc, 1)
                    mc := add(mc, 0x20)
                } { sstore(sc, mload(mc)) }

                mask := exp(0x100, sub(mc, end))

                sstore(sc, mul(div(mload(mc), mask), mask))
            }
        }
    }

    function slice(bytes memory _bytes, uint256 _start, uint256 _length) internal pure returns (bytes memory) {
        require(_bytes.length >= (_start + _length));

        bytes memory tempBytes;

        assembly {
            switch iszero(_length)
            case 0 {
                // Get a location of some free memory and store it in tempBytes as
                // Solidity does for memory variables.
                tempBytes := mload(0x40)

                // The first word of the slice result is potentially a partial
                // word read from the original array. To read it, we calculate
                // the length of that partial word and start copying that many
                // bytes into the array. The first word we copy will start with
                // data we don't care about, but the last `lengthmod` bytes will
                // land at the beginning of the contents of the new array. When
                // we're done copying, we overwrite the full first word with
                // the actual length of the slice.
                let lengthmod := and(_length, 31)

                // The multiplication in the next line is necessary
                // because when slicing multiples of 32 bytes (lengthmod == 0)
                // the following copy loop was copying the origin's length
                // and then ending prematurely not copying everything it should.
                let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))
                let end := add(mc, _length)

                for {
                    // The multiplication in the next line has the same exact purpose
                    // as the one above.
                    let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)
                } lt(mc, end) {
                    mc := add(mc, 0x20)
                    cc := add(cc, 0x20)
                } { mstore(mc, mload(cc)) }

                mstore(tempBytes, _length)

                //update free-memory pointer
                //allocating the array padded to 32 bytes like the compiler does now
                mstore(0x40, and(add(mc, 31), not(31)))
            }
            //if we want a zero-length slice let's just return a zero-length array
            default {
                tempBytes := mload(0x40)

                mstore(0x40, add(tempBytes, 0x20))
            }
        }

        return tempBytes;
    }

    function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {
        require(_bytes.length >= (_start + 20));
        address tempAddress;

        assembly {
            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)
        }

        return tempAddress;
    }

    function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) {
        require(_bytes.length >= (_start + 1));
        uint8 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x1), _start))
        }

        return tempUint;
    }

    function toUint16(bytes memory _bytes, uint256 _start) internal pure returns (uint16) {
        require(_bytes.length >= (_start + 2));
        uint16 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x2), _start))
        }

        return tempUint;
    }

    function toUint32(bytes memory _bytes, uint256 _start) internal pure returns (uint32) {
        require(_bytes.length >= (_start + 4));
        uint32 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x4), _start))
        }

        return tempUint;
    }

    function toUint64(bytes memory _bytes, uint256 _start) internal pure returns (uint64) {
        require(_bytes.length >= (_start + 8));
        uint64 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x8), _start))
        }

        return tempUint;
    }

    function toUint96(bytes memory _bytes, uint256 _start) internal pure returns (uint96) {
        require(_bytes.length >= (_start + 12));
        uint96 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0xc), _start))
        }

        return tempUint;
    }

    function toUint128(bytes memory _bytes, uint256 _start) internal pure returns (uint128) {
        require(_bytes.length >= (_start + 16));
        uint128 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x10), _start))
        }

        return tempUint;
    }

    function toUint(bytes memory _bytes, uint256 _start) internal pure returns (uint256) {
        require(_bytes.length >= (_start + 32));
        uint256 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x20), _start))
        }

        return tempUint;
    }

    function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) {
        require(_bytes.length >= (_start + 32));
        bytes32 tempBytes32;

        assembly {
            tempBytes32 := mload(add(add(_bytes, 0x20), _start))
        }

        return tempBytes32;
    }

    function equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) {
        bool success = true;

        assembly {
            let length := mload(_preBytes)

            // if lengths don't match the arrays are not equal
            switch eq(length, mload(_postBytes))
            case 1 {
                // cb is a circuit breaker in the for loop since there's
                //  no said feature for inline assembly loops
                // cb = 1 - don't breaker
                // cb = 0 - break
                let cb := 1

                let mc := add(_preBytes, 0x20)
                let end := add(mc, length)

                for { let cc := add(_postBytes, 0x20) }
                // the next line is the loop condition:
                // while (uint(mc < end) + cb == 2)
                eq(add(lt(mc, end), cb), 2) {
                    mc := add(mc, 0x20)
                    cc := add(cc, 0x20)
                } {
                    // if any of these checks fails then arrays are not equal
                    if iszero(eq(mload(mc), mload(cc))) {
                        // unsuccess:
                        success := 0
                        cb := 0
                    }
                }
            }
            default {
                // unsuccess:
                success := 0
            }
        }

        return success;
    }

    function equalStorage(bytes storage _preBytes, bytes memory _postBytes) internal view returns (bool) {
        bool success = true;

        assembly {
            // we know _preBytes_offset is 0
            let fslot := sload(_preBytes_slot)
            // Decode the length of the stored array like in concatStorage().
            let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)
            let mlength := mload(_postBytes)

            // if lengths don't match the arrays are not equal
            switch eq(slength, mlength)
            case 1 {
                // slength can contain both the length and contents of the array
                // if length < 32 bytes so let's prepare for that
                // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage
                if iszero(iszero(slength)) {
                    switch lt(slength, 32)
                    case 1 {
                        // blank the last byte which is the length
                        fslot := mul(div(fslot, 0x100), 0x100)

                        if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) {
                            // unsuccess:
                            success := 0
                        }
                    }
                    default {
                        // cb is a circuit breaker in the for loop since there's
                        //  no said feature for inline assembly loops
                        // cb = 1 - don't breaker
                        // cb = 0 - break
                        let cb := 1

                        // get the keccak hash to get the contents of the array
                        mstore(0x0, _preBytes_slot)
                        let sc := keccak256(0x0, 0x20)

                        let mc := add(_postBytes, 0x20)
                        let end := add(mc, mlength)

                        // the next line is the loop condition:
                        // while (uint(mc < end) + cb == 2)
                        for { } eq(add(lt(mc, end), cb), 2) {
                            sc := add(sc, 1)
                            mc := add(mc, 0x20)
                        } {
                            if iszero(eq(sload(sc), mload(mc))) {
                                // unsuccess:
                                success := 0
                                cb := 0
                            }
                        }
                    }
                }
            }
            default {
                // unsuccess:
                success := 0
            }
        }

        return success;
    }
}

// contracts/lib/BytesToTypes.sol

/**
 * @title BytesToTypes
 * Copyright (c) 2016-2020 zpouladzade/Seriality
 * @dev The BytesToTypes contract converts the memory byte arrays to the standard solidity types
 * @author [email protected]
 */
library BytesToTypes {
    function bytesToAddress(uint256 _offst, bytes memory _input) internal pure returns (address _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToBool(uint256 _offst, bytes memory _input) internal pure returns (bool _output) {
        uint8 x;
        assembly {
            x := mload(add(_input, _offst))
        }
        x == 0 ? _output = false : _output = true;
    }

    function getStringSize(uint256 _offst, bytes memory _input) internal pure returns (uint256 size) {
        assembly {
            size := mload(add(_input, _offst))
            let chunk_count := add(div(size, 32), 1) // chunk_count = size/32 + 1

            if gt(mod(size, 32), 0) {
                // if size%32 > 0
                chunk_count := add(chunk_count, 1)
            }

            size := mul(chunk_count, 32) // first 32 bytes reseves for size in strings
        }
    }

    function bytesToString(uint256 _offst, bytes memory _input, bytes memory _output) internal pure {
        uint256 size = 32;
        assembly {
            let chunk_count

            size := mload(add(_input, _offst))
            chunk_count := add(div(size, 32), 1) // chunk_count = size/32 + 1

            if gt(mod(size, 32), 0) { chunk_count := add(chunk_count, 1) } // chunk_count++

            for { let index := 0 } lt(index, chunk_count) { index := add(index, 1) } {
                mstore(add(_output, mul(index, 32)), mload(add(_input, _offst)))
                _offst := sub(_offst, 32) // _offst -= 32
            }
        }
    }

    function bytesToBytes32(uint256 _offst, bytes memory _input, bytes32 _output) internal pure {
        assembly {
            mstore(_output, add(_input, _offst))
            mstore(add(_output, 32), add(add(_input, _offst), 32))
        }
    }

    function bytesToInt8(uint256 _offst, bytes memory _input) internal pure returns (int8 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToInt16(uint256 _offst, bytes memory _input) internal pure returns (int16 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToInt24(uint256 _offst, bytes memory _input) internal pure returns (int24 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToInt32(uint256 _offst, bytes memory _input) internal pure returns (int32 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToInt40(uint256 _offst, bytes memory _input) internal pure returns (int40 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToInt48(uint256 _offst, bytes memory _input) internal pure returns (int48 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToInt56(uint256 _offst, bytes memory _input) internal pure returns (int56 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToInt64(uint256 _offst, bytes memory _input) internal pure returns (int64 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToInt72(uint256 _offst, bytes memory _input) internal pure returns (int72 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToInt80(uint256 _offst, bytes memory _input) internal pure returns (int80 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToInt88(uint256 _offst, bytes memory _input) internal pure returns (int88 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToInt96(uint256 _offst, bytes memory _input) internal pure returns (int96 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToInt104(uint256 _offst, bytes memory _input) internal pure returns (int104 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToInt112(uint256 _offst, bytes memory _input) internal pure returns (int112 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToInt120(uint256 _offst, bytes memory _input) internal pure returns (int120 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToInt128(uint256 _offst, bytes memory _input) internal pure returns (int128 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToInt136(uint256 _offst, bytes memory _input) internal pure returns (int136 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToInt144(uint256 _offst, bytes memory _input) internal pure returns (int144 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToInt152(uint256 _offst, bytes memory _input) internal pure returns (int152 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToInt160(uint256 _offst, bytes memory _input) internal pure returns (int160 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToInt168(uint256 _offst, bytes memory _input) internal pure returns (int168 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToInt176(uint256 _offst, bytes memory _input) internal pure returns (int176 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToInt184(uint256 _offst, bytes memory _input) internal pure returns (int184 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToInt192(uint256 _offst, bytes memory _input) internal pure returns (int192 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToInt200(uint256 _offst, bytes memory _input) internal pure returns (int200 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToInt208(uint256 _offst, bytes memory _input) internal pure returns (int208 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToInt216(uint256 _offst, bytes memory _input) internal pure returns (int216 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToInt224(uint256 _offst, bytes memory _input) internal pure returns (int224 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToInt232(uint256 _offst, bytes memory _input) internal pure returns (int232 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToInt240(uint256 _offst, bytes memory _input) internal pure returns (int240 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToInt248(uint256 _offst, bytes memory _input) internal pure returns (int248 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToInt256(uint256 _offst, bytes memory _input) internal pure returns (int256 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToUint8(uint256 _offst, bytes memory _input) internal pure returns (uint8 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToUint16(uint256 _offst, bytes memory _input) internal pure returns (uint16 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToUint24(uint256 _offst, bytes memory _input) internal pure returns (uint24 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToUint32(uint256 _offst, bytes memory _input) internal pure returns (uint32 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToUint40(uint256 _offst, bytes memory _input) internal pure returns (uint40 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToUint48(uint256 _offst, bytes memory _input) internal pure returns (uint48 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToUint56(uint256 _offst, bytes memory _input) internal pure returns (uint56 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToUint64(uint256 _offst, bytes memory _input) internal pure returns (uint64 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToUint72(uint256 _offst, bytes memory _input) internal pure returns (uint72 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToUint80(uint256 _offst, bytes memory _input) internal pure returns (uint80 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToUint88(uint256 _offst, bytes memory _input) internal pure returns (uint88 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToUint96(uint256 _offst, bytes memory _input) internal pure returns (uint96 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToUint104(uint256 _offst, bytes memory _input) internal pure returns (uint104 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToUint112(uint256 _offst, bytes memory _input) internal pure returns (uint112 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToUint120(uint256 _offst, bytes memory _input) internal pure returns (uint120 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToUint128(uint256 _offst, bytes memory _input) internal pure returns (uint128 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToUint136(uint256 _offst, bytes memory _input) internal pure returns (uint136 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToUint144(uint256 _offst, bytes memory _input) internal pure returns (uint144 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToUint152(uint256 _offst, bytes memory _input) internal pure returns (uint152 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToUint160(uint256 _offst, bytes memory _input) internal pure returns (uint160 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToUint168(uint256 _offst, bytes memory _input) internal pure returns (uint168 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToUint176(uint256 _offst, bytes memory _input) internal pure returns (uint176 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToUint184(uint256 _offst, bytes memory _input) internal pure returns (uint184 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToUint192(uint256 _offst, bytes memory _input) internal pure returns (uint192 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToUint200(uint256 _offst, bytes memory _input) internal pure returns (uint200 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToUint208(uint256 _offst, bytes memory _input) internal pure returns (uint208 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToUint216(uint256 _offst, bytes memory _input) internal pure returns (uint216 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToUint224(uint256 _offst, bytes memory _input) internal pure returns (uint224 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToUint232(uint256 _offst, bytes memory _input) internal pure returns (uint232 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToUint240(uint256 _offst, bytes memory _input) internal pure returns (uint240 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToUint248(uint256 _offst, bytes memory _input) internal pure returns (uint248 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }

    function bytesToUint256(uint256 _offst, bytes memory _input) internal pure returns (uint256 _output) {
        assembly {
            _output := mload(add(_input, _offst))
        }
    }
}

// contracts/lib/Memory.sol

library Memory {
    // Size of a word, in bytes.
    uint256 internal constant WORD_SIZE = 32;
    // Size of the header of a 'bytes' array.
    uint256 internal constant BYTES_HEADER_SIZE = 32;
    // Address of the free memory pointer.
    uint256 internal constant FREE_MEM_PTR = 0x40;

    // Compares the 'len' bytes starting at address 'addr' in memory with the 'len'
    // bytes starting at 'addr2'.
    // Returns 'true' if the bytes are the same, otherwise 'false'.
    function equals(uint256 addr, uint256 addr2, uint256 len) internal pure returns (bool equal) {
        assembly {
            equal := eq(keccak256(addr, len), keccak256(addr2, len))
        }
    }

    // Compares the 'len' bytes starting at address 'addr' in memory with the bytes stored in
    // 'bts'. It is allowed to set 'len' to a lower value then 'bts.length', in which case only
    // the first 'len' bytes will be compared.
    // Requires that 'bts.length >= len'
    function equals(uint256 addr, uint256 len, bytes memory bts) internal pure returns (bool equal) {
        require(bts.length >= len);
        uint256 addr2;
        assembly {
            addr2 := add(bts, /*BYTES_HEADER_SIZE*/ 32)
        }
        return equals(addr, addr2, len);
    }

    function compareStrings(string memory a, string memory b) internal pure returns (bool) {
        return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b))));
    }

    // Copy 'len' bytes from memory address 'src', to address 'dest'.
    // This function does not check the or destination, it only copies
    // the bytes.
    function copy(uint256 src, uint256 dest, uint256 len) internal pure {
        // Copy word-length chunks while possible
        for (; len >= WORD_SIZE; len -= WORD_SIZE) {
            assembly {
                mstore(dest, mload(src))
            }
            dest += WORD_SIZE;
            src += WORD_SIZE;
        }

        // Copy remaining bytes
        uint256 mask = 256 ** (WORD_SIZE - len) - 1;
        assembly {
            let srcpart := and(mload(src), not(mask))
            let destpart := and(mload(dest), mask)
            mstore(dest, or(destpart, srcpart))
        }
    }

    // Returns a memory pointer to the provided bytes array.
    function ptr(bytes memory bts) internal pure returns (uint256 addr) {
        assembly {
            addr := bts
        }
    }

    // Returns a memory pointer to the data portion of the provided bytes array.
    function dataPtr(bytes memory bts) internal pure returns (uint256 addr) {
        assembly {
            addr := add(bts, /*BYTES_HEADER_SIZE*/ 32)
        }
    }

    // This function does the same as 'dataPtr(bytes memory)', but will also return the
    // length of the provided bytes array.
    function fromBytes(bytes memory bts) internal pure returns (uint256 addr, uint256 len) {
        len = bts.length;
        assembly {
            addr := add(bts, /*BYTES_HEADER_SIZE*/ 32)
        }
    }

    // Creates a 'bytes memory' variable from the memory address 'addr', with the
    // length 'len'. The function will allocate new memory for the bytes array, and
    // the 'len bytes starting at 'addr' will be copied into that new memory.
    function toBytes(uint256 addr, uint256 len) internal pure returns (bytes memory bts) {
        bts = new bytes(len);
        uint256 btsptr;
        assembly {
            btsptr := add(bts, /*BYTES_HEADER_SIZE*/ 32)
        }
        copy(addr, btsptr, len);
    }

    // Get the word stored at memory address 'addr' as a 'uint'.
    function toUint(uint256 addr) internal pure returns (uint256 n) {
        assembly {
            n := mload(addr)
        }
    }

    // Get the word stored at memory address 'addr' as a 'bytes32'.
    function toBytes32(uint256 addr) internal pure returns (bytes32 bts) {
        assembly {
            bts := mload(addr)
        }
    }
}

// contracts/lib/RLPDecode.sol

library RLPDecode {
    uint8 constant STRING_SHORT_START = 0x80;
    uint8 constant STRING_LONG_START = 0xb8;
    uint8 constant LIST_SHORT_START = 0xc0;
    uint8 constant LIST_LONG_START = 0xf8;

    uint8 constant WORD_SIZE = 32;

    struct RLPItem {
        uint256 len;
        uint256 memPtr;
    }

    struct Iterator {
        RLPItem item; // Item that's being iterated over.
        uint256 nextPtr; // Position of the next item in the list.
    }

    function next(Iterator memory self) internal pure returns (RLPItem memory) {
        require(hasNext(self));

        uint256 ptr = self.nextPtr;
        uint256 itemLength = _itemLength(ptr);
        self.nextPtr = ptr + itemLength;

        return RLPItem(itemLength, ptr);
    }

    function hasNext(Iterator memory self) internal pure returns (bool) {
        RLPItem memory item = self.item;
        return self.nextPtr < item.memPtr + item.len;
    }

    function toRLPItem(bytes memory self) internal pure returns (RLPItem memory) {
        uint256 memPtr;
        assembly {
            memPtr := add(self, 0x20)
        }

        return RLPItem(self.length, memPtr);
    }

    function iterator(RLPItem memory self) internal pure returns (Iterator memory) {
        require(isList(self));

        uint256 ptr = self.memPtr + _payloadOffset(self.memPtr);
        return Iterator(self, ptr);
    }

    function rlpLen(RLPItem memory item) internal pure returns (uint256) {
        return item.len;
    }

    function payloadLen(RLPItem memory item) internal pure returns (uint256) {
        return item.len - _payloadOffset(item.memPtr);
    }

    function toList(RLPItem memory item) internal pure returns (RLPItem[] memory) {
        require(isList(item));

        uint256 items = numItems(item);
        RLPItem[] memory result = new RLPItem[](items);

        uint256 memPtr = item.memPtr + _payloadOffset(item.memPtr);
        uint256 dataLen;
        for (uint256 i = 0; i < items; ++i) {
            dataLen = _itemLength(memPtr);
            result[i] = RLPItem(dataLen, memPtr);
            memPtr = memPtr + dataLen;
        }

        return result;
    }

    function isList(RLPItem memory item) internal pure returns (bool) {
        if (item.len == 0) return false;

        uint8 byte0;
        uint256 memPtr = item.memPtr;
        assembly {
            byte0 := byte(0, mload(memPtr))
        }

        if (byte0 < LIST_SHORT_START) {
            return false;
        }
        return true;
    }

    function toRlpBytes(RLPItem memory item) internal pure returns (bytes memory) {
        bytes memory result = new bytes(item.len);
        if (result.length == 0) return result;

        uint256 ptr;
        assembly {
            ptr := add(0x20, result)
        }

        copy(item.memPtr, ptr, item.len);
        return result;
    }

    function toBoolean(RLPItem memory item) internal pure returns (bool) {
        require(item.len == 1);
        uint256 result;
        uint256 memPtr = item.memPtr;
        assembly {
            result := byte(0, mload(memPtr))
        }

        if (result == 0 || result == STRING_SHORT_START) {
            return false;
        } else {
            return true;
        }
    }

    function toAddress(RLPItem memory item) internal pure returns (address) {
        // 1 byte for the length prefix
        require(item.len == 21);

        return address(toUint(item));
    }

    function toUint(RLPItem memory item) internal pure returns (uint256) {
        require(item.len > 0 && item.len <= 33);

        uint256 offset = _payloadOffset(item.memPtr);
        require(item.len >= offset, "length is less than offset");
        uint256 len = item.len - offset;

        uint256 result;
        uint256 memPtr = item.memPtr + offset;
        assembly {
            result := mload(memPtr)

            // shfit to the correct location if neccesary
            if lt(len, 32) { result := div(result, exp(256, sub(32, len))) }
        }

        return result;
    }

    // enforces 32 byte length
    function toUintStrict(RLPItem memory item) internal pure returns (uint256) {
        // one byte prefix
        require(item.len == 33);

        uint256 result;
        uint256 memPtr = item.memPtr + 1;
        assembly {
            result := mload(memPtr)
        }

        return result;
    }

    function toBytes(RLPItem memory item) internal pure returns (bytes memory) {
        require(item.len > 0);

        uint256 offset = _payloadOffset(item.memPtr);
        uint256 len = item.len - offset; // data length
        bytes memory result = new bytes(len);

        uint256 destPtr;
        assembly {
            destPtr := add(0x20, result)
        }

        copy(item.memPtr + offset, destPtr, len);
        return result;
    }

    function numItems(RLPItem memory item) private pure returns (uint256) {
        if (item.len == 0) return 0;

        uint256 count = 0;
        uint256 currPtr = item.memPtr + _payloadOffset(item.memPtr);
        uint256 endPtr = item.memPtr + item.len;
        while (currPtr < endPtr) {
            currPtr = currPtr + _itemLength(currPtr); // skip over an item
            ++count;
        }

        return count;
    }

    function _itemLength(uint256 memPtr) private pure returns (uint256) {
        uint256 itemLen;
        uint256 byte0;
        assembly {
            byte0 := byte(0, mload(memPtr))
        }

        if (byte0 < STRING_SHORT_START) {
            itemLen = 1;
        } else if (byte0 < STRING_LONG_START) {
            itemLen = byte0 - STRING_SHORT_START + 1;
        } else if (byte0 < LIST_SHORT_START) {
            uint256 dataLen;
            assembly {
                let byteLen := sub(byte0, 0xb7) // # of bytes the actual length is
                memPtr := add(memPtr, 1) // skip over the first byte

                /* 32 byte word size */
                dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to get the len
                itemLen := add(dataLen, add(byteLen, 1))
            }
            require(itemLen >= dataLen, "addition overflow");
        } else if (byte0 < LIST_LONG_START) {
            itemLen = byte0 - LIST_SHORT_START + 1;
        } else {
            uint256 dataLen;
            assembly {
                let byteLen := sub(byte0, 0xf7)
                memPtr := add(memPtr, 1)

                dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to the correct length
                itemLen := add(dataLen, add(byteLen, 1))
            }
            require(itemLen >= dataLen, "addition overflow");
        }

        return itemLen;
    }

    // @return number of bytes until the data
    function _payloadOffset(uint256 memPtr) private pure returns (uint256) {
        uint256 byte0;
        assembly {
            byte0 := byte(0, mload(memPtr))
        }

        if (byte0 < STRING_SHORT_START) {
            return 0;
        } else if (byte0 < STRING_LONG_START || (byte0 >= LIST_SHORT_START && byte0 < LIST_LONG_START)) {
            return 1;
        } else if (
            byte0 < LIST_SHORT_START // being explicit
        ) {
            return byte0 - (STRING_LONG_START - 1) + 1;
        } else {
            return byte0 - (LIST_LONG_START - 1) + 1;
        }
    }

    /*
    * @param src Pointer to source
    * @param dest Pointer to destination
    * @param len Amount of memory to copy from the source
    */
    function copy(uint256 src, uint256 dest, uint256 len) private pure {
        if (len == 0) return;

        // copy as many word sizes as possible
        for (; len >= WORD_SIZE; len -= WORD_SIZE) {
            assembly {
                mstore(dest, mload(src))
            }

            src += WORD_SIZE;
            dest += WORD_SIZE;
        }

        // left over bytes. Mask is used to remove unwanted bytes from the word
        uint256 mask = 256 ** (WORD_SIZE - len) - 1;
        assembly {
            let srcpart := and(mload(src), not(mask)) // zero out src
            let destpart := and(mload(dest), mask) // retrieve the bytes
            mstore(dest, or(destpart, srcpart))
        }
    }
}

// contracts/lib/RLPEncode.sol

library RLPEncode {
    uint8 constant STRING_OFFSET = 0x80;
    uint8 constant LIST_OFFSET = 0xc0;

    /**
     * @notice Encode string item
     * @param self The string (ie. byte array) item to encode
     * @return The RLP encoded string in bytes
     */
    function encodeBytes(bytes memory self) internal pure returns (bytes memory) {
        if (self.length == 1 && self[0] <= 0x7f) {
            return self;
        }
        return mergeBytes(encodeLength(self.length, STRING_OFFSET), self);
    }

    /**
     * @notice Encode address
     * @param self The address to encode
     * @return The RLP encoded address in bytes
     */
    function encodeAddress(address self) internal pure returns (bytes memory) {
        bytes memory b;
        assembly {
            let m := mload(0x40)
            mstore(add(m, 20), xor(0x140000000000000000000000000000000000000000, self))
            mstore(0x40, add(m, 52))
            b := m
        }
        return encodeBytes(b);
    }

    /**
     * @notice Encode uint
     * @param self The uint to encode
     * @return The RLP encoded uint in bytes
     */
    function encodeUint(uint256 self) internal pure returns (bytes memory) {
        return encodeBytes(toBinary(self));
    }

    /**
     * @notice Encode int
     * @param self The int to encode
     * @return The RLP encoded int in bytes
     */
    function encodeInt(int256 self) internal pure returns (bytes memory) {
        return encodeUint(uint256(self));
    }

    /**
     * @notice Encode bool
     * @param self The bool to encode
     * @return The RLP encoded bool in bytes
     */
    function encodeBool(bool self) internal pure returns (bytes memory) {
        bytes memory rs = new bytes(1);
        rs[0] = (self ? bytes1(0x01) : bytes1(0x80));
        return rs;
    }

    /**
     * @notice Encode list of items
     * @param self The list of items to encode, each item in list must be already encoded
     * @return The RLP encoded list of items in bytes
     */
    function encodeList(bytes[] memory self) internal pure returns (bytes memory) {
        if (self.length == 0) {
            return new bytes(0);
        }
        bytes memory payload = self[0];
        for (uint256 i = 1; i < self.length; ++i) {
            payload = mergeBytes(payload, self[i]);
        }
        return mergeBytes(encodeLength(payload.length, LIST_OFFSET), payload);
    }

    /**
     * @notice Concat two bytes arrays
     * @param _preBytes The first bytes array
     * @param _postBytes The second bytes array
     * @return The merged bytes array
     */
    function mergeBytes(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bytes memory) {
        bytes memory tempBytes;

        assembly {
            // Get a location of some free memory and store it in tempBytes as
            // Solidity does for memory variables.
            tempBytes := mload(0x40)

            // Store the length of the first bytes array at the beginning of
            // the memory for tempBytes.
            let length := mload(_preBytes)
            mstore(tempBytes, length)

            // Maintain a memory counter for the current write location in the
            // temp bytes array by adding the 32 bytes for the array length to
            // the starting location.
            let mc := add(tempBytes, 0x20)
            // Stop copying when the memory counter reaches the length of the
            // first bytes array.
            let end := add(mc, length)

            for {
                // Initialize a copy counter to the start of the _preBytes data,
                // 32 bytes into its memory.
                let cc := add(_preBytes, 0x20)
            } lt(mc, end) {
                // Increase both counters by 32 bytes each iteration.
                mc := add(mc, 0x20)
                cc := add(cc, 0x20)
            } {
                // Write the _preBytes data into the tempBytes memory 32 bytes
                // at a time.
                mstore(mc, mload(cc))
            }

            // Add the length of _postBytes to the current length of tempBytes
            // and store it as the new length in the first 32 bytes of the
            // tempBytes memory.
            length := mload(_postBytes)
            mstore(tempBytes, add(length, mload(tempBytes)))

            // Move the memory counter back from a multiple of 0x20 to the
            // actual end of the _preBytes data.
            mc := end
            // Stop copying when the memory counter reaches the new combined
            // length of the arrays.
            end := add(mc, length)

            for { let cc := add(_postBytes, 0x20) } lt(mc, end) {
                mc := add(mc, 0x20)
                cc := add(cc, 0x20)
            } { mstore(mc, mload(cc)) }

            // Update the free-memory pointer by padding our last write location
            // to 32 bytes: add 31 bytes to the end of tempBytes to move to the
            // next 32 byte block, then round down to the nearest multiple of
            // 32. If the sum of the length of the two arrays is zero then add
            // one before rounding down to leave a blank 32 bytes (the length block with 0).
            mstore(
                0x40,
                and(
                    add(add(end, iszero(add(length, mload(_preBytes)))), 31),
                    not(31) // Round down to the nearest 32 bytes.
                )
            )
        }

        return tempBytes;
    }

    /**
     * @notice Encode the first byte, followed by the `length` in binary form if `length` is more than 55.
     * @param length The length of the string or the payload
     * @param offset `STRING_OFFSET` if item is string, `LIST_OFFSET` if item is list
     * @return RLP encoded bytes
     */
    function encodeLength(uint256 length, uint256 offset) internal pure returns (bytes memory) {
        require(length < 256 ** 8, "input too long");
        bytes memory rs = new bytes(1);
        if (length <= 55) {
            rs[0] = bytes1(uint8(length + offset));
            return rs;
        }
        bytes memory bl = toBinary(length);
        rs[0] = bytes1(uint8(bl.length + offset + 55));
        return mergeBytes(rs, bl);
    }

    /**
     * @notice Encode integer in big endian binary form with no leading zeroes
     * @param x The integer to encode
     * @return RLP encoded bytes
     */
    function toBinary(uint256 x) internal pure returns (bytes memory) {
        bytes memory b = new bytes(32);
        assembly {
            mstore(add(b, 32), x)
        }
        uint256 i;
        if (x & 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 == 0) {
            i = 24;
        } else if (x & 0xffffffffffffffffffffffffffffffff00000000000000000000000000000000 == 0) {
            i = 16;
        } else {
            i = 0;
        }
        for (; i < 32; ++i) {
            if (b[i] != 0) {
                break;
            }
        }
        uint256 length = 32 - i;
        bytes memory rs = new bytes(length);
        assembly {
            mstore(add(rs, length), x)
            mstore(rs, length)
        }
        return rs;
    }
}

// contracts/lib/SafeMath.sol

/**
 * Copyright (c) 2016-2019 zOS Global Limited
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        // Solidity only automatically asserts when dividing by 0
        require(b > 0, errorMessage);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return mod(a, b, "SafeMath: modulo by zero");
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts with custom message when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }
}

// contracts/lib/CmnPkg.sol

library CmnPkg {
    using RLPEncode for *;
    using RLPDecode for *;

    struct CommonAckPackage {
        uint32 code;
    }

    function encodeCommonAckPackage(uint32 code) internal pure returns (bytes memory) {
        bytes[] memory elements = new bytes[](1);
        elements[0] = uint256(code).encodeUint();
        return elements.encodeList();
    }

    function decodeCommonAckPackage(bytes memory msgBytes) internal pure returns (CommonAckPackage memory, bool) {
        CommonAckPackage memory ackPkg;
        RLPDecode.Iterator memory iter = msgBytes.toRLPItem().iterator();

        bool success = false;
        uint256 idx = 0;
        while (iter.hasNext()) {
            if (idx == 0) {
                ackPkg.code = uint32(iter.next().toUint());
                success = true;
            } else {
                break;
            }
            ++idx;
        }
        return (ackPkg, success);
    }
}

// contracts/System.sol

contract System {
    bool public alreadyInit;

    uint32 public constant CODE_OK = 0;
    uint32 public constant ERROR_FAIL_DECODE = 100;

    uint8 public constant BIND_CHANNELID = 0x01;
    uint8 public constant TRANSFER_IN_CHANNELID = 0x02;
    uint8 public constant TRANSFER_OUT_CHANNELID = 0x03;
    uint8 public constant STAKING_CHANNELID = 0x08;
    uint8 public constant GOV_CHANNELID = 0x09;
    uint8 public constant SLASH_CHANNELID = 0x0b;
    uint8 public constant CROSS_STAKE_CHANNELID = 0x10;
    uint8 public constant BC_FUSION_CHANNELID = 0x11; // new channel id for cross-chain redelegate from Beacon Chain to Smart Chain after Feynman upgrade
    uint16 public constant bscChainID = 0x0038;

    address public constant VALIDATOR_CONTRACT_ADDR = 0x0000000000000000000000000000000000001000;
    address public constant SLASH_CONTRACT_ADDR = 0x0000000000000000000000000000000000001001;
    address public constant SYSTEM_REWARD_ADDR = 0x0000000000000000000000000000000000001002;
    address public constant LIGHT_CLIENT_ADDR = 0x0000000000000000000000000000000000001003;
    address public constant TOKEN_HUB_ADDR = 0x0000000000000000000000000000000000001004;
    address public constant INCENTIVIZE_ADDR = 0x0000000000000000000000000000000000001005;
    address public constant RELAYERHUB_CONTRACT_ADDR = 0x0000000000000000000000000000000000001006;
    address public constant GOV_HUB_ADDR = 0x0000000000000000000000000000000000001007;
    address public constant TOKEN_MANAGER_ADDR = 0x0000000000000000000000000000000000001008;
    address public constant CROSS_CHAIN_CONTRACT_ADDR = 0x0000000000000000000000000000000000002000;
    address public constant STAKING_CONTRACT_ADDR = 0x0000000000000000000000000000000000002001;
    address public constant STAKE_HUB_ADDR = 0x0000000000000000000000000000000000002002;
    address public constant STAKE_CREDIT_ADDR = 0x0000000000000000000000000000000000002003;
    address public constant GOVERNOR_ADDR = 0x0000000000000000000000000000000000002004;
    address public constant GOV_TOKEN_ADDR = 0x0000000000000000000000000000000000002005;
    address public constant TIMELOCK_ADDR = 0x0000000000000000000000000000000000002006;
    address public constant TOKEN_RECOVER_PORTAL_ADDR = 0x0000000000000000000000000000000000003000;

    modifier onlyCoinbase() {
        require(msg.sender == block.coinbase, "the message sender must be the block producer");
        _;
    }

    modifier onlyZeroGasPrice() {
        require(tx.gasprice == 0, "gasprice is not zero");
        _;
    }

    modifier onlyNotInit() {
        require(!alreadyInit, "the contract already init");
        _;
    }

    modifier onlyInit() {
        require(alreadyInit, "the contract not init yet");
        _;
    }

    modifier onlySlash() {
        require(msg.sender == SLASH_CONTRACT_ADDR, "the message sender must be slash contract");
        _;
    }

    modifier onlyTokenHub() {
        require(msg.sender == TOKEN_HUB_ADDR, "the message sender must be token hub contract");
        _;
    }

    modifier onlyGov() {
        require(msg.sender == GOV_HUB_ADDR, "the message sender must be governance contract");
        _;
    }

    modifier onlyValidatorContract() {
        require(msg.sender == VALIDATOR_CONTRACT_ADDR, "the message sender must be validatorSet contract");
        _;
    }

    modifier onlyCrossChainContract() {
        require(msg.sender == CROSS_CHAIN_CONTRACT_ADDR, "the message sender must be cross chain contract");
        _;
    }

    modifier onlyRelayerIncentivize() {
        require(msg.sender == INCENTIVIZE_ADDR, "the message sender must be incentivize contract");
        _;
    }

    modifier onlyRelayer() {
        require(IRelayerHub(RELAYERHUB_CONTRACT_ADDR).isRelayer(msg.sender), "the msg sender is not a relayer");
        _;
    }

    modifier onlyTokenManager() {
        require(msg.sender == TOKEN_MANAGER_ADDR, "the msg sender must be tokenManager");
        _;
    }

    modifier onlyStakeHub() {
        require(msg.sender == STAKE_HUB_ADDR, "the msg sender must be stakeHub");
        _;
    }

    modifier onlyGovernorTimelock() {
        require(msg.sender == TIMELOCK_ADDR, "the msg sender must be governor timelock contract");
        _;
    }

    modifier onlyTokenRecoverPortal() {
        require(msg.sender == TOKEN_RECOVER_PORTAL_ADDR, "the msg sender must be token recover portal");
        _;
    }

    // Not reliable, do not use when need strong verify
    function isContract(address addr) internal view returns (bool) {
        uint256 size;
        assembly {
            size := extcodesize(addr)
        }
        return size > 0;
    }
}

// contracts/BSCValidatorSet.sol

interface ICrossChain {
    function registeredContractChannelMap(address, uint8) external view returns (bool);
}

contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplication {
    using SafeMath for uint256;

    using RLPDecode for *;

    // will not transfer value less than 0.1 BNB for validators
    uint256 public constant DUSTY_INCOMING = 1e17;

    uint8 public constant JAIL_MESSAGE_TYPE = 1;
    uint8 public constant VALIDATORS_UPDATE_MESSAGE_TYPE = 0;

    // the precision of cross chain value transfer.
    uint256 public constant PRECISION = 1e10;
    uint256 public constant EXPIRE_TIME_SECOND_GAP = 1000;
    uint256 public constant MAX_NUM_OF_VALIDATORS = 100;

    bytes public constant INIT_VALIDATORSET_BYTES = hex"0x6080604052600436106104fb5760003560e01c806388b32f111161028c578063c6d339451161015a578063e40716a1116100cc578063f92eb86b11610085578063f92eb86b14610d2d578063f9a2bbc714610d42578063fc3e590814610d57578063fccc281314610d6c578063fd4ad81f14610d81578063fd6a687914610db057610502565b8063e40716a114610c9b578063ea321e4914610cb0578063eb57e20214610cd0578063eda5868c14610cf0578063f1fad10414610d05578063f340fa0114610d1a57610502565b8063d86222d51161011e578063d86222d514610c1d578063daacdb6614610c32578063dc927faf14610c47578063df8079e914610c5c578063e086c7b114610c71578063e1c7392a14610c8657610502565b8063c6d3394514610bbe578063c81b166214610bd3578063c8509d811461098d578063ce910b0c14610be8578063d68fb56a14610c0857610502565b8063a78abc16116101fe578063ad3c9da6116101b7578063ad3c9da614610b3d578063aef198a914610b5d578063b7ab4db514610b72578063b8cf4ef114610b94578063bf9f4995146106fe578063c466689d14610ba957610502565b8063a78abc1614610ab4578063aa82dce114610ac9578063aad5606314610ade578063aaf5eb6814610af3578063ab51bb9614610b08578063ac43175114610b1d57610502565b806396713da91161025057806396713da914610a365780639dc0926214610a4b5780639fe0f81614610a60578063a0dc275814610a75578063a1a11bf514610a8a578063a5422d5c14610a9f57610502565b806388b32f11146109c25780638a7beb01146109d75780638b5ad0c9146109ec5780638d19a41014610a015780639369d7de14610a2157610502565b806351b4dce3116103c957806370fd5bad1161033b5780637e434d54116102f45780637e434d541461094e57806381650b6214610963578063820dcaa814610978578063831d65d11461098d578063853230aa1461090f57806386249882146109ad57610502565b806370fd5bad146108d0578063718a8aa8146108e557806375d47a0a146108fa57806378dfed4a1461090f5780637942fd05146109245780637a84ca2a1461093957610502565b80635d77156c1161038d5780635d77156c1461082a5780635de1e22c1461083f57806360eba4fe1461085457806362b72cf5146108745780636969a25c146108895780636e47b482146108bb57610502565b806351b4dce3146107ab57806351e80672146107c057806355614fcc146107d5578063565c56b3146107f55780635667515a1461081557610502565b8063300c35671161046d57806343756e5c1161042657806343756e5c1461072057806345cf9daf14610735578063493279b11461074a5780634bf6c8821461076c5780634df6e0c3146107815780635192c82c1461079657610502565b8063300c35671461065b578063321d398a1461067b5780633365af3a1461069b57806335409f7f146106bb5780633b071dcc146106db5780633dffc387146106fe57610502565b8063152ad3b8116104bf578063152ad3b8146105ba5780631e4c1524146105dc5780631ff18069146105fc578063219f22d51461061157806328087028146106265780632a0ffb6e1461063b57610502565b806304c4fec61461050757806307a568471461051e5780630bee7a67146105495780630e2374a51461056b5780631182b8751461058d57610502565b3661050257005b600080fd5b34801561051357600080fd5b5061051c610dc5565b005b34801561052a57600080fd5b50610533610e37565b6040516105409190618ed8565b60405180910390f35b34801561055557600080fd5b5061055e610e3d565b6040516105409190618f02565b34801561057757600080fd5b50610580610e42565b60405161054091906181eb565b34801561059957600080fd5b506105ad6105a83660046180d1565b610e48565b604051610540919061837e565b3480156105c657600080fd5b506105cf611165565b6040516105409190618373565b3480156105e857600080fd5b5061051c6105f7366004617edf565b61116e565b34801561060857600080fd5b50610533611844565b34801561061d57600080fd5b5061055e61184a565b34801561063257600080fd5b5061058061184f565b34801561064757600080fd5b5061051c610656366004617e3f565b611855565b34801561066757600080fd5b5061051c610676366004617e77565b611902565b34801561068757600080fd5b506105cf61069636600461807e565b611c4b565b3480156106a757600080fd5b506105cf6106b636600461807e565b611d1a565b3480156106c757600080fd5b5061051c6106d6366004617e3f565b611dcb565b3480156106e757600080fd5b506106f0611f30565b604051610540929190618289565b34801561070a57600080fd5b5061071361220c565b6040516105409190618f13565b34801561072c57600080fd5b50610580612211565b34801561074157600080fd5b50610533612217565b34801561075657600080fd5b5061075f61221d565b6040516105409190618ec9565b34801561077857600080fd5b50610713612222565b34801561078d57600080fd5b506106f0612227565b3480156107a257600080fd5b506105336123b3565b3480156107b757600080fd5b506105806123b9565b3480156107cc57600080fd5b506105806123bf565b3480156107e157600080fd5b506105cf6107f0366004617e3f565b6123c5565b34801561080157600080fd5b50610533610810366004617e3f565b6123fa565b34801561082157600080fd5b5061071361244b565b34801561083657600080fd5b5061055e612450565b34801561084b57600080fd5b50610533612455565b34801561086057600080fd5b506105ad61086f36600461807e565b61245b565b34801561088057600080fd5b50610533612501565b34801561089557600080fd5b506108a96108a436600461807e565b612507565b60405161054096959493929190618218565b3480156108c757600080fd5b5061058061256b565b3480156108dc57600080fd5b50610713612571565b3480156108f157600080fd5b50610713612576565b34801561090657600080fd5b5061058061257b565b34801561091b57600080fd5b50610533612581565b34801561093057600080fd5b50610713612587565b34801561094557600080fd5b5061053361258c565b34801561095a57600080fd5b50610580612592565b34801561096f57600080fd5b5061055e612598565b34801561098457600080fd5b5061053361259d565b34801561099957600080fd5b5061051c6109a83660046180d1565b6125a3565b3480156109b957600080fd5b50610533612604565b3480156109ce57600080fd5b5061053361260a565b3480156109e357600080fd5b506105cf612610565b3480156109f857600080fd5b50610533612619565b348015610a0d57600080fd5b50610533610a1c366004617e3f565b61261f565b348015610a2d57600080fd5b5061051c61265f565b348015610a4257600080fd5b50610713612773565b348015610a5757600080fd5b50610580612778565b348015610a6c57600080fd5b5061053361277e565b348015610a8157600080fd5b50610533612783565b348015610a9657600080fd5b50610580612788565b348015610aab57600080fd5b506105ad61278e565b348015610ac057600080fd5b506105cf6127ad565b348015610ad557600080fd5b506105806127b6565b348015610aea57600080fd5b506105806127bc565b348015610aff57600080fd5b506105336127c2565b348015610b1457600080fd5b5061055e61244b565b348015610b2957600080fd5b5061051c610b38366004618022565b6127cb565b348015610b4957600080fd5b50610533610b58366004617e3f565b613084565b348015610b6957600080fd5b50610533613096565b348015610b7e57600080fd5b50610b876130a3565b6040516105409190618276565b348015610ba057600080fd5b5061053361318f565b348015610bb557600080fd5b50610533613194565b348015610bca57600080fd5b50610533612571565b348015610bdf57600080fd5b5061058061319a565b348015610bf457600080fd5b506105ad610c0336600461807e565b6131a0565b348015610c1457600080fd5b506105336131ad565b348015610c2957600080fd5b506105336131ec565b348015610c3e57600080fd5b506105336131f8565b348015610c5357600080fd5b506105806131fe565b348015610c6857600080fd5b50610580613204565b348015610c7d57600080fd5b50610533610e3d565b348015610c9257600080fd5b5061051c61320a565b348015610ca757600080fd5b506105336133b9565b348015610cbc57600080fd5b506105cf610ccb366004617fe3565b6133bf565b348015610cdc57600080fd5b5061051c610ceb366004617e3f565b613545565b348015610cfc57600080fd5b5061055e613649565b348015610d1157600080fd5b5061071361364e565b61051c610d28366004617e3f565b613653565b348015610d3957600080fd5b506105336139d2565b348015610d4e57600080fd5b506105806139d8565b348015610d6357600080fd5b5061071361277e565b348015610d7857600080fd5b506105806139de565b348015610d8d57600080fd5b50610da1610d9c36600461807e565b6139e4565b60405161054093929190618ee1565b348015610dbc57600080fd5b50610580613aa6565b6000610dd03361261f565b9050600b8181548110610ddf57fe5b600091825260209091206001601690920201015460ff16610e1b5760405162461bcd60e51b8152600401610e1290618ae4565b60405180910390fd5b6000610e256131ad565b9050610e32338383613aac565b505050565b60095481565b606481565b61200181565b60005460609060ff16610e6d5760405162461bcd60e51b8152600401610e12906185a5565b3361200014610e8e5760405162461bcd60e51b8152600401610e1290618ce5565b600b54610f4c57610e9d6179eb565b60015460005b81811015610f4857600b80546001810182556000919091528351600080516020618fe583398151915260169092029182019081556020808601516000805160206196148339815191528401805460ff1916911515919091179055604086015180518794610f2493600080516020619005833981519152909101920190617a1a565b506060820151610f3a9060038301906013617a94565b505050806001019050610ea3565b5050505b610f54617ac1565b6000610f9585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613d7192505050565b9150915080610fb157610fa86064613f2d565b9250505061115e565b815160009060ff16610fd657610fcf83602001518460400151613f8e565b905061112a565b825160ff16600114156111265782602001515160011461101b57600080516020618fc583398151915260405161100b9061899d565b60405180910390a1506067611121565b6000836020015160008151811061102e57fe5b602090810291909101810151516001600160a01b0381166000908152600490925260409091205490915080158061108f575060018082038154811061106f57fe5b9060005260206000209060040201600201601c9054906101000a900460ff165b156110cd576040516001600160a01b038316907fe209c46bebf57cf265d5d9009a00870e256d9150f3ed5281ab9d9eb3cec6e4be90600090a261111a565b60006110dc8360018403615150565b905080611118576040516001600160a01b038416907fe209c46bebf57cf265d5d9009a00870e256d9150f3ed5281ab9d9eb3cec6e4be90600090a25b505b6000925050505b61112a565b5060655b63ffffffff811661114f575050604080516000815260208101909152915061115e9050565b61115881613f2d565b93505050505b9392505050565b60075460ff1681565b33411461118d5760405162461bcd60e51b8152600401610e1290618d34565b3a156111ab5760405162461bcd60e51b8152600401610e1290618a23565b82516040805182815260208084028201019091526060908280156111e957816020015b6111d6617ae5565b8152602001906001900390816111ce5790505b50905060005b82811015611293576040518060c0016040528087838151811061120e57fe5b60200260200101516001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200186838151811061125057fe5b60200260200101516001600160401b03168152602001600015158152602001600081525082828151811061128057fe5b60209081029190910101526001016111ef565b5060405163d31f968d60e01b81526120009063d31f968d906112be906110009060089060040161825a565b60206040518083038186803b1580156112d657600080fd5b505afa1580156112ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061130e9190617fc3565b15611631578051601554818111156113b057815b818110156113ae57601580548061133557fe5b60008281526020812060046000199093019283020180546001600160a01b0319908116825560018201805490911690556002810180546001600160e81b0319169055600301559055601680548061138857fe5b6001900381819060005260206000200160006113a49190617b1a565b9055600101611322565b505b60005b828110156115f0578181106114d85760158482815181106113d057fe5b602090810291909101810151825460018181018555600094855293839020825160049092020180546001600160a01b039283166001600160a01b0319918216178255938301519481018054958316958516959095179094556040820151600285018054606085015160808601511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b199590961692909716919091179290921692909217169290921790915560a0015160039091015585516016908790839081106114a057fe5b602090810291909101810151825460018101845560009384529282902081516114d29491909101929190910190617a1a565b506115e8565b8381815181106114e457fe5b6020026020010151601582815481106114f957fe5b6000918252602091829020835160049092020180546001600160a01b039283166001600160a01b0319918216178255928401516001820180549184169185169190911790556040840151600282018054606087015160808801511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b1995909716929097169190911792909216939093171692909217905560a09091015160039091015585518690829081106115b457fe5b6020026020010151601682815481106115c957fe5b9060005260206000200190805190602001906115e6929190617a1a565b505b6001016113b3565b507fb8e726330a0dad1cf3d04e925663b17e391f1ed547d79b7f4e5f344119b44246826040516116209190618ed8565b60405180910390a150505050610e32565b60608061163e8386615513565b9150915060005b6001548110156117345760006001828154811061165e57fe5b90600052602060002090600402016003015490508060001461172b5760006001838154811061168957fe5b9060005260206000209060040201600301819055506120026001600160a01b031663092193ab82600185815481106116bd57fe5b60009182526020909120600491820201546040516001600160e01b031960e086901b1681526116f8926001600160a01b0390921691016181eb565b6000604051808303818588803b15801561171157600080fd5b505af1158015611725573d6000803e3d6000fd5b50505050505b50600101611645565b5047156117a2577f6ecc855f9440a9282c90913bbc91619fd44f5ec0b462af28d127b116f130aa4d4760405161176a9190618ed8565b60405180910390a1604051611002904780156108fc02916000818181858888f193505050501580156117a0573d6000803e3d6000fd5b505b600060038190556005558151156117bd576117bd82826159fa565b6110016001600160a01b031663fc4333cd6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156117fa57600080fd5b505af115801561180e573d6000803e3d6000fd5b50506040517fedd8d7296956dd970ab4de3f2fc03be2b0ffc615d20cd4c72c6e44f928630ebf925060009150a150505050505050565b60035481565b606881565b61200581565b33612002146118765760405162461bcd60e51b8152600401610e1290618e92565b60005b6015548110156118fe57816001600160a01b03166015828154811061189a57fe5b60009182526020909120600490910201546001600160a01b031614156118f6576001601582815481106118c957fe5b9060005260206000209060040201600201601c6101000a81548160ff0219169083151502179055506118fe565b600101611879565b5050565b3341146119215760405162461bcd60e51b8152600401610e1290618d34565b60105443116119425760405162461bcd60e51b8152600401610e1290618738565b3a156119605760405162461bcd60e51b8152600401610e1290618a23565b60005460ff166119825760405162461bcd60e51b8152600401610e12906185a5565b60006110023168056bc75e2d631000008111156119b9576119b28168056bc75e2d6310000063ffffffff6161e916565b91506119c0565b5050611c41565b6040516309a99b4f60e41b815261100290639a99b4f0906119e790309086906004016181ff565b602060405180830381600087803b158015611a0157600080fd5b505af1158015611a15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a399190618096565b915081611a47575050611c41565b6000805b84811015611a7557858582818110611a5f57fe5b9050602002013582019150806001019050611a4b565b5080611a8357505050611c41565b6000806000805b89811015611c395784898983818110611a9f57fe5b90506020020135880281611aaf57fe5b0493508a8a82818110611abe57fe5b9050602002016020810190611ad39190617e3f565b6001600160a01b03811660009081526004602052604090205490935091508115611bef576000600180840381548110611b0857fe5b9060005260206000209060040201905080600201601c9054906101000a900460ff1615611b7557836001600160a01b03167fb9c75cbbfde137c4281689580799ef5f52144e78858f776a5979b2b212137d8586604051611b689190618ed8565b60405180910390a2611be9565b600354611b88908663ffffffff61622b16565b6003908155810154611ba0908663ffffffff61622b16565b60038201556040516001600160a01b038516907fcb0aad6cf9cd03bdf6137e359f541c42f38b39f007cae8e89e88aa7d8c6617b290611be0908890618ed8565b60405180910390a25b50611c31565b826001600160a01b03167fb9c75cbbfde137c4281689580799ef5f52144e78858f776a5979b2b212137d8585604051611c289190618ed8565b60405180910390a25b600101611a8a565b505050505050505b5050436010555050565b6001546000908210611c5f57506000611d15565b60006001600160a01b031660018381548110611c7757fe5b60009182526020909120600490910201546001600160a01b03161480611ca757506008541580611ca75750600a54155b80611cb6575060085460095410155b80611cc75750611cc582611d1a565b155b80611cf057506000600b8381548110611cdc57fe5b906000526020600020906016020160000154115b80611d0457506001611d006130a3565b5111155b15611d1157506000611d15565b5060015b919050565b6001546000908210611d2e57506000611d15565b600b548210611d6b5760018281548110611d4457fe5b9060005260206000209060040201600201601c9054906101000a900460ff16159050611d15565b60018281548110611d7857fe5b9060005260206000209060040201600201601c9054906101000a900460ff16158015611dc55750600b8281548110611dac57fe5b600091825260209091206001601690920201015460ff16155b92915050565b600b54611e8957611dda6179eb565b60015460005b81811015611e8557600b80546001810182556000919091528351600080516020618fe583398151915260169092029182019081556020808601516000805160206196148339815191528401805460ff1916911515919091179055604086015180518794611e6193600080516020619005833981519152909101920190617a1a565b506060820151611e779060038301906013617a94565b505050806001019050611de0565b5050505b336110011480611e9a575033612002145b611eb65760405162461bcd60e51b8152600401610e12906185dc565b6001600160a01b03811660009081526004602052604090205480611eda5750611f2d565b6001810390506000600b8281548110611eef57fe5b600091825260209091206001601690920201015460ff169050611f128383615150565b8015611f1b5750805b15610e32576009805460001901905550505b50565b60015460609081906000805b82811015611f835760018181548110611f5157fe5b9060005260206000209060040201600201601c9054906101000a900460ff16611f7b576001909101905b600101611f3c565b50606081604051908082528060200260200182016040528015611fb0578160200160208202803683370190505b509050606082604051908082528060200260200182016040528015611fe957816020015b6060815260200190600190039081611fd45790505b50600b54600094509091508414156121645760005b8481101561215e576001818154811061201357fe5b9060005260206000209060040201600201601c9054906101000a900460ff16612156576001818154811061204357fe5b600091825260209091206004909102015483516001600160a01b039091169084908690811061206e57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050600b818154811061209b57fe5b600091825260209182902060026016909202018101805460408051601f6000196101006001861615020190931694909404918201859004850284018501905280835291929091908301828280156121335780601f1061210857610100808354040283529160200191612133565b820191906000526020600020905b81548152906001019060200180831161211657829003601f168201915b505050505082858151811061214457fe5b60209081029190910101526001909301925b600101611ffe565b50612200565b60005b848110156121fe576001818154811061217c57fe5b9060005260206000209060040201600201601c9054906101000a900460ff166121f657600181815481106121ac57fe5b600091825260209091206004909102015483516001600160a01b03909116908490869081106121d757fe5b6001600160a01b03909216602092830291909101909101526001909301925b600101612167565b505b909450925050505b9091565b600181565b61100181565b60085481565b603881565b600881565b6060806000600e549050600080600c5411612243576015612247565b600c545b905060606122536130a3565b9050606061226082616250565b905082825111612277579094509250612208915050565b83838351031015612289578282510393505b83156122bf5760c843046122a583838388880360008a8a6163be565b6122bd8383838888038989038a8b8b8b5103016163be565b505b6060836040519080825280602002602001820160405280156122eb578160200160208202803683370190505b50905060608460405190808252806020026020018201604052801561232457816020015b606081526020019060019003908161230f5790505b50905060005b858110156123a55784818151811061233e57fe5b602002602001015183828151811061235257fe5b60200260200101906001600160a01b031690816001600160a01b03168152505083818151811061237e57fe5b602002602001015182828151811061239257fe5b602090810291909101015260010161232a565b509096509450505050509091565b60065481565b61200681565b61200081565b6001600160a01b038116600090815260046020526040812054806123ed576000915050611d15565b6000190161115e81611d1a565b6001600160a01b03811660009081526004602052604081205480612422576000915050611d15565b60018082038154811061243157fe5b906000526020600020906004020160030154915050919050565b600081565b606781565b600f5481565b6012818154811061246857fe5b600091825260209182902001805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152935090918301828280156124f95780601f106124ce576101008083540402835291602001916124f9565b820191906000526020600020905b8154815290600101906020018083116124dc57829003601f168201915b505050505081565b60105481565b6001818154811061251457fe5b600091825260209091206004909102018054600182015460028301546003909301546001600160a01b0392831694509082169291821691600160a01b81046001600160401b031691600160e01b90910460ff169086565b61100581565b600281565b601081565b61100881565b6103e881565b600b81565b600c5481565b61200381565b606681565b61271081565b33612000146125c45760405162461bcd60e51b8152600401610e1290618ce5565b7f41ce201247b6ceb957dcdb217d0b8acb50b9ea0e12af9af4f5e7f389021016058383836040516125f793929190618f21565b60405180910390a1505050565b60025481565b60115481565b60145460ff1681565b600a5481565b6001600160a01b038116600090815260046020526040812054806126555760405162461bcd60e51b8152600401610e1290618c6d565b6000190192915050565b600b5461271d5761266e6179eb565b60015460005b8181101561271957600b80546001810182556000919091528351600080516020618fe583398151915260169092029182019081556020808601516000805160206196148339815191528401805460ff19169115159190911790556040860151805187946126f593600080516020619005833981519152909101920190617a1a565b50606082015161270b9060038301906013617a94565b505050806001019050612674565b5050505b60085461272a5760036008555b600a54612737576002600a555b60006127423361261f565b905061274d81611c4b565b6127695760405162461bcd60e51b8152600401610e129061895a565b611f2d3382616515565b600981565b61100781565b600381565b60c881565b61100681565b6040518061062001604052806105ef81526020016190256105ef913981565b60005460ff1681565b61200281565b61300081565b6402540be40081565b60005460ff166127ed5760405162461bcd60e51b8152600401610e12906185a5565b336110071461280e5760405162461bcd60e51b8152600401610e1290618a51565b61287884848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080518082019091526013815272065787069726554696d655365636f6e6447617606c1b602082015291506165ad9050565b15612915576020811461289d5760405162461bcd60e51b8152600401610e1290618c27565b604080516020601f84018190048102820181019092528281526000916128db9185858083850183828082843760009201919091525061660692505050565b9050606481101580156128f15750620186a08111155b61290d5760405162461bcd60e51b8152600401610e129061884a565b600255613041565b61297584848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260098152686275726e526174696f60b81b602082015291506165ad9050565b15612a18576020811461299a5760405162461bcd60e51b8152600401610e12906183c3565b604080516020601f84018190048102820181019092528281526000916129d89185858083850183828082843760009201919091525061660692505050565b90506127106129f2600f548361622b90919063ffffffff16565b1115612a105760405162461bcd60e51b8152600401610e12906183fa565b600655613041565b612a8284848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260138152726d61784e756d4f664d61696e7461696e696e6760681b602082015291506165ad9050565b15612b1c5760208114612aa75760405162461bcd60e51b8152600401610e1290618462565b604080516020601f8401819004810282018101909252828152600091612ae59185858083850183828082843760009201919091525061660692505050565b600c5490915080612af4575060155b808210612b135760405162461bcd60e51b8152600401610e12906187a2565b50600855613041565b612b8584848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260128152716d61696e7461696e536c6173685363616c6560701b602082015291506165ad9050565b15612c1e5760208114612baa5760405162461bcd60e51b8152600401610e129061852b565b604080516020601f8401819004810282018101909252828152600091612be89185858083850183828082843760009201919091525061660692505050565b9050600081118015612bfa5750600a81105b612c165760405162461bcd60e51b8152600401610e1290618dc5565b600a55613041565b612c9284848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601981527f6d61784e756d4f66576f726b696e6743616e6469646174657300000000000000602082015291506165ad9050565b15612d215760208114612cb75760405162461bcd60e51b8152600401610e12906184df565b604080516020601f8401819004810282018101909252828152600091612cf59185858083850183828082843760009201919091525061660692505050565b9050600d54811115612d195760405162461bcd60e51b8152600401610e12906188c0565b600e55613041565b612d8a84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260128152716d61784e756d4f6643616e6469646174657360701b602082015291506165ad9050565b15612e0c5760208114612daf5760405162461bcd60e51b8152600401610e1290618a9f565b604080516020601f8401819004810282018101909252828152600091612ded9185858083850183828082843760009201919091525061660692505050565b600d819055600e54909150811015612e0657600d54600e555b50613041565b612e7084848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600d81526c6e756d4f66436162696e65747360981b602082015291506165ad9050565b15612f1e5760208114612e955760405162461bcd60e51b8152600401610e1290618570565b604080516020601f8401819004810282018101909252828152600091612ed39185858083850183828082843760009201919091525061660692505050565b905060008111612ef55760405162461bcd60e51b8152600401610e129061864a565b6064811115612f165760405162461bcd60e51b8152600401610e1290618692565b600c55613041565b612f8684848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601181527073797374656d526577617264526174696f60781b602082015291506165ad9050565b156130295760208114612fab5760405162461bcd60e51b8152600401610e1290618d81565b604080516020601f8401819004810282018101909252828152600091612fe99185858083850183828082843760009201919091525061660692505050565b90506127106130036006548361622b90919063ffffffff16565b11156130215760405162461bcd60e51b8152600401610e1290618b88565b600f55613041565b60405162461bcd60e51b8152600401610e1290618e22565b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a848484846040516130769493929190618391565b60405180910390a150505050565b60046020526000908152604090205481565b68056bc75e2d6310000081565b6001546060906000805b828110156130d2576130be81611d1a565b156130ca578160010191505b6001016130ad565b506060816040519080825280602002602001820160405280156130ff578160200160208202803683370190505b5090506000915060005b838110156131865761311a81611d1a565b1561317e576001818154811061312c57fe5b600091825260209091206004909102015482516001600160a01b039091169083908590811061315757fe5b60200260200101906001600160a01b031690816001600160a01b0316815250508260010192505b600101613109565b50925050505b90565b601581565b61027181565b61100281565b6013818154811061246857fe5b60006131b76130a3565b519050600080600c54116131cc5760156131d0565b600c545b9050808211156131de578091505b816131e857600191505b5090565b67016345785d8a000081565b60055481565b61100381565b61200481565b60005460ff161561322d5760405162461bcd60e51b8152600401610e1290618b51565b613235617ac1565b600061325b6040518061062001604052806105ef81526020016190256105ef9139613d71565b915091508061327c5760405162461bcd60e51b8152600401610e1290618ca4565b60005b8260200151518110156133a15760018360200151828151811061329e57fe5b60209081029190910181015182546001818101855560009485528385208351600493840290910180546001600160a01b039283166001600160a01b03199182161782558587015182850180549185169183169190911790556040860151600283018054606089015160808a01511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b199590981692909516919091179290921694909417161790915560a09093015160039093019290925591860151805191850193918590811061337457fe5b602090810291909101810151516001600160a01b031682528101919091526040016000205560010161327f565b50506103e8600255506000805460ff19166001179055565b600d5481565b601354600090815b818110156134c8576134b085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060138054909250859150811061341857fe5b600091825260209182902001805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152928301828280156134a65780601f1061347b576101008083540402835291602001916134a6565b820191906000526020600020905b81548152906001019060200180831161348957829003601f168201915b505050505061660b565b156134c057600192505050611dc5565b6001016133c7565b5060125460005b818110156135395761352086868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060128054909250859150811061341857fe5b156135315760019350505050611dc5565b6001016134cf565b50600095945050505050565b33611001146135665760405162461bcd60e51b8152600401610e1290618e49565b600b54613624576135756179eb565b60015460005b8181101561362057600b80546001810182556000919091528351600080516020618fe583398151915260169092029182019081556020808601516000805160206196148339815191528401805460ff19169115159190911790556040860151805187946135fc93600080516020619005833981519152909101920190617a1a565b5060608201516136129060038301906013617a94565b50505080600101905061357b565b5050505b600061362f8261666f565b905061363a81611c4b565b156118fe576118fe8282616515565b606581565b601181565b3341146136725760405162461bcd60e51b8152600401610e1290618d34565b60005460ff166136945760405162461bcd60e51b8152600401610e12906185a5565b600034116136b45760405162461bcd60e51b8152600401610e1290618891565b3a156136d25760405162461bcd60e51b8152600401610e1290618a23565b6001600160a01b03811660009081526004602052604090205460145434919060ff1661371257610271600f556103e86006556014805460ff191660011790555b60008211801561372457506000600f54115b156137d6576000613752612710613746600f54346167f290919063ffffffff16565b9063ffffffff61682c16565b905080156137d4576040516110029082156108fc029083906000818181858888f19350505050158015613789573d6000803e3d6000fd5b507f6ecc855f9440a9282c90913bbc91619fd44f5ec0b462af28d127b116f130aa4d816040516137b99190618ed8565b60405180910390a16137d1838263ffffffff6161e916565b92505b505b6000821180156137e857506000600654115b1561388e57600061380a612710613746600654346167f290919063ffffffff16565b9050801561388c5760405161dead9082156108fc029083906000818181858888f19350505050158015613841573d6000803e3d6000fd5b507f627059660ea01c4733a328effb2294d2f86905bf806da763a89cee254de8bee5816040516138719190618ed8565b60405180910390a1613889838263ffffffff6161e916565b92505b505b801561398c5760006001808303815481106138a557fe5b9060005260206000209060040201905080600201601c9054906101000a900460ff161561391257836001600160a01b03167ff177e5d6c5764d79c32883ed824111d9b13f5668cf6ab1cc12dd36791dd955b4846040516139059190618ed8565b60405180910390a2613986565b600354613925908463ffffffff61622b16565b600390815581015461393d908463ffffffff61622b16565b60038201556040516001600160a01b038516907f93a090ecc682c002995fad3c85b30c5651d7fd29b0be5da9d784a3302aedc0559061397d908690618ed8565b60405180910390a25b50610e32565b826001600160a01b03167ff177e5d6c5764d79c32883ed824111d9b13f5668cf6ab1cc12dd36791dd955b4836040516139c59190618ed8565b60405180910390a2505050565b600e5481565b61100081565b61dead81565b600b81815481106139f157fe5b6000918252602091829020601691909102018054600180830154600280850180546040805161010096831615969096026000190190911692909204601f810188900488028501880190925281845293965060ff90911694919291830182828015613a9c5780601f10613a7157610100808354040283529160200191613a9c565b820191906000526020600020905b815481529060010190602001808311613a7f57829003601f168201915b5050505050905083565b61100481565b6000600a5460001480613abd575081155b80613ac85750600954155b15613ad55750600061115e565b6000613b0f600a5461374685613746600b8981548110613af157fe5b6000918252602090912060169091020154439063ffffffff6161e916565b90506000806110016001600160a01b0316638256ace66040518163ffffffff1660e01b8152600401604080518083038186803b158015613b4e57600080fd5b505afa158015613b62573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b8691906180ae565b9150915060009350808310613ce557613b9f8787615150565b5060405163436aa28360e11b8152600090612002906386d5450690613bc8908b906004016181eb565b60206040518083038186803b158015613be057600080fd5b505afa158015613bf4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c189190617e5b565b6001600160a01b031614613c84576040516313d13bdb60e31b815261100190639e89ded890613c4d908a9087906004016181ff565b600060405180830381600087803b158015613c6757600080fd5b505af1158015613c7b573d6000803e3d6000fd5b50505050613cdc565b6040516305bfb49960e41b815261100190635bfb499090613ca9908a906004016181eb565b600060405180830381600087803b158015613cc357600080fd5b505af1158015613cd7573d6000803e3d6000fd5b505050505b60019350613cf7565b818310613cf757613cf58761666f565b505b60098054600019019055600b80546000919088908110613d1357fe5b60009182526020822060169190910201600101805460ff1916921515929092179091556040516001600160a01b038916917fb9d38178dc641ff1817967a63c9078cbcd955a9f1fcd75e0e3636de615d44d3b91a25050509392505050565b613d79617ac1565b6000613d83617ac1565b613d8b617b5e565b613d9c613d978661686e565b616893565b90506000805b613dab836168dd565b15613f1f5780613dd057613dc6613dc1846168fe565b61694c565b60ff168452613f17565b8060011415613f12576060613dec613de7856168fe565b6169cc565b90508051604051908082528060200260200182016040528015613e2957816020015b613e16617ae5565b815260200190600190039081613e0e5790505b5085602001819052508051604051908082528060200260200182016040528015613e6757816020015b6060815260200190600190039081613e525790505b50604086015260005b8151811015613f0757613e81617ae5565b60606000613ea1858581518110613e9457fe5b6020026020010151616a9d565b92509250925080613ec1578860009a509a50505050505050505050613f28565b8289602001518581518110613ed257fe5b60200260200101819052508189604001518581518110613eee57fe5b6020026020010181905250505050806001019050613e70565b506001925050613f17565b613f1f565b600101613da2565b50919350909150505b915091565b604080516001808252818301909252606091829190816020015b6060815260200190600190039081613f47579050509050613f6d8363ffffffff16616bb7565b81600081518110613f7a57fe5b602002602001018190525061115e81616bca565b6000606483511115613fc557600080516020618fc5833981519152604051613fb5906186ef565b60405180910390a1506066611dc5565b60005b83518110156140635760005b8181101561405a57848181518110613fe857fe5b6020026020010151600001516001600160a01b031685838151811061400957fe5b6020026020010151600001516001600160a01b0316141561405257600080516020618fc583398151915260405161403f906187ff565b60405180910390a1606692505050611dc5565b600101613fd4565b50600101613fc8565b5060608060606015805480602002602001604051908101604052809291908181526020016000905b828210156141155760008481526020908190206040805160c0810182526004860290920180546001600160a01b039081168452600180830154821685870152600283015491821693850193909352600160a01b81046001600160401b03166060850152600160e01b900460ff16151560808401526003015460a0830152908352909201910161408b565b50505050905060606016805480602002602001604051908101604052809291908181526020016000905b828210156141ea5760008481526020908190208301805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152928301828280156141d65780601f106141ab576101008083540402835291602001916141d6565b820191906000526020600020905b8154815290600101906020018083116141b957829003601f168201915b50505050508152602001906001019061413f565b50505050905060005b82518110156142475782818151811061420857fe5b60200260200101516060015160030283828151811061422357fe5b60209081029190910101516001600160401b039091166060909101526001016141f3565b5060608061425789898686616c54565b915091506142658282615513565b600154604080518281526020808402820101909152929850909650600095508594509250606091508280156142a4578160200160208202803683370190505b50905060005b828110156144355760006001600160a01b03166120026001600160a01b03166386d54506600184815481106142db57fe5b60009182526020909120600491820201546040516001600160e01b031960e085901b168152614316926001600160a01b0390921691016181eb565b60206040518083038186803b15801561432e57600080fd5b505afa158015614342573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143669190617e5b565b6001600160a01b0316146143c857600182828151811061438257fe5b602002602001019060ff16908160ff1681525050600181815481106143a357fe5b9060005260206000209060040201600301546000146143c3578360010193505b61442d565b67016345785d8a0000600182815481106143de57fe5b906000526020600020906004020160030154106144005784600101945061442d565b6001818154811061440d57fe5b90600052602060002090600402016003015460001461442d578360010193505b6001016142aa565b50606084604051908082528060200260200182016040528015614462578160200160208202803683370190505b509050606085604051908082528060200260200182016040528015614491578160200160208202803683370190505b5090506060866040519080825280602002602001820160405280156144c0578160200160208202803683370190505b5090506060876040519080825280602002602001820160405280156144ef578160200160208202803683370190505b5090506000606088604051908082528060200260200182016040528015614520578160200160208202803683370190505b50905060608960405190808252806020026020018201604052801561454f578160200160208202803683370190505b50905060009a506000995060006110046001600160a01b031663149d14d96040518163ffffffff1660e01b815260040160206040518083038186803b15801561459757600080fd5b505afa1580156145ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145cf9190618096565b905067016345785d8a000081111561461b57600080516020618fc58339815191526040516145fc90618b10565b60405180910390a160689e505050505050505050505050505050611dc5565b60005b8a8110156149af5789818151811061463257fe5b602002602001015160ff1660011415614728576001818154811061465257fe5b906000526020600020906004020160030154600014614723576001818154811061467857fe5b600091825260209091206004909102015484516001600160a01b039091169085908e9081106146a357fe5b60200260200101906001600160a01b031690816001600160a01b031681525050600181815481106146d057fe5b906000526020600020906004020160030154838d815181106146ee57fe5b60200260200101818152505060018a8d8151811061470857fe5b602002602001019060ff16908160ff16815250508b6001019b505b6149a7565b67016345785d8a00006001828154811061473e57fe5b906000526020600020906004020160030154106148c3576001818154811061476257fe5b906000526020600020906004020160020160009054906101000a90046001600160a01b0316898e8151811061479357fe5b60200260200101906001600160a01b031690816001600160a01b03168152505060006402540be400600183815481106147c857fe5b906000526020600020906004020160030154816147e157fe5b06600183815481106147ef57fe5b90600052602060002090600402016003015403905061481783826161e990919063ffffffff16565b898f8151811061482357fe5b6020026020010181815250506001828154811061483c57fe5b906000526020600020906004020160010160009054906101000a90046001600160a01b0316878f8151811061486d57fe5b60200260200101906001600160a01b031690816001600160a01b03168152505081888f8151811061489a57fe5b60209081029190910101526148b5868263ffffffff61622b16565b95508d6001019d50506149a7565b600181815481106148d057fe5b9060005260206000209060040201600301546000146149a757600181815481106148f657fe5b906000526020600020906004020160010160009054906101000a90046001600160a01b0316848d8151811061492757fe5b60200260200101906001600160a01b031690816001600160a01b0316815250506001818154811061495457fe5b906000526020600020906004020160030154838d8151811061497257fe5b60200260200101818152505060008a8d8151811061498c57fe5b602002602001019060ff16908160ff16815250508b6001019b505b60010161461e565b5060008415614c25576002546040516303702b2960e51b815261100491636e0565209188916149e9918e918e918d914201906004016182f9565b6020604051808303818588803b158015614a0257600080fd5b505af193505050508015614a33575060408051601f3d908101601f19168201909252614a3091810190617fc3565b60015b614baa576040516000815260443d1015614a4f57506000614aea565b60046000803e60005160e01c6308c379a08114614a70576000915050614aea565b60043d036004833e81513d60248201116001600160401b0382111715614a9b57600092505050614aea565b80830180516001600160401b03811115614abc576000945050505050614aea565b8060208301013d8601811115614ada57600095505050505050614aea565b601f01601f191660405250925050505b80614af55750614b37565b60019150857fa7cdeed7d0db45e3219a6e5d60838824c16f1d39991fcfe3f963029c844bf28082604051614b29919061837e565b60405180910390a250614ba5565b3d808015614b61576040519150601f19603f3d011682016040523d82523d6000602084013e614b66565b606091505b5060019150857fbfa884552dd8921b6ce90bfe906952ae5b3b29be0cc1a951d4f62697635a3a4582604051614b9b919061837e565b60405180910390a2505b614c25565b8015614bec577fa217d08e65f80c73121cd9db834d81652d544bfbf452f6d04922b16c90a37b7086604051614bdf9190618ed8565b60405180910390a1614c23565b857fa7cdeed7d0db45e3219a6e5d60838824c16f1d39991fcfe3f963029c844bf280604051614c1a906184a8565b60405180910390a25b505b8015614ddb5760005b8751811015614dd9576000888281518110614c4557fe5b60200260200101519050600060018281548110614c5e57fe5b60009182526020909120600160049092020181015481546001600160a01b03909116916108fc9185908110614c8f57fe5b9060005260206000209060040201600301549081150290604051600060405180830381858888f1935050505090508015614d4b5760018281548110614cd057fe5b60009182526020909120600160049092020181015481546001600160a01b03909116917f6c61d60f69a7beb3e1c80db7f39f37b208537cbb19da3174511b477812b2fc7d9185908110614d1f57fe5b906000526020600020906004020160030154604051614d3e9190618ed8565b60405180910390a2614dcf565b60018281548110614d5857fe5b60009182526020909120600160049092020181015481546001600160a01b03909116917f25d0ce7d2f0cec669a8c17efe49d195c13455bb8872b65fa610ac7f53fe4ca7d9185908110614da757fe5b906000526020600020906004020160030154604051614dc69190618ed8565b60405180910390a25b5050600101614c2e565b505b835115614fd15760005b8451811015614fcf578a8181518110614dfa57fe5b602002602001015160ff1660011415614e99576120026001600160a01b031663092193ab858381518110614e2a57fe5b6020026020010151878481518110614e3e57fe5b60200260200101516040518363ffffffff1660e01b8152600401614e6291906181eb565b6000604051808303818588803b158015614e7b57600080fd5b505af1158015614e8f573d6000803e3d6000fd5b5050505050614fc7565b6000858281518110614ea757fe5b60200260200101516001600160a01b03166108fc868481518110614ec757fe5b60200260200101519081150290604051600060405180830381858888f1935050505090508015614f5d57858281518110614efd57fe5b60200260200101516001600160a01b03167f6c61d60f69a7beb3e1c80db7f39f37b208537cbb19da3174511b477812b2fc7d868481518110614f3b57fe5b6020026020010151604051614f509190618ed8565b60405180910390a2614fc5565b858281518110614f6957fe5b60200260200101516001600160a01b03167f25d0ce7d2f0cec669a8c17efe49d195c13455bb8872b65fa610ac7f53fe4ca7d868481518110614fa757fe5b6020026020010151604051614fbc9190618ed8565b60405180910390a25b505b600101614de5565b505b5050505050505050505050505060005b60015481101561503e5760018181548110614ff857fe5b9060005260206000209060040201600301546000146150365760006001828154811061502057fe5b9060005260206000209060040201600301819055505b600101614fe1565b5047156150ac577f6ecc855f9440a9282c90913bbc91619fd44f5ec0b462af28d127b116f130aa4d476040516150749190618ed8565b60405180910390a1604051611002904780156108fc02916000818181858888f193505050501580156150aa573d6000803e3d6000fd5b505b600060038190556005558151156150c7576150c782826159fa565b6110016001600160a01b031663fc4333cd6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561510457600080fd5b505af1158015615118573d6000803e3d6000fd5b50506040517fedd8d7296956dd970ab4de3f2fc03be2b0ffc615d20cd4c72c6e44f928630ebf925060009150a1506000949350505050565b6000806001838154811061516057fe5b9060005260206000209060040201600301549050600060018080549050039050600161518a6130a3565b51116151bf5760006001858154811061519f57fe5b906000526020600020906004020160030181905550600092505050611dc5565b846001600160a01b03167f3b6f9ef90462b512a1293ecec018670bf7b7f1876fb727590a8a6d7643130a70836040516151f89190618ed8565b60405180910390a26001600160a01b038516600090815260046020526040812055835b600154600019018110156153e5576001816001018154811061523957fe5b90600052602060002090600402016001828154811061525457fe5b60009182526020909120825460049092020180546001600160a01b03199081166001600160a01b0393841617825560018085015481840180548416918616919091179055600280860180549185018054909416919095161780835584546001600160401b03600160a01b91829004160267ffffffffffffffff60a01b1990911617808355935460ff600160e01b918290041615150260ff60e01b19909416939093179055600392830154920191909155600b80549091830190811061531557fe5b9060005260206000209060160201600b828154811061533057fe5b600091825260209091208254601690920201908155600180830154818301805460ff909216151560ff1990921691909117905560028084018054615387938386019390821615610100026000190190911604617b7e565b5061539a60038281019084016013617bf3565b509050508060010160046000600184815481106153b357fe5b600091825260208083206004909202909101546001600160a01b0316835282019290925260400190205560010161521b565b5060018054806153f157fe5b60008281526020812060046000199093019283020180546001600160a01b0319908116825560018201805490911690556002810180546001600160e81b0319169055600301559055600b80548061544457fe5b60008281526020812060166000199093019283020181815560018101805460ff19169055906154766002830182617b1a565b615484600383016000617c1d565b50509055600081838161549357fe5b04905080156155075760015460005b81811015615504576154db83600183815481106154bb57fe5b90600052602060002090600402016003015461622b90919063ffffffff16565b600182815481106154e857fe5b60009182526020909120600360049092020101556001016154a2565b50505b50600195945050505050565b6060806000808080806155246131ad565b6001549091505b801561575357600181039250600b838154811061554457fe5b600091825260209091206001601690920201015460ff166155645761574a565b6001838154811061557157fe5b60009182526020909120600490910201546001600160a01b03169450615598858484613aac565b9350836155a45761574a565b60405163436aa28360e11b81526000908190612002906386d54506906155ce908a906004016181eb565b60206040518083038186803b1580156155e657600080fd5b505afa1580156155fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061561e9190617e5b565b90506001600160a01b038116156156a7576040516302ceee9160e11b81526120029063059ddd22906156549084906004016181eb565b60206040518083038186803b15801561566c57600080fd5b505afa158015615680573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906156a49190617e5b565b91505b60005b8c5181101561574657876001600160a01b03168d82815181106156c957fe5b6020026020010151600001516001600160a01b031614806157125750826001600160a01b03168d82815181106156fb57fe5b6020026020010151600001516001600160a01b0316145b1561573e5760018d828151811061572557fe5b6020908102919091010151901515608090910152615746565b6001016156aa565b5050505b6000190161552b565b5060005b89518110156157c05789818151811061576c57fe5b602002602001015160800151806157ac575060006001600160a01b03168a828151811061579557fe5b6020026020010151600001516001600160a01b0316145b156157b8578560010195505b600101615757565b50885185106158a85760408051600180825281830190925290816020015b6157e6617ae5565b8152602001906001900390816157de575050604080516001808252818301909252919850602082015b606081526020019060019003908161580f5790505095508860008151811061583357fe5b60200260200101518760008151811061584857fe5b60200260200101819052508760008151811061586057fe5b60200260200101518660008151811061587557fe5b602002602001018190525060008760008151811061588f57fe5b60209081029190910101519015156080909101526159ed565b848951036040519080825280602002602001820160405280156158e557816020015b6158d2617ae5565b8152602001906001900390816158ca5790505b5096508489510360405190808252806020026020018201604052801561591f57816020015b606081526020019060019003908161590a5790505b5095506000915060005b89518110156159eb5789818151811061593e57fe5b602002602001015160800151158015615981575060006001600160a01b03168a828151811061596957fe5b6020026020010151600001516001600160a01b031614155b156159e35789818151811061599257fe5b60200260200101518884815181106159a657fe5b60200260200101819052508881815181106159bd57fe5b60200260200101518784815181106159d157fe5b60200260200101819052508260010192505b600101615929565b505b50505050505b9250929050565b600154825160005b82811015615b17576001615a14617ae5565b60018381548110615a2157fe5b600091825260208083206040805160c08101825260049490940290910180546001600160a01b0390811685526001820154811693850193909352600281015492831691840191909152600160a01b82046001600160401b03166060840152600160e01b90910460ff16151560808301526003015460a082015291505b84811015615aeb57878181518110615ab157fe5b6020026020010151600001516001600160a01b031682600001516001600160a01b03161415615ae35760009250615aeb565b600101615a9d565b508115615b0d5780516001600160a01b03166000908152600460205260408120555b5050600101615a02565b5080821115615bd657805b82811015615bd4576001805480615b3557fe5b60008281526020812060046000199093019283020180546001600160a01b0319908116825560018201805490911690556002810180546001600160e81b0319169055600301559055600b805480615b8857fe5b60008281526020812060166000199093019283020181815560018101805460ff1916905590615bba6002830182617b1a565b615bc8600383016000617c1d565b50509055600101615b22565b505b6000818310615be55781615be7565b825b905060005b81811015615f8b57615c99868281518110615c0357fe5b602002602001015160018381548110615c1857fe5b60009182526020918290206040805160c08101825260049390930290910180546001600160a01b0390811684526001820154811694840194909452600281015493841691830191909152600160a01b83046001600160401b03166060830152600160e01b90920460ff161515608082015260039091015460a0820152617020565b615e4d578060010160046000888481518110615cb157fe5b6020026020010151600001516001600160a01b03166001600160a01b0316815260200190815260200160002081905550858181518110615ced57fe5b602002602001015160018281548110615d0257fe5b6000918252602091829020835160049092020180546001600160a01b039283166001600160a01b0319918216178255928401516001820180549184169185169190911790556040840151600282018054606087015160808801511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b1995909716929097169190911792909216939093171692909217905560a0909101516003909101558451859082908110615dbd57fe5b6020026020010151600b8281548110615dd257fe5b90600052602060002090601602016002019080519060200190615df6929190617a1a565b506000600b8281548110615e0657fe5b60009182526020822060169190910201600101805460ff191692151592909217909155600b805483908110615e3757fe5b6000918252602090912060169091020155615f83565b858181518110615e5957fe5b60200260200101516060015160018281548110615e7257fe5b906000526020600020906004020160020160146101000a8154816001600160401b0302191690836001600160401b03160217905550615f38858281518110615eb657fe5b6020026020010151600b8381548110615ecb57fe5b600091825260209182902060026016909202018101805460408051601f6000196101006001861615020190931694909404918201859004850284018501905280835291929091908301828280156134a65780601f1061347b576101008083540402835291602001916134a6565b615f8357848181518110615f4857fe5b6020026020010151600b8281548110615f5d57fe5b90600052602060002090601602016002019080519060200190615f81929190617a1a565b505b600101615bec565b508282111561616357615f9c6179eb565b835b8381101561616057858181518110615fb257fe5b602002602001015182604001819052506001878281518110615fd057fe5b6020908102919091018101518254600181810185556000948552838520835160049093020180546001600160a01b039384166001600160a01b0319918216178255848601518284018054918616918316919091179055604080860151600284018054606089015160808a01511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b1995909a1692909616919091179290921696909617169190911790935560a090930151600390930192909255600b8054928301815590935284516016909102600080516020618fe58339815191528101918255858301516000805160206196148339815191528201805491151560ff19909216919091179055928501518051869492936161069360008051602061900583398151915201920190617a1a565b50606082015161611c9060038301906013617a94565b505050806001016004600089848151811061613357fe5b602090810291909101810151516001600160a01b0316825281019190915260400160002055600101615f9e565b50505b61616b61707c565b616173617264565b6000600981905560015493505b838110156161e1576000600b828154811061619757fe5b60009182526020822060169190910201600101805460ff191692151592909217909155600b8054839081106161c857fe5b6000918252602090912060169091020155600101616180565b505050505050565b600061115e83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250617452565b60008282018381101561115e5760405162461bcd60e51b8152600401610e1290618613565b60015481516040805182815260208084028201019091526060929190839082801561628f57816020015b606081526020019060019003908161627a5790505b50600b5490915083146162a6579250611d15915050565b60005b828110156163b557600b6001600460008985815181106162c557fe5b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205403815481106162f957fe5b600091825260209182902060026016909202018101805460408051601f6000196101006001861615020190931694909404918201859004850284018501905280835291929091908301828280156163915780601f1061636657610100808354040283529160200191616391565b820191906000526020600020905b81548152906001019060200180831161637457829003601f168201915b50505050508282815181106163a257fe5b60209081029190910101526001016162a9565b50949350505050565b60005b8281101561650b57600082878388016040516020016163e19291906181dd565b6040516020818303038152906040528051906020012060001c8161640157fe5b06905080850182870114616502576000898388018151811061641f57fe5b602002602001015190506060898489018151811061643957fe5b602002602001015190508a8388018151811061645157fe5b60200260200101518b858a018151811061646757fe5b60200260200101906001600160a01b031690816001600160a01b031681525050818b8489018151811061649657fe5b60200260200101906001600160a01b031690816001600160a01b03168152505089838801815181106164c457fe5b60200260200101518a858a01815181106164da57fe5b6020026020010181905250808a848901815181106164f457fe5b602002602001018190525050505b506001016163c1565b5050505050505050565b600980546001908101909155600b80548390811061652f57fe5b906000526020600020906016020160010160006101000a81548160ff02191690831515021790555043600b828154811061656557fe5b600091825260208220601690910201919091556040516001600160a01b038416917ff62981a567ec3cec866c6fa93c55bcdf841d6292d18b8d522ececa769375d82d91a25050565b6000816040516020016165c091906181c1565b60405160208183030381529060405280519060200120836040516020016165e791906181c1565b6040516020818303038152906040528051906020012014905092915050565b015190565b8151815160009160019181148083146166275760009250616665565b600160208701838101602088015b6002848385100114156166605780518351146166545760009650600093505b60209283019201616635565b505050505b5090949350505050565b6001600160a01b0381166000908152600460205260408120548061669857506000199050611d15565b6001810390506000600182815481106166ad57fe5b90600052602060002090600402016003015490506000600183815481106166d057fe5b6000918252602090912060036004909202010155600154604051600019909101906001600160a01b038616907f8cd4e147d8af98a9e3b6724021b8bf6aed2e5dac71c38f2dce8161b82585b25d90616729908590618ed8565b60405180910390a28061674157829350505050611d15565b600081838161674c57fe5b04905080156167e85760005b8481101561679a5761677182600183815481106154bb57fe5b6001828154811061677e57fe5b6000918252602090912060036004909202010155600101616758565b50600180549085015b818110156167e5576167bc83600183815481106154bb57fe5b600182815481106167c957fe5b60009182526020909120600360049092020101556001016167a3565b50505b5091949350505050565b60008261680157506000611dc5565b8282028284828161680e57fe5b041461115e5760405162461bcd60e51b8152600401610e12906189e2565b600061115e83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061747e565b616876617c2c565b506040805180820190915281518152602082810190820152919050565b61689b617b5e565b6168a4826174b5565b6168ad57600080fd5b60006168bc83602001516174ef565b60208085015160408051808201909152868152920190820152915050919050565b60006168e7617c2c565b505080518051602091820151919092015191011190565b616906617c2c565b61690f826168dd565b61691857600080fd5b6020820151600061692882617552565b80830160209586015260408051808201909152908152938401919091525090919050565b80516000901580159061696157508151602110155b61696a57600080fd5b600061697983602001516174ef565b9050808360000151101561699f5760405162461bcd60e51b8152600401610e1290618bf0565b8251602080850151830180519284900392918310156163b557506020919091036101000a90049392505050565b60606169d7826174b5565b6169e057600080fd5b60006169eb83617633565b9050606081604051908082528060200260200182016040528015616a2957816020015b616a16617c2c565b815260200190600190039081616a0e5790505b5090506000616a3b85602001516174ef565b60208601510190506000805b84811015616a9257616a5883617552565b9150604051806040016040528083815260200184815250848281518110616a7b57fe5b602090810291909101015291810191600101616a47565b509195945050505050565b616aa5617ae5565b60606000616ab1617ae5565b6060616abb617b5e565b616ac487616893565b90506000805b616ad3836168dd565b15616ba85780616afe57616aee616ae9846168fe565b61768f565b6001600160a01b03168552616ba0565b8060011415616b2657616b13616ae9846168fe565b6001600160a01b03166020860152616ba0565b8060021415616b4e57616b3b616ae9846168fe565b6001600160a01b03166040860152616ba0565b8060031415616b7a57616b63613dc1846168fe565b6001600160401b0316606086015260019150616ba0565b8060041415616b9b57616b94616b8f846168fe565b6176a9565b9350616ba0565b616ba8565b600101616aca565b50929791965091945092505050565b6060611dc5616bc583617719565b6177ff565b6060815160001415616beb5750604080516000815260208101909152611d15565b606082600081518110616bfa57fe5b602002602001015190506000600190505b8351811015616c3b57616c3182858381518110616c2457fe5b6020026020010151617851565b9150600101616c0b565b5061115e616c4e825160c060ff166178ce565b82617851565b60608060006120026001600160a01b031663c473318f6040518163ffffffff1660e01b815260040160206040518083038186803b158015616c9457600080fd5b505afa158015616ca8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190616ccc9190618096565b90508085518851011015616ce1575083518651015b606081604051908082528060200260200182016040528015616d1d57816020015b616d0a617ae5565b815260200190600190039081616d025790505b509050606082604051908082528060200260200182016040528015616d5657816020015b6060815260200190600190039081616d415790505b50905060008060005b8b51831080616d6e5750895182105b8015616d7957508581105b1561700e578b51831415616de957898281518110616d9357fe5b6020026020010151858281518110616da757fe5b6020026020010181905250888281518110616dbe57fe5b6020026020010151848281518110616dd257fe5b602090810291909101015260019182019101616d5f565b8951821415616e54578b8381518110616dfe57fe5b6020026020010151858281518110616e1257fe5b60200260200101819052508a8381518110616e2957fe5b6020026020010151848281518110616e3d57fe5b602090810291909101015260019283019201616d5f565b898281518110616e6057fe5b6020026020010151606001516001600160401b03168c8481518110616e8157fe5b6020026020010151606001516001600160401b03161115616efd578b8381518110616ea857fe5b6020026020010151858281518110616ebc57fe5b60200260200101819052508a8381518110616ed357fe5b6020026020010151848281518110616ee757fe5b6020026020010181905250826001019250617006565b898281518110616f0957fe5b6020026020010151606001516001600160401b03168c8481518110616f2a57fe5b6020026020010151606001516001600160401b03161015616fa657898281518110616f5157fe5b6020026020010151858281518110616f6557fe5b6020026020010181905250888281518110616f7c57fe5b6020026020010151848281518110616f9057fe5b6020026020010181905250816001019150617006565b898281518110616fb257fe5b6020026020010151600001516001600160a01b03168c8481518110616fd357fe5b6020026020010151600001516001600160a01b03161015616ffa578b8381518110616ea857fe5b898281518110616d9357fe5b600101616d5f565b50929a91995090975050505050505050565b805182516000916001600160a01b03918216911614801561705a575081602001516001600160a01b031683602001516001600160a01b0316145b801561115e5750506040908101519101516001600160a01b0390811691161490565b601254601354808211156170c757805b828110156170c557601280548061709f57fe5b6001900381819060005260206000200160006170bb9190617b1a565b905560010161708c565b505b60008183106170d657816170d8565b825b905060005b818110156171f057617195601282815481106170f557fe5b600091825260209182902001805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152928301828280156171835780601f1061715857610100808354040283529160200191617183565b820191906000526020600020905b81548152906001019060200180831161716657829003601f168201915b50505050506013838154811061341857fe5b6171e857601381815481106171a657fe5b90600052602060002001601282815481106171bd57fe5b9060005260206000200190805460018160011615610100020316600290046171e6929190617b7e565b505b6001016170dd565b5082821115610e3257825b8281101561725e5760126013828154811061721257fe5b6000918252602080832084546001818101875595855291909320929091018054617255949390920192909160026101009282161592909202600019011604617b7e565b506001016171fb565b50505050565b601354600b54808211156172af57805b828110156172ad57601380548061728757fe5b6001900381819060005260206000200160006172a39190617b1a565b9055600101617274565b505b60008183106172be57816172c0565b825b905060005b818110156173df5761737d601382815481106172dd57fe5b600091825260209182902001805460408051601f600260001961010060018716150201909416939093049283018590048502810185019091528181529283018282801561736b5780601f106173405761010080835404028352916020019161736b565b820191906000526020600020905b81548152906001019060200180831161734e57829003601f168201915b5050505050600b8381548110615ecb57fe5b6173d757600b818154811061738e57fe5b9060005260206000209060160201600201601382815481106173ac57fe5b9060005260206000200190805460018160011615610100020316600290046173d5929190617b7e565b505b6001016172c5565b5082821115610e3257825b8281101561725e576013600b828154811061740157fe5b60009182526020808320845460018082018755958552919093206016929092029092016002908101805461744995939094019390926000199082161561010002011604617b7e565b506001016173ea565b600081848411156174765760405162461bcd60e51b8152600401610e12919061837e565b505050900390565b6000818361749f5760405162461bcd60e51b8152600401610e12919061837e565b5060008385816174ab57fe5b0495945050505050565b80516000906174c657506000611d15565b6020820151805160001a9060c08210156174e557600092505050611d15565b5060019392505050565b8051600090811a6080811015617509576000915050611d15565b60b8811080617524575060c08110801590617524575060f881105b15617533576001915050611d15565b60c08110156175475760b519019050611d15565b60f519019050611d15565b80516000908190811a608081101561756d576001915061762c565b60b881101561758257607e198101915061762c565b60c08110156175d357600060b78203600186019550806020036101000a8651049150600181018201935050808310156175cd5760405162461bcd60e51b8152600401610e129061892f565b5061762c565b60f88110156175e85760be198101915061762c565b600060f78203600186019550806020036101000a86510491506001810182019350508083101561762a5760405162461bcd60e51b8152600401610e129061892f565b505b5092915050565b805160009061764457506000611d15565b6000809050600061765884602001516174ef565b602085015185519181019250015b808210156176865761767782617552565b82019150826001019250617666565b50909392505050565b80516000906015146176a057600080fd5b611dc58261694c565b80516060906176b757600080fd5b60006176c683602001516174ef565b83516040805191839003808352601f19601f82011683016020019091529192506060908280156176fd576020820181803683370190505b50905060008160200190506163b58487602001510182856179a0565b604080516020808252818301909252606091829190602082018180368337505050602081018490529050600067ffffffffffffffff19841661775d57506018617781565b6fffffffffffffffffffffffffffffffff19841661777d57506010617781565b5060005b60208110156177b75781818151811061779657fe5b01602001516001600160f81b031916156177af576177b7565b600101617781565b60008160200390506060816040519080825280601f01601f1916602001820160405280156177ec576020820181803683370190505b5080830196909652508452509192915050565b6060815160011480156178315750607f60f81b8260008151811061781f57fe5b01602001516001600160f81b03191611155b1561783d575080611d15565b611dc561784f8351608060ff166178ce565b835b6060806040519050835180825260208201818101602087015b8183101561788257805183526020928301920161786a565b50855184518101855292509050808201602086015b818310156178af578051835260209283019201617897565b508651929092011591909101601f01601f191660405250905092915050565b60606801000000000000000083106178f85760405162461bcd60e51b8152600401610e129061877a565b604080516001808252818301909252606091602082018180368337019050509050603784116179525782840160f81b8160008151811061793457fe5b60200101906001600160f81b031916908160001a9053509050611dc5565b606061795d85617719565b90508381510160370160f81b8260008151811061797657fe5b60200101906001600160f81b031916908160001a9053506179978282617851565b95945050505050565b806179aa57610e32565b5b602081106179ca578251825260209283019290910190601f19016179ab565b915181516020939093036101000a6000190180199091169216919091179052565b60405180608001604052806000815260200160001515815260200160608152602001617a15617c46565b905290565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10617a5b57805160ff1916838001178555617a88565b82800160010185558215617a88579182015b82811115617a88578251825591602001919060010190617a6d565b506131e8929150617c65565b8260138101928215617a885791602002820182811115617a88578251825591602001919060010190617a6d565b6040518060600160405280600060ff16815260200160608152602001606081525090565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b50805460018160011615610100020316600290046000825580601f10617b405750611f2d565b601f016020900490600052602060002090810190611f2d9190617c65565b6040518060400160405280617b71617c2c565b8152602001600081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10617bb75780548555617a88565b82800160010185558215617a8857600052602060002091601f016020900482015b82811115617a88578254825591600101919060010190617bd8565b8260138101928215617a885791820182811115617a88578254825591600101919060010190617bd8565b50611f2d906013810190617c65565b604051806040016040528060008152602001600081525090565b6040518061026001604052806013906020820280368337509192915050565b61318c91905b808211156131e85760008155600101617c6b565b8035611dc581618faf565b60008083601f840112617c9b578182fd5b5081356001600160401b03811115617cb1578182fd5b60208301915083602080830285010111156159f357600080fd5b6000601f8381840112617cdc578182fd5b8235617cef617cea82618f64565b618f3e565b818152925060208084019085810160005b84811015617d81578135880189603f820112617d1b57600080fd5b838101356001600160401b03811115617d3357600080fd5b617d44818901601f19168601618f3e565b81815260408c81848601011115617d5a57600080fd5b82818501888401375060009181018601919091528552509282019290820190600101617d00565b50505050505092915050565b600082601f830112617d9d578081fd5b8135617dab617cea82618f64565b818152915060208083019084810181840286018201871015617dcc57600080fd5b6000805b85811015617d815782356001600160401b0381168114617dee578283fd5b85529383019391830191600101617dd0565b60008083601f840112617e11578182fd5b5081356001600160401b03811115617e27578182fd5b6020830191508360208285010111156159f357600080fd5b600060208284031215617e50578081fd5b813561115e81618faf565b600060208284031215617e6c578081fd5b815161115e81618faf565b60008060008060408587031215617e8c578283fd5b84356001600160401b0380821115617ea2578485fd5b617eae88838901617c8a565b90965094506020870135915080821115617ec6578384fd5b50617ed387828801617c8a565b95989497509550505050565b600080600060608486031215617ef3578283fd5b83356001600160401b0380821115617f09578485fd5b81860187601f820112617f1a578586fd5b80359250617f2a617cea84618f64565b80848252602080830192508084018b828389028701011115617f4a57898afd5b8994505b86851015617f7457617f608c82617c7f565b845260019490940193928101928101617f4e565b509097508801359350505080821115617f8b578384fd5b617f9787838801617d8d565b93506040860135915080821115617fac578283fd5b50617fb986828701617ccb565b9150509250925092565b600060208284031215617fd4578081fd5b8151801515811461115e578182fd5b60008060208385031215617ff5578182fd5b82356001600160401b0381111561800a578283fd5b61801685828601617e00565b90969095509350505050565b60008060008060408587031215618037578384fd5b84356001600160401b038082111561804d578586fd5b61805988838901617e00565b90965094506020870135915080821115618071578384fd5b50617ed387828801617e00565b60006020828403121561808f578081fd5b5035919050565b6000602082840312156180a7578081fd5b5051919050565b600080604083850312156180c0578182fd5b505080516020909101519092909150565b6000806000604084860312156180e5578081fd5b833560ff811681146180f5578182fd5b925060208401356001600160401b0381111561810f578182fd5b61811b86828701617e00565b9497909650939450505050565b6000815180845260208085019450808401835b838110156181605781516001600160a01b03168752958201959082019060010161813b565b509495945050505050565b60008284528282602086013780602084860101526020601f19601f85011685010190509392505050565b600081518084526181ad816020860160208601618f83565b601f01601f19169290920160200192915050565b600082516181d3818460208701618f83565b9190910192915050565b918252602082015260400190565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b03968716815294861660208601529290941660408401526001600160401b03166060830152911515608082015260a081019190915260c00190565b6001600160a01b0392909216825260ff16602082015260400190565b60006020825261115e6020830184618128565b60006040825261829c6040830185618128565b602083820381850152818551808452828401915082838202850101838801865b838110156182ea57601f198784030185526182d8838351618195565b948601949250908501906001016182bc565b50909998505050505050505050565b60006080825261830c6080830187618128565b828103602084810191909152865180835287820192820190845b8181101561834257845183529383019391830191600101618326565b505084810360408601526183568188618128565b93505050506001600160401b038316606083015295945050505050565b901515815260200190565b60006020825261115e6020830184618195565b6000604082526183a560408301868861816b565b82810360208401526183b881858761816b565b979650505050505050565b6020808252601c908201527f6c656e677468206f66206275726e526174696f206d69736d6174636800000000604082015260600190565b60208082526042908201527f746865206275726e526174696f20706c75732073797374656d5265776172645260408201527f6174696f206d757374206265206e6f2067726561746572207468616e20313030606082015261030360f41b608082015260a00190565b60208082526026908201527f6c656e677468206f66206d61784e756d4f664d61696e7461696e696e67206d696040820152650e6dac2e8c6d60d31b606082015260800190565b6020808252601b908201527f6261746368207472616e736665722072657475726e2066616c73650000000000604082015260600190565b6020808252602c908201527f6c656e677468206f66206d61784e756d4f66576f726b696e6743616e6469646160408201526b0e8cae640dad2e6dac2e8c6d60a31b606082015260800190565b60208082526025908201527f6c656e677468206f66206d61696e7461696e536c6173685363616c65206d69736040820152640dac2e8c6d60db1b606082015260800190565b6020808252818101527f6c656e677468206f66206e756d4f66436162696e657473206d69736d61746368604082015260600190565b60208082526019908201527f74686520636f6e7472616374206e6f7420696e69742079657400000000000000604082015260600190565b6020808252601f908201527f6f6e6c7920736c617368206f72207374616b6548756220636f6e747261637400604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b60208082526028908201527f746865206e756d4f66436162696e657473206d75737420626520677265617465604082015267072207468616e20360c41b606082015260800190565b60208082526039908201527f746865206e756d4f66436162696e657473206d757374206265206c657373207460408201527f68616e204d41585f4e554d5f4f465f56414c494441544f525300000000000000606082015260800190565b60208082526029908201527f746865206e756d626572206f662076616c696461746f727320657863656564206040820152681d1a19481b1a5b5a5d60ba1b606082015260800190565b60208082526022908201527f63616e206e6f7420646f207468697320747769636520696e206f6e6520626c6f604082015261636b60f01b606082015260800190565b6020808252600e908201526d696e70757420746f6f206c6f6e6760901b604082015260600190565b60208082526037908201527f746865206d61784e756d4f664d61696e7461696e696e67206d7573742062652060408201527f6c657373207468616e206e756d4f66436162696e657473000000000000000000606082015260800190565b6020808252602b908201527f6475706c696361746520636f6e73656e7375732061646472657373206f66207660408201526a185b1a59185d1bdc94d95d60aa1b606082015260800190565b60208082526027908201527f7468652065787069726554696d655365636f6e64476170206973206f7574206f604082015266662072616e676560c81b606082015260800190565b6020808252601590820152746465706f7369742076616c7565206973207a65726f60581b604082015260600190565b60208082526049908201527f746865206d61784e756d4f66576f726b696e6743616e64696461746573206d7560408201527f7374206265206e6f742067726561746572207468616e206d61784e756d4f6643606082015268616e6469646174657360b81b608082015260a00190565b6020808252601190820152706164646974696f6e206f766572666c6f7760781b604082015260600190565b60208082526023908201527f63616e206e6f7420656e7465722054656d706f72617279204d61696e74656e616040820152626e636560e81b606082015260800190565b60208082526025908201527f6c656e677468206f66206a61696c2076616c696461746f7273206d757374206260408201526465206f6e6560d81b606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252601490820152736761737072696365206973206e6f74207a65726f60601b604082015260600190565b6020808252602e908201527f746865206d6573736167652073656e646572206d75737420626520676f76657260408201526d1b985b98d94818dbdb9d1c9858dd60921b606082015260800190565b60208082526025908201527f6c656e677468206f66206d61784e756d4f6643616e64696461746573206d69736040820152640dac2e8c6d60db1b606082015260800190565b6020808252601290820152716e6f7420696e206d61696e74656e616e636560701b604082015260600190565b60208082526021908201527f666565206973206c6172676572207468616e2044555354595f494e434f4d494e6040820152604760f81b606082015260800190565b60208082526019908201527f74686520636f6e747261637420616c726561647920696e697400000000000000604082015260600190565b60208082526042908201527f7468652073797374656d526577617264526174696f20706c7573206275726e5260408201527f6174696f206d757374206265206e6f2067726561746572207468616e20313030606082015261030360f41b608082015260a00190565b6020808252601a908201527f6c656e677468206973206c657373207468616e206f6666736574000000000000604082015260600190565b60208082526026908201527f6c656e677468206f662065787069726554696d655365636f6e64476170206d696040820152650e6dac2e8c6d60d31b606082015260800190565b60208082526017908201527f6f6e6c792063757272656e742076616c696461746f7273000000000000000000604082015260600190565b60208082526021908201527f6661696c656420746f20706172736520696e69742076616c696461746f7253656040820152601d60fa1b606082015260800190565b6020808252602f908201527f746865206d6573736167652073656e646572206d7573742062652063726f737360408201526e0818da185a5b8818dbdb9d1c9858dd608a1b606082015260800190565b6020808252602d908201527f746865206d6573736167652073656e646572206d75737420626520746865206260408201526c3637b1b590383937b23ab1b2b960991b606082015260800190565b60208082526024908201527f6c656e677468206f662073797374656d526577617264526174696f206d69736d6040820152630c2e8c6d60e31b606082015260800190565b6020808252603e908201527f746865206d61696e7461696e536c6173685363616c65206d757374206265206760408201527f726561746572207468616e203020616e64206c657373207468616e2031300000606082015260800190565b6020808252600d908201526c756e6b6e6f776e20706172616d60981b604082015260600190565b60208082526029908201527f746865206d6573736167652073656e646572206d75737420626520736c6173686040820152680818dbdb9d1c9858dd60ba1b606082015260800190565b6020808252601f908201527f746865206d73672073656e646572206d757374206265207374616b6548756200604082015260600190565b61ffff91909116815260200190565b90815260200190565b60008482528315156020830152606060408301526179976060830184618195565b63ffffffff91909116815260200190565b60ff91909116815260200190565b600060ff851682526040602083015261799760408301848661816b565b6040518181016001600160401b0381118282101715618f5c57600080fd5b604052919050565b60006001600160401b03821115618f79578081fd5b5060209081020190565b60005b83811015618f9e578181015183820152602001618f86565b8381111561725e5750506000910152565b6001600160a01b0381168114611f2d57600080fdfe70e72399380dcfb0338abc03dc8d47f9f470ada8e769c9a78d644ea97385ecb20175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dbbf905ec80f905e8f846942a7cdd959bfe8d9487b2a43b33565295a698f7e294b6a7edd747c0554875d3fc531d19ba1497992c5e941ff80f3f7f110ffd8920a3ac38fdef318fe94a3f86048c27395000f846946488aa4d1955ee33403f8ccb1d4de5fb97c7ade294220f003d8bdfaadf52aa1e55ae4cc485e6794875941a87e90e440a39c99aa9cb5cea0ad6a3f0b2407b86048c27395000f846949ef9f4360c606c7ab4db26b016007d3ad0ab86a0946103af86a874b705854033438383c82575f25bc29418e2db06cbff3e3c5f856410a1838649e760175786048c27395000f84694ee01c3b1283aa067c58eab4709f85e99d46de5fe94ee4b9bfb1871c64e2bcabb1dc382dc8b7c4218a29415904ab26ab0e99d70b51c220ccdcccabee6e29786048c27395000f84694685b1ded8013785d6623cc18d214320b6bb6475994a20ef4e5e4e7e36258dbf51f4d905114cb1b34bc9413e39085dc88704f4394d35209a02b1a9520320c86048c27395000f8469478f3adfc719c99674c072166708589033e2d9afe9448a30d5eaa7b64492a160f139e2da2800ec3834e94055838358c29edf4dcc1ba1985ad58aedbb6be2b86048c27395000f84694c2be4ec20253b8642161bc3f444f53679c1f3d479466f50c616d737e60d7ca6311ff0d9c434197898a94d1d678a2506eeaa365056fe565df8bc8659f28b086048c27395000f846942f7be8361c80a4c1e7e9aaf001d0877f1cfde218945f93992ac37f3e61db2ef8a587a436a161fd210b94ecbc4fb1a97861344dad0867ca3cba2b860411f086048c27395000f84694ce2fd7544e0b2cc94692d4a704debef7bcb613289444abc67b4b2fba283c582387f54c9cba7c34bafa948acc2ab395ded08bb75ce85bf0f95ad2abc51ad586048c27395000f84694b8f7166496996a7da21cf1f1b04d9b3e26a3d077946770572763289aac606e4f327c2f6cc1aa3b3e3b94882d745ed97d4422ca8da1c22ec49d880c4c097286048c27395000f846942d4c407bbe49438ed859fe965b140dcf1aab71a9943ad0939e120f33518fbba04631afe7a3ed6327b194b2bbb170ca4e499a2b0f3cc85ebfa6e8c4dfcbea86048c27395000f846946bbad7cf34b5fa511d8e963dbba288b1960e75d694853b0f6c324d1f4e76c8266942337ac1b0af1a229442498946a51ca5924552ead6fc2af08b94fcba648601d1a94a2000f846944430b3230294d12c6ab2aac5c2cd68e80b16b581947b107f4976a252a6939b771202c28e64e03f52d694795811a7f214084116949fc4f53cedbf189eeab28601d1a94a2000f84694ea0a6e3c511bbd10f4519ece37dc24887e11b55d946811ca77acfb221a49393c193f3a22db829fcc8e9464feb7c04830dd9ace164fc5c52b3f5a29e5018a8601d1a94a2000f846947ae2f5b9e386cd1b50a4550696d957cb4900f03a94e83bcc5077e6b873995c24bac871b5ad856047e19464e48d4057a90b233e026c1041e6012ada897fe88601d1a94a2000f8469482012708dafc9e1b880fd083b32182b869be8e09948e5adc73a2d233a1b496ed3115464dd6c7b887509428b383d324bc9a37f4e276190796ba5a8947f5ed8601d1a94a2000f8469422b81f8e175ffde54d797fe11eb03f9e3bf75f1d94a1c3ef7ca38d8ba80cce3bfc53ebd2903ed21658942767f7447f7b9b70313d4147b795414aecea54718601d1a94a2000f8469468bf0b8b6fb4e317a0f9d6f03eaf8ce6675bc60d94675cfe570b7902623f47e7f59c9664b5f5065dcf94d84f0d2e50bcf00f2fc476e1c57f5ca2d57f625b8601d1a94a2000f846948c4d90829ce8f72d0163c1d5cf348a862d5506309485c42a7b34309bee2ed6a235f86d16f059deec5894cc2cedc53f0fa6d376336efb67e43d167169f3b78601d1a94a2000f8469435e7a025f4da968de7e4d7e4004197917f4070f194b1182abaeeb3b4d8eba7e6a4162eac7ace23d57394c4fd0d870da52e73de2dd8ded19fe3d26f43a1138601d1a94a2000f84694d6caa02bbebaebb5d7e581e4b66559e635f805ff94c07335cf083c1c46a487f0325769d88e163b653694efaff03b42e41f953a925fc43720e45fb61a19938601d1a94a20000175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dbaa164736f6c6343000604000a";

    uint32 public constant ERROR_UNKNOWN_PACKAGE_TYPE = 101;
    uint32 public constant ERROR_FAIL_CHECK_VALIDATORS = 102;
    uint32 public constant ERROR_LEN_OF_VAL_MISMATCH = 103;
    uint32 public constant ERROR_RELAYFEE_TOO_LARGE = 104;

    uint256 public constant INIT_NUM_OF_CABINETS = 21;
    uint256 public constant EPOCH = 200;

    /*----------------- state of the contract -----------------*/
    Validator[] public currentValidatorSet;
    uint256 public expireTimeSecondGap;
    uint256 public totalInComing;

    // key is the `consensusAddress` of `Validator`,
    // value is the index of the element in `currentValidatorSet`.
    mapping(address => uint256) public currentValidatorSetMap;
    uint256 public numOfJailed;

    uint256 public constant BLOCK_FEES_RATIO_SCALE = 10000;
    address public constant BURN_ADDRESS = 0x000000000000000000000000000000000000dEaD;
    uint256 public constant INIT_BURN_RATIO = 1000;
    uint256 public burnRatio;
    bool public burnRatioInitialized; // deprecated

    // BEP-127 Temporary Maintenance
    uint256 public constant INIT_MAX_NUM_OF_MAINTAINING = 3;
    uint256 public constant INIT_MAINTAIN_SLASH_SCALE = 2;

    uint256 public maxNumOfMaintaining;
    uint256 public numOfMaintaining;
    uint256 public maintainSlashScale;

    // Corresponds strictly to currentValidatorSet
    // validatorExtraSet[index] = the `ValidatorExtra` info of currentValidatorSet[index]
    ValidatorExtra[] public validatorExtraSet;
    // BEP-131 candidate validator
    uint256 public numOfCabinets;
    uint256 public maxNumOfCandidates;
    uint256 public maxNumOfWorkingCandidates;

    // BEP-126 Fast Finality
    uint256 public constant INIT_SYSTEM_REWARD_RATIO = 625; // 625/10000 is 1/16
    uint256 public constant MAX_SYSTEM_REWARD_BALANCE = 100 ether;

    uint256 public systemRewardRatio;
    uint256 public previousHeight;
    uint256 public previousBalanceOfSystemReward; // deprecated
    bytes[] public previousVoteAddrFullSet;
    bytes[] public currentVoteAddrFullSet;
    bool public isSystemRewardIncluded;

    // BEP-294 BC-fusion
    Validator[] private _tmpMigratedValidatorSet;
    bytes[] private _tmpMigratedVoteAddrs;

    struct Validator {
        address consensusAddress;
        address payable feeAddress;
        address BBCFeeAddress;
        uint64 votingPower;
        // only in state
        bool jailed;
        uint256 incoming;
    }

    struct ValidatorExtra {
        // BEP-127 Temporary Maintenance
        uint256 enterMaintenanceHeight; // the height from where the validator enters Maintenance
        bool isMaintaining;
        // BEP-126 Fast Finality
        bytes voteAddress;
        // reserve for future use
        uint256[19] slots;
    }

    /*----------------- cross chain package -----------------*/
    struct IbcValidatorSetPackage {
        uint8 packageType;
        Validator[] validatorSet;
        bytes[] voteAddrs;
    }

    /*----------------- modifiers -----------------*/
    modifier noEmptyDeposit() {
        require(msg.value > 0, "deposit value is zero");
        _;
    }

    modifier initValidatorExtraSet() {
        if (validatorExtraSet.length == 0) {
            ValidatorExtra memory validatorExtra;
            // init validatorExtraSet
            uint256 validatorsNum = currentValidatorSet.length;
            for (uint256 i; i < validatorsNum; ++i) {
                validatorExtraSet.push(validatorExtra);
            }
        }

        _;
    }

    modifier oncePerBlock() {
        require(block.number > previousHeight, "can not do this twice in one block");
        _;
        previousHeight = block.number;
    }

    /*----------------- events -----------------*/
    event validatorSetUpdated();
    event validatorJailed(address indexed validator);
    event validatorEmptyJailed(address indexed validator);
    event batchTransfer(uint256 amount);
    event batchTransferFailed(uint256 indexed amount, string reason);
    event batchTransferLowerFailed(uint256 indexed amount, bytes reason);
    event systemTransfer(uint256 amount);
    event directTransfer(address payable indexed validator, uint256 amount);
    event directTransferFail(address payable indexed validator, uint256 amount);
    event deprecatedDeposit(address indexed validator, uint256 amount);
    event validatorDeposit(address indexed validator, uint256 amount);
    event validatorMisdemeanor(address indexed validator, uint256 amount);
    event validatorFelony(address indexed validator, uint256 amount);
    event failReasonWithStr(string message);
    event unexpectedPackage(uint8 channelId, bytes msgBytes);
    event paramChange(string key, bytes value);
    event feeBurned(uint256 amount);
    event validatorEnterMaintenance(address indexed validator);
    event validatorExitMaintenance(address indexed validator);
    event finalityRewardDeposit(address indexed validator, uint256 amount);
    event deprecatedFinalityRewardDeposit(address indexed validator, uint256 amount);
    event tmpValidatorSetUpdated(uint256 validatorsNum);

    /*----------------- init -----------------*/
    function init() external onlyNotInit {
        (IbcValidatorSetPackage memory validatorSetPkg, bool valid) =
            decodeValidatorSetSynPackage(INIT_VALIDATORSET_BYTES);
        require(valid, "failed to parse init validatorSet");
        for (uint256 i; i < validatorSetPkg.validatorSet.length; ++i) {
            currentValidatorSet.push(validatorSetPkg.validatorSet[i]);
            currentValidatorSetMap[validatorSetPkg.validatorSet[i].consensusAddress] = i + 1;
        }
        expireTimeSecondGap = EXPIRE_TIME_SECOND_GAP;
        alreadyInit = true;
    }

    receive() external payable { }

    /*----------------- Cross Chain App Implement -----------------*/
    function handleSynPackage(
        uint8,
        bytes calldata msgBytes
    ) external override onlyInit onlyCrossChainContract initValidatorExtraSet returns (bytes memory responsePayload) {
        (IbcValidatorSetPackage memory validatorSetPackage, bool ok) = decodeValidatorSetSynPackage(msgBytes);
        if (!ok) {
            return CmnPkg.encodeCommonAckPackage(ERROR_FAIL_DECODE);
        }
        uint32 resCode;
        if (validatorSetPackage.packageType == VALIDATORS_UPDATE_MESSAGE_TYPE) {
            resCode = updateValidatorSet(validatorSetPackage.validatorSet, validatorSetPackage.voteAddrs);
        } else if (validatorSetPackage.packageType == JAIL_MESSAGE_TYPE) {
            if (validatorSetPackage.validatorSet.length != 1) {
                emit failReasonWithStr("length of jail validators must be one");
                resCode = ERROR_LEN_OF_VAL_MISMATCH;
            } else {
                address validator = validatorSetPackage.validatorSet[0].consensusAddress;
                uint256 index = currentValidatorSetMap[validator];
                if (index == 0 || currentValidatorSet[index - 1].jailed) {
                    emit validatorEmptyJailed(validator);
                } else {
                    // felony will failed if the validator is the only one in the validator set
                    bool success = _felony(validator, index - 1);
                    if (!success) {
                        emit validatorEmptyJailed(validator);
                    }
                }
                resCode = CODE_OK;
            }
        } else {
            resCode = ERROR_UNKNOWN_PACKAGE_TYPE;
        }
        if (resCode == CODE_OK) {
            return new bytes(0);
        } else {
            return CmnPkg.encodeCommonAckPackage(resCode);
        }
    }

    function handleAckPackage(uint8 channelId, bytes calldata msgBytes) external override onlyCrossChainContract {
        // should not happen
        emit unexpectedPackage(channelId, msgBytes);
    }

    function handleFailAckPackage(uint8 channelId, bytes calldata msgBytes) external override onlyCrossChainContract {
        // should not happen
        emit unexpectedPackage(channelId, msgBytes);
    }

    /*----------------- External Functions -----------------*/
    /**
     * @dev Update validator set method after fusion fork.
     */
    function updateValidatorSetV2(
        address[] memory _consensusAddrs,
        uint64[] memory _votingPowers,
        bytes[] memory _voteAddrs
    ) public onlyCoinbase onlyZeroGasPrice {
        uint256 _length = _consensusAddrs.length;
        Validator[] memory _validatorSet = new Validator[](_length);
        for (uint256 i; i < _length; ++i) {
            _validatorSet[i] = Validator({
                consensusAddress: _consensusAddrs[i],
                feeAddress: payable(address(0)),
                BBCFeeAddress: address(0),
                votingPower: _votingPowers[i],
                jailed: false,
                incoming: 0
            });
        }

        // if staking channel is not closed, store the migrated validator set and return
        if (
            ICrossChain(CROSS_CHAIN_CONTRACT_ADDR).registeredContractChannelMap(
                VALIDATOR_CONTRACT_ADDR, STAKING_CHANNELID
            )
        ) {
            uint256 newLength = _validatorSet.length;
            uint256 oldLength = _tmpMigratedValidatorSet.length;
            if (oldLength > newLength) {
                for (uint256 i = newLength; i < oldLength; ++i) {
                    _tmpMigratedValidatorSet.pop();
                    _tmpMigratedVoteAddrs.pop();
                }
            }

            for (uint256 i; i < newLength; ++i) {
                if (i >= oldLength) {
                    _tmpMigratedValidatorSet.push(_validatorSet[i]);
                    _tmpMigratedVoteAddrs.push(_voteAddrs[i]);
                } else {
                    _tmpMigratedValidatorSet[i] = _validatorSet[i];
                    _tmpMigratedVoteAddrs[i] = _voteAddrs[i];
                }
            }

            emit tmpValidatorSetUpdated(newLength);
            return;
        }

        // step 0: force all maintaining validators to exit `Temporary Maintenance`
        // - 1. validators exit maintenance
        // - 2. clear all maintainInfo
        // - 3. get unjailed validators from validatorSet
        (Validator[] memory validatorSetTemp, bytes[] memory voteAddrsTemp) =
            _forceMaintainingValidatorsExit(_validatorSet, _voteAddrs);

        // step 1: distribute incoming
        for (uint256 i; i < currentValidatorSet.length; ++i) {
            uint256 incoming = currentValidatorSet[i].incoming;
            if (incoming != 0) {
                currentValidatorSet[i].incoming = 0;
                IStakeHub(STAKE_HUB_ADDR).distributeReward{ value: incoming }(currentValidatorSet[i].consensusAddress);
            }
        }

        // step 2: do dusk transfer
        if (address(this).balance > 0) {
            emit systemTransfer(address(this).balance);
            address(uint160(SYSTEM_REWARD_ADDR)).transfer(address(this).balance);
        }

        // step 3: do update validator set state
        totalInComing = 0;
        numOfJailed = 0;
        if (validatorSetTemp.length != 0) {
            doUpdateState(validatorSetTemp, voteAddrsTemp);
        }

        // step 3: clean slash contract
        ISlashIndicator(SLASH_CONTRACT_ADDR).clean();
        emit validatorSetUpdated();
    }

    /**
     * @dev Collect all fee of transactions from the current block and deposit it to the contract
     *
     * @param valAddr The validator address who produced the current block
     */
    function deposit(address valAddr) external payable onlyCoinbase onlyInit noEmptyDeposit onlyZeroGasPrice {
        uint256 value = msg.value;
        uint256 index = currentValidatorSetMap[valAddr];

        if (isSystemRewardIncluded == false) {
            systemRewardRatio = INIT_SYSTEM_REWARD_RATIO;
            burnRatio = INIT_BURN_RATIO;
            isSystemRewardIncluded = true;
        }

        if (value > 0 && systemRewardRatio > 0) {
            uint256 toSystemReward = msg.value.mul(systemRewardRatio).div(BLOCK_FEES_RATIO_SCALE);
            if (toSystemReward > 0) {
                address(uint160(SYSTEM_REWARD_ADDR)).transfer(toSystemReward);
                emit systemTransfer(toSystemReward);

                value = value.sub(toSystemReward);
            }
        }

        if (value > 0 && burnRatio > 0) {
            uint256 toBurn = msg.value.mul(burnRatio).div(BLOCK_FEES_RATIO_SCALE);
            if (toBurn > 0) {
                address(uint160(BURN_ADDRESS)).transfer(toBurn);
                emit feeBurned(toBurn);

                value = value.sub(toBurn);
            }
        }

        if (index > 0) {
            Validator storage validator = currentValidatorSet[index - 1];
            if (validator.jailed) {
                emit deprecatedDeposit(valAddr, value);
            } else {
                totalInComing = totalInComing.add(value);
                validator.incoming = validator.incoming.add(value);
                emit validatorDeposit(valAddr, value);
            }
        } else {
            // get incoming from deprecated validator;
            emit deprecatedDeposit(valAddr, value);
        }
    }

    function distributeFinalityReward(
        address[] calldata valAddrs,
        uint256[] calldata weights
    ) external onlyCoinbase oncePerBlock onlyZeroGasPrice onlyInit {
        uint256 totalValue;
        uint256 balanceOfSystemReward = address(SYSTEM_REWARD_ADDR).balance;
        if (balanceOfSystemReward > MAX_SYSTEM_REWARD_BALANCE) {
            // when a slash happens, theres will no rewards in some epochs,
            // it's tolerated because slash happens rarely
            totalValue = balanceOfSystemReward.sub(MAX_SYSTEM_REWARD_BALANCE);
        } else {
            return;
        }

        totalValue = ISystemReward(SYSTEM_REWARD_ADDR).claimRewards(payable(address(this)), totalValue);
        if (totalValue == 0) {
            return;
        }

        uint256 totalWeight;
        for (uint256 i; i < weights.length; ++i) {
            totalWeight += weights[i];
        }
        if (totalWeight == 0) {
            return;
        }

        uint256 value;
        address valAddr;
        uint256 index;

        for (uint256 i; i < valAddrs.length; ++i) {
            value = (totalValue * weights[i]) / totalWeight;
            valAddr = valAddrs[i];
            index = currentValidatorSetMap[valAddr];
            if (index > 0) {
                Validator storage validator = currentValidatorSet[index - 1];
                if (validator.jailed) {
                    emit deprecatedFinalityRewardDeposit(valAddr, value);
                } else {
                    totalInComing = totalInComing.add(value);
                    validator.incoming = validator.incoming.add(value);
                    emit finalityRewardDeposit(valAddr, value);
                }
            } else {
                // get incoming from deprecated validator;
                emit deprecatedFinalityRewardDeposit(valAddr, value);
            }
        }
    }

    /*----------------- View Functions -----------------*/
    /**
     * @notice Return the vote address and consensus address of the validators in `currentValidatorSet` that are not jailed
     */
    function getLivingValidators() external view override returns (address[] memory, bytes[] memory) {
        uint256 n = currentValidatorSet.length;
        uint256 living;
        for (uint256 i; i < n; ++i) {
            if (!currentValidatorSet[i].jailed) {
                living++;
            }
        }
        address[] memory consensusAddrs = new address[](living);
        bytes[] memory voteAddrs = new bytes[](living);
        living = 0;
        if (validatorExtraSet.length == n) {
            for (uint256 i; i < n; ++i) {
                if (!currentValidatorSet[i].jailed) {
                    consensusAddrs[living] = currentValidatorSet[i].consensusAddress;
                    voteAddrs[living] = validatorExtraSet[i].voteAddress;
                    living++;
                }
            }
        } else {
            for (uint256 i; i < n; ++i) {
                if (!currentValidatorSet[i].jailed) {
                    consensusAddrs[living] = currentValidatorSet[i].consensusAddress;
                    living++;
                }
            }
        }
        return (consensusAddrs, voteAddrs);
    }

    /**
     * @notice Return the vote address and consensus address of mining validators
     *
     * Mining validators are block producers in the current epoch
     * including most of the cabinets and a few of the candidates
     */
    function getMiningValidators() external view override returns (address[] memory, bytes[] memory) {
        uint256 _maxNumOfWorkingCandidates = maxNumOfWorkingCandidates;
        uint256 _numOfCabinets = numOfCabinets > 0 ? numOfCabinets : INIT_NUM_OF_CABINETS;

        address[] memory validators = getValidators();
        bytes[] memory voteAddrs = getVoteAddresses(validators);
        if (validators.length <= _numOfCabinets) {
            return (validators, voteAddrs);
        }

        if ((validators.length - _numOfCabinets) < _maxNumOfWorkingCandidates) {
            _maxNumOfWorkingCandidates = validators.length - _numOfCabinets;
        }
        if (_maxNumOfWorkingCandidates > 0) {
            uint256 epochNumber = block.number / EPOCH;
            shuffle(
                validators,
                voteAddrs,
                epochNumber,
                _numOfCabinets - _maxNumOfWorkingCandidates,
                0,
                _maxNumOfWorkingCandidates,
                _numOfCabinets
            );
            shuffle(
                validators,
                voteAddrs,
                epochNumber,
                _numOfCabinets - _maxNumOfWorkingCandidates,
                _numOfCabinets - _maxNumOfWorkingCandidates,
                _maxNumOfWorkingCandidates,
                validators.length - _numOfCabinets + _maxNumOfWorkingCandidates
            );
        }
        address[] memory miningValidators = new address[](_numOfCabinets);
        bytes[] memory miningVoteAddrs = new bytes[](_numOfCabinets);
        for (uint256 i; i < _numOfCabinets; ++i) {
            miningValidators[i] = validators[i];
            miningVoteAddrs[i] = voteAddrs[i];
        }
        return (miningValidators, miningVoteAddrs);
    }

    /**
     * @notice Return the consensus address of the validators in `currentValidatorSet` that are not jailed and not maintaining
     */
    function getValidators() public view returns (address[] memory) {
        uint256 n = currentValidatorSet.length;
        uint256 valid = 0;
        for (uint256 i; i < n; ++i) {
            if (isWorkingValidator(i)) {
                ++valid;
            }
        }
        address[] memory consensusAddrs = new address[](valid);
        valid = 0;
        for (uint256 i; i < n; ++i) {
            if (isWorkingValidator(i)) {
                consensusAddrs[valid] = currentValidatorSet[i].consensusAddress;
                ++valid;
            }
        }
        return consensusAddrs;
    }

    /**
     * @notice Return the current incoming of the validator
     */
    function getIncoming(address validator) external view returns (uint256) {
        uint256 index = currentValidatorSetMap[validator];
        if (index <= 0) {
            return 0;
        }
        return currentValidatorSet[index - 1].incoming;
    }

    /**
     * @notice Return whether the validator is a working validator(not jailed or maintaining) by index
     *
     * @param index The index of the validator in `currentValidatorSet`(from 0 to `currentValidatorSet.length-1`)
     */
    function isWorkingValidator(uint256 index) public view returns (bool) {
        if (index >= currentValidatorSet.length) {
            return false;
        }

        // validatorExtraSet[index] should not be used before it has been init.
        if (index >= validatorExtraSet.length) {
            return !currentValidatorSet[index].jailed;
        }

        return !currentValidatorSet[index].jailed && !validatorExtraSet[index].isMaintaining;
    }

    /**
     * @notice Return whether the validator is a working validator(not jailed or maintaining) by consensus address
     * Will return false if the validator is not in `currentValidatorSet`
     */
    function isCurrentValidator(address validator) external view override returns (bool) {
        uint256 index = currentValidatorSetMap[validator];
        if (index <= 0) {
            return false;
        }

        // the actual index
        index = index - 1;
        return isWorkingValidator(index);
    }

    /**
     * @notice Return the index of the validator in `currentValidatorSet`(from 0 to `currentValidatorSet.length-1`)
     */
    function getCurrentValidatorIndex(address validator) public view returns (uint256) {
        uint256 index = currentValidatorSetMap[validator];
        require(index > 0, "only current validators");

        // the actual index
        return index - 1;
    }

    /**
     * @notice Return the number of mining validators.
     * The function name is misleading, it should be `getMiningValidatorCount`. But it's kept for compatibility.
     */
    function getWorkingValidatorCount() public view returns (uint256 workingValidatorCount) {
        workingValidatorCount = getValidators().length;
        uint256 _numOfCabinets = numOfCabinets > 0 ? numOfCabinets : INIT_NUM_OF_CABINETS;
        if (workingValidatorCount > _numOfCabinets) {
            workingValidatorCount = _numOfCabinets;
        }
        if (workingValidatorCount == 0) {
            workingValidatorCount = 1;
        }
    }

    /*----------------- For slash -----------------*/
    function misdemeanor(address validator) external override onlySlash initValidatorExtraSet {
        uint256 validatorIndex = _misdemeanor(validator);
        if (canEnterMaintenance(validatorIndex)) {
            _enterMaintenance(validator, validatorIndex);
        }
    }

    function felony(address validator) external override initValidatorExtraSet {
        require(msg.sender == SLASH_CONTRACT_ADDR || msg.sender == STAKE_HUB_ADDR, "only slash or stakeHub contract");

        uint256 index = currentValidatorSetMap[validator];
        if (index <= 0) {
            return;
        }
        // the actual index
        index = index - 1;

        bool isMaintaining = validatorExtraSet[index].isMaintaining;
        if (_felony(validator, index) && isMaintaining) {
            --numOfMaintaining;
        }
    }

    function removeTmpMigratedValidator(address validator) external onlyStakeHub {
        for (uint256 i; i < _tmpMigratedValidatorSet.length; ++i) {
            if (_tmpMigratedValidatorSet[i].consensusAddress == validator) {
                _tmpMigratedValidatorSet[i].jailed = true;
                break;
            }
        }
    }

    /*----------------- For Temporary Maintenance -----------------*/
    /**
     * @notice Return whether the validator at index could enter maintenance
     */
    function canEnterMaintenance(uint256 index) public view returns (bool) {
        if (index >= currentValidatorSet.length) {
            return false;
        }

        if (
            currentValidatorSet[index].consensusAddress == address(0) // - 0. check if empty validator
                || (maxNumOfMaintaining == 0 || maintainSlashScale == 0) // - 1. check if not start
                || numOfMaintaining >= maxNumOfMaintaining // - 2. check if reached upper limit
                || !isWorkingValidator(index) // - 3. check if not working(not jailed and not maintaining)
                || validatorExtraSet[index].enterMaintenanceHeight > 0 // - 5. check if has Maintained during current 24-hour period
                    // current validators are selected every 24 hours(from 00:00:00 UTC to 23:59:59 UTC)
                || getValidators().length <= 1 // - 6. check num of remaining working validators
        ) {
            return false;
        }

        return true;
    }

    /**
     * @dev Enter maintenance for current validators. refer to https://github.com/bnb-chain/BEPs/blob/master/BEP127.md
     */
    function enterMaintenance() external initValidatorExtraSet {
        // check maintain config
        if (maxNumOfMaintaining == 0) {
            maxNumOfMaintaining = INIT_MAX_NUM_OF_MAINTAINING;
        }
        if (maintainSlashScale == 0) {
            maintainSlashScale = INIT_MAINTAIN_SLASH_SCALE;
        }

        uint256 index = getCurrentValidatorIndex(msg.sender);
        require(canEnterMaintenance(index), "can not enter Temporary Maintenance");
        _enterMaintenance(msg.sender, index);
    }

    /**
     * @dev Exit maintenance for current validators. refer to https://github.com/bnb-chain/BEPs/blob/master/BEP127.md
     */
    function exitMaintenance() external {
        uint256 index = getCurrentValidatorIndex(msg.sender);

        // jailed validators are allowed to exit maintenance
        require(validatorExtraSet[index].isMaintaining, "not in maintenance");
        uint256 miningValidatorCount = getWorkingValidatorCount();
        _exitMaintenance(msg.sender, index, miningValidatorCount);
    }

    /*----------------- Param update -----------------*/
    function updateParam(string calldata key, bytes calldata value) external override onlyInit onlyGov {
        if (Memory.compareStrings(key, "expireTimeSecondGap")) {
            require(value.length == 32, "length of expireTimeSecondGap mismatch");
            uint256 newExpireTimeSecondGap = BytesToTypes.bytesToUint256(32, value);
            require(
                newExpireTimeSecondGap >= 100 && newExpireTimeSecondGap <= 1e5,
                "the expireTimeSecondGap is out of range"
            );
            expireTimeSecondGap = newExpireTimeSecondGap;
        } else if (Memory.compareStrings(key, "burnRatio")) {
            require(value.length == 32, "length of burnRatio mismatch");
            uint256 newBurnRatio = BytesToTypes.bytesToUint256(32, value);
            require(
                newBurnRatio.add(systemRewardRatio) <= BLOCK_FEES_RATIO_SCALE,
                "the burnRatio plus systemRewardRatio must be no greater than 10000"
            );
            burnRatio = newBurnRatio;
        } else if (Memory.compareStrings(key, "maxNumOfMaintaining")) {
            require(value.length == 32, "length of maxNumOfMaintaining mismatch");
            uint256 newMaxNumOfMaintaining = BytesToTypes.bytesToUint256(32, value);
            uint256 _numOfCabinets = numOfCabinets;
            if (_numOfCabinets == 0) {
                _numOfCabinets = INIT_NUM_OF_CABINETS;
            }
            require(newMaxNumOfMaintaining < _numOfCabinets, "the maxNumOfMaintaining must be less than numOfCabinets");
            maxNumOfMaintaining = newMaxNumOfMaintaining;
        } else if (Memory.compareStrings(key, "maintainSlashScale")) {
            require(value.length == 32, "length of maintainSlashScale mismatch");
            uint256 newMaintainSlashScale = BytesToTypes.bytesToUint256(32, value);
            require(
                newMaintainSlashScale > 0 && newMaintainSlashScale < 10,
                "the maintainSlashScale must be greater than 0 and less than 10"
            );
            maintainSlashScale = newMaintainSlashScale;
        } else if (Memory.compareStrings(key, "maxNumOfWorkingCandidates")) {
            require(value.length == 32, "length of maxNumOfWorkingCandidates mismatch");
            uint256 newMaxNumOfWorkingCandidates = BytesToTypes.bytesToUint256(32, value);
            require(
                newMaxNumOfWorkingCandidates <= maxNumOfCandidates,
                "the maxNumOfWorkingCandidates must be not greater than maxNumOfCandidates"
            );
            maxNumOfWorkingCandidates = newMaxNumOfWorkingCandidates;
        } else if (Memory.compareStrings(key, "maxNumOfCandidates")) {
            require(value.length == 32, "length of maxNumOfCandidates mismatch");
            uint256 newMaxNumOfCandidates = BytesToTypes.bytesToUint256(32, value);
            maxNumOfCandidates = newMaxNumOfCandidates;
            if (maxNumOfWorkingCandidates > maxNumOfCandidates) {
                maxNumOfWorkingCandidates = maxNumOfCandidates;
            }
        } else if (Memory.compareStrings(key, "numOfCabinets")) {
            require(value.length == 32, "length of numOfCabinets mismatch");
            uint256 newNumOfCabinets = BytesToTypes.bytesToUint256(32, value);
            require(newNumOfCabinets > 0, "the numOfCabinets must be greater than 0");
            require(
                newNumOfCabinets <= MAX_NUM_OF_VALIDATORS, "the numOfCabinets must be less than MAX_NUM_OF_VALIDATORS"
            );
            numOfCabinets = newNumOfCabinets;
        } else if (Memory.compareStrings(key, "systemRewardRatio")) {
            require(value.length == 32, "length of systemRewardRatio mismatch");
            uint256 newSystemRewardRatio = BytesToTypes.bytesToUint256(32, value);
            require(
                newSystemRewardRatio.add(burnRatio) <= BLOCK_FEES_RATIO_SCALE,
                "the systemRewardRatio plus burnRatio must be no greater than 10000"
            );
            systemRewardRatio = newSystemRewardRatio;
        } else {
            require(false, "unknown param");
        }
        emit paramChange(key, value);
    }

    /*----------------- Internal Functions -----------------*/
    function updateValidatorSet(Validator[] memory validatorSet, bytes[] memory voteAddrs) internal returns (uint32) {
        {
            // do verify.
            if (validatorSet.length > MAX_NUM_OF_VALIDATORS) {
                emit failReasonWithStr("the number of validators exceed the limit");
                return ERROR_FAIL_CHECK_VALIDATORS;
            }
            for (uint256 i; i < validatorSet.length; ++i) {
                for (uint256 j; j < i; ++j) {
                    if (validatorSet[i].consensusAddress == validatorSet[j].consensusAddress) {
                        emit failReasonWithStr("duplicate consensus address of validatorSet");
                        return ERROR_FAIL_CHECK_VALIDATORS;
                    }
                }
            }
        }

        // step 0: force all maintaining validators to exit `Temporary Maintenance`
        // - 1. validators exit maintenance
        // - 2. clear all maintainInfo
        // - 3. get unjailed validators from validatorSet
        Validator[] memory validatorSetTemp;
        bytes[] memory voteAddrsTemp;
        {
            // get migrated validators
            Validator[] memory bscValidatorSet = _tmpMigratedValidatorSet;
            bytes[] memory bscVoteAddrs = _tmpMigratedVoteAddrs;
            for (uint256 i; i < bscValidatorSet.length; ++i) {
                bscValidatorSet[i].votingPower = bscValidatorSet[i].votingPower * 3; // amplify the voting power for BSC validators
            }
            (Validator[] memory mergedValidators, bytes[] memory mergedVoteAddrs) =
                _mergeValidatorSet(validatorSet, voteAddrs, bscValidatorSet, bscVoteAddrs);

            (validatorSetTemp, voteAddrsTemp) = _forceMaintainingValidatorsExit(mergedValidators, mergedVoteAddrs);
        }

        {
            //step 1: do calculate distribution, do not make it as an internal function for saving gas.
            uint256 crossSize;
            uint256 directSize;
            uint256 validatorsNum = currentValidatorSet.length;
            uint8[] memory isMigrated = new uint8[](validatorsNum);
            for (uint256 i; i < validatorsNum; ++i) {
                if (
                    IStakeHub(STAKE_HUB_ADDR).consensusToOperator(currentValidatorSet[i].consensusAddress) != address(0)
                ) {
                    isMigrated[i] = 1;
                    if (currentValidatorSet[i].incoming != 0) {
                        ++directSize;
                    }
                } else if (currentValidatorSet[i].incoming >= DUSTY_INCOMING) {
                    ++crossSize;
                } else if (currentValidatorSet[i].incoming != 0) {
                    ++directSize;
                }
            }

            //cross transfer
            address[] memory crossAddrs = new address[](crossSize);
            uint256[] memory crossAmounts = new uint256[](crossSize);
            uint256[] memory crossIndexes = new uint256[](crossSize);
            address[] memory crossRefundAddrs = new address[](crossSize);
            uint256 crossTotal;
            // direct transfer
            address payable[] memory directAddrs = new address payable[](directSize);
            uint256[] memory directAmounts = new uint256[](directSize);
            crossSize = 0;
            directSize = 0;
            uint256 relayFee = ITokenHub(TOKEN_HUB_ADDR).getMiniRelayFee();
            if (relayFee > DUSTY_INCOMING) {
                emit failReasonWithStr("fee is larger than DUSTY_INCOMING");
                return ERROR_RELAYFEE_TOO_LARGE;
            }
            for (uint256 i; i < validatorsNum; ++i) {
                if (isMigrated[i] == 1) {
                    if (currentValidatorSet[i].incoming != 0) {
                        directAddrs[directSize] = payable(currentValidatorSet[i].consensusAddress);
                        directAmounts[directSize] = currentValidatorSet[i].incoming;
                        isMigrated[directSize] = 1; // directSize must be less than i. so we can use directSize as index
                        ++directSize;
                    }
                } else if (currentValidatorSet[i].incoming >= DUSTY_INCOMING) {
                    crossAddrs[crossSize] = currentValidatorSet[i].BBCFeeAddress;
                    uint256 value = currentValidatorSet[i].incoming - currentValidatorSet[i].incoming % PRECISION;
                    crossAmounts[crossSize] = value.sub(relayFee);
                    crossRefundAddrs[crossSize] = currentValidatorSet[i].feeAddress;
                    crossIndexes[crossSize] = i;
                    crossTotal = crossTotal.add(value);
                    ++crossSize;
                } else if (currentValidatorSet[i].incoming != 0) {
                    directAddrs[directSize] = currentValidatorSet[i].feeAddress;
                    directAmounts[directSize] = currentValidatorSet[i].incoming;
                    isMigrated[directSize] = 0;
                    ++directSize;
                }
            }

            //step 2: do cross chain transfer
            bool failCross = false;
            if (crossTotal > 0) {
                try ITokenHub(TOKEN_HUB_ADDR).batchTransferOutBNB{ value: crossTotal }(
                    crossAddrs, crossAmounts, crossRefundAddrs, uint64(block.timestamp + expireTimeSecondGap)
                ) returns (bool success) {
                    if (success) {
                        emit batchTransfer(crossTotal);
                    } else {
                        emit batchTransferFailed(crossTotal, "batch transfer return false");
                    }
                } catch Error(string memory reason) {
                    failCross = true;
                    emit batchTransferFailed(crossTotal, reason);
                } catch (bytes memory lowLevelData) {
                    failCross = true;
                    emit batchTransferLowerFailed(crossTotal, lowLevelData);
                }
            }

            if (failCross) {
                for (uint256 i; i < crossIndexes.length; ++i) {
                    uint256 idx = crossIndexes[i];
                    bool success = currentValidatorSet[idx].feeAddress.send(currentValidatorSet[idx].incoming);
                    if (success) {
                        emit directTransfer(currentValidatorSet[idx].feeAddress, currentValidatorSet[idx].incoming);
                    } else {
                        emit directTransferFail(currentValidatorSet[idx].feeAddress, currentValidatorSet[idx].incoming);
                    }
                }
            }

            // step 3: direct transfer
            if (directAddrs.length > 0) {
                for (uint256 i; i < directAddrs.length; ++i) {
                    if (isMigrated[i] == 1) {
                        IStakeHub(STAKE_HUB_ADDR).distributeReward{ value: directAmounts[i] }(directAddrs[i]);
                    } else {
                        bool success = directAddrs[i].send(directAmounts[i]);
                        if (success) {
                            emit directTransfer(directAddrs[i], directAmounts[i]);
                        } else {
                            emit directTransferFail(directAddrs[i], directAmounts[i]);
                        }
                    }
                }
            }
        }

        for (uint256 i; i < currentValidatorSet.length; ++i) {
            if (currentValidatorSet[i].incoming != 0) {
                currentValidatorSet[i].incoming = 0;
            }
        }

        // step 4: do dusk transfer
        if (address(this).balance > 0) {
            emit systemTransfer(address(this).balance);
            address(uint160(SYSTEM_REWARD_ADDR)).transfer(address(this).balance);
        }

        // step 5: do update validator set state
        totalInComing = 0;
        numOfJailed = 0;
        if (validatorSetTemp.length > 0) {
            doUpdateState(validatorSetTemp, voteAddrsTemp);
        }

        // step 6: clean slash contract
        ISlashIndicator(SLASH_CONTRACT_ADDR).clean();
        emit validatorSetUpdated();
        return CODE_OK;
    }

    function doUpdateState(Validator[] memory newValidatorSet, bytes[] memory newVoteAddrs) private {
        uint256 n = currentValidatorSet.length;
        uint256 m = newValidatorSet.length;

        // delete stale validators
        for (uint256 i; i < n; ++i) {
            bool stale = true;
            Validator memory oldValidator = currentValidatorSet[i];
            for (uint256 j; j < m; ++j) {
                if (oldValidator.consensusAddress == newValidatorSet[j].consensusAddress) {
                    stale = false;
                    break;
                }
            }
            if (stale) {
                delete currentValidatorSetMap[oldValidator.consensusAddress];
            }
        }

        // if old validator set is larger than new validator set, pop the extra validators
        if (n > m) {
            for (uint256 i = m; i < n; ++i) {
                currentValidatorSet.pop();
                validatorExtraSet.pop();
            }
        }

        uint256 k = n < m ? n : m;
        for (uint256 i; i < k; ++i) {
            // if the validator is not the same, update the validator set directly
            if (!isSameValidator(newValidatorSet[i], currentValidatorSet[i])) {
                currentValidatorSetMap[newValidatorSet[i].consensusAddress] = i + 1;
                currentValidatorSet[i] = newValidatorSet[i];
                validatorExtraSet[i].voteAddress = newVoteAddrs[i];
                validatorExtraSet[i].isMaintaining = false;
                validatorExtraSet[i].enterMaintenanceHeight = 0;
            } else {
                currentValidatorSet[i].votingPower = newValidatorSet[i].votingPower;
                // update the vote address if it is different
                if (!BytesLib.equal(newVoteAddrs[i], validatorExtraSet[i].voteAddress)) {
                    validatorExtraSet[i].voteAddress = newVoteAddrs[i];
                }
            }
        }

        if (m > n) {
            ValidatorExtra memory _validatorExtra;
            for (uint256 i = n; i < m; ++i) {
                _validatorExtra.voteAddress = newVoteAddrs[i];
                currentValidatorSet.push(newValidatorSet[i]);
                validatorExtraSet.push(_validatorExtra);
                currentValidatorSetMap[newValidatorSet[i].consensusAddress] = i + 1;
            }
        }

        // update vote addr full set
        setPreviousVoteAddrFullSet();
        setCurrentVoteAddrFullSet();

        // make sure all new validators are cleared maintainInfo
        // should not happen, still protect
        numOfMaintaining = 0;
        n = currentValidatorSet.length;
        for (uint256 i; i < n; ++i) {
            validatorExtraSet[i].isMaintaining = false;
            validatorExtraSet[i].enterMaintenanceHeight = 0;
        }
    }

    /**
     * @dev With each epoch, there will be a partial rotation between cabinets and candidates. Rotation is determined by this function
     */
    function shuffle(
        address[] memory validators,
        bytes[] memory voteAddrs,
        uint256 epochNumber,
        uint256 startIdx,
        uint256 offset,
        uint256 limit,
        uint256 modNumber
    ) internal pure {
        for (uint256 i; i < limit; ++i) {
            uint256 random = uint256(keccak256(abi.encodePacked(epochNumber, startIdx + i))) % modNumber;
            if ((startIdx + i) != (offset + random)) {
                address tmpAddr = validators[startIdx + i];
                bytes memory tmpBLS = voteAddrs[startIdx + i];
                validators[startIdx + i] = validators[offset + random];
                validators[offset + random] = tmpAddr;
                voteAddrs[startIdx + i] = voteAddrs[offset + random];
                voteAddrs[offset + random] = tmpBLS;
            }
        }
    }

    /**
     * @dev Check if two validators are the same
     *
     * Vote address is not considered
     */
    function isSameValidator(Validator memory v1, Validator memory v2) private pure returns (bool) {
        return v1.consensusAddress == v2.consensusAddress && v1.feeAddress == v2.feeAddress
            && v1.BBCFeeAddress == v2.BBCFeeAddress;
    }

    function getVoteAddresses(address[] memory validators) internal view returns (bytes[] memory) {
        uint256 n = currentValidatorSet.length;
        uint256 length = validators.length;
        bytes[] memory voteAddrs = new bytes[](length);

        // check if validatorExtraSet has been initialized
        if (validatorExtraSet.length != n) {
            return voteAddrs;
        }

        for (uint256 i; i < length; ++i) {
            voteAddrs[i] = validatorExtraSet[currentValidatorSetMap[validators[i]] - 1].voteAddress;
        }
        return voteAddrs;
    }

    function setPreviousVoteAddrFullSet() private {
        uint256 n = previousVoteAddrFullSet.length;
        uint256 m = currentVoteAddrFullSet.length;

        if (n > m) {
            for (uint256 i = m; i < n; ++i) {
                previousVoteAddrFullSet.pop();
            }
        }

        uint256 k = n < m ? n : m;
        for (uint256 i; i < k; ++i) {
            if (!BytesLib.equal(previousVoteAddrFullSet[i], currentVoteAddrFullSet[i])) {
                previousVoteAddrFullSet[i] = currentVoteAddrFullSet[i];
            }
        }

        if (m > n) {
            for (uint256 i = n; i < m; ++i) {
                previousVoteAddrFullSet.push(currentVoteAddrFullSet[i]);
            }
        }
    }

    function setCurrentVoteAddrFullSet() private {
        uint256 n = currentVoteAddrFullSet.length;
        uint256 m = validatorExtraSet.length;

        if (n > m) {
            for (uint256 i = m; i < n; ++i) {
                currentVoteAddrFullSet.pop();
            }
        }

        uint256 k = n < m ? n : m;
        for (uint256 i; i < k; ++i) {
            if (!BytesLib.equal(currentVoteAddrFullSet[i], validatorExtraSet[i].voteAddress)) {
                currentVoteAddrFullSet[i] = validatorExtraSet[i].voteAddress;
            }
        }

        if (m > n) {
            for (uint256 i = n; i < m; ++i) {
                currentVoteAddrFullSet.push(validatorExtraSet[i].voteAddress);
            }
        }
    }

    function isMonitoredForMaliciousVote(bytes calldata voteAddr) external view override returns (bool) {
        uint256 m = currentVoteAddrFullSet.length;
        for (uint256 i; i < m; ++i) {
            if (BytesLib.equal(voteAddr, currentVoteAddrFullSet[i])) {
                return true;
            }
        }

        uint256 n = previousVoteAddrFullSet.length;
        for (uint256 i; i < n; ++i) {
            if (BytesLib.equal(voteAddr, previousVoteAddrFullSet[i])) {
                return true;
            }
        }

        return false;
    }

    function _misdemeanor(address validator) private returns (uint256) {
        uint256 index = currentValidatorSetMap[validator];
        if (index <= 0) {
            return ~uint256(0);
        }
        // the actually index
        index = index - 1;

        uint256 income = currentValidatorSet[index].incoming;
        currentValidatorSet[index].incoming = 0;
        uint256 rest = currentValidatorSet.length - 1;
        emit validatorMisdemeanor(validator, income);
        if (rest == 0) {
            // should not happen, but still protect
            return index;
        }

        // averageDistribute*rest may less than income, but it is ok, the dust income will go to system reward eventually.
        uint256 averageDistribute = income / rest;
        if (averageDistribute != 0) {
            for (uint256 i; i < index; ++i) {
                currentValidatorSet[i].incoming = currentValidatorSet[i].incoming.add(averageDistribute);
            }
            uint256 n = currentValidatorSet.length;
            for (uint256 i = index + 1; i < n; ++i) {
                currentValidatorSet[i].incoming = currentValidatorSet[i].incoming.add(averageDistribute);
            }
        }

        return index;
    }

    function _felony(address validator, uint256 index) private returns (bool) {
        uint256 income = currentValidatorSet[index].incoming;
        uint256 rest = currentValidatorSet.length - 1;
        if (getValidators().length <= 1) {
            // will not remove the validator if it is the only one validator.
            currentValidatorSet[index].incoming = 0;
            return false;
        }
        emit validatorFelony(validator, income);

        // remove the validator from currentValidatorSet
        delete currentValidatorSetMap[validator];
        // remove felony validator
        for (uint256 i = index; i < (currentValidatorSet.length - 1); ++i) {
            currentValidatorSet[i] = currentValidatorSet[i + 1];
            validatorExtraSet[i] = validatorExtraSet[i + 1];
            currentValidatorSetMap[currentValidatorSet[i].consensusAddress] = i + 1;
        }
        currentValidatorSet.pop();
        validatorExtraSet.pop();

        // averageDistribute*rest may less than income, but it is ok, the dust income will go to system reward eventually.
        uint256 averageDistribute = income / rest;
        if (averageDistribute != 0) {
            uint256 n = currentValidatorSet.length;
            for (uint256 i; i < n; ++i) {
                currentValidatorSet[i].incoming = currentValidatorSet[i].incoming.add(averageDistribute);
            }
        }
        return true;
    }

    function _forceMaintainingValidatorsExit(
        Validator[] memory _validatorSet,
        bytes[] memory _voteAddrs
    ) private returns (Validator[] memory unjailedValidatorSet, bytes[] memory unjailedVoteAddrs) {
        uint256 numOfFelony = 0;
        address validator;
        bool isFelony;

        // 1. validators exit maintenance
        uint256 i;
        // caution: it must calculate miningValidatorCount before _exitMaintenance loop
        // because the miningValidatorCount will be changed in _exitMaintenance
        uint256 miningValidatorCount = getWorkingValidatorCount();
        // caution: it must loop from the endIndex to startIndex in currentValidatorSet
        // because the validators order in currentValidatorSet may be changed by _felony(validator)
        for (uint256 index = currentValidatorSet.length; index > 0; --index) {
            i = index - 1; // the actual index
            if (!validatorExtraSet[i].isMaintaining) {
                continue;
            }

            // only maintaining validators
            validator = currentValidatorSet[i].consensusAddress;

            // exit maintenance
            isFelony = _exitMaintenance(validator, i, miningValidatorCount);
            if (!isFelony) {
                continue;
            }

            // get the latest consensus address
            address latestConsensusAddress;
            address operatorAddress = IStakeHub(STAKE_HUB_ADDR).consensusToOperator(validator);
            if (operatorAddress != address(0)) {
                latestConsensusAddress = IStakeHub(STAKE_HUB_ADDR).getValidatorConsensusAddress(operatorAddress);
            }

            // record the jailed validator in validatorSet
            for (uint256 j; j < _validatorSet.length; ++j) {
                if (
                    _validatorSet[j].consensusAddress == validator
                        || _validatorSet[j].consensusAddress == latestConsensusAddress
                ) {
                    _validatorSet[j].jailed = true;
                    break;
                }
            }
        }

        // count the number of felony validators
        for (uint256 k; k < _validatorSet.length; ++k) {
            if (_validatorSet[k].jailed || _validatorSet[k].consensusAddress == address(0)) {
                ++numOfFelony;
            }
        }

        // 2. get unjailed validators from validatorSet
        if (numOfFelony >= _validatorSet.length) {
            // make sure there is at least one validator
            unjailedValidatorSet = new Validator[](1);
            unjailedVoteAddrs = new bytes[](1);
            unjailedValidatorSet[0] = _validatorSet[0];
            unjailedVoteAddrs[0] = _voteAddrs[0];
            unjailedValidatorSet[0].jailed = false;
        } else {
            unjailedValidatorSet = new Validator[](_validatorSet.length - numOfFelony);
            unjailedVoteAddrs = new bytes[](_validatorSet.length - numOfFelony);
            i = 0;
            for (uint256 index; index < _validatorSet.length; ++index) {
                if (!_validatorSet[index].jailed && _validatorSet[index].consensusAddress != address(0)) {
                    unjailedValidatorSet[i] = _validatorSet[index];
                    unjailedVoteAddrs[i] = _voteAddrs[index];
                    ++i;
                }
            }
        }

        return (unjailedValidatorSet, unjailedVoteAddrs);
    }

    function _enterMaintenance(address validator, uint256 index) private {
        ++numOfMaintaining;
        validatorExtraSet[index].isMaintaining = true;
        validatorExtraSet[index].enterMaintenanceHeight = block.number;
        emit validatorEnterMaintenance(validator);
    }

    function _exitMaintenance(
        address validator,
        uint256 index,
        uint256 miningValidatorCount
    ) private returns (bool isFelony) {
        if (maintainSlashScale == 0 || miningValidatorCount == 0 || numOfMaintaining == 0) {
            // should not happen, still protect
            return false;
        }

        // step 1: calculate slashCount
        uint256 slashCount = block.number.sub(validatorExtraSet[index].enterMaintenanceHeight).div(miningValidatorCount)
            .div(maintainSlashScale);

        // step2: slash the validator
        (uint256 misdemeanorThreshold, uint256 felonyThreshold) =
            ISlashIndicator(SLASH_CONTRACT_ADDR).getSlashThresholds();
        isFelony = false;
        if (slashCount >= felonyThreshold) {
            _felony(validator, index);
            if (IStakeHub(STAKE_HUB_ADDR).consensusToOperator(validator) != address(0)) {
                ISlashIndicator(SLASH_CONTRACT_ADDR).downtimeSlash(validator, slashCount);
            } else {
                ISlashIndicator(SLASH_CONTRACT_ADDR).sendFelonyPackage(validator);
            }
            isFelony = true;
        } else if (slashCount >= misdemeanorThreshold) {
            _misdemeanor(validator);
        }

        // step 3: modify global storage
        --numOfMaintaining;
        validatorExtraSet[index].isMaintaining = false;

        emit validatorExitMaintenance(validator);
    }

    function _mergeValidatorSet(
        Validator[] memory validatorSet1,
        bytes[] memory voteAddrSet1,
        Validator[] memory validatorSet2,
        bytes[] memory voteAddrSet2
    ) internal view returns (Validator[] memory, bytes[] memory) {
        uint256 _length = IStakeHub(STAKE_HUB_ADDR).maxElectedValidators();
        if (validatorSet1.length + validatorSet2.length < _length) {
            _length = validatorSet1.length + validatorSet2.length;
        }
        Validator[] memory mergedValidatorSet = new Validator[](_length);
        bytes[] memory mergedVoteAddrSet = new bytes[](_length);

        uint256 i;
        uint256 j;
        uint256 k;
        while ((i < validatorSet1.length || j < validatorSet2.length) && k < _length) {
            if (i == validatorSet1.length) {
                mergedValidatorSet[k] = validatorSet2[j];
                mergedVoteAddrSet[k] = voteAddrSet2[j];
                ++j;
                ++k;
                continue;
            }

            if (j == validatorSet2.length) {
                mergedValidatorSet[k] = validatorSet1[i];
                mergedVoteAddrSet[k] = voteAddrSet1[i];
                ++i;
                ++k;
                continue;
            }

            if (validatorSet1[i].votingPower > validatorSet2[j].votingPower) {
                mergedValidatorSet[k] = validatorSet1[i];
                mergedVoteAddrSet[k] = voteAddrSet1[i];
                ++i;
            } else if (validatorSet1[i].votingPower < validatorSet2[j].votingPower) {
                mergedValidatorSet[k] = validatorSet2[j];
                mergedVoteAddrSet[k] = voteAddrSet2[j];
                ++j;
            } else {
                if (validatorSet1[i].consensusAddress < validatorSet2[j].consensusAddress) {
                    mergedValidatorSet[k] = validatorSet1[i];
                    mergedVoteAddrSet[k] = voteAddrSet1[i];
                    ++i;
                } else {
                    mergedValidatorSet[k] = validatorSet2[j];
                    mergedVoteAddrSet[k] = voteAddrSet2[j];
                    ++j;
                }
            }
            ++k;
        }

        return (mergedValidatorSet, mergedVoteAddrSet);
    }

    //rlp encode & decode function
    function decodeValidatorSetSynPackage(bytes memory msgBytes)
        internal
        pure
        returns (IbcValidatorSetPackage memory, bool)
    {
        IbcValidatorSetPackage memory validatorSetPkg;

        RLPDecode.Iterator memory iter = msgBytes.toRLPItem().iterator();
        bool success = false;
        uint256 idx = 0;
        while (iter.hasNext()) {
            if (idx == 0) {
                validatorSetPkg.packageType = uint8(iter.next().toUint());
            } else if (idx == 1) {
                RLPDecode.RLPItem[] memory items = iter.next().toList();
                validatorSetPkg.validatorSet = new Validator[](items.length);
                validatorSetPkg.voteAddrs = new bytes[](items.length);
                for (uint256 j; j < items.length; ++j) {
                    (Validator memory val, bytes memory voteAddr, bool ok) = decodeValidator(items[j]);
                    if (!ok) {
                        return (validatorSetPkg, false);
                    }
                    validatorSetPkg.validatorSet[j] = val;
                    validatorSetPkg.voteAddrs[j] = voteAddr;
                }
                success = true;
            } else {
                break;
            }
            ++idx;
        }
        return (validatorSetPkg, success);
    }

    function decodeValidator(RLPDecode.RLPItem memory itemValidator)
        internal
        pure
        returns (Validator memory, bytes memory, bool)
    {
        Validator memory validator;
        bytes memory voteAddr;
        RLPDecode.Iterator memory iter = itemValidator.iterator();
        bool success = false;
        uint256 idx = 0;
        while (iter.hasNext()) {
            if (idx == 0) {
                validator.consensusAddress = iter.next().toAddress();
            } else if (idx == 1) {
                validator.feeAddress = address(uint160(iter.next().toAddress()));
            } else if (idx == 2) {
                validator.BBCFeeAddress = iter.next().toAddress();
            } else if (idx == 3) {
                validator.votingPower = uint64(iter.next().toUint());
                success = true;
            } else if (idx == 4) {
                voteAddr = iter.next().toBytes();
            } else {
                break;
            }
            ++idx;
        }
        return (validator, voteAddr, success);
    }
}

Contract Security Audit

Contract ABI

[{"anonymous": false,"inputs": [{"indexed": false,"internalType": "uint256","name": "amount","type": "uint256"}],"name": "batchTransfer","type": "event"},{"anonymous": false,"inputs": [{"indexed": true,"internalType": "uint256","name": "amount","type": "uint256"},{"indexed": false,"internalType": "string","name": "reason","type": "string"}],"name": "batchTransferFailed","type": "event"},{"anonymous": false,"inputs": [{"indexed": true,"internalType": "uint256","name": "amount","type": "uint256"},{"indexed": false,"internalType": "bytes","name": "reason","type": "bytes"}],"name": "batchTransferLowerFailed","type": "event"},{"anonymous": false,"inputs": [{"indexed": true,"internalType": "address","name": "validator","type": "address"},{"indexed": false,"internalType": "uint256","name": "amount","type": "uint256"}],"name": "deprecatedDeposit","type": "event"},{"anonymous": false,"inputs": [{"indexed": true,"internalType": "address","name": "validator","type": "address"},{"indexed": false,"internalType": "uint256","name": "amount","type": "uint256"}],"name": "deprecatedFinalityRewardDeposit","type": "event"},{"anonymous": false,"inputs": [{"indexed": true,"internalType": "address payable","name": "validator","type": "address"},{"indexed": false,"internalType": "uint256","name": "amount","type": "uint256"}],"name": "directTransfer","type": "event"},{"anonymous": false,"inputs": [{"indexed": true,"internalType": "address payable","name": "validator","type": "address"},{"indexed": false,"internalType": "uint256","name": "amount","type": "uint256"}],"name": "directTransferFail","type": "event"},{"anonymous": false,"inputs": [{"indexed": false,"internalType": "string","name": "message","type": "string"}],"name": "failReasonWithStr","type": "event"},{"anonymous": false,"inputs": [{"indexed": false,"internalType": "uint256","name": "amount","type": "uint256"}],"name": "feeBurned","type": "event"},{"anonymous": false,"inputs": [{"indexed": true,"internalType": "address","name": "validator","type": "address"},{"indexed": false,"internalType": "uint256","name": "amount","type": "uint256"}],"name": "finalityRewardDeposit","type": "event"},{"anonymous": false,"inputs": [{"indexed": false,"internalType": "string","name": "key","type": "string"},{"indexed": false,"internalType": "bytes","name": "value","type": "bytes"}],"name": "paramChange","type": "event"},{"anonymous": false,"inputs": [{"indexed": false,"internalType": "uint256","name": "amount","type": "uint256"}],"name": "systemTransfer","type": "event"},{"anonymous": false,"inputs": [{"indexed": false,"internalType": "uint256","name": "validatorsNum","type": "uint256"}],"name": "tmpValidatorSetUpdated","type": "event"},{"anonymous": false,"inputs": [{"indexed": false,"internalType": "uint8","name": "channelId","type": "uint8"},{"indexed": false,"internalType": "bytes","name": "msgBytes","type": "bytes"}],"name": "unexpectedPackage","type": "event"},{"anonymous": false,"inputs": [{"indexed": true,"internalType": "address","name": "validator","type": "address"},{"indexed": false,"internalType": "uint256","name": "amount","type": "uint256"}],"name": "validatorDeposit","type": "event"},{"anonymous": false,"inputs": [{"indexed": true,"internalType": "address","name": "validator","type": "address"}],"name": "validatorEmptyJailed","type": "event"},{"anonymous": false,"inputs": [{"indexed": true,"internalType": "address","name": "validator","type": "address"}],"name": "validatorEnterMaintenance","type": "event"},{"anonymous": false,"inputs": [{"indexed": true,"internalType": "address","name": "validator","type": "address"}],"name": "validatorExitMaintenance","type": "event"},{"anonymous": false,"inputs": [{"indexed": true,"internalType": "address","name": "validator","type": "address"},{"indexed": false,"internalType": "uint256","name": "amount","type": "uint256"}],"name": "validatorFelony","type": "event"},{"anonymous": false,"inputs": [{"indexed": true,"internalType": "address","name": "validator","type": "address"}],"name": "validatorJailed","type": "event"},{"anonymous": false,"inputs": [{"indexed": true,"internalType": "address","name": "validator","type": "address"},{"indexed": false,"internalType": "uint256","name": "amount","type": "uint256"}],"name": "validatorMisdemeanor","type": "event"},{"anonymous": false,"inputs": [],"name": "validatorSetUpdated","type": "event"},{"inputs": [],"name": "BC_FUSION_CHANNELID","outputs": [{"internalType": "uint8","name": "","type": "uint8"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "BIND_CHANNELID","outputs": [{"internalType": "uint8","name": "","type": "uint8"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "BLOCK_FEES_RATIO_SCALE","outputs": [{"internalType": "uint256","name": "","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "BURN_ADDRESS","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "CODE_OK","outputs": [{"internalType": "uint32","name": "","type": "uint32"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "CROSS_CHAIN_CONTRACT_ADDR","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "CROSS_STAKE_CHANNELID","outputs": [{"internalType": "uint8","name": "","type": "uint8"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "DUSTY_INCOMING","outputs": [{"internalType": "uint256","name": "","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "EPOCH","outputs": [{"internalType": "uint256","name": "","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "ERROR_FAIL_CHECK_VALIDATORS","outputs": [{"internalType": "uint32","name": "","type": "uint32"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "ERROR_FAIL_DECODE","outputs": [{"internalType": "uint32","name": "","type": "uint32"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "ERROR_LEN_OF_VAL_MISMATCH","outputs": [{"internalType": "uint32","name": "","type": "uint32"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "ERROR_RELAYFEE_TOO_LARGE","outputs": [{"internalType": "uint32","name": "","type": "uint32"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "ERROR_UNKNOWN_PACKAGE_TYPE","outputs": [{"internalType": "uint32","name": "","type": "uint32"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "EXPIRE_TIME_SECOND_GAP","outputs": [{"internalType": "uint256","name": "","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "GOVERNOR_ADDR","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "GOV_CHANNELID","outputs": [{"internalType": "uint8","name": "","type": "uint8"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "GOV_HUB_ADDR","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "GOV_TOKEN_ADDR","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "INCENTIVIZE_ADDR","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "INIT_BURN_RATIO","outputs": [{"internalType": "uint256","name": "","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "INIT_MAINTAIN_SLASH_SCALE","outputs": [{"internalType": "uint256","name": "","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "INIT_MAX_NUM_OF_MAINTAINING","outputs": [{"internalType": "uint256","name": "","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "INIT_NUM_OF_CABINETS","outputs": [{"internalType": "uint256","name": "","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "INIT_SYSTEM_REWARD_RATIO","outputs": [{"internalType": "uint256","name": "","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "INIT_VALIDATORSET_BYTES","outputs": [{"internalType": "bytes","name": "","type": "bytes"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "JAIL_MESSAGE_TYPE","outputs": [{"internalType": "uint8","name": "","type": "uint8"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "LIGHT_CLIENT_ADDR","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "MAX_NUM_OF_VALIDATORS","outputs": [{"internalType": "uint256","name": "","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "MAX_SYSTEM_REWARD_BALANCE","outputs": [{"internalType": "uint256","name": "","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "PRECISION","outputs": [{"internalType": "uint256","name": "","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "RELAYERHUB_CONTRACT_ADDR","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "SLASH_CHANNELID","outputs": [{"internalType": "uint8","name": "","type": "uint8"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "SLASH_CONTRACT_ADDR","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "STAKE_CREDIT_ADDR","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "STAKE_HUB_ADDR","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "STAKING_CHANNELID","outputs": [{"internalType": "uint8","name": "","type": "uint8"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "STAKING_CONTRACT_ADDR","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "SYSTEM_REWARD_ADDR","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "TIMELOCK_ADDR","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "TOKEN_HUB_ADDR","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "TOKEN_MANAGER_ADDR","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "TOKEN_RECOVER_PORTAL_ADDR","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "TRANSFER_IN_CHANNELID","outputs": [{"internalType": "uint8","name": "","type": "uint8"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "TRANSFER_OUT_CHANNELID","outputs": [{"internalType": "uint8","name": "","type": "uint8"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "VALIDATORS_UPDATE_MESSAGE_TYPE","outputs": [{"internalType": "uint8","name": "","type": "uint8"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "VALIDATOR_CONTRACT_ADDR","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "alreadyInit","outputs": [{"internalType": "bool","name": "","type": "bool"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "bscChainID","outputs": [{"internalType": "uint16","name": "","type": "uint16"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "burnRatio","outputs": [{"internalType": "uint256","name": "","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "burnRatioInitialized","outputs": [{"internalType": "bool","name": "","type": "bool"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "uint256","name": "index","type": "uint256"}],"name": "canEnterMaintenance","outputs": [{"internalType": "bool","name": "","type": "bool"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "uint256","name": "","type": "uint256"}],"name": "currentValidatorSet","outputs": [{"internalType": "address","name": "consensusAddress","type": "address"},{"internalType": "address payable","name": "feeAddress","type": "address"},{"internalType": "address","name": "BBCFeeAddress","type": "address"},{"internalType": "uint64","name": "votingPower","type": "uint64"},{"internalType": "bool","name": "jailed","type": "bool"},{"internalType": "uint256","name": "incoming","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "address","name": "","type": "address"}],"name": "currentValidatorSetMap","outputs": [{"internalType": "uint256","name": "","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "uint256","name": "","type": "uint256"}],"name": "currentVoteAddrFullSet","outputs": [{"internalType": "bytes","name": "","type": "bytes"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "address","name": "valAddr","type": "address"}],"name": "deposit","outputs": [],"stateMutability": "payable","type": "function"},{"inputs": [{"internalType": "address[]","name": "valAddrs","type": "address[]"},{"internalType": "uint256[]","name": "weights","type": "uint256[]"}],"name": "distributeFinalityReward","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [],"name": "enterMaintenance","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [],"name": "exitMaintenance","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [],"name": "expireTimeSecondGap","outputs": [{"internalType": "uint256","name": "","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "address","name": "validator","type": "address"}],"name": "felony","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [{"internalType": "address","name": "validator","type": "address"}],"name": "getCurrentValidatorIndex","outputs": [{"internalType": "uint256","name": "","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "address","name": "validator","type": "address"}],"name": "getIncoming","outputs": [{"internalType": "uint256","name": "","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "getLivingValidators","outputs": [{"internalType": "address[]","name": "","type": "address[]"},{"internalType": "bytes[]","name": "","type": "bytes[]"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "getMiningValidators","outputs": [{"internalType": "address[]","name": "","type": "address[]"},{"internalType": "bytes[]","name": "","type": "bytes[]"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "getValidators","outputs": [{"internalType": "address[]","name": "","type": "address[]"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "getWorkingValidatorCount","outputs": [{"internalType": "uint256","name": "workingValidatorCount","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "uint8","name": "channelId","type": "uint8"},{"internalType": "bytes","name": "msgBytes","type": "bytes"}],"name": "handleAckPackage","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [{"internalType": "uint8","name": "channelId","type": "uint8"},{"internalType": "bytes","name": "msgBytes","type": "bytes"}],"name": "handleFailAckPackage","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [{"internalType": "uint8","name": "","type": "uint8"},{"internalType": "bytes","name": "msgBytes","type": "bytes"}],"name": "handleSynPackage","outputs": [{"internalType": "bytes","name": "responsePayload","type": "bytes"}],"stateMutability": "nonpayable","type": "function"},{"inputs": [],"name": "init","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [{"internalType": "address","name": "validator","type": "address"}],"name": "isCurrentValidator","outputs": [{"internalType": "bool","name": "","type": "bool"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "bytes","name": "voteAddr","type": "bytes"}],"name": "isMonitoredForMaliciousVote","outputs": [{"internalType": "bool","name": "","type": "bool"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "isSystemRewardIncluded","outputs": [{"internalType": "bool","name": "","type": "bool"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "uint256","name": "index","type": "uint256"}],"name": "isWorkingValidator","outputs": [{"internalType": "bool","name": "","type": "bool"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "maintainSlashScale","outputs": [{"internalType": "uint256","name": "","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "maxNumOfCandidates","outputs": [{"internalType": "uint256","name": "","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "maxNumOfMaintaining","outputs": [{"internalType": "uint256","name": "","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "maxNumOfWorkingCandidates","outputs": [{"internalType": "uint256","name": "","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "address","name": "validator","type": "address"}],"name": "misdemeanor","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [],"name": "numOfCabinets","outputs": [{"internalType": "uint256","name": "","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "numOfJailed","outputs": [{"internalType": "uint256","name": "","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "numOfMaintaining","outputs": [{"internalType": "uint256","name": "","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "previousBalanceOfSystemReward","outputs": [{"internalType": "uint256","name": "","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "previousHeight","outputs": [{"internalType": "uint256","name": "","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "uint256","name": "","type": "uint256"}],"name": "previousVoteAddrFullSet","outputs": [{"internalType": "bytes","name": "","type": "bytes"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "address","name": "validator","type": "address"}],"name": "removeTmpMigratedValidator","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [],"name": "systemRewardRatio","outputs": [{"internalType": "uint256","name": "","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "totalInComing","outputs": [{"internalType": "uint256","name": "","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "string","name": "key","type": "string"},{"internalType": "bytes","name": "value","type": "bytes"}],"name": "updateParam","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [{"internalType": "address[]","name": "_consensusAddrs","type": "address[]"},{"internalType": "uint64[]","name": "_votingPowers","type": "uint64[]"},{"internalType": "bytes[]","name": "_voteAddrs","type": "bytes[]"}],"name": "updateValidatorSetV2","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [{"internalType": "uint256","name": "","type": "uint256"}],"name": "validatorExtraSet","outputs": [{"internalType": "uint256","name": "enterMaintenanceHeight","type": "uint256"},{"internalType": "bool","name": "isMaintaining","type": "bool"},{"internalType": "bytes","name": "voteAddress","type": "bytes"}],"stateMutability": "view","type": "function"},{"stateMutability": "payable","type": "receive"}]

0x6080604052600436106104fb5760003560e01c806388b32f111161028c578063c6d339451161015a578063e40716a1116100cc578063f92eb86b11610085578063f92eb86b14610d2d578063f9a2bbc714610d42578063fc3e590814610d57578063fccc281314610d6c578063fd4ad81f14610d81578063fd6a687914610db057610502565b8063e40716a114610c9b578063ea321e4914610cb0578063eb57e20214610cd0578063eda5868c14610cf0578063f1fad10414610d05578063f340fa0114610d1a57610502565b8063d86222d51161011e578063d86222d514610c1d578063daacdb6614610c32578063dc927faf14610c47578063df8079e914610c5c578063e086c7b114610c71578063e1c7392a14610c8657610502565b8063c6d3394514610bbe578063c81b166214610bd3578063c8509d811461098d578063ce910b0c14610be8578063d68fb56a14610c0857610502565b8063a78abc16116101fe578063ad3c9da6116101b7578063ad3c9da614610b3d578063aef198a914610b5d578063b7ab4db514610b72578063b8cf4ef114610b94578063bf9f4995146106fe578063c466689d14610ba957610502565b8063a78abc1614610ab4578063aa82dce114610ac9578063aad5606314610ade578063aaf5eb6814610af3578063ab51bb9614610b08578063ac43175114610b1d57610502565b806396713da91161025057806396713da914610a365780639dc0926214610a4b5780639fe0f81614610a60578063a0dc275814610a75578063a1a11bf514610a8a578063a5422d5c14610a9f57610502565b806388b32f11146109c25780638a7beb01146109d75780638b5ad0c9146109ec5780638d19a41014610a015780639369d7de14610a2157610502565b806351b4dce3116103c957806370fd5bad1161033b5780637e434d54116102f45780637e434d541461094e57806381650b6214610963578063820dcaa814610978578063831d65d11461098d578063853230aa1461090f57806386249882146109ad57610502565b806370fd5bad146108d0578063718a8aa8146108e557806375d47a0a146108fa57806378dfed4a1461090f5780637942fd05146109245780637a84ca2a1461093957610502565b80635d77156c1161038d5780635d77156c1461082a5780635de1e22c1461083f57806360eba4fe1461085457806362b72cf5146108745780636969a25c146108895780636e47b482146108bb57610502565b806351b4dce3146107ab57806351e80672146107c057806355614fcc146107d5578063565c56b3146107f55780635667515a1461081557610502565b8063300c35671161046d57806343756e5c1161042657806343756e5c1461072057806345cf9daf14610735578063493279b11461074a5780634bf6c8821461076c5780634df6e0c3146107815780635192c82c1461079657610502565b8063300c35671461065b578063321d398a1461067b5780633365af3a1461069b57806335409f7f146106bb5780633b071dcc146106db5780633dffc387146106fe57610502565b8063152ad3b8116104bf578063152ad3b8146105ba5780631e4c1524146105dc5780631ff18069146105fc578063219f22d51461061157806328087028146106265780632a0ffb6e1461063b57610502565b806304c4fec61461050757806307a568471461051e5780630bee7a67146105495780630e2374a51461056b5780631182b8751461058d57610502565b3661050257005b600080fd5b34801561051357600080fd5b5061051c610dc5565b005b34801561052a57600080fd5b50610533610e37565b6040516105409190618ed8565b60405180910390f35b34801561055557600080fd5b5061055e610e3d565b6040516105409190618f02565b34801561057757600080fd5b50610580610e42565b60405161054091906181eb565b34801561059957600080fd5b506105ad6105a83660046180d1565b610e48565b604051610540919061837e565b3480156105c657600080fd5b506105cf611165565b6040516105409190618373565b3480156105e857600080fd5b5061051c6105f7366004617edf565b61116e565b34801561060857600080fd5b50610533611844565b34801561061d57600080fd5b5061055e61184a565b34801561063257600080fd5b5061058061184f565b34801561064757600080fd5b5061051c610656366004617e3f565b611855565b34801561066757600080fd5b5061051c610676366004617e77565b611902565b34801561068757600080fd5b506105cf61069636600461807e565b611c4b565b3480156106a757600080fd5b506105cf6106b636600461807e565b611d1a565b3480156106c757600080fd5b5061051c6106d6366004617e3f565b611dcb565b3480156106e757600080fd5b506106f0611f30565b604051610540929190618289565b34801561070a57600080fd5b5061071361220c565b6040516105409190618f13565b34801561072c57600080fd5b50610580612211565b34801561074157600080fd5b50610533612217565b34801561075657600080fd5b5061075f61221d565b6040516105409190618ec9565b34801561077857600080fd5b50610713612222565b34801561078d57600080fd5b506106f0612227565b3480156107a257600080fd5b506105336123b3565b3480156107b757600080fd5b506105806123b9565b3480156107cc57600080fd5b506105806123bf565b3480156107e157600080fd5b506105cf6107f0366004617e3f565b6123c5565b34801561080157600080fd5b50610533610810366004617e3f565b6123fa565b34801561082157600080fd5b5061071361244b565b34801561083657600080fd5b5061055e612450565b34801561084b57600080fd5b50610533612455565b34801561086057600080fd5b506105ad61086f36600461807e565b61245b565b34801561088057600080fd5b50610533612501565b34801561089557600080fd5b506108a96108a436600461807e565b612507565b60405161054096959493929190618218565b3480156108c757600080fd5b5061058061256b565b3480156108dc57600080fd5b50610713612571565b3480156108f157600080fd5b50610713612576565b34801561090657600080fd5b5061058061257b565b34801561091b57600080fd5b50610533612581565b34801561093057600080fd5b50610713612587565b34801561094557600080fd5b5061053361258c565b34801561095a57600080fd5b50610580612592565b34801561096f57600080fd5b5061055e612598565b34801561098457600080fd5b5061053361259d565b34801561099957600080fd5b5061051c6109a83660046180d1565b6125a3565b3480156109b957600080fd5b50610533612604565b3480156109ce57600080fd5b5061053361260a565b3480156109e357600080fd5b506105cf612610565b3480156109f857600080fd5b50610533612619565b348015610a0d57600080fd5b50610533610a1c366004617e3f565b61261f565b348015610a2d57600080fd5b5061051c61265f565b348015610a4257600080fd5b50610713612773565b348015610a5757600080fd5b50610580612778565b348015610a6c57600080fd5b5061053361277e565b348015610a8157600080fd5b50610533612783565b348015610a9657600080fd5b50610580612788565b348015610aab57600080fd5b506105ad61278e565b348015610ac057600080fd5b506105cf6127ad565b348015610ad557600080fd5b506105806127b6565b348015610aea57600080fd5b506105806127bc565b348015610aff57600080fd5b506105336127c2565b348015610b1457600080fd5b5061055e61244b565b348015610b2957600080fd5b5061051c610b38366004618022565b6127cb565b348015610b4957600080fd5b50610533610b58366004617e3f565b613084565b348015610b6957600080fd5b50610533613096565b348015610b7e57600080fd5b50610b876130a3565b6040516105409190618276565b348015610ba057600080fd5b5061053361318f565b348015610bb557600080fd5b50610533613194565b348015610bca57600080fd5b50610533612571565b348015610bdf57600080fd5b5061058061319a565b348015610bf457600080fd5b506105ad610c0336600461807e565b6131a0565b348015610c1457600080fd5b506105336131ad565b348015610c2957600080fd5b506105336131ec565b348015610c3e57600080fd5b506105336131f8565b348015610c5357600080fd5b506105806131fe565b348015610c6857600080fd5b50610580613204565b348015610c7d57600080fd5b50610533610e3d565b348015610c9257600080fd5b5061051c61320a565b348015610ca757600080fd5b506105336133b9565b348015610cbc57600080fd5b506105cf610ccb366004617fe3565b6133bf565b348015610cdc57600080fd5b5061051c610ceb366004617e3f565b613545565b348015610cfc57600080fd5b5061055e613649565b348015610d1157600080fd5b5061071361364e565b61051c610d28366004617e3f565b613653565b348015610d3957600080fd5b506105336139d2565b348015610d4e57600080fd5b506105806139d8565b348015610d6357600080fd5b5061071361277e565b348015610d7857600080fd5b506105806139de565b348015610d8d57600080fd5b50610da1610d9c36600461807e565b6139e4565b60405161054093929190618ee1565b348015610dbc57600080fd5b50610580613aa6565b6000610dd03361261f565b9050600b8181548110610ddf57fe5b600091825260209091206001601690920201015460ff16610e1b5760405162461bcd60e51b8152600401610e1290618ae4565b60405180910390fd5b6000610e256131ad565b9050610e32338383613aac565b505050565b60095481565b606481565b61200181565b60005460609060ff16610e6d5760405162461bcd60e51b8152600401610e12906185a5565b3361200014610e8e5760405162461bcd60e51b8152600401610e1290618ce5565b600b54610f4c57610e9d6179eb565b60015460005b81811015610f4857600b80546001810182556000919091528351600080516020618fe583398151915260169092029182019081556020808601516000805160206196148339815191528401805460ff1916911515919091179055604086015180518794610f2493600080516020619005833981519152909101920190617a1a565b506060820151610f3a9060038301906013617a94565b505050806001019050610ea3565b5050505b610f54617ac1565b6000610f9585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613d7192505050565b9150915080610fb157610fa86064613f2d565b9250505061115e565b815160009060ff16610fd657610fcf83602001518460400151613f8e565b905061112a565b825160ff16600114156111265782602001515160011461101b57600080516020618fc583398151915260405161100b9061899d565b60405180910390a1506067611121565b6000836020015160008151811061102e57fe5b602090810291909101810151516001600160a01b0381166000908152600490925260409091205490915080158061108f575060018082038154811061106f57fe5b9060005260206000209060040201600201601c9054906101000a900460ff165b156110cd576040516001600160a01b038316907fe209c46bebf57cf265d5d9009a00870e256d9150f3ed5281ab9d9eb3cec6e4be90600090a261111a565b60006110dc8360018403615150565b905080611118576040516001600160a01b038416907fe209c46bebf57cf265d5d9009a00870e256d9150f3ed5281ab9d9eb3cec6e4be90600090a25b505b6000925050505b61112a565b5060655b63ffffffff811661114f575050604080516000815260208101909152915061115e9050565b61115881613f2d565b93505050505b9392505050565b60075460ff1681565b33411461118d5760405162461bcd60e51b8152600401610e1290618d34565b3a156111ab5760405162461bcd60e51b8152600401610e1290618a23565b82516040805182815260208084028201019091526060908280156111e957816020015b6111d6617ae5565b8152602001906001900390816111ce5790505b50905060005b82811015611293576040518060c0016040528087838151811061120e57fe5b60200260200101516001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200186838151811061125057fe5b60200260200101516001600160401b03168152602001600015158152602001600081525082828151811061128057fe5b60209081029190910101526001016111ef565b5060405163d31f968d60e01b81526120009063d31f968d906112be906110009060089060040161825a565b60206040518083038186803b1580156112d657600080fd5b505afa1580156112ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061130e9190617fc3565b15611631578051601554818111156113b057815b818110156113ae57601580548061133557fe5b60008281526020812060046000199093019283020180546001600160a01b0319908116825560018201805490911690556002810180546001600160e81b0319169055600301559055601680548061138857fe5b6001900381819060005260206000200160006113a49190617b1a565b9055600101611322565b505b60005b828110156115f0578181106114d85760158482815181106113d057fe5b602090810291909101810151825460018181018555600094855293839020825160049092020180546001600160a01b039283166001600160a01b0319918216178255938301519481018054958316958516959095179094556040820151600285018054606085015160808601511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b199590961692909716919091179290921692909217169290921790915560a0015160039091015585516016908790839081106114a057fe5b602090810291909101810151825460018101845560009384529282902081516114d29491909101929190910190617a1a565b506115e8565b8381815181106114e457fe5b6020026020010151601582815481106114f957fe5b6000918252602091829020835160049092020180546001600160a01b039283166001600160a01b0319918216178255928401516001820180549184169185169190911790556040840151600282018054606087015160808801511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b1995909716929097169190911792909216939093171692909217905560a09091015160039091015585518690829081106115b457fe5b6020026020010151601682815481106115c957fe5b9060005260206000200190805190602001906115e6929190617a1a565b505b6001016113b3565b507fb8e726330a0dad1cf3d04e925663b17e391f1ed547d79b7f4e5f344119b44246826040516116209190618ed8565b60405180910390a150505050610e32565b60608061163e8386615513565b9150915060005b6001548110156117345760006001828154811061165e57fe5b90600052602060002090600402016003015490508060001461172b5760006001838154811061168957fe5b9060005260206000209060040201600301819055506120026001600160a01b031663092193ab82600185815481106116bd57fe5b60009182526020909120600491820201546040516001600160e01b031960e086901b1681526116f8926001600160a01b0390921691016181eb565b6000604051808303818588803b15801561171157600080fd5b505af1158015611725573d6000803e3d6000fd5b50505050505b50600101611645565b5047156117a2577f6ecc855f9440a9282c90913bbc91619fd44f5ec0b462af28d127b116f130aa4d4760405161176a9190618ed8565b60405180910390a1604051611002904780156108fc02916000818181858888f193505050501580156117a0573d6000803e3d6000fd5b505b600060038190556005558151156117bd576117bd82826159fa565b6110016001600160a01b031663fc4333cd6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156117fa57600080fd5b505af115801561180e573d6000803e3d6000fd5b50506040517fedd8d7296956dd970ab4de3f2fc03be2b0ffc615d20cd4c72c6e44f928630ebf925060009150a150505050505050565b60035481565b606881565b61200581565b33612002146118765760405162461bcd60e51b8152600401610e1290618e92565b60005b6015548110156118fe57816001600160a01b03166015828154811061189a57fe5b60009182526020909120600490910201546001600160a01b031614156118f6576001601582815481106118c957fe5b9060005260206000209060040201600201601c6101000a81548160ff0219169083151502179055506118fe565b600101611879565b5050565b3341146119215760405162461bcd60e51b8152600401610e1290618d34565b60105443116119425760405162461bcd60e51b8152600401610e1290618738565b3a156119605760405162461bcd60e51b8152600401610e1290618a23565b60005460ff166119825760405162461bcd60e51b8152600401610e12906185a5565b60006110023168056bc75e2d631000008111156119b9576119b28168056bc75e2d6310000063ffffffff6161e916565b91506119c0565b5050611c41565b6040516309a99b4f60e41b815261100290639a99b4f0906119e790309086906004016181ff565b602060405180830381600087803b158015611a0157600080fd5b505af1158015611a15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a399190618096565b915081611a47575050611c41565b6000805b84811015611a7557858582818110611a5f57fe5b9050602002013582019150806001019050611a4b565b5080611a8357505050611c41565b6000806000805b89811015611c395784898983818110611a9f57fe5b90506020020135880281611aaf57fe5b0493508a8a82818110611abe57fe5b9050602002016020810190611ad39190617e3f565b6001600160a01b03811660009081526004602052604090205490935091508115611bef576000600180840381548110611b0857fe5b9060005260206000209060040201905080600201601c9054906101000a900460ff1615611b7557836001600160a01b03167fb9c75cbbfde137c4281689580799ef5f52144e78858f776a5979b2b212137d8586604051611b689190618ed8565b60405180910390a2611be9565b600354611b88908663ffffffff61622b16565b6003908155810154611ba0908663ffffffff61622b16565b60038201556040516001600160a01b038516907fcb0aad6cf9cd03bdf6137e359f541c42f38b39f007cae8e89e88aa7d8c6617b290611be0908890618ed8565b60405180910390a25b50611c31565b826001600160a01b03167fb9c75cbbfde137c4281689580799ef5f52144e78858f776a5979b2b212137d8585604051611c289190618ed8565b60405180910390a25b600101611a8a565b505050505050505b5050436010555050565b6001546000908210611c5f57506000611d15565b60006001600160a01b031660018381548110611c7757fe5b60009182526020909120600490910201546001600160a01b03161480611ca757506008541580611ca75750600a54155b80611cb6575060085460095410155b80611cc75750611cc582611d1a565b155b80611cf057506000600b8381548110611cdc57fe5b906000526020600020906016020160000154115b80611d0457506001611d006130a3565b5111155b15611d1157506000611d15565b5060015b919050565b6001546000908210611d2e57506000611d15565b600b548210611d6b5760018281548110611d4457fe5b9060005260206000209060040201600201601c9054906101000a900460ff16159050611d15565b60018281548110611d7857fe5b9060005260206000209060040201600201601c9054906101000a900460ff16158015611dc55750600b8281548110611dac57fe5b600091825260209091206001601690920201015460ff16155b92915050565b600b54611e8957611dda6179eb565b60015460005b81811015611e8557600b80546001810182556000919091528351600080516020618fe583398151915260169092029182019081556020808601516000805160206196148339815191528401805460ff1916911515919091179055604086015180518794611e6193600080516020619005833981519152909101920190617a1a565b506060820151611e779060038301906013617a94565b505050806001019050611de0565b5050505b336110011480611e9a575033612002145b611eb65760405162461bcd60e51b8152600401610e12906185dc565b6001600160a01b03811660009081526004602052604090205480611eda5750611f2d565b6001810390506000600b8281548110611eef57fe5b600091825260209091206001601690920201015460ff169050611f128383615150565b8015611f1b5750805b15610e32576009805460001901905550505b50565b60015460609081906000805b82811015611f835760018181548110611f5157fe5b9060005260206000209060040201600201601c9054906101000a900460ff16611f7b576001909101905b600101611f3c565b50606081604051908082528060200260200182016040528015611fb0578160200160208202803683370190505b509050606082604051908082528060200260200182016040528015611fe957816020015b6060815260200190600190039081611fd45790505b50600b54600094509091508414156121645760005b8481101561215e576001818154811061201357fe5b9060005260206000209060040201600201601c9054906101000a900460ff16612156576001818154811061204357fe5b600091825260209091206004909102015483516001600160a01b039091169084908690811061206e57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050600b818154811061209b57fe5b600091825260209182902060026016909202018101805460408051601f6000196101006001861615020190931694909404918201859004850284018501905280835291929091908301828280156121335780601f1061210857610100808354040283529160200191612133565b820191906000526020600020905b81548152906001019060200180831161211657829003601f168201915b505050505082858151811061214457fe5b60209081029190910101526001909301925b600101611ffe565b50612200565b60005b848110156121fe576001818154811061217c57fe5b9060005260206000209060040201600201601c9054906101000a900460ff166121f657600181815481106121ac57fe5b600091825260209091206004909102015483516001600160a01b03909116908490869081106121d757fe5b6001600160a01b03909216602092830291909101909101526001909301925b600101612167565b505b909450925050505b9091565b600181565b61100181565b60085481565b603881565b600881565b6060806000600e549050600080600c5411612243576015612247565b600c545b905060606122536130a3565b9050606061226082616250565b905082825111612277579094509250612208915050565b83838351031015612289578282510393505b83156122bf5760c843046122a583838388880360008a8a6163be565b6122bd8383838888038989038a8b8b8b5103016163be565b505b6060836040519080825280602002602001820160405280156122eb578160200160208202803683370190505b50905060608460405190808252806020026020018201604052801561232457816020015b606081526020019060019003908161230f5790505b50905060005b858110156123a55784818151811061233e57fe5b602002602001015183828151811061235257fe5b60200260200101906001600160a01b031690816001600160a01b03168152505083818151811061237e57fe5b602002602001015182828151811061239257fe5b602090810291909101015260010161232a565b509096509450505050509091565b60065481565b61200681565b61200081565b6001600160a01b038116600090815260046020526040812054806123ed576000915050611d15565b6000190161115e81611d1a565b6001600160a01b03811660009081526004602052604081205480612422576000915050611d15565b60018082038154811061243157fe5b906000526020600020906004020160030154915050919050565b600081565b606781565b600f5481565b6012818154811061246857fe5b600091825260209182902001805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152935090918301828280156124f95780601f106124ce576101008083540402835291602001916124f9565b820191906000526020600020905b8154815290600101906020018083116124dc57829003601f168201915b505050505081565b60105481565b6001818154811061251457fe5b600091825260209091206004909102018054600182015460028301546003909301546001600160a01b0392831694509082169291821691600160a01b81046001600160401b031691600160e01b90910460ff169086565b61100581565b600281565b601081565b61100881565b6103e881565b600b81565b600c5481565b61200381565b606681565b61271081565b33612000146125c45760405162461bcd60e51b8152600401610e1290618ce5565b7f41ce201247b6ceb957dcdb217d0b8acb50b9ea0e12af9af4f5e7f389021016058383836040516125f793929190618f21565b60405180910390a1505050565b60025481565b60115481565b60145460ff1681565b600a5481565b6001600160a01b038116600090815260046020526040812054806126555760405162461bcd60e51b8152600401610e1290618c6d565b6000190192915050565b600b5461271d5761266e6179eb565b60015460005b8181101561271957600b80546001810182556000919091528351600080516020618fe583398151915260169092029182019081556020808601516000805160206196148339815191528401805460ff19169115159190911790556040860151805187946126f593600080516020619005833981519152909101920190617a1a565b50606082015161270b9060038301906013617a94565b505050806001019050612674565b5050505b60085461272a5760036008555b600a54612737576002600a555b60006127423361261f565b905061274d81611c4b565b6127695760405162461bcd60e51b8152600401610e129061895a565b611f2d3382616515565b600981565b61100781565b600381565b60c881565b61100681565b6040518061062001604052806105ef81526020016190256105ef913981565b60005460ff1681565b61200281565b61300081565b6402540be40081565b60005460ff166127ed5760405162461bcd60e51b8152600401610e12906185a5565b336110071461280e5760405162461bcd60e51b8152600401610e1290618a51565b61287884848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080518082019091526013815272065787069726554696d655365636f6e6447617606c1b602082015291506165ad9050565b15612915576020811461289d5760405162461bcd60e51b8152600401610e1290618c27565b604080516020601f84018190048102820181019092528281526000916128db9185858083850183828082843760009201919091525061660692505050565b9050606481101580156128f15750620186a08111155b61290d5760405162461bcd60e51b8152600401610e129061884a565b600255613041565b61297584848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260098152686275726e526174696f60b81b602082015291506165ad9050565b15612a18576020811461299a5760405162461bcd60e51b8152600401610e12906183c3565b604080516020601f84018190048102820181019092528281526000916129d89185858083850183828082843760009201919091525061660692505050565b90506127106129f2600f548361622b90919063ffffffff16565b1115612a105760405162461bcd60e51b8152600401610e12906183fa565b600655613041565b612a8284848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260138152726d61784e756d4f664d61696e7461696e696e6760681b602082015291506165ad9050565b15612b1c5760208114612aa75760405162461bcd60e51b8152600401610e1290618462565b604080516020601f8401819004810282018101909252828152600091612ae59185858083850183828082843760009201919091525061660692505050565b600c5490915080612af4575060155b808210612b135760405162461bcd60e51b8152600401610e12906187a2565b50600855613041565b612b8584848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260128152716d61696e7461696e536c6173685363616c6560701b602082015291506165ad9050565b15612c1e5760208114612baa5760405162461bcd60e51b8152600401610e129061852b565b604080516020601f8401819004810282018101909252828152600091612be89185858083850183828082843760009201919091525061660692505050565b9050600081118015612bfa5750600a81105b612c165760405162461bcd60e51b8152600401610e1290618dc5565b600a55613041565b612c9284848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601981527f6d61784e756d4f66576f726b696e6743616e6469646174657300000000000000602082015291506165ad9050565b15612d215760208114612cb75760405162461bcd60e51b8152600401610e12906184df565b604080516020601f8401819004810282018101909252828152600091612cf59185858083850183828082843760009201919091525061660692505050565b9050600d54811115612d195760405162461bcd60e51b8152600401610e12906188c0565b600e55613041565b612d8a84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260128152716d61784e756d4f6643616e6469646174657360701b602082015291506165ad9050565b15612e0c5760208114612daf5760405162461bcd60e51b8152600401610e1290618a9f565b604080516020601f8401819004810282018101909252828152600091612ded9185858083850183828082843760009201919091525061660692505050565b600d819055600e54909150811015612e0657600d54600e555b50613041565b612e7084848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600d81526c6e756d4f66436162696e65747360981b602082015291506165ad9050565b15612f1e5760208114612e955760405162461bcd60e51b8152600401610e1290618570565b604080516020601f8401819004810282018101909252828152600091612ed39185858083850183828082843760009201919091525061660692505050565b905060008111612ef55760405162461bcd60e51b8152600401610e129061864a565b6064811115612f165760405162461bcd60e51b8152600401610e1290618692565b600c55613041565b612f8684848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601181527073797374656d526577617264526174696f60781b602082015291506165ad9050565b156130295760208114612fab5760405162461bcd60e51b8152600401610e1290618d81565b604080516020601f8401819004810282018101909252828152600091612fe99185858083850183828082843760009201919091525061660692505050565b90506127106130036006548361622b90919063ffffffff16565b11156130215760405162461bcd60e51b8152600401610e1290618b88565b600f55613041565b60405162461bcd60e51b8152600401610e1290618e22565b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a848484846040516130769493929190618391565b60405180910390a150505050565b60046020526000908152604090205481565b68056bc75e2d6310000081565b6001546060906000805b828110156130d2576130be81611d1a565b156130ca578160010191505b6001016130ad565b506060816040519080825280602002602001820160405280156130ff578160200160208202803683370190505b5090506000915060005b838110156131865761311a81611d1a565b1561317e576001818154811061312c57fe5b600091825260209091206004909102015482516001600160a01b039091169083908590811061315757fe5b60200260200101906001600160a01b031690816001600160a01b0316815250508260010192505b600101613109565b50925050505b90565b601581565b61027181565b61100281565b6013818154811061246857fe5b60006131b76130a3565b519050600080600c54116131cc5760156131d0565b600c545b9050808211156131de578091505b816131e857600191505b5090565b67016345785d8a000081565b60055481565b61100381565b61200481565b60005460ff161561322d5760405162461bcd60e51b8152600401610e1290618b51565b613235617ac1565b600061325b6040518061062001604052806105ef81526020016190256105ef9139613d71565b915091508061327c5760405162461bcd60e51b8152600401610e1290618ca4565b60005b8260200151518110156133a15760018360200151828151811061329e57fe5b60209081029190910181015182546001818101855560009485528385208351600493840290910180546001600160a01b039283166001600160a01b03199182161782558587015182850180549185169183169190911790556040860151600283018054606089015160808a01511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b199590981692909516919091179290921694909417161790915560a09093015160039093019290925591860151805191850193918590811061337457fe5b602090810291909101810151516001600160a01b031682528101919091526040016000205560010161327f565b50506103e8600255506000805460ff19166001179055565b600d5481565b601354600090815b818110156134c8576134b085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060138054909250859150811061341857fe5b600091825260209182902001805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152928301828280156134a65780601f1061347b576101008083540402835291602001916134a6565b820191906000526020600020905b81548152906001019060200180831161348957829003601f168201915b505050505061660b565b156134c057600192505050611dc5565b6001016133c7565b5060125460005b818110156135395761352086868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060128054909250859150811061341857fe5b156135315760019350505050611dc5565b6001016134cf565b50600095945050505050565b33611001146135665760405162461bcd60e51b8152600401610e1290618e49565b600b54613624576135756179eb565b60015460005b8181101561362057600b80546001810182556000919091528351600080516020618fe583398151915260169092029182019081556020808601516000805160206196148339815191528401805460ff19169115159190911790556040860151805187946135fc93600080516020619005833981519152909101920190617a1a565b5060608201516136129060038301906013617a94565b50505080600101905061357b565b5050505b600061362f8261666f565b905061363a81611c4b565b156118fe576118fe8282616515565b606581565b601181565b3341146136725760405162461bcd60e51b8152600401610e1290618d34565b60005460ff166136945760405162461bcd60e51b8152600401610e12906185a5565b600034116136b45760405162461bcd60e51b8152600401610e1290618891565b3a156136d25760405162461bcd60e51b8152600401610e1290618a23565b6001600160a01b03811660009081526004602052604090205460145434919060ff1661371257610271600f556103e86006556014805460ff191660011790555b60008211801561372457506000600f54115b156137d6576000613752612710613746600f54346167f290919063ffffffff16565b9063ffffffff61682c16565b905080156137d4576040516110029082156108fc029083906000818181858888f19350505050158015613789573d6000803e3d6000fd5b507f6ecc855f9440a9282c90913bbc91619fd44f5ec0b462af28d127b116f130aa4d816040516137b99190618ed8565b60405180910390a16137d1838263ffffffff6161e916565b92505b505b6000821180156137e857506000600654115b1561388e57600061380a612710613746600654346167f290919063ffffffff16565b9050801561388c5760405161dead9082156108fc029083906000818181858888f19350505050158015613841573d6000803e3d6000fd5b507f627059660ea01c4733a328effb2294d2f86905bf806da763a89cee254de8bee5816040516138719190618ed8565b60405180910390a1613889838263ffffffff6161e916565b92505b505b801561398c5760006001808303815481106138a557fe5b9060005260206000209060040201905080600201601c9054906101000a900460ff161561391257836001600160a01b03167ff177e5d6c5764d79c32883ed824111d9b13f5668cf6ab1cc12dd36791dd955b4846040516139059190618ed8565b60405180910390a2613986565b600354613925908463ffffffff61622b16565b600390815581015461393d908463ffffffff61622b16565b60038201556040516001600160a01b038516907f93a090ecc682c002995fad3c85b30c5651d7fd29b0be5da9d784a3302aedc0559061397d908690618ed8565b60405180910390a25b50610e32565b826001600160a01b03167ff177e5d6c5764d79c32883ed824111d9b13f5668cf6ab1cc12dd36791dd955b4836040516139c59190618ed8565b60405180910390a2505050565b600e5481565b61100081565b61dead81565b600b81815481106139f157fe5b6000918252602091829020601691909102018054600180830154600280850180546040805161010096831615969096026000190190911692909204601f810188900488028501880190925281845293965060ff90911694919291830182828015613a9c5780601f10613a7157610100808354040283529160200191613a9c565b820191906000526020600020905b815481529060010190602001808311613a7f57829003601f168201915b5050505050905083565b61100481565b6000600a5460001480613abd575081155b80613ac85750600954155b15613ad55750600061115e565b6000613b0f600a5461374685613746600b8981548110613af157fe5b6000918252602090912060169091020154439063ffffffff6161e916565b90506000806110016001600160a01b0316638256ace66040518163ffffffff1660e01b8152600401604080518083038186803b158015613b4e57600080fd5b505afa158015613b62573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b8691906180ae565b9150915060009350808310613ce557613b9f8787615150565b5060405163436aa28360e11b8152600090612002906386d5450690613bc8908b906004016181eb565b60206040518083038186803b158015613be057600080fd5b505afa158015613bf4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c189190617e5b565b6001600160a01b031614613c84576040516313d13bdb60e31b815261100190639e89ded890613c4d908a9087906004016181ff565b600060405180830381600087803b158015613c6757600080fd5b505af1158015613c7b573d6000803e3d6000fd5b50505050613cdc565b6040516305bfb49960e41b815261100190635bfb499090613ca9908a906004016181eb565b600060405180830381600087803b158015613cc357600080fd5b505af1158015613cd7573d6000803e3d6000fd5b505050505b60019350613cf7565b818310613cf757613cf58761666f565b505b60098054600019019055600b80546000919088908110613d1357fe5b60009182526020822060169190910201600101805460ff1916921515929092179091556040516001600160a01b038916917fb9d38178dc641ff1817967a63c9078cbcd955a9f1fcd75e0e3636de615d44d3b91a25050509392505050565b613d79617ac1565b6000613d83617ac1565b613d8b617b5e565b613d9c613d978661686e565b616893565b90506000805b613dab836168dd565b15613f1f5780613dd057613dc6613dc1846168fe565b61694c565b60ff168452613f17565b8060011415613f12576060613dec613de7856168fe565b6169cc565b90508051604051908082528060200260200182016040528015613e2957816020015b613e16617ae5565b815260200190600190039081613e0e5790505b5085602001819052508051604051908082528060200260200182016040528015613e6757816020015b6060815260200190600190039081613e525790505b50604086015260005b8151811015613f0757613e81617ae5565b60606000613ea1858581518110613e9457fe5b6020026020010151616a9d565b92509250925080613ec1578860009a509a50505050505050505050613f28565b8289602001518581518110613ed257fe5b60200260200101819052508189604001518581518110613eee57fe5b6020026020010181905250505050806001019050613e70565b506001925050613f17565b613f1f565b600101613da2565b50919350909150505b915091565b604080516001808252818301909252606091829190816020015b6060815260200190600190039081613f47579050509050613f6d8363ffffffff16616bb7565b81600081518110613f7a57fe5b602002602001018190525061115e81616bca565b6000606483511115613fc557600080516020618fc5833981519152604051613fb5906186ef565b60405180910390a1506066611dc5565b60005b83518110156140635760005b8181101561405a57848181518110613fe857fe5b6020026020010151600001516001600160a01b031685838151811061400957fe5b6020026020010151600001516001600160a01b0316141561405257600080516020618fc583398151915260405161403f906187ff565b60405180910390a1606692505050611dc5565b600101613fd4565b50600101613fc8565b5060608060606015805480602002602001604051908101604052809291908181526020016000905b828210156141155760008481526020908190206040805160c0810182526004860290920180546001600160a01b039081168452600180830154821685870152600283015491821693850193909352600160a01b81046001600160401b03166060850152600160e01b900460ff16151560808401526003015460a0830152908352909201910161408b565b50505050905060606016805480602002602001604051908101604052809291908181526020016000905b828210156141ea5760008481526020908190208301805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152928301828280156141d65780601f106141ab576101008083540402835291602001916141d6565b820191906000526020600020905b8154815290600101906020018083116141b957829003601f168201915b50505050508152602001906001019061413f565b50505050905060005b82518110156142475782818151811061420857fe5b60200260200101516060015160030283828151811061422357fe5b60209081029190910101516001600160401b039091166060909101526001016141f3565b5060608061425789898686616c54565b915091506142658282615513565b600154604080518281526020808402820101909152929850909650600095508594509250606091508280156142a4578160200160208202803683370190505b50905060005b828110156144355760006001600160a01b03166120026001600160a01b03166386d54506600184815481106142db57fe5b60009182526020909120600491820201546040516001600160e01b031960e085901b168152614316926001600160a01b0390921691016181eb565b60206040518083038186803b15801561432e57600080fd5b505afa158015614342573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143669190617e5b565b6001600160a01b0316146143c857600182828151811061438257fe5b602002602001019060ff16908160ff1681525050600181815481106143a357fe5b9060005260206000209060040201600301546000146143c3578360010193505b61442d565b67016345785d8a0000600182815481106143de57fe5b906000526020600020906004020160030154106144005784600101945061442d565b6001818154811061440d57fe5b90600052602060002090600402016003015460001461442d578360010193505b6001016142aa565b50606084604051908082528060200260200182016040528015614462578160200160208202803683370190505b509050606085604051908082528060200260200182016040528015614491578160200160208202803683370190505b5090506060866040519080825280602002602001820160405280156144c0578160200160208202803683370190505b5090506060876040519080825280602002602001820160405280156144ef578160200160208202803683370190505b5090506000606088604051908082528060200260200182016040528015614520578160200160208202803683370190505b50905060608960405190808252806020026020018201604052801561454f578160200160208202803683370190505b50905060009a506000995060006110046001600160a01b031663149d14d96040518163ffffffff1660e01b815260040160206040518083038186803b15801561459757600080fd5b505afa1580156145ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145cf9190618096565b905067016345785d8a000081111561461b57600080516020618fc58339815191526040516145fc90618b10565b60405180910390a160689e505050505050505050505050505050611dc5565b60005b8a8110156149af5789818151811061463257fe5b602002602001015160ff1660011415614728576001818154811061465257fe5b906000526020600020906004020160030154600014614723576001818154811061467857fe5b600091825260209091206004909102015484516001600160a01b039091169085908e9081106146a357fe5b60200260200101906001600160a01b031690816001600160a01b031681525050600181815481106146d057fe5b906000526020600020906004020160030154838d815181106146ee57fe5b60200260200101818152505060018a8d8151811061470857fe5b602002602001019060ff16908160ff16815250508b6001019b505b6149a7565b67016345785d8a00006001828154811061473e57fe5b906000526020600020906004020160030154106148c3576001818154811061476257fe5b906000526020600020906004020160020160009054906101000a90046001600160a01b0316898e8151811061479357fe5b60200260200101906001600160a01b031690816001600160a01b03168152505060006402540be400600183815481106147c857fe5b906000526020600020906004020160030154816147e157fe5b06600183815481106147ef57fe5b90600052602060002090600402016003015403905061481783826161e990919063ffffffff16565b898f8151811061482357fe5b6020026020010181815250506001828154811061483c57fe5b906000526020600020906004020160010160009054906101000a90046001600160a01b0316878f8151811061486d57fe5b60200260200101906001600160a01b031690816001600160a01b03168152505081888f8151811061489a57fe5b60209081029190910101526148b5868263ffffffff61622b16565b95508d6001019d50506149a7565b600181815481106148d057fe5b9060005260206000209060040201600301546000146149a757600181815481106148f657fe5b906000526020600020906004020160010160009054906101000a90046001600160a01b0316848d8151811061492757fe5b60200260200101906001600160a01b031690816001600160a01b0316815250506001818154811061495457fe5b906000526020600020906004020160030154838d8151811061497257fe5b60200260200101818152505060008a8d8151811061498c57fe5b602002602001019060ff16908160ff16815250508b6001019b505b60010161461e565b5060008415614c25576002546040516303702b2960e51b815261100491636e0565209188916149e9918e918e918d914201906004016182f9565b6020604051808303818588803b158015614a0257600080fd5b505af193505050508015614a33575060408051601f3d908101601f19168201909252614a3091810190617fc3565b60015b614baa576040516000815260443d1015614a4f57506000614aea565b60046000803e60005160e01c6308c379a08114614a70576000915050614aea565b60043d036004833e81513d60248201116001600160401b0382111715614a9b57600092505050614aea565b80830180516001600160401b03811115614abc576000945050505050614aea565b8060208301013d8601811115614ada57600095505050505050614aea565b601f01601f191660405250925050505b80614af55750614b37565b60019150857fa7cdeed7d0db45e3219a6e5d60838824c16f1d39991fcfe3f963029c844bf28082604051614b29919061837e565b60405180910390a250614ba5565b3d808015614b61576040519150601f19603f3d011682016040523d82523d6000602084013e614b66565b606091505b5060019150857fbfa884552dd8921b6ce90bfe906952ae5b3b29be0cc1a951d4f62697635a3a4582604051614b9b919061837e565b60405180910390a2505b614c25565b8015614bec577fa217d08e65f80c73121cd9db834d81652d544bfbf452f6d04922b16c90a37b7086604051614bdf9190618ed8565b60405180910390a1614c23565b857fa7cdeed7d0db45e3219a6e5d60838824c16f1d39991fcfe3f963029c844bf280604051614c1a906184a8565b60405180910390a25b505b8015614ddb5760005b8751811015614dd9576000888281518110614c4557fe5b60200260200101519050600060018281548110614c5e57fe5b60009182526020909120600160049092020181015481546001600160a01b03909116916108fc9185908110614c8f57fe5b9060005260206000209060040201600301549081150290604051600060405180830381858888f1935050505090508015614d4b5760018281548110614cd057fe5b60009182526020909120600160049092020181015481546001600160a01b03909116917f6c61d60f69a7beb3e1c80db7f39f37b208537cbb19da3174511b477812b2fc7d9185908110614d1f57fe5b906000526020600020906004020160030154604051614d3e9190618ed8565b60405180910390a2614dcf565b60018281548110614d5857fe5b60009182526020909120600160049092020181015481546001600160a01b03909116917f25d0ce7d2f0cec669a8c17efe49d195c13455bb8872b65fa610ac7f53fe4ca7d9185908110614da757fe5b906000526020600020906004020160030154604051614dc69190618ed8565b60405180910390a25b5050600101614c2e565b505b835115614fd15760005b8451811015614fcf578a8181518110614dfa57fe5b602002602001015160ff1660011415614e99576120026001600160a01b031663092193ab858381518110614e2a57fe5b6020026020010151878481518110614e3e57fe5b60200260200101516040518363ffffffff1660e01b8152600401614e6291906181eb565b6000604051808303818588803b158015614e7b57600080fd5b505af1158015614e8f573d6000803e3d6000fd5b5050505050614fc7565b6000858281518110614ea757fe5b60200260200101516001600160a01b03166108fc868481518110614ec757fe5b60200260200101519081150290604051600060405180830381858888f1935050505090508015614f5d57858281518110614efd57fe5b60200260200101516001600160a01b03167f6c61d60f69a7beb3e1c80db7f39f37b208537cbb19da3174511b477812b2fc7d868481518110614f3b57fe5b6020026020010151604051614f509190618ed8565b60405180910390a2614fc5565b858281518110614f6957fe5b60200260200101516001600160a01b03167f25d0ce7d2f0cec669a8c17efe49d195c13455bb8872b65fa610ac7f53fe4ca7d868481518110614fa757fe5b6020026020010151604051614fbc9190618ed8565b60405180910390a25b505b600101614de5565b505b5050505050505050505050505060005b60015481101561503e5760018181548110614ff857fe5b9060005260206000209060040201600301546000146150365760006001828154811061502057fe5b9060005260206000209060040201600301819055505b600101614fe1565b5047156150ac577f6ecc855f9440a9282c90913bbc91619fd44f5ec0b462af28d127b116f130aa4d476040516150749190618ed8565b60405180910390a1604051611002904780156108fc02916000818181858888f193505050501580156150aa573d6000803e3d6000fd5b505b600060038190556005558151156150c7576150c782826159fa565b6110016001600160a01b031663fc4333cd6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561510457600080fd5b505af1158015615118573d6000803e3d6000fd5b50506040517fedd8d7296956dd970ab4de3f2fc03be2b0ffc615d20cd4c72c6e44f928630ebf925060009150a1506000949350505050565b6000806001838154811061516057fe5b9060005260206000209060040201600301549050600060018080549050039050600161518a6130a3565b51116151bf5760006001858154811061519f57fe5b906000526020600020906004020160030181905550600092505050611dc5565b846001600160a01b03167f3b6f9ef90462b512a1293ecec018670bf7b7f1876fb727590a8a6d7643130a70836040516151f89190618ed8565b60405180910390a26001600160a01b038516600090815260046020526040812055835b600154600019018110156153e5576001816001018154811061523957fe5b90600052602060002090600402016001828154811061525457fe5b60009182526020909120825460049092020180546001600160a01b03199081166001600160a01b0393841617825560018085015481840180548416918616919091179055600280860180549185018054909416919095161780835584546001600160401b03600160a01b91829004160267ffffffffffffffff60a01b1990911617808355935460ff600160e01b918290041615150260ff60e01b19909416939093179055600392830154920191909155600b80549091830190811061531557fe5b9060005260206000209060160201600b828154811061533057fe5b600091825260209091208254601690920201908155600180830154818301805460ff909216151560ff1990921691909117905560028084018054615387938386019390821615610100026000190190911604617b7e565b5061539a60038281019084016013617bf3565b509050508060010160046000600184815481106153b357fe5b600091825260208083206004909202909101546001600160a01b0316835282019290925260400190205560010161521b565b5060018054806153f157fe5b60008281526020812060046000199093019283020180546001600160a01b0319908116825560018201805490911690556002810180546001600160e81b0319169055600301559055600b80548061544457fe5b60008281526020812060166000199093019283020181815560018101805460ff19169055906154766002830182617b1a565b615484600383016000617c1d565b50509055600081838161549357fe5b04905080156155075760015460005b81811015615504576154db83600183815481106154bb57fe5b90600052602060002090600402016003015461622b90919063ffffffff16565b600182815481106154e857fe5b60009182526020909120600360049092020101556001016154a2565b50505b50600195945050505050565b6060806000808080806155246131ad565b6001549091505b801561575357600181039250600b838154811061554457fe5b600091825260209091206001601690920201015460ff166155645761574a565b6001838154811061557157fe5b60009182526020909120600490910201546001600160a01b03169450615598858484613aac565b9350836155a45761574a565b60405163436aa28360e11b81526000908190612002906386d54506906155ce908a906004016181eb565b60206040518083038186803b1580156155e657600080fd5b505afa1580156155fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061561e9190617e5b565b90506001600160a01b038116156156a7576040516302ceee9160e11b81526120029063059ddd22906156549084906004016181eb565b60206040518083038186803b15801561566c57600080fd5b505afa158015615680573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906156a49190617e5b565b91505b60005b8c5181101561574657876001600160a01b03168d82815181106156c957fe5b6020026020010151600001516001600160a01b031614806157125750826001600160a01b03168d82815181106156fb57fe5b6020026020010151600001516001600160a01b0316145b1561573e5760018d828151811061572557fe5b6020908102919091010151901515608090910152615746565b6001016156aa565b5050505b6000190161552b565b5060005b89518110156157c05789818151811061576c57fe5b602002602001015160800151806157ac575060006001600160a01b03168a828151811061579557fe5b6020026020010151600001516001600160a01b0316145b156157b8578560010195505b600101615757565b50885185106158a85760408051600180825281830190925290816020015b6157e6617ae5565b8152602001906001900390816157de575050604080516001808252818301909252919850602082015b606081526020019060019003908161580f5790505095508860008151811061583357fe5b60200260200101518760008151811061584857fe5b60200260200101819052508760008151811061586057fe5b60200260200101518660008151811061587557fe5b602002602001018190525060008760008151811061588f57fe5b60209081029190910101519015156080909101526159ed565b848951036040519080825280602002602001820160405280156158e557816020015b6158d2617ae5565b8152602001906001900390816158ca5790505b5096508489510360405190808252806020026020018201604052801561591f57816020015b606081526020019060019003908161590a5790505b5095506000915060005b89518110156159eb5789818151811061593e57fe5b602002602001015160800151158015615981575060006001600160a01b03168a828151811061596957fe5b6020026020010151600001516001600160a01b031614155b156159e35789818151811061599257fe5b60200260200101518884815181106159a657fe5b60200260200101819052508881815181106159bd57fe5b60200260200101518784815181106159d157fe5b60200260200101819052508260010192505b600101615929565b505b50505050505b9250929050565b600154825160005b82811015615b17576001615a14617ae5565b60018381548110615a2157fe5b600091825260208083206040805160c08101825260049490940290910180546001600160a01b0390811685526001820154811693850193909352600281015492831691840191909152600160a01b82046001600160401b03166060840152600160e01b90910460ff16151560808301526003015460a082015291505b84811015615aeb57878181518110615ab157fe5b6020026020010151600001516001600160a01b031682600001516001600160a01b03161415615ae35760009250615aeb565b600101615a9d565b508115615b0d5780516001600160a01b03166000908152600460205260408120555b5050600101615a02565b5080821115615bd657805b82811015615bd4576001805480615b3557fe5b60008281526020812060046000199093019283020180546001600160a01b0319908116825560018201805490911690556002810180546001600160e81b0319169055600301559055600b805480615b8857fe5b60008281526020812060166000199093019283020181815560018101805460ff1916905590615bba6002830182617b1a565b615bc8600383016000617c1d565b50509055600101615b22565b505b6000818310615be55781615be7565b825b905060005b81811015615f8b57615c99868281518110615c0357fe5b602002602001015160018381548110615c1857fe5b60009182526020918290206040805160c08101825260049390930290910180546001600160a01b0390811684526001820154811694840194909452600281015493841691830191909152600160a01b83046001600160401b03166060830152600160e01b90920460ff161515608082015260039091015460a0820152617020565b615e4d578060010160046000888481518110615cb157fe5b6020026020010151600001516001600160a01b03166001600160a01b0316815260200190815260200160002081905550858181518110615ced57fe5b602002602001015160018281548110615d0257fe5b6000918252602091829020835160049092020180546001600160a01b039283166001600160a01b0319918216178255928401516001820180549184169185169190911790556040840151600282018054606087015160808801511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b1995909716929097169190911792909216939093171692909217905560a0909101516003909101558451859082908110615dbd57fe5b6020026020010151600b8281548110615dd257fe5b90600052602060002090601602016002019080519060200190615df6929190617a1a565b506000600b8281548110615e0657fe5b60009182526020822060169190910201600101805460ff191692151592909217909155600b805483908110615e3757fe5b6000918252602090912060169091020155615f83565b858181518110615e5957fe5b60200260200101516060015160018281548110615e7257fe5b906000526020600020906004020160020160146101000a8154816001600160401b0302191690836001600160401b03160217905550615f38858281518110615eb657fe5b6020026020010151600b8381548110615ecb57fe5b600091825260209182902060026016909202018101805460408051601f6000196101006001861615020190931694909404918201859004850284018501905280835291929091908301828280156134a65780601f1061347b576101008083540402835291602001916134a6565b615f8357848181518110615f4857fe5b6020026020010151600b8281548110615f5d57fe5b90600052602060002090601602016002019080519060200190615f81929190617a1a565b505b600101615bec565b508282111561616357615f9c6179eb565b835b8381101561616057858181518110615fb257fe5b602002602001015182604001819052506001878281518110615fd057fe5b6020908102919091018101518254600181810185556000948552838520835160049093020180546001600160a01b039384166001600160a01b0319918216178255848601518284018054918616918316919091179055604080860151600284018054606089015160808a01511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b1995909a1692909616919091179290921696909617169190911790935560a090930151600390930192909255600b8054928301815590935284516016909102600080516020618fe58339815191528101918255858301516000805160206196148339815191528201805491151560ff19909216919091179055928501518051869492936161069360008051602061900583398151915201920190617a1a565b50606082015161611c9060038301906013617a94565b505050806001016004600089848151811061613357fe5b602090810291909101810151516001600160a01b0316825281019190915260400160002055600101615f9e565b50505b61616b61707c565b616173617264565b6000600981905560015493505b838110156161e1576000600b828154811061619757fe5b60009182526020822060169190910201600101805460ff191692151592909217909155600b8054839081106161c857fe5b6000918252602090912060169091020155600101616180565b505050505050565b600061115e83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250617452565b60008282018381101561115e5760405162461bcd60e51b8152600401610e1290618613565b60015481516040805182815260208084028201019091526060929190839082801561628f57816020015b606081526020019060019003908161627a5790505b50600b5490915083146162a6579250611d15915050565b60005b828110156163b557600b6001600460008985815181106162c557fe5b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205403815481106162f957fe5b600091825260209182902060026016909202018101805460408051601f6000196101006001861615020190931694909404918201859004850284018501905280835291929091908301828280156163915780601f1061636657610100808354040283529160200191616391565b820191906000526020600020905b81548152906001019060200180831161637457829003601f168201915b50505050508282815181106163a257fe5b60209081029190910101526001016162a9565b50949350505050565b60005b8281101561650b57600082878388016040516020016163e19291906181dd565b6040516020818303038152906040528051906020012060001c8161640157fe5b06905080850182870114616502576000898388018151811061641f57fe5b602002602001015190506060898489018151811061643957fe5b602002602001015190508a8388018151811061645157fe5b60200260200101518b858a018151811061646757fe5b60200260200101906001600160a01b031690816001600160a01b031681525050818b8489018151811061649657fe5b60200260200101906001600160a01b031690816001600160a01b03168152505089838801815181106164c457fe5b60200260200101518a858a01815181106164da57fe5b6020026020010181905250808a848901815181106164f457fe5b602002602001018190525050505b506001016163c1565b5050505050505050565b600980546001908101909155600b80548390811061652f57fe5b906000526020600020906016020160010160006101000a81548160ff02191690831515021790555043600b828154811061656557fe5b600091825260208220601690910201919091556040516001600160a01b038416917ff62981a567ec3cec866c6fa93c55bcdf841d6292d18b8d522ececa769375d82d91a25050565b6000816040516020016165c091906181c1565b60405160208183030381529060405280519060200120836040516020016165e791906181c1565b6040516020818303038152906040528051906020012014905092915050565b015190565b8151815160009160019181148083146166275760009250616665565b600160208701838101602088015b6002848385100114156166605780518351146166545760009650600093505b60209283019201616635565b505050505b5090949350505050565b6001600160a01b0381166000908152600460205260408120548061669857506000199050611d15565b6001810390506000600182815481106166ad57fe5b90600052602060002090600402016003015490506000600183815481106166d057fe5b6000918252602090912060036004909202010155600154604051600019909101906001600160a01b038616907f8cd4e147d8af98a9e3b6724021b8bf6aed2e5dac71c38f2dce8161b82585b25d90616729908590618ed8565b60405180910390a28061674157829350505050611d15565b600081838161674c57fe5b04905080156167e85760005b8481101561679a5761677182600183815481106154bb57fe5b6001828154811061677e57fe5b6000918252602090912060036004909202010155600101616758565b50600180549085015b818110156167e5576167bc83600183815481106154bb57fe5b600182815481106167c957fe5b60009182526020909120600360049092020101556001016167a3565b50505b5091949350505050565b60008261680157506000611dc5565b8282028284828161680e57fe5b041461115e5760405162461bcd60e51b8152600401610e12906189e2565b600061115e83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061747e565b616876617c2c565b506040805180820190915281518152602082810190820152919050565b61689b617b5e565b6168a4826174b5565b6168ad57600080fd5b60006168bc83602001516174ef565b60208085015160408051808201909152868152920190820152915050919050565b60006168e7617c2c565b505080518051602091820151919092015191011190565b616906617c2c565b61690f826168dd565b61691857600080fd5b6020820151600061692882617552565b80830160209586015260408051808201909152908152938401919091525090919050565b80516000901580159061696157508151602110155b61696a57600080fd5b600061697983602001516174ef565b9050808360000151101561699f5760405162461bcd60e51b8152600401610e1290618bf0565b8251602080850151830180519284900392918310156163b557506020919091036101000a90049392505050565b60606169d7826174b5565b6169e057600080fd5b60006169eb83617633565b9050606081604051908082528060200260200182016040528015616a2957816020015b616a16617c2c565b815260200190600190039081616a0e5790505b5090506000616a3b85602001516174ef565b60208601510190506000805b84811015616a9257616a5883617552565b9150604051806040016040528083815260200184815250848281518110616a7b57fe5b602090810291909101015291810191600101616a47565b509195945050505050565b616aa5617ae5565b60606000616ab1617ae5565b6060616abb617b5e565b616ac487616893565b90506000805b616ad3836168dd565b15616ba85780616afe57616aee616ae9846168fe565b61768f565b6001600160a01b03168552616ba0565b8060011415616b2657616b13616ae9846168fe565b6001600160a01b03166020860152616ba0565b8060021415616b4e57616b3b616ae9846168fe565b6001600160a01b03166040860152616ba0565b8060031415616b7a57616b63613dc1846168fe565b6001600160401b0316606086015260019150616ba0565b8060041415616b9b57616b94616b8f846168fe565b6176a9565b9350616ba0565b616ba8565b600101616aca565b50929791965091945092505050565b6060611dc5616bc583617719565b6177ff565b6060815160001415616beb5750604080516000815260208101909152611d15565b606082600081518110616bfa57fe5b602002602001015190506000600190505b8351811015616c3b57616c3182858381518110616c2457fe5b6020026020010151617851565b9150600101616c0b565b5061115e616c4e825160c060ff166178ce565b82617851565b60608060006120026001600160a01b031663c473318f6040518163ffffffff1660e01b815260040160206040518083038186803b158015616c9457600080fd5b505afa158015616ca8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190616ccc9190618096565b90508085518851011015616ce1575083518651015b606081604051908082528060200260200182016040528015616d1d57816020015b616d0a617ae5565b815260200190600190039081616d025790505b509050606082604051908082528060200260200182016040528015616d5657816020015b6060815260200190600190039081616d415790505b50905060008060005b8b51831080616d6e5750895182105b8015616d7957508581105b1561700e578b51831415616de957898281518110616d9357fe5b6020026020010151858281518110616da757fe5b6020026020010181905250888281518110616dbe57fe5b6020026020010151848281518110616dd257fe5b602090810291909101015260019182019101616d5f565b8951821415616e54578b8381518110616dfe57fe5b6020026020010151858281518110616e1257fe5b60200260200101819052508a8381518110616e2957fe5b6020026020010151848281518110616e3d57fe5b602090810291909101015260019283019201616d5f565b898281518110616e6057fe5b6020026020010151606001516001600160401b03168c8481518110616e8157fe5b6020026020010151606001516001600160401b03161115616efd578b8381518110616ea857fe5b6020026020010151858281518110616ebc57fe5b60200260200101819052508a8381518110616ed357fe5b6020026020010151848281518110616ee757fe5b6020026020010181905250826001019250617006565b898281518110616f0957fe5b6020026020010151606001516001600160401b03168c8481518110616f2a57fe5b6020026020010151606001516001600160401b03161015616fa657898281518110616f5157fe5b6020026020010151858281518110616f6557fe5b6020026020010181905250888281518110616f7c57fe5b6020026020010151848281518110616f9057fe5b6020026020010181905250816001019150617006565b898281518110616fb257fe5b6020026020010151600001516001600160a01b03168c8481518110616fd357fe5b6020026020010151600001516001600160a01b03161015616ffa578b8381518110616ea857fe5b898281518110616d9357fe5b600101616d5f565b50929a91995090975050505050505050565b805182516000916001600160a01b03918216911614801561705a575081602001516001600160a01b031683602001516001600160a01b0316145b801561115e5750506040908101519101516001600160a01b0390811691161490565b601254601354808211156170c757805b828110156170c557601280548061709f57fe5b6001900381819060005260206000200160006170bb9190617b1a565b905560010161708c565b505b60008183106170d657816170d8565b825b905060005b818110156171f057617195601282815481106170f557fe5b600091825260209182902001805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152928301828280156171835780601f1061715857610100808354040283529160200191617183565b820191906000526020600020905b81548152906001019060200180831161716657829003601f168201915b50505050506013838154811061341857fe5b6171e857601381815481106171a657fe5b90600052602060002001601282815481106171bd57fe5b9060005260206000200190805460018160011615610100020316600290046171e6929190617b7e565b505b6001016170dd565b5082821115610e3257825b8281101561725e5760126013828154811061721257fe5b6000918252602080832084546001818101875595855291909320929091018054617255949390920192909160026101009282161592909202600019011604617b7e565b506001016171fb565b50505050565b601354600b54808211156172af57805b828110156172ad57601380548061728757fe5b6001900381819060005260206000200160006172a39190617b1a565b9055600101617274565b505b60008183106172be57816172c0565b825b905060005b818110156173df5761737d601382815481106172dd57fe5b600091825260209182902001805460408051601f600260001961010060018716150201909416939093049283018590048502810185019091528181529283018282801561736b5780601f106173405761010080835404028352916020019161736b565b820191906000526020600020905b81548152906001019060200180831161734e57829003601f168201915b5050505050600b8381548110615ecb57fe5b6173d757600b818154811061738e57fe5b9060005260206000209060160201600201601382815481106173ac57fe5b9060005260206000200190805460018160011615610100020316600290046173d5929190617b7e565b505b6001016172c5565b5082821115610e3257825b8281101561725e576013600b828154811061740157fe5b60009182526020808320845460018082018755958552919093206016929092029092016002908101805461744995939094019390926000199082161561010002011604617b7e565b506001016173ea565b600081848411156174765760405162461bcd60e51b8152600401610e12919061837e565b505050900390565b6000818361749f5760405162461bcd60e51b8152600401610e12919061837e565b5060008385816174ab57fe5b0495945050505050565b80516000906174c657506000611d15565b6020820151805160001a9060c08210156174e557600092505050611d15565b5060019392505050565b8051600090811a6080811015617509576000915050611d15565b60b8811080617524575060c08110801590617524575060f881105b15617533576001915050611d15565b60c08110156175475760b519019050611d15565b60f519019050611d15565b80516000908190811a608081101561756d576001915061762c565b60b881101561758257607e198101915061762c565b60c08110156175d357600060b78203600186019550806020036101000a8651049150600181018201935050808310156175cd5760405162461bcd60e51b8152600401610e129061892f565b5061762c565b60f88110156175e85760be198101915061762c565b600060f78203600186019550806020036101000a86510491506001810182019350508083101561762a5760405162461bcd60e51b8152600401610e129061892f565b505b5092915050565b805160009061764457506000611d15565b6000809050600061765884602001516174ef565b602085015185519181019250015b808210156176865761767782617552565b82019150826001019250617666565b50909392505050565b80516000906015146176a057600080fd5b611dc58261694c565b80516060906176b757600080fd5b60006176c683602001516174ef565b83516040805191839003808352601f19601f82011683016020019091529192506060908280156176fd576020820181803683370190505b50905060008160200190506163b58487602001510182856179a0565b604080516020808252818301909252606091829190602082018180368337505050602081018490529050600067ffffffffffffffff19841661775d57506018617781565b6fffffffffffffffffffffffffffffffff19841661777d57506010617781565b5060005b60208110156177b75781818151811061779657fe5b01602001516001600160f81b031916156177af576177b7565b600101617781565b60008160200390506060816040519080825280601f01601f1916602001820160405280156177ec576020820181803683370190505b5080830196909652508452509192915050565b6060815160011480156178315750607f60f81b8260008151811061781f57fe5b01602001516001600160f81b03191611155b1561783d575080611d15565b611dc561784f8351608060ff166178ce565b835b6060806040519050835180825260208201818101602087015b8183101561788257805183526020928301920161786a565b50855184518101855292509050808201602086015b818310156178af578051835260209283019201617897565b508651929092011591909101601f01601f191660405250905092915050565b60606801000000000000000083106178f85760405162461bcd60e51b8152600401610e129061877a565b604080516001808252818301909252606091602082018180368337019050509050603784116179525782840160f81b8160008151811061793457fe5b60200101906001600160f81b031916908160001a9053509050611dc5565b606061795d85617719565b90508381510160370160f81b8260008151811061797657fe5b60200101906001600160f81b031916908160001a9053506179978282617851565b95945050505050565b806179aa57610e32565b5b602081106179ca578251825260209283019290910190601f19016179ab565b915181516020939093036101000a6000190180199091169216919091179052565b60405180608001604052806000815260200160001515815260200160608152602001617a15617c46565b905290565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10617a5b57805160ff1916838001178555617a88565b82800160010185558215617a88579182015b82811115617a88578251825591602001919060010190617a6d565b506131e8929150617c65565b8260138101928215617a885791602002820182811115617a88578251825591602001919060010190617a6d565b6040518060600160405280600060ff16815260200160608152602001606081525090565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b50805460018160011615610100020316600290046000825580601f10617b405750611f2d565b601f016020900490600052602060002090810190611f2d9190617c65565b6040518060400160405280617b71617c2c565b8152602001600081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10617bb75780548555617a88565b82800160010185558215617a8857600052602060002091601f016020900482015b82811115617a88578254825591600101919060010190617bd8565b8260138101928215617a885791820182811115617a88578254825591600101919060010190617bd8565b50611f2d906013810190617c65565b604051806040016040528060008152602001600081525090565b6040518061026001604052806013906020820280368337509192915050565b61318c91905b808211156131e85760008155600101617c6b565b8035611dc581618faf565b60008083601f840112617c9b578182fd5b5081356001600160401b03811115617cb1578182fd5b60208301915083602080830285010111156159f357600080fd5b6000601f8381840112617cdc578182fd5b8235617cef617cea82618f64565b618f3e565b818152925060208084019085810160005b84811015617d81578135880189603f820112617d1b57600080fd5b838101356001600160401b03811115617d3357600080fd5b617d44818901601f19168601618f3e565b81815260408c81848601011115617d5a57600080fd5b82818501888401375060009181018601919091528552509282019290820190600101617d00565b50505050505092915050565b600082601f830112617d9d578081fd5b8135617dab617cea82618f64565b818152915060208083019084810181840286018201871015617dcc57600080fd5b6000805b85811015617d815782356001600160401b0381168114617dee578283fd5b85529383019391830191600101617dd0565b60008083601f840112617e11578182fd5b5081356001600160401b03811115617e27578182fd5b6020830191508360208285010111156159f357600080fd5b600060208284031215617e50578081fd5b813561115e81618faf565b600060208284031215617e6c578081fd5b815161115e81618faf565b60008060008060408587031215617e8c578283fd5b84356001600160401b0380821115617ea2578485fd5b617eae88838901617c8a565b90965094506020870135915080821115617ec6578384fd5b50617ed387828801617c8a565b95989497509550505050565b600080600060608486031215617ef3578283fd5b83356001600160401b0380821115617f09578485fd5b81860187601f820112617f1a578586fd5b80359250617f2a617cea84618f64565b80848252602080830192508084018b828389028701011115617f4a57898afd5b8994505b86851015617f7457617f608c82617c7f565b845260019490940193928101928101617f4e565b509097508801359350505080821115617f8b578384fd5b617f9787838801617d8d565b93506040860135915080821115617fac578283fd5b50617fb986828701617ccb565b9150509250925092565b600060208284031215617fd4578081fd5b8151801515811461115e578182fd5b60008060208385031215617ff5578182fd5b82356001600160401b0381111561800a578283fd5b61801685828601617e00565b90969095509350505050565b60008060008060408587031215618037578384fd5b84356001600160401b038082111561804d578586fd5b61805988838901617e00565b90965094506020870135915080821115618071578384fd5b50617ed387828801617e00565b60006020828403121561808f578081fd5b5035919050565b6000602082840312156180a7578081fd5b5051919050565b600080604083850312156180c0578182fd5b505080516020909101519092909150565b6000806000604084860312156180e5578081fd5b833560ff811681146180f5578182fd5b925060208401356001600160401b0381111561810f578182fd5b61811b86828701617e00565b9497909650939450505050565b6000815180845260208085019450808401835b838110156181605781516001600160a01b03168752958201959082019060010161813b565b509495945050505050565b60008284528282602086013780602084860101526020601f19601f85011685010190509392505050565b600081518084526181ad816020860160208601618f83565b601f01601f19169290920160200192915050565b600082516181d3818460208701618f83565b9190910192915050565b918252602082015260400190565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b03968716815294861660208601529290941660408401526001600160401b03166060830152911515608082015260a081019190915260c00190565b6001600160a01b0392909216825260ff16602082015260400190565b60006020825261115e6020830184618128565b60006040825261829c6040830185618128565b602083820381850152818551808452828401915082838202850101838801865b838110156182ea57601f198784030185526182d8838351618195565b948601949250908501906001016182bc565b50909998505050505050505050565b60006080825261830c6080830187618128565b828103602084810191909152865180835287820192820190845b8181101561834257845183529383019391830191600101618326565b505084810360408601526183568188618128565b93505050506001600160401b038316606083015295945050505050565b901515815260200190565b60006020825261115e6020830184618195565b6000604082526183a560408301868861816b565b82810360208401526183b881858761816b565b979650505050505050565b6020808252601c908201527f6c656e677468206f66206275726e526174696f206d69736d6174636800000000604082015260600190565b60208082526042908201527f746865206275726e526174696f20706c75732073797374656d5265776172645260408201527f6174696f206d757374206265206e6f2067726561746572207468616e20313030606082015261030360f41b608082015260a00190565b60208082526026908201527f6c656e677468206f66206d61784e756d4f664d61696e7461696e696e67206d696040820152650e6dac2e8c6d60d31b606082015260800190565b6020808252601b908201527f6261746368207472616e736665722072657475726e2066616c73650000000000604082015260600190565b6020808252602c908201527f6c656e677468206f66206d61784e756d4f66576f726b696e6743616e6469646160408201526b0e8cae640dad2e6dac2e8c6d60a31b606082015260800190565b60208082526025908201527f6c656e677468206f66206d61696e7461696e536c6173685363616c65206d69736040820152640dac2e8c6d60db1b606082015260800190565b6020808252818101527f6c656e677468206f66206e756d4f66436162696e657473206d69736d61746368604082015260600190565b60208082526019908201527f74686520636f6e7472616374206e6f7420696e69742079657400000000000000604082015260600190565b6020808252601f908201527f6f6e6c7920736c617368206f72207374616b6548756220636f6e747261637400604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b60208082526028908201527f746865206e756d4f66436162696e657473206d75737420626520677265617465604082015267072207468616e20360c41b606082015260800190565b60208082526039908201527f746865206e756d4f66436162696e657473206d757374206265206c657373207460408201527f68616e204d41585f4e554d5f4f465f56414c494441544f525300000000000000606082015260800190565b60208082526029908201527f746865206e756d626572206f662076616c696461746f727320657863656564206040820152681d1a19481b1a5b5a5d60ba1b606082015260800190565b60208082526022908201527f63616e206e6f7420646f207468697320747769636520696e206f6e6520626c6f604082015261636b60f01b606082015260800190565b6020808252600e908201526d696e70757420746f6f206c6f6e6760901b604082015260600190565b60208082526037908201527f746865206d61784e756d4f664d61696e7461696e696e67206d7573742062652060408201527f6c657373207468616e206e756d4f66436162696e657473000000000000000000606082015260800190565b6020808252602b908201527f6475706c696361746520636f6e73656e7375732061646472657373206f66207660408201526a185b1a59185d1bdc94d95d60aa1b606082015260800190565b60208082526027908201527f7468652065787069726554696d655365636f6e64476170206973206f7574206f604082015266662072616e676560c81b606082015260800190565b6020808252601590820152746465706f7369742076616c7565206973207a65726f60581b604082015260600190565b60208082526049908201527f746865206d61784e756d4f66576f726b696e6743616e64696461746573206d7560408201527f7374206265206e6f742067726561746572207468616e206d61784e756d4f6643606082015268616e6469646174657360b81b608082015260a00190565b6020808252601190820152706164646974696f6e206f766572666c6f7760781b604082015260600190565b60208082526023908201527f63616e206e6f7420656e7465722054656d706f72617279204d61696e74656e616040820152626e636560e81b606082015260800190565b60208082526025908201527f6c656e677468206f66206a61696c2076616c696461746f7273206d757374206260408201526465206f6e6560d81b606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252601490820152736761737072696365206973206e6f74207a65726f60601b604082015260600190565b6020808252602e908201527f746865206d6573736167652073656e646572206d75737420626520676f76657260408201526d1b985b98d94818dbdb9d1c9858dd60921b606082015260800190565b60208082526025908201527f6c656e677468206f66206d61784e756d4f6643616e64696461746573206d69736040820152640dac2e8c6d60db1b606082015260800190565b6020808252601290820152716e6f7420696e206d61696e74656e616e636560701b604082015260600190565b60208082526021908201527f666565206973206c6172676572207468616e2044555354595f494e434f4d494e6040820152604760f81b606082015260800190565b60208082526019908201527f74686520636f6e747261637420616c726561647920696e697400000000000000604082015260600190565b60208082526042908201527f7468652073797374656d526577617264526174696f20706c7573206275726e5260408201527f6174696f206d757374206265206e6f2067726561746572207468616e20313030606082015261030360f41b608082015260a00190565b6020808252601a908201527f6c656e677468206973206c657373207468616e206f6666736574000000000000604082015260600190565b60208082526026908201527f6c656e677468206f662065787069726554696d655365636f6e64476170206d696040820152650e6dac2e8c6d60d31b606082015260800190565b60208082526017908201527f6f6e6c792063757272656e742076616c696461746f7273000000000000000000604082015260600190565b60208082526021908201527f6661696c656420746f20706172736520696e69742076616c696461746f7253656040820152601d60fa1b606082015260800190565b6020808252602f908201527f746865206d6573736167652073656e646572206d7573742062652063726f737360408201526e0818da185a5b8818dbdb9d1c9858dd608a1b606082015260800190565b6020808252602d908201527f746865206d6573736167652073656e646572206d75737420626520746865206260408201526c3637b1b590383937b23ab1b2b960991b606082015260800190565b60208082526024908201527f6c656e677468206f662073797374656d526577617264526174696f206d69736d6040820152630c2e8c6d60e31b606082015260800190565b6020808252603e908201527f746865206d61696e7461696e536c6173685363616c65206d757374206265206760408201527f726561746572207468616e203020616e64206c657373207468616e2031300000606082015260800190565b6020808252600d908201526c756e6b6e6f776e20706172616d60981b604082015260600190565b60208082526029908201527f746865206d6573736167652073656e646572206d75737420626520736c6173686040820152680818dbdb9d1c9858dd60ba1b606082015260800190565b6020808252601f908201527f746865206d73672073656e646572206d757374206265207374616b6548756200604082015260600190565b61ffff91909116815260200190565b90815260200190565b60008482528315156020830152606060408301526179976060830184618195565b63ffffffff91909116815260200190565b60ff91909116815260200190565b600060ff851682526040602083015261799760408301848661816b565b6040518181016001600160401b0381118282101715618f5c57600080fd5b604052919050565b60006001600160401b03821115618f79578081fd5b5060209081020190565b60005b83811015618f9e578181015183820152602001618f86565b8381111561725e5750506000910152565b6001600160a01b0381168114611f2d57600080fdfe70e72399380dcfb0338abc03dc8d47f9f470ada8e769c9a78d644ea97385ecb20175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dbbf905ec80f905e8f846942a7cdd959bfe8d9487b2a43b33565295a698f7e294b6a7edd747c0554875d3fc531d19ba1497992c5e941ff80f3f7f110ffd8920a3ac38fdef318fe94a3f86048c27395000f846946488aa4d1955ee33403f8ccb1d4de5fb97c7ade294220f003d8bdfaadf52aa1e55ae4cc485e6794875941a87e90e440a39c99aa9cb5cea0ad6a3f0b2407b86048c27395000f846949ef9f4360c606c7ab4db26b016007d3ad0ab86a0946103af86a874b705854033438383c82575f25bc29418e2db06cbff3e3c5f856410a1838649e760175786048c27395000f84694ee01c3b1283aa067c58eab4709f85e99d46de5fe94ee4b9bfb1871c64e2bcabb1dc382dc8b7c4218a29415904ab26ab0e99d70b51c220ccdcccabee6e29786048c27395000f84694685b1ded8013785d6623cc18d214320b6bb6475994a20ef4e5e4e7e36258dbf51f4d905114cb1b34bc9413e39085dc88704f4394d35209a02b1a9520320c86048c27395000f8469478f3adfc719c99674c072166708589033e2d9afe9448a30d5eaa7b64492a160f139e2da2800ec3834e94055838358c29edf4dcc1ba1985ad58aedbb6be2b86048c27395000f84694c2be4ec20253b8642161bc3f444f53679c1f3d479466f50c616d737e60d7ca6311ff0d9c434197898a94d1d678a2506eeaa365056fe565df8bc8659f28b086048c27395000f846942f7be8361c80a4c1e7e9aaf001d0877f1cfde218945f93992ac37f3e61db2ef8a587a436a161fd210b94ecbc4fb1a97861344dad0867ca3cba2b860411f086048c27395000f84694ce2fd7544e0b2cc94692d4a704debef7bcb613289444abc67b4b2fba283c582387f54c9cba7c34bafa948acc2ab395ded08bb75ce85bf0f95ad2abc51ad586048c27395000f84694b8f7166496996a7da21cf1f1b04d9b3e26a3d077946770572763289aac606e4f327c2f6cc1aa3b3e3b94882d745ed97d4422ca8da1c22ec49d880c4c097286048c27395000f846942d4c407bbe49438ed859fe965b140dcf1aab71a9943ad0939e120f33518fbba04631afe7a3ed6327b194b2bbb170ca4e499a2b0f3cc85ebfa6e8c4dfcbea86048c27395000f846946bbad7cf34b5fa511d8e963dbba288b1960e75d694853b0f6c324d1f4e76c8266942337ac1b0af1a229442498946a51ca5924552ead6fc2af08b94fcba648601d1a94a2000f846944430b3230294d12c6ab2aac5c2cd68e80b16b581947b107f4976a252a6939b771202c28e64e03f52d694795811a7f214084116949fc4f53cedbf189eeab28601d1a94a2000f84694ea0a6e3c511bbd10f4519ece37dc24887e11b55d946811ca77acfb221a49393c193f3a22db829fcc8e9464feb7c04830dd9ace164fc5c52b3f5a29e5018a8601d1a94a2000f846947ae2f5b9e386cd1b50a4550696d957cb4900f03a94e83bcc5077e6b873995c24bac871b5ad856047e19464e48d4057a90b233e026c1041e6012ada897fe88601d1a94a2000f8469482012708dafc9e1b880fd083b32182b869be8e09948e5adc73a2d233a1b496ed3115464dd6c7b887509428b383d324bc9a37f4e276190796ba5a8947f5ed8601d1a94a2000f8469422b81f8e175ffde54d797fe11eb03f9e3bf75f1d94a1c3ef7ca38d8ba80cce3bfc53ebd2903ed21658942767f7447f7b9b70313d4147b795414aecea54718601d1a94a2000f8469468bf0b8b6fb4e317a0f9d6f03eaf8ce6675bc60d94675cfe570b7902623f47e7f59c9664b5f5065dcf94d84f0d2e50bcf00f2fc476e1c57f5ca2d57f625b8601d1a94a2000f846948c4d90829ce8f72d0163c1d5cf348a862d5506309485c42a7b34309bee2ed6a235f86d16f059deec5894cc2cedc53f0fa6d376336efb67e43d167169f3b78601d1a94a2000f8469435e7a025f4da968de7e4d7e4004197917f4070f194b1182abaeeb3b4d8eba7e6a4162eac7ace23d57394c4fd0d870da52e73de2dd8ded19fe3d26f43a1138601d1a94a2000f84694d6caa02bbebaebb5d7e581e4b66559e635f805ff94c07335cf083c1c46a487f0325769d88e163b653694efaff03b42e41f953a925fc43720e45fb61a19938601d1a94a20000175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dbaa164736f6c6343000604000a

Deployed Bytecode

0x6080604052600436106104fb5760003560e01c806388b32f111161028c578063c6d339451161015a578063e40716a1116100cc578063f92eb86b11610085578063f92eb86b14610d2d578063f9a2bbc714610d42578063fc3e590814610d57578063fccc281314610d6c578063fd4ad81f14610d81578063fd6a687914610db057610502565b8063e40716a114610c9b578063ea321e4914610cb0578063eb57e20214610cd0578063eda5868c14610cf0578063f1fad10414610d05578063f340fa0114610d1a57610502565b8063d86222d51161011e578063d86222d514610c1d578063daacdb6614610c32578063dc927faf14610c47578063df8079e914610c5c578063e086c7b114610c71578063e1c7392a14610c8657610502565b8063c6d3394514610bbe578063c81b166214610bd3578063c8509d811461098d578063ce910b0c14610be8578063d68fb56a14610c0857610502565b8063a78abc16116101fe578063ad3c9da6116101b7578063ad3c9da614610b3d578063aef198a914610b5d578063b7ab4db514610b72578063b8cf4ef114610b94578063bf9f4995146106fe578063c466689d14610ba957610502565b8063a78abc1614610ab4578063aa82dce114610ac9578063aad5606314610ade578063aaf5eb6814610af3578063ab51bb9614610b08578063ac43175114610b1d57610502565b806396713da91161025057806396713da914610a365780639dc0926214610a4b5780639fe0f81614610a60578063a0dc275814610a75578063a1a11bf514610a8a578063a5422d5c14610a9f57610502565b806388b32f11146109c25780638a7beb01146109d75780638b5ad0c9146109ec5780638d19a41014610a015780639369d7de14610a2157610502565b806351b4dce3116103c957806370fd5bad1161033b5780637e434d54116102f45780637e434d541461094e57806381650b6214610963578063820dcaa814610978578063831d65d11461098d578063853230aa1461090f57806386249882146109ad57610502565b806370fd5bad146108d0578063718a8aa8146108e557806375d47a0a146108fa57806378dfed4a1461090f5780637942fd05146109245780637a84ca2a1461093957610502565b80635d77156c1161038d5780635d77156c1461082a5780635de1e22c1461083f57806360eba4fe1461085457806362b72cf5146108745780636969a25c146108895780636e47b482146108bb57610502565b806351b4dce3146107ab57806351e80672146107c057806355614fcc146107d5578063565c56b3146107f55780635667515a1461081557610502565b8063300c35671161046d57806343756e5c1161042657806343756e5c1461072057806345cf9daf14610735578063493279b11461074a5780634bf6c8821461076c5780634df6e0c3146107815780635192c82c1461079657610502565b8063300c35671461065b578063321d398a1461067b5780633365af3a1461069b57806335409f7f146106bb5780633b071dcc146106db5780633dffc387146106fe57610502565b8063152ad3b8116104bf578063152ad3b8146105ba5780631e4c1524146105dc5780631ff18069146105fc578063219f22d51461061157806328087028146106265780632a0ffb6e1461063b57610502565b806304c4fec61461050757806307a568471461051e5780630bee7a67146105495780630e2374a51461056b5780631182b8751461058d57610502565b3661050257005b600080fd5b34801561051357600080fd5b5061051c610dc5565b005b34801561052a57600080fd5b50610533610e37565b6040516105409190618ed8565b60405180910390f35b34801561055557600080fd5b5061055e610e3d565b6040516105409190618f02565b34801561057757600080fd5b50610580610e42565b60405161054091906181eb565b34801561059957600080fd5b506105ad6105a83660046180d1565b610e48565b604051610540919061837e565b3480156105c657600080fd5b506105cf611165565b6040516105409190618373565b3480156105e857600080fd5b5061051c6105f7366004617edf565b61116e565b34801561060857600080fd5b50610533611844565b34801561061d57600080fd5b5061055e61184a565b34801561063257600080fd5b5061058061184f565b34801561064757600080fd5b5061051c610656366004617e3f565b611855565b34801561066757600080fd5b5061051c610676366004617e77565b611902565b34801561068757600080fd5b506105cf61069636600461807e565b611c4b565b3480156106a757600080fd5b506105cf6106b636600461807e565b611d1a565b3480156106c757600080fd5b5061051c6106d6366004617e3f565b611dcb565b3480156106e757600080fd5b506106f0611f30565b604051610540929190618289565b34801561070a57600080fd5b5061071361220c565b6040516105409190618f13565b34801561072c57600080fd5b50610580612211565b34801561074157600080fd5b50610533612217565b34801561075657600080fd5b5061075f61221d565b6040516105409190618ec9565b34801561077857600080fd5b50610713612222565b34801561078d57600080fd5b506106f0612227565b3480156107a257600080fd5b506105336123b3565b3480156107b757600080fd5b506105806123b9565b3480156107cc57600080fd5b506105806123bf565b3480156107e157600080fd5b506105cf6107f0366004617e3f565b6123c5565b34801561080157600080fd5b50610533610810366004617e3f565b6123fa565b34801561082157600080fd5b5061071361244b565b34801561083657600080fd5b5061055e612450565b34801561084b57600080fd5b50610533612455565b34801561086057600080fd5b506105ad61086f36600461807e565b61245b565b34801561088057600080fd5b50610533612501565b34801561089557600080fd5b506108a96108a436600461807e565b612507565b60405161054096959493929190618218565b3480156108c757600080fd5b5061058061256b565b3480156108dc57600080fd5b50610713612571565b3480156108f157600080fd5b50610713612576565b34801561090657600080fd5b5061058061257b565b34801561091b57600080fd5b50610533612581565b34801561093057600080fd5b50610713612587565b34801561094557600080fd5b5061053361258c565b34801561095a57600080fd5b50610580612592565b34801561096f57600080fd5b5061055e612598565b34801561098457600080fd5b5061053361259d565b34801561099957600080fd5b5061051c6109a83660046180d1565b6125a3565b3480156109b957600080fd5b50610533612604565b3480156109ce57600080fd5b5061053361260a565b3480156109e357600080fd5b506105cf612610565b3480156109f857600080fd5b50610533612619565b348015610a0d57600080fd5b50610533610a1c366004617e3f565b61261f565b348015610a2d57600080fd5b5061051c61265f565b348015610a4257600080fd5b50610713612773565b348015610a5757600080fd5b50610580612778565b348015610a6c57600080fd5b5061053361277e565b348015610a8157600080fd5b50610533612783565b348015610a9657600080fd5b50610580612788565b348015610aab57600080fd5b506105ad61278e565b348015610ac057600080fd5b506105cf6127ad565b348015610ad557600080fd5b506105806127b6565b348015610aea57600080fd5b506105806127bc565b348015610aff57600080fd5b506105336127c2565b348015610b1457600080fd5b5061055e61244b565b348015610b2957600080fd5b5061051c610b38366004618022565b6127cb565b348015610b4957600080fd5b50610533610b58366004617e3f565b613084565b348015610b6957600080fd5b50610533613096565b348015610b7e57600080fd5b50610b876130a3565b6040516105409190618276565b348015610ba057600080fd5b5061053361318f565b348015610bb557600080fd5b50610533613194565b348015610bca57600080fd5b50610533612571565b348015610bdf57600080fd5b5061058061319a565b348015610bf457600080fd5b506105ad610c0336600461807e565b6131a0565b348015610c1457600080fd5b506105336131ad565b348015610c2957600080fd5b506105336131ec565b348015610c3e57600080fd5b506105336131f8565b348015610c5357600080fd5b506105806131fe565b348015610c6857600080fd5b50610580613204565b348015610c7d57600080fd5b50610533610e3d565b348015610c9257600080fd5b5061051c61320a565b348015610ca757600080fd5b506105336133b9565b348015610cbc57600080fd5b506105cf610ccb366004617fe3565b6133bf565b348015610cdc57600080fd5b5061051c610ceb366004617e3f565b613545565b348015610cfc57600080fd5b5061055e613649565b348015610d1157600080fd5b5061071361364e565b61051c610d28366004617e3f565b613653565b348015610d3957600080fd5b506105336139d2565b348015610d4e57600080fd5b506105806139d8565b348015610d6357600080fd5b5061071361277e565b348015610d7857600080fd5b506105806139de565b348015610d8d57600080fd5b50610da1610d9c36600461807e565b6139e4565b60405161054093929190618ee1565b348015610dbc57600080fd5b50610580613aa6565b6000610dd03361261f565b9050600b8181548110610ddf57fe5b600091825260209091206001601690920201015460ff16610e1b5760405162461bcd60e51b8152600401610e1290618ae4565b60405180910390fd5b6000610e256131ad565b9050610e32338383613aac565b505050565b60095481565b606481565b61200181565b60005460609060ff16610e6d5760405162461bcd60e51b8152600401610e12906185a5565b3361200014610e8e5760405162461bcd60e51b8152600401610e1290618ce5565b600b54610f4c57610e9d6179eb565b60015460005b81811015610f4857600b80546001810182556000919091528351600080516020618fe583398151915260169092029182019081556020808601516000805160206196148339815191528401805460ff1916911515919091179055604086015180518794610f2493600080516020619005833981519152909101920190617a1a565b506060820151610f3a9060038301906013617a94565b505050806001019050610ea3565b5050505b610f54617ac1565b6000610f9585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613d7192505050565b9150915080610fb157610fa86064613f2d565b9250505061115e565b815160009060ff16610fd657610fcf83602001518460400151613f8e565b905061112a565b825160ff16600114156111265782602001515160011461101b57600080516020618fc583398151915260405161100b9061899d565b60405180910390a1506067611121565b6000836020015160008151811061102e57fe5b602090810291909101810151516001600160a01b0381166000908152600490925260409091205490915080158061108f575060018082038154811061106f57fe5b9060005260206000209060040201600201601c9054906101000a900460ff165b156110cd576040516001600160a01b038316907fe209c46bebf57cf265d5d9009a00870e256d9150f3ed5281ab9d9eb3cec6e4be90600090a261111a565b60006110dc8360018403615150565b905080611118576040516001600160a01b038416907fe209c46bebf57cf265d5d9009a00870e256d9150f3ed5281ab9d9eb3cec6e4be90600090a25b505b6000925050505b61112a565b5060655b63ffffffff811661114f575050604080516000815260208101909152915061115e9050565b61115881613f2d565b93505050505b9392505050565b60075460ff1681565b33411461118d5760405162461bcd60e51b8152600401610e1290618d34565b3a156111ab5760405162461bcd60e51b8152600401610e1290618a23565b82516040805182815260208084028201019091526060908280156111e957816020015b6111d6617ae5565b8152602001906001900390816111ce5790505b50905060005b82811015611293576040518060c0016040528087838151811061120e57fe5b60200260200101516001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200186838151811061125057fe5b60200260200101516001600160401b03168152602001600015158152602001600081525082828151811061128057fe5b60209081029190910101526001016111ef565b5060405163d31f968d60e01b81526120009063d31f968d906112be906110009060089060040161825a565b60206040518083038186803b1580156112d657600080fd5b505afa1580156112ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061130e9190617fc3565b15611631578051601554818111156113b057815b818110156113ae57601580548061133557fe5b60008281526020812060046000199093019283020180546001600160a01b0319908116825560018201805490911690556002810180546001600160e81b0319169055600301559055601680548061138857fe5b6001900381819060005260206000200160006113a49190617b1a565b9055600101611322565b505b60005b828110156115f0578181106114d85760158482815181106113d057fe5b602090810291909101810151825460018181018555600094855293839020825160049092020180546001600160a01b039283166001600160a01b0319918216178255938301519481018054958316958516959095179094556040820151600285018054606085015160808601511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b199590961692909716919091179290921692909217169290921790915560a0015160039091015585516016908790839081106114a057fe5b602090810291909101810151825460018101845560009384529282902081516114d29491909101929190910190617a1a565b506115e8565b8381815181106114e457fe5b6020026020010151601582815481106114f957fe5b6000918252602091829020835160049092020180546001600160a01b039283166001600160a01b0319918216178255928401516001820180549184169185169190911790556040840151600282018054606087015160808801511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b1995909716929097169190911792909216939093171692909217905560a09091015160039091015585518690829081106115b457fe5b6020026020010151601682815481106115c957fe5b9060005260206000200190805190602001906115e6929190617a1a565b505b6001016113b3565b507fb8e726330a0dad1cf3d04e925663b17e391f1ed547d79b7f4e5f344119b44246826040516116209190618ed8565b60405180910390a150505050610e32565b60608061163e8386615513565b9150915060005b6001548110156117345760006001828154811061165e57fe5b90600052602060002090600402016003015490508060001461172b5760006001838154811061168957fe5b9060005260206000209060040201600301819055506120026001600160a01b031663092193ab82600185815481106116bd57fe5b60009182526020909120600491820201546040516001600160e01b031960e086901b1681526116f8926001600160a01b0390921691016181eb565b6000604051808303818588803b15801561171157600080fd5b505af1158015611725573d6000803e3d6000fd5b50505050505b50600101611645565b5047156117a2577f6ecc855f9440a9282c90913bbc91619fd44f5ec0b462af28d127b116f130aa4d4760405161176a9190618ed8565b60405180910390a1604051611002904780156108fc02916000818181858888f193505050501580156117a0573d6000803e3d6000fd5b505b600060038190556005558151156117bd576117bd82826159fa565b6110016001600160a01b031663fc4333cd6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156117fa57600080fd5b505af115801561180e573d6000803e3d6000fd5b50506040517fedd8d7296956dd970ab4de3f2fc03be2b0ffc615d20cd4c72c6e44f928630ebf925060009150a150505050505050565b60035481565b606881565b61200581565b33612002146118765760405162461bcd60e51b8152600401610e1290618e92565b60005b6015548110156118fe57816001600160a01b03166015828154811061189a57fe5b60009182526020909120600490910201546001600160a01b031614156118f6576001601582815481106118c957fe5b9060005260206000209060040201600201601c6101000a81548160ff0219169083151502179055506118fe565b600101611879565b5050565b3341146119215760405162461bcd60e51b8152600401610e1290618d34565b60105443116119425760405162461bcd60e51b8152600401610e1290618738565b3a156119605760405162461bcd60e51b8152600401610e1290618a23565b60005460ff166119825760405162461bcd60e51b8152600401610e12906185a5565b60006110023168056bc75e2d631000008111156119b9576119b28168056bc75e2d6310000063ffffffff6161e916565b91506119c0565b5050611c41565b6040516309a99b4f60e41b815261100290639a99b4f0906119e790309086906004016181ff565b602060405180830381600087803b158015611a0157600080fd5b505af1158015611a15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a399190618096565b915081611a47575050611c41565b6000805b84811015611a7557858582818110611a5f57fe5b9050602002013582019150806001019050611a4b565b5080611a8357505050611c41565b6000806000805b89811015611c395784898983818110611a9f57fe5b90506020020135880281611aaf57fe5b0493508a8a82818110611abe57fe5b9050602002016020810190611ad39190617e3f565b6001600160a01b03811660009081526004602052604090205490935091508115611bef576000600180840381548110611b0857fe5b9060005260206000209060040201905080600201601c9054906101000a900460ff1615611b7557836001600160a01b03167fb9c75cbbfde137c4281689580799ef5f52144e78858f776a5979b2b212137d8586604051611b689190618ed8565b60405180910390a2611be9565b600354611b88908663ffffffff61622b16565b6003908155810154611ba0908663ffffffff61622b16565b60038201556040516001600160a01b038516907fcb0aad6cf9cd03bdf6137e359f541c42f38b39f007cae8e89e88aa7d8c6617b290611be0908890618ed8565b60405180910390a25b50611c31565b826001600160a01b03167fb9c75cbbfde137c4281689580799ef5f52144e78858f776a5979b2b212137d8585604051611c289190618ed8565b60405180910390a25b600101611a8a565b505050505050505b5050436010555050565b6001546000908210611c5f57506000611d15565b60006001600160a01b031660018381548110611c7757fe5b60009182526020909120600490910201546001600160a01b03161480611ca757506008541580611ca75750600a54155b80611cb6575060085460095410155b80611cc75750611cc582611d1a565b155b80611cf057506000600b8381548110611cdc57fe5b906000526020600020906016020160000154115b80611d0457506001611d006130a3565b5111155b15611d1157506000611d15565b5060015b919050565b6001546000908210611d2e57506000611d15565b600b548210611d6b5760018281548110611d4457fe5b9060005260206000209060040201600201601c9054906101000a900460ff16159050611d15565b60018281548110611d7857fe5b9060005260206000209060040201600201601c9054906101000a900460ff16158015611dc55750600b8281548110611dac57fe5b600091825260209091206001601690920201015460ff16155b92915050565b600b54611e8957611dda6179eb565b60015460005b81811015611e8557600b80546001810182556000919091528351600080516020618fe583398151915260169092029182019081556020808601516000805160206196148339815191528401805460ff1916911515919091179055604086015180518794611e6193600080516020619005833981519152909101920190617a1a565b506060820151611e779060038301906013617a94565b505050806001019050611de0565b5050505b336110011480611e9a575033612002145b611eb65760405162461bcd60e51b8152600401610e12906185dc565b6001600160a01b03811660009081526004602052604090205480611eda5750611f2d565b6001810390506000600b8281548110611eef57fe5b600091825260209091206001601690920201015460ff169050611f128383615150565b8015611f1b5750805b15610e32576009805460001901905550505b50565b60015460609081906000805b82811015611f835760018181548110611f5157fe5b9060005260206000209060040201600201601c9054906101000a900460ff16611f7b576001909101905b600101611f3c565b50606081604051908082528060200260200182016040528015611fb0578160200160208202803683370190505b509050606082604051908082528060200260200182016040528015611fe957816020015b6060815260200190600190039081611fd45790505b50600b54600094509091508414156121645760005b8481101561215e576001818154811061201357fe5b9060005260206000209060040201600201601c9054906101000a900460ff16612156576001818154811061204357fe5b600091825260209091206004909102015483516001600160a01b039091169084908690811061206e57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050600b818154811061209b57fe5b600091825260209182902060026016909202018101805460408051601f6000196101006001861615020190931694909404918201859004850284018501905280835291929091908301828280156121335780601f1061210857610100808354040283529160200191612133565b820191906000526020600020905b81548152906001019060200180831161211657829003601f168201915b505050505082858151811061214457fe5b60209081029190910101526001909301925b600101611ffe565b50612200565b60005b848110156121fe576001818154811061217c57fe5b9060005260206000209060040201600201601c9054906101000a900460ff166121f657600181815481106121ac57fe5b600091825260209091206004909102015483516001600160a01b03909116908490869081106121d757fe5b6001600160a01b03909216602092830291909101909101526001909301925b600101612167565b505b909450925050505b9091565b600181565b61100181565b60085481565b603881565b600881565b6060806000600e549050600080600c5411612243576015612247565b600c545b905060606122536130a3565b9050606061226082616250565b905082825111612277579094509250612208915050565b83838351031015612289578282510393505b83156122bf5760c843046122a583838388880360008a8a6163be565b6122bd8383838888038989038a8b8b8b5103016163be565b505b6060836040519080825280602002602001820160405280156122eb578160200160208202803683370190505b50905060608460405190808252806020026020018201604052801561232457816020015b606081526020019060019003908161230f5790505b50905060005b858110156123a55784818151811061233e57fe5b602002602001015183828151811061235257fe5b60200260200101906001600160a01b031690816001600160a01b03168152505083818151811061237e57fe5b602002602001015182828151811061239257fe5b602090810291909101015260010161232a565b509096509450505050509091565b60065481565b61200681565b61200081565b6001600160a01b038116600090815260046020526040812054806123ed576000915050611d15565b6000190161115e81611d1a565b6001600160a01b03811660009081526004602052604081205480612422576000915050611d15565b60018082038154811061243157fe5b906000526020600020906004020160030154915050919050565b600081565b606781565b600f5481565b6012818154811061246857fe5b600091825260209182902001805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152935090918301828280156124f95780601f106124ce576101008083540402835291602001916124f9565b820191906000526020600020905b8154815290600101906020018083116124dc57829003601f168201915b505050505081565b60105481565b6001818154811061251457fe5b600091825260209091206004909102018054600182015460028301546003909301546001600160a01b0392831694509082169291821691600160a01b81046001600160401b031691600160e01b90910460ff169086565b61100581565b600281565b601081565b61100881565b6103e881565b600b81565b600c5481565b61200381565b606681565b61271081565b33612000146125c45760405162461bcd60e51b8152600401610e1290618ce5565b7f41ce201247b6ceb957dcdb217d0b8acb50b9ea0e12af9af4f5e7f389021016058383836040516125f793929190618f21565b60405180910390a1505050565b60025481565b60115481565b60145460ff1681565b600a5481565b6001600160a01b038116600090815260046020526040812054806126555760405162461bcd60e51b8152600401610e1290618c6d565b6000190192915050565b600b5461271d5761266e6179eb565b60015460005b8181101561271957600b80546001810182556000919091528351600080516020618fe583398151915260169092029182019081556020808601516000805160206196148339815191528401805460ff19169115159190911790556040860151805187946126f593600080516020619005833981519152909101920190617a1a565b50606082015161270b9060038301906013617a94565b505050806001019050612674565b5050505b60085461272a5760036008555b600a54612737576002600a555b60006127423361261f565b905061274d81611c4b565b6127695760405162461bcd60e51b8152600401610e129061895a565b611f2d3382616515565b600981565b61100781565b600381565b60c881565b61100681565b6040518061062001604052806105ef81526020016190256105ef913981565b60005460ff1681565b61200281565b61300081565b6402540be40081565b60005460ff166127ed5760405162461bcd60e51b8152600401610e12906185a5565b336110071461280e5760405162461bcd60e51b8152600401610e1290618a51565b61287884848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080518082019091526013815272065787069726554696d655365636f6e6447617606c1b602082015291506165ad9050565b15612915576020811461289d5760405162461bcd60e51b8152600401610e1290618c27565b604080516020601f84018190048102820181019092528281526000916128db9185858083850183828082843760009201919091525061660692505050565b9050606481101580156128f15750620186a08111155b61290d5760405162461bcd60e51b8152600401610e129061884a565b600255613041565b61297584848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260098152686275726e526174696f60b81b602082015291506165ad9050565b15612a18576020811461299a5760405162461bcd60e51b8152600401610e12906183c3565b604080516020601f84018190048102820181019092528281526000916129d89185858083850183828082843760009201919091525061660692505050565b90506127106129f2600f548361622b90919063ffffffff16565b1115612a105760405162461bcd60e51b8152600401610e12906183fa565b600655613041565b612a8284848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260138152726d61784e756d4f664d61696e7461696e696e6760681b602082015291506165ad9050565b15612b1c5760208114612aa75760405162461bcd60e51b8152600401610e1290618462565b604080516020601f8401819004810282018101909252828152600091612ae59185858083850183828082843760009201919091525061660692505050565b600c5490915080612af4575060155b808210612b135760405162461bcd60e51b8152600401610e12906187a2565b50600855613041565b612b8584848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260128152716d61696e7461696e536c6173685363616c6560701b602082015291506165ad9050565b15612c1e5760208114612baa5760405162461bcd60e51b8152600401610e129061852b565b604080516020601f8401819004810282018101909252828152600091612be89185858083850183828082843760009201919091525061660692505050565b9050600081118015612bfa5750600a81105b612c165760405162461bcd60e51b8152600401610e1290618dc5565b600a55613041565b612c9284848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601981527f6d61784e756d4f66576f726b696e6743616e6469646174657300000000000000602082015291506165ad9050565b15612d215760208114612cb75760405162461bcd60e51b8152600401610e12906184df565b604080516020601f8401819004810282018101909252828152600091612cf59185858083850183828082843760009201919091525061660692505050565b9050600d54811115612d195760405162461bcd60e51b8152600401610e12906188c0565b600e55613041565b612d8a84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260128152716d61784e756d4f6643616e6469646174657360701b602082015291506165ad9050565b15612e0c5760208114612daf5760405162461bcd60e51b8152600401610e1290618a9f565b604080516020601f8401819004810282018101909252828152600091612ded9185858083850183828082843760009201919091525061660692505050565b600d819055600e54909150811015612e0657600d54600e555b50613041565b612e7084848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600d81526c6e756d4f66436162696e65747360981b602082015291506165ad9050565b15612f1e5760208114612e955760405162461bcd60e51b8152600401610e1290618570565b604080516020601f8401819004810282018101909252828152600091612ed39185858083850183828082843760009201919091525061660692505050565b905060008111612ef55760405162461bcd60e51b8152600401610e129061864a565b6064811115612f165760405162461bcd60e51b8152600401610e1290618692565b600c55613041565b612f8684848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601181527073797374656d526577617264526174696f60781b602082015291506165ad9050565b156130295760208114612fab5760405162461bcd60e51b8152600401610e1290618d81565b604080516020601f8401819004810282018101909252828152600091612fe99185858083850183828082843760009201919091525061660692505050565b90506127106130036006548361622b90919063ffffffff16565b11156130215760405162461bcd60e51b8152600401610e1290618b88565b600f55613041565b60405162461bcd60e51b8152600401610e1290618e22565b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a848484846040516130769493929190618391565b60405180910390a150505050565b60046020526000908152604090205481565b68056bc75e2d6310000081565b6001546060906000805b828110156130d2576130be81611d1a565b156130ca578160010191505b6001016130ad565b506060816040519080825280602002602001820160405280156130ff578160200160208202803683370190505b5090506000915060005b838110156131865761311a81611d1a565b1561317e576001818154811061312c57fe5b600091825260209091206004909102015482516001600160a01b039091169083908590811061315757fe5b60200260200101906001600160a01b031690816001600160a01b0316815250508260010192505b600101613109565b50925050505b90565b601581565b61027181565b61100281565b6013818154811061246857fe5b60006131b76130a3565b519050600080600c54116131cc5760156131d0565b600c545b9050808211156131de578091505b816131e857600191505b5090565b67016345785d8a000081565b60055481565b61100381565b61200481565b60005460ff161561322d5760405162461bcd60e51b8152600401610e1290618b51565b613235617ac1565b600061325b6040518061062001604052806105ef81526020016190256105ef9139613d71565b915091508061327c5760405162461bcd60e51b8152600401610e1290618ca4565b60005b8260200151518110156133a15760018360200151828151811061329e57fe5b60209081029190910181015182546001818101855560009485528385208351600493840290910180546001600160a01b039283166001600160a01b03199182161782558587015182850180549185169183169190911790556040860151600283018054606089015160808a01511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b199590981692909516919091179290921694909417161790915560a09093015160039093019290925591860151805191850193918590811061337457fe5b602090810291909101810151516001600160a01b031682528101919091526040016000205560010161327f565b50506103e8600255506000805460ff19166001179055565b600d5481565b601354600090815b818110156134c8576134b085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060138054909250859150811061341857fe5b600091825260209182902001805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152928301828280156134a65780601f1061347b576101008083540402835291602001916134a6565b820191906000526020600020905b81548152906001019060200180831161348957829003601f168201915b505050505061660b565b156134c057600192505050611dc5565b6001016133c7565b5060125460005b818110156135395761352086868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060128054909250859150811061341857fe5b156135315760019350505050611dc5565b6001016134cf565b50600095945050505050565b33611001146135665760405162461bcd60e51b8152600401610e1290618e49565b600b54613624576135756179eb565b60015460005b8181101561362057600b80546001810182556000919091528351600080516020618fe583398151915260169092029182019081556020808601516000805160206196148339815191528401805460ff19169115159190911790556040860151805187946135fc93600080516020619005833981519152909101920190617a1a565b5060608201516136129060038301906013617a94565b50505080600101905061357b565b5050505b600061362f8261666f565b905061363a81611c4b565b156118fe576118fe8282616515565b606581565b601181565b3341146136725760405162461bcd60e51b8152600401610e1290618d34565b60005460ff166136945760405162461bcd60e51b8152600401610e12906185a5565b600034116136b45760405162461bcd60e51b8152600401610e1290618891565b3a156136d25760405162461bcd60e51b8152600401610e1290618a23565b6001600160a01b03811660009081526004602052604090205460145434919060ff1661371257610271600f556103e86006556014805460ff191660011790555b60008211801561372457506000600f54115b156137d6576000613752612710613746600f54346167f290919063ffffffff16565b9063ffffffff61682c16565b905080156137d4576040516110029082156108fc029083906000818181858888f19350505050158015613789573d6000803e3d6000fd5b507f6ecc855f9440a9282c90913bbc91619fd44f5ec0b462af28d127b116f130aa4d816040516137b99190618ed8565b60405180910390a16137d1838263ffffffff6161e916565b92505b505b6000821180156137e857506000600654115b1561388e57600061380a612710613746600654346167f290919063ffffffff16565b9050801561388c5760405161dead9082156108fc029083906000818181858888f19350505050158015613841573d6000803e3d6000fd5b507f627059660ea01c4733a328effb2294d2f86905bf806da763a89cee254de8bee5816040516138719190618ed8565b60405180910390a1613889838263ffffffff6161e916565b92505b505b801561398c5760006001808303815481106138a557fe5b9060005260206000209060040201905080600201601c9054906101000a900460ff161561391257836001600160a01b03167ff177e5d6c5764d79c32883ed824111d9b13f5668cf6ab1cc12dd36791dd955b4846040516139059190618ed8565b60405180910390a2613986565b600354613925908463ffffffff61622b16565b600390815581015461393d908463ffffffff61622b16565b60038201556040516001600160a01b038516907f93a090ecc682c002995fad3c85b30c5651d7fd29b0be5da9d784a3302aedc0559061397d908690618ed8565b60405180910390a25b50610e32565b826001600160a01b03167ff177e5d6c5764d79c32883ed824111d9b13f5668cf6ab1cc12dd36791dd955b4836040516139c59190618ed8565b60405180910390a2505050565b600e5481565b61100081565b61dead81565b600b81815481106139f157fe5b6000918252602091829020601691909102018054600180830154600280850180546040805161010096831615969096026000190190911692909204601f810188900488028501880190925281845293965060ff90911694919291830182828015613a9c5780601f10613a7157610100808354040283529160200191613a9c565b820191906000526020600020905b815481529060010190602001808311613a7f57829003601f168201915b5050505050905083565b61100481565b6000600a5460001480613abd575081155b80613ac85750600954155b15613ad55750600061115e565b6000613b0f600a5461374685613746600b8981548110613af157fe5b6000918252602090912060169091020154439063ffffffff6161e916565b90506000806110016001600160a01b0316638256ace66040518163ffffffff1660e01b8152600401604080518083038186803b158015613b4e57600080fd5b505afa158015613b62573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b8691906180ae565b9150915060009350808310613ce557613b9f8787615150565b5060405163436aa28360e11b8152600090612002906386d5450690613bc8908b906004016181eb565b60206040518083038186803b158015613be057600080fd5b505afa158015613bf4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c189190617e5b565b6001600160a01b031614613c84576040516313d13bdb60e31b815261100190639e89ded890613c4d908a9087906004016181ff565b600060405180830381600087803b158015613c6757600080fd5b505af1158015613c7b573d6000803e3d6000fd5b50505050613cdc565b6040516305bfb49960e41b815261100190635bfb499090613ca9908a906004016181eb565b600060405180830381600087803b158015613cc357600080fd5b505af1158015613cd7573d6000803e3d6000fd5b505050505b60019350613cf7565b818310613cf757613cf58761666f565b505b60098054600019019055600b80546000919088908110613d1357fe5b60009182526020822060169190910201600101805460ff1916921515929092179091556040516001600160a01b038916917fb9d38178dc641ff1817967a63c9078cbcd955a9f1fcd75e0e3636de615d44d3b91a25050509392505050565b613d79617ac1565b6000613d83617ac1565b613d8b617b5e565b613d9c613d978661686e565b616893565b90506000805b613dab836168dd565b15613f1f5780613dd057613dc6613dc1846168fe565b61694c565b60ff168452613f17565b8060011415613f12576060613dec613de7856168fe565b6169cc565b90508051604051908082528060200260200182016040528015613e2957816020015b613e16617ae5565b815260200190600190039081613e0e5790505b5085602001819052508051604051908082528060200260200182016040528015613e6757816020015b6060815260200190600190039081613e525790505b50604086015260005b8151811015613f0757613e81617ae5565b60606000613ea1858581518110613e9457fe5b6020026020010151616a9d565b92509250925080613ec1578860009a509a50505050505050505050613f28565b8289602001518581518110613ed257fe5b60200260200101819052508189604001518581518110613eee57fe5b6020026020010181905250505050806001019050613e70565b506001925050613f17565b613f1f565b600101613da2565b50919350909150505b915091565b604080516001808252818301909252606091829190816020015b6060815260200190600190039081613f47579050509050613f6d8363ffffffff16616bb7565b81600081518110613f7a57fe5b602002602001018190525061115e81616bca565b6000606483511115613fc557600080516020618fc5833981519152604051613fb5906186ef565b60405180910390a1506066611dc5565b60005b83518110156140635760005b8181101561405a57848181518110613fe857fe5b6020026020010151600001516001600160a01b031685838151811061400957fe5b6020026020010151600001516001600160a01b0316141561405257600080516020618fc583398151915260405161403f906187ff565b60405180910390a1606692505050611dc5565b600101613fd4565b50600101613fc8565b5060608060606015805480602002602001604051908101604052809291908181526020016000905b828210156141155760008481526020908190206040805160c0810182526004860290920180546001600160a01b039081168452600180830154821685870152600283015491821693850193909352600160a01b81046001600160401b03166060850152600160e01b900460ff16151560808401526003015460a0830152908352909201910161408b565b50505050905060606016805480602002602001604051908101604052809291908181526020016000905b828210156141ea5760008481526020908190208301805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152928301828280156141d65780601f106141ab576101008083540402835291602001916141d6565b820191906000526020600020905b8154815290600101906020018083116141b957829003601f168201915b50505050508152602001906001019061413f565b50505050905060005b82518110156142475782818151811061420857fe5b60200260200101516060015160030283828151811061422357fe5b60209081029190910101516001600160401b039091166060909101526001016141f3565b5060608061425789898686616c54565b915091506142658282615513565b600154604080518281526020808402820101909152929850909650600095508594509250606091508280156142a4578160200160208202803683370190505b50905060005b828110156144355760006001600160a01b03166120026001600160a01b03166386d54506600184815481106142db57fe5b60009182526020909120600491820201546040516001600160e01b031960e085901b168152614316926001600160a01b0390921691016181eb565b60206040518083038186803b15801561432e57600080fd5b505afa158015614342573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143669190617e5b565b6001600160a01b0316146143c857600182828151811061438257fe5b602002602001019060ff16908160ff1681525050600181815481106143a357fe5b9060005260206000209060040201600301546000146143c3578360010193505b61442d565b67016345785d8a0000600182815481106143de57fe5b906000526020600020906004020160030154106144005784600101945061442d565b6001818154811061440d57fe5b90600052602060002090600402016003015460001461442d578360010193505b6001016142aa565b50606084604051908082528060200260200182016040528015614462578160200160208202803683370190505b509050606085604051908082528060200260200182016040528015614491578160200160208202803683370190505b5090506060866040519080825280602002602001820160405280156144c0578160200160208202803683370190505b5090506060876040519080825280602002602001820160405280156144ef578160200160208202803683370190505b5090506000606088604051908082528060200260200182016040528015614520578160200160208202803683370190505b50905060608960405190808252806020026020018201604052801561454f578160200160208202803683370190505b50905060009a506000995060006110046001600160a01b031663149d14d96040518163ffffffff1660e01b815260040160206040518083038186803b15801561459757600080fd5b505afa1580156145ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145cf9190618096565b905067016345785d8a000081111561461b57600080516020618fc58339815191526040516145fc90618b10565b60405180910390a160689e505050505050505050505050505050611dc5565b60005b8a8110156149af5789818151811061463257fe5b602002602001015160ff1660011415614728576001818154811061465257fe5b906000526020600020906004020160030154600014614723576001818154811061467857fe5b600091825260209091206004909102015484516001600160a01b039091169085908e9081106146a357fe5b60200260200101906001600160a01b031690816001600160a01b031681525050600181815481106146d057fe5b906000526020600020906004020160030154838d815181106146ee57fe5b60200260200101818152505060018a8d8151811061470857fe5b602002602001019060ff16908160ff16815250508b6001019b505b6149a7565b67016345785d8a00006001828154811061473e57fe5b906000526020600020906004020160030154106148c3576001818154811061476257fe5b906000526020600020906004020160020160009054906101000a90046001600160a01b0316898e8151811061479357fe5b60200260200101906001600160a01b031690816001600160a01b03168152505060006402540be400600183815481106147c857fe5b906000526020600020906004020160030154816147e157fe5b06600183815481106147ef57fe5b90600052602060002090600402016003015403905061481783826161e990919063ffffffff16565b898f8151811061482357fe5b6020026020010181815250506001828154811061483c57fe5b906000526020600020906004020160010160009054906101000a90046001600160a01b0316878f8151811061486d57fe5b60200260200101906001600160a01b031690816001600160a01b03168152505081888f8151811061489a57fe5b60209081029190910101526148b5868263ffffffff61622b16565b95508d6001019d50506149a7565b600181815481106148d057fe5b9060005260206000209060040201600301546000146149a757600181815481106148f657fe5b906000526020600020906004020160010160009054906101000a90046001600160a01b0316848d8151811061492757fe5b60200260200101906001600160a01b031690816001600160a01b0316815250506001818154811061495457fe5b906000526020600020906004020160030154838d8151811061497257fe5b60200260200101818152505060008a8d8151811061498c57fe5b602002602001019060ff16908160ff16815250508b6001019b505b60010161461e565b5060008415614c25576002546040516303702b2960e51b815261100491636e0565209188916149e9918e918e918d914201906004016182f9565b6020604051808303818588803b158015614a0257600080fd5b505af193505050508015614a33575060408051601f3d908101601f19168201909252614a3091810190617fc3565b60015b614baa576040516000815260443d1015614a4f57506000614aea565b60046000803e60005160e01c6308c379a08114614a70576000915050614aea565b60043d036004833e81513d60248201116001600160401b0382111715614a9b57600092505050614aea565b80830180516001600160401b03811115614abc576000945050505050614aea565b8060208301013d8601811115614ada57600095505050505050614aea565b601f01601f191660405250925050505b80614af55750614b37565b60019150857fa7cdeed7d0db45e3219a6e5d60838824c16f1d39991fcfe3f963029c844bf28082604051614b29919061837e565b60405180910390a250614ba5565b3d808015614b61576040519150601f19603f3d011682016040523d82523d6000602084013e614b66565b606091505b5060019150857fbfa884552dd8921b6ce90bfe906952ae5b3b29be0cc1a951d4f62697635a3a4582604051614b9b919061837e565b60405180910390a2505b614c25565b8015614bec577fa217d08e65f80c73121cd9db834d81652d544bfbf452f6d04922b16c90a37b7086604051614bdf9190618ed8565b60405180910390a1614c23565b857fa7cdeed7d0db45e3219a6e5d60838824c16f1d39991fcfe3f963029c844bf280604051614c1a906184a8565b60405180910390a25b505b8015614ddb5760005b8751811015614dd9576000888281518110614c4557fe5b60200260200101519050600060018281548110614c5e57fe5b60009182526020909120600160049092020181015481546001600160a01b03909116916108fc9185908110614c8f57fe5b9060005260206000209060040201600301549081150290604051600060405180830381858888f1935050505090508015614d4b5760018281548110614cd057fe5b60009182526020909120600160049092020181015481546001600160a01b03909116917f6c61d60f69a7beb3e1c80db7f39f37b208537cbb19da3174511b477812b2fc7d9185908110614d1f57fe5b906000526020600020906004020160030154604051614d3e9190618ed8565b60405180910390a2614dcf565b60018281548110614d5857fe5b60009182526020909120600160049092020181015481546001600160a01b03909116917f25d0ce7d2f0cec669a8c17efe49d195c13455bb8872b65fa610ac7f53fe4ca7d9185908110614da757fe5b906000526020600020906004020160030154604051614dc69190618ed8565b60405180910390a25b5050600101614c2e565b505b835115614fd15760005b8451811015614fcf578a8181518110614dfa57fe5b602002602001015160ff1660011415614e99576120026001600160a01b031663092193ab858381518110614e2a57fe5b6020026020010151878481518110614e3e57fe5b60200260200101516040518363ffffffff1660e01b8152600401614e6291906181eb565b6000604051808303818588803b158015614e7b57600080fd5b505af1158015614e8f573d6000803e3d6000fd5b5050505050614fc7565b6000858281518110614ea757fe5b60200260200101516001600160a01b03166108fc868481518110614ec757fe5b60200260200101519081150290604051600060405180830381858888f1935050505090508015614f5d57858281518110614efd57fe5b60200260200101516001600160a01b03167f6c61d60f69a7beb3e1c80db7f39f37b208537cbb19da3174511b477812b2fc7d868481518110614f3b57fe5b6020026020010151604051614f509190618ed8565b60405180910390a2614fc5565b858281518110614f6957fe5b60200260200101516001600160a01b03167f25d0ce7d2f0cec669a8c17efe49d195c13455bb8872b65fa610ac7f53fe4ca7d868481518110614fa757fe5b6020026020010151604051614fbc9190618ed8565b60405180910390a25b505b600101614de5565b505b5050505050505050505050505060005b60015481101561503e5760018181548110614ff857fe5b9060005260206000209060040201600301546000146150365760006001828154811061502057fe5b9060005260206000209060040201600301819055505b600101614fe1565b5047156150ac577f6ecc855f9440a9282c90913bbc91619fd44f5ec0b462af28d127b116f130aa4d476040516150749190618ed8565b60405180910390a1604051611002904780156108fc02916000818181858888f193505050501580156150aa573d6000803e3d6000fd5b505b600060038190556005558151156150c7576150c782826159fa565b6110016001600160a01b031663fc4333cd6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561510457600080fd5b505af1158015615118573d6000803e3d6000fd5b50506040517fedd8d7296956dd970ab4de3f2fc03be2b0ffc615d20cd4c72c6e44f928630ebf925060009150a1506000949350505050565b6000806001838154811061516057fe5b9060005260206000209060040201600301549050600060018080549050039050600161518a6130a3565b51116151bf5760006001858154811061519f57fe5b906000526020600020906004020160030181905550600092505050611dc5565b846001600160a01b03167f3b6f9ef90462b512a1293ecec018670bf7b7f1876fb727590a8a6d7643130a70836040516151f89190618ed8565b60405180910390a26001600160a01b038516600090815260046020526040812055835b600154600019018110156153e5576001816001018154811061523957fe5b90600052602060002090600402016001828154811061525457fe5b60009182526020909120825460049092020180546001600160a01b03199081166001600160a01b0393841617825560018085015481840180548416918616919091179055600280860180549185018054909416919095161780835584546001600160401b03600160a01b91829004160267ffffffffffffffff60a01b1990911617808355935460ff600160e01b918290041615150260ff60e01b19909416939093179055600392830154920191909155600b80549091830190811061531557fe5b9060005260206000209060160201600b828154811061533057fe5b600091825260209091208254601690920201908155600180830154818301805460ff909216151560ff1990921691909117905560028084018054615387938386019390821615610100026000190190911604617b7e565b5061539a60038281019084016013617bf3565b509050508060010160046000600184815481106153b357fe5b600091825260208083206004909202909101546001600160a01b0316835282019290925260400190205560010161521b565b5060018054806153f157fe5b60008281526020812060046000199093019283020180546001600160a01b0319908116825560018201805490911690556002810180546001600160e81b0319169055600301559055600b80548061544457fe5b60008281526020812060166000199093019283020181815560018101805460ff19169055906154766002830182617b1a565b615484600383016000617c1d565b50509055600081838161549357fe5b04905080156155075760015460005b81811015615504576154db83600183815481106154bb57fe5b90600052602060002090600402016003015461622b90919063ffffffff16565b600182815481106154e857fe5b60009182526020909120600360049092020101556001016154a2565b50505b50600195945050505050565b6060806000808080806155246131ad565b6001549091505b801561575357600181039250600b838154811061554457fe5b600091825260209091206001601690920201015460ff166155645761574a565b6001838154811061557157fe5b60009182526020909120600490910201546001600160a01b03169450615598858484613aac565b9350836155a45761574a565b60405163436aa28360e11b81526000908190612002906386d54506906155ce908a906004016181eb565b60206040518083038186803b1580156155e657600080fd5b505afa1580156155fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061561e9190617e5b565b90506001600160a01b038116156156a7576040516302ceee9160e11b81526120029063059ddd22906156549084906004016181eb565b60206040518083038186803b15801561566c57600080fd5b505afa158015615680573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906156a49190617e5b565b91505b60005b8c5181101561574657876001600160a01b03168d82815181106156c957fe5b6020026020010151600001516001600160a01b031614806157125750826001600160a01b03168d82815181106156fb57fe5b6020026020010151600001516001600160a01b0316145b1561573e5760018d828151811061572557fe5b6020908102919091010151901515608090910152615746565b6001016156aa565b5050505b6000190161552b565b5060005b89518110156157c05789818151811061576c57fe5b602002602001015160800151806157ac575060006001600160a01b03168a828151811061579557fe5b6020026020010151600001516001600160a01b0316145b156157b8578560010195505b600101615757565b50885185106158a85760408051600180825281830190925290816020015b6157e6617ae5565b8152602001906001900390816157de575050604080516001808252818301909252919850602082015b606081526020019060019003908161580f5790505095508860008151811061583357fe5b60200260200101518760008151811061584857fe5b60200260200101819052508760008151811061586057fe5b60200260200101518660008151811061587557fe5b602002602001018190525060008760008151811061588f57fe5b60209081029190910101519015156080909101526159ed565b848951036040519080825280602002602001820160405280156158e557816020015b6158d2617ae5565b8152602001906001900390816158ca5790505b5096508489510360405190808252806020026020018201604052801561591f57816020015b606081526020019060019003908161590a5790505b5095506000915060005b89518110156159eb5789818151811061593e57fe5b602002602001015160800151158015615981575060006001600160a01b03168a828151811061596957fe5b6020026020010151600001516001600160a01b031614155b156159e35789818151811061599257fe5b60200260200101518884815181106159a657fe5b60200260200101819052508881815181106159bd57fe5b60200260200101518784815181106159d157fe5b60200260200101819052508260010192505b600101615929565b505b50505050505b9250929050565b600154825160005b82811015615b17576001615a14617ae5565b60018381548110615a2157fe5b600091825260208083206040805160c08101825260049490940290910180546001600160a01b0390811685526001820154811693850193909352600281015492831691840191909152600160a01b82046001600160401b03166060840152600160e01b90910460ff16151560808301526003015460a082015291505b84811015615aeb57878181518110615ab157fe5b6020026020010151600001516001600160a01b031682600001516001600160a01b03161415615ae35760009250615aeb565b600101615a9d565b508115615b0d5780516001600160a01b03166000908152600460205260408120555b5050600101615a02565b5080821115615bd657805b82811015615bd4576001805480615b3557fe5b60008281526020812060046000199093019283020180546001600160a01b0319908116825560018201805490911690556002810180546001600160e81b0319169055600301559055600b805480615b8857fe5b60008281526020812060166000199093019283020181815560018101805460ff1916905590615bba6002830182617b1a565b615bc8600383016000617c1d565b50509055600101615b22565b505b6000818310615be55781615be7565b825b905060005b81811015615f8b57615c99868281518110615c0357fe5b602002602001015160018381548110615c1857fe5b60009182526020918290206040805160c08101825260049390930290910180546001600160a01b0390811684526001820154811694840194909452600281015493841691830191909152600160a01b83046001600160401b03166060830152600160e01b90920460ff161515608082015260039091015460a0820152617020565b615e4d578060010160046000888481518110615cb157fe5b6020026020010151600001516001600160a01b03166001600160a01b0316815260200190815260200160002081905550858181518110615ced57fe5b602002602001015160018281548110615d0257fe5b6000918252602091829020835160049092020180546001600160a01b039283166001600160a01b0319918216178255928401516001820180549184169185169190911790556040840151600282018054606087015160808801511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b1995909716929097169190911792909216939093171692909217905560a0909101516003909101558451859082908110615dbd57fe5b6020026020010151600b8281548110615dd257fe5b90600052602060002090601602016002019080519060200190615df6929190617a1a565b506000600b8281548110615e0657fe5b60009182526020822060169190910201600101805460ff191692151592909217909155600b805483908110615e3757fe5b6000918252602090912060169091020155615f83565b858181518110615e5957fe5b60200260200101516060015160018281548110615e7257fe5b906000526020600020906004020160020160146101000a8154816001600160401b0302191690836001600160401b03160217905550615f38858281518110615eb657fe5b6020026020010151600b8381548110615ecb57fe5b600091825260209182902060026016909202018101805460408051601f6000196101006001861615020190931694909404918201859004850284018501905280835291929091908301828280156134a65780601f1061347b576101008083540402835291602001916134a6565b615f8357848181518110615f4857fe5b6020026020010151600b8281548110615f5d57fe5b90600052602060002090601602016002019080519060200190615f81929190617a1a565b505b600101615bec565b508282111561616357615f9c6179eb565b835b8381101561616057858181518110615fb257fe5b602002602001015182604001819052506001878281518110615fd057fe5b6020908102919091018101518254600181810185556000948552838520835160049093020180546001600160a01b039384166001600160a01b0319918216178255848601518284018054918616918316919091179055604080860151600284018054606089015160808a01511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b1995909a1692909616919091179290921696909617169190911790935560a090930151600390930192909255600b8054928301815590935284516016909102600080516020618fe58339815191528101918255858301516000805160206196148339815191528201805491151560ff19909216919091179055928501518051869492936161069360008051602061900583398151915201920190617a1a565b50606082015161611c9060038301906013617a94565b505050806001016004600089848151811061613357fe5b602090810291909101810151516001600160a01b0316825281019190915260400160002055600101615f9e565b50505b61616b61707c565b616173617264565b6000600981905560015493505b838110156161e1576000600b828154811061619757fe5b60009182526020822060169190910201600101805460ff191692151592909217909155600b8054839081106161c857fe5b6000918252602090912060169091020155600101616180565b505050505050565b600061115e83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250617452565b60008282018381101561115e5760405162461bcd60e51b8152600401610e1290618613565b60015481516040805182815260208084028201019091526060929190839082801561628f57816020015b606081526020019060019003908161627a5790505b50600b5490915083146162a6579250611d15915050565b60005b828110156163b557600b6001600460008985815181106162c557fe5b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205403815481106162f957fe5b600091825260209182902060026016909202018101805460408051601f6000196101006001861615020190931694909404918201859004850284018501905280835291929091908301828280156163915780601f1061636657610100808354040283529160200191616391565b820191906000526020600020905b81548152906001019060200180831161637457829003601f168201915b50505050508282815181106163a257fe5b60209081029190910101526001016162a9565b50949350505050565b60005b8281101561650b57600082878388016040516020016163e19291906181dd565b6040516020818303038152906040528051906020012060001c8161640157fe5b06905080850182870114616502576000898388018151811061641f57fe5b602002602001015190506060898489018151811061643957fe5b602002602001015190508a8388018151811061645157fe5b60200260200101518b858a018151811061646757fe5b60200260200101906001600160a01b031690816001600160a01b031681525050818b8489018151811061649657fe5b60200260200101906001600160a01b031690816001600160a01b03168152505089838801815181106164c457fe5b60200260200101518a858a01815181106164da57fe5b6020026020010181905250808a848901815181106164f457fe5b602002602001018190525050505b506001016163c1565b5050505050505050565b600980546001908101909155600b80548390811061652f57fe5b906000526020600020906016020160010160006101000a81548160ff02191690831515021790555043600b828154811061656557fe5b600091825260208220601690910201919091556040516001600160a01b038416917ff62981a567ec3cec866c6fa93c55bcdf841d6292d18b8d522ececa769375d82d91a25050565b6000816040516020016165c091906181c1565b60405160208183030381529060405280519060200120836040516020016165e791906181c1565b6040516020818303038152906040528051906020012014905092915050565b015190565b8151815160009160019181148083146166275760009250616665565b600160208701838101602088015b6002848385100114156166605780518351146166545760009650600093505b60209283019201616635565b505050505b5090949350505050565b6001600160a01b0381166000908152600460205260408120548061669857506000199050611d15565b6001810390506000600182815481106166ad57fe5b90600052602060002090600402016003015490506000600183815481106166d057fe5b6000918252602090912060036004909202010155600154604051600019909101906001600160a01b038616907f8cd4e147d8af98a9e3b6724021b8bf6aed2e5dac71c38f2dce8161b82585b25d90616729908590618ed8565b60405180910390a28061674157829350505050611d15565b600081838161674c57fe5b04905080156167e85760005b8481101561679a5761677182600183815481106154bb57fe5b6001828154811061677e57fe5b6000918252602090912060036004909202010155600101616758565b50600180549085015b818110156167e5576167bc83600183815481106154bb57fe5b600182815481106167c957fe5b60009182526020909120600360049092020101556001016167a3565b50505b5091949350505050565b60008261680157506000611dc5565b8282028284828161680e57fe5b041461115e5760405162461bcd60e51b8152600401610e12906189e2565b600061115e83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061747e565b616876617c2c565b506040805180820190915281518152602082810190820152919050565b61689b617b5e565b6168a4826174b5565b6168ad57600080fd5b60006168bc83602001516174ef565b60208085015160408051808201909152868152920190820152915050919050565b60006168e7617c2c565b505080518051602091820151919092015191011190565b616906617c2c565b61690f826168dd565b61691857600080fd5b6020820151600061692882617552565b80830160209586015260408051808201909152908152938401919091525090919050565b80516000901580159061696157508151602110155b61696a57600080fd5b600061697983602001516174ef565b9050808360000151101561699f5760405162461bcd60e51b8152600401610e1290618bf0565b8251602080850151830180519284900392918310156163b557506020919091036101000a90049392505050565b60606169d7826174b5565b6169e057600080fd5b60006169eb83617633565b9050606081604051908082528060200260200182016040528015616a2957816020015b616a16617c2c565b815260200190600190039081616a0e5790505b5090506000616a3b85602001516174ef565b60208601510190506000805b84811015616a9257616a5883617552565b9150604051806040016040528083815260200184815250848281518110616a7b57fe5b602090810291909101015291810191600101616a47565b509195945050505050565b616aa5617ae5565b60606000616ab1617ae5565b6060616abb617b5e565b616ac487616893565b90506000805b616ad3836168dd565b15616ba85780616afe57616aee616ae9846168fe565b61768f565b6001600160a01b03168552616ba0565b8060011415616b2657616b13616ae9846168fe565b6001600160a01b03166020860152616ba0565b8060021415616b4e57616b3b616ae9846168fe565b6001600160a01b03166040860152616ba0565b8060031415616b7a57616b63613dc1846168fe565b6001600160401b0316606086015260019150616ba0565b8060041415616b9b57616b94616b8f846168fe565b6176a9565b9350616ba0565b616ba8565b600101616aca565b50929791965091945092505050565b6060611dc5616bc583617719565b6177ff565b6060815160001415616beb5750604080516000815260208101909152611d15565b606082600081518110616bfa57fe5b602002602001015190506000600190505b8351811015616c3b57616c3182858381518110616c2457fe5b6020026020010151617851565b9150600101616c0b565b5061115e616c4e825160c060ff166178ce565b82617851565b60608060006120026001600160a01b031663c473318f6040518163ffffffff1660e01b815260040160206040518083038186803b158015616c9457600080fd5b505afa158015616ca8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190616ccc9190618096565b90508085518851011015616ce1575083518651015b606081604051908082528060200260200182016040528015616d1d57816020015b616d0a617ae5565b815260200190600190039081616d025790505b509050606082604051908082528060200260200182016040528015616d5657816020015b6060815260200190600190039081616d415790505b50905060008060005b8b51831080616d6e5750895182105b8015616d7957508581105b1561700e578b51831415616de957898281518110616d9357fe5b6020026020010151858281518110616da757fe5b6020026020010181905250888281518110616dbe57fe5b6020026020010151848281518110616dd257fe5b602090810291909101015260019182019101616d5f565b8951821415616e54578b8381518110616dfe57fe5b6020026020010151858281518110616e1257fe5b60200260200101819052508a8381518110616e2957fe5b6020026020010151848281518110616e3d57fe5b602090810291909101015260019283019201616d5f565b898281518110616e6057fe5b6020026020010151606001516001600160401b03168c8481518110616e8157fe5b6020026020010151606001516001600160401b03161115616efd578b8381518110616ea857fe5b6020026020010151858281518110616ebc57fe5b60200260200101819052508a8381518110616ed357fe5b6020026020010151848281518110616ee757fe5b6020026020010181905250826001019250617006565b898281518110616f0957fe5b6020026020010151606001516001600160401b03168c8481518110616f2a57fe5b6020026020010151606001516001600160401b03161015616fa657898281518110616f5157fe5b6020026020010151858281518110616f6557fe5b6020026020010181905250888281518110616f7c57fe5b6020026020010151848281518110616f9057fe5b6020026020010181905250816001019150617006565b898281518110616fb257fe5b6020026020010151600001516001600160a01b03168c8481518110616fd357fe5b6020026020010151600001516001600160a01b03161015616ffa578b8381518110616ea857fe5b898281518110616d9357fe5b600101616d5f565b50929a91995090975050505050505050565b805182516000916001600160a01b03918216911614801561705a575081602001516001600160a01b031683602001516001600160a01b0316145b801561115e5750506040908101519101516001600160a01b0390811691161490565b601254601354808211156170c757805b828110156170c557601280548061709f57fe5b6001900381819060005260206000200160006170bb9190617b1a565b905560010161708c565b505b60008183106170d657816170d8565b825b905060005b818110156171f057617195601282815481106170f557fe5b600091825260209182902001805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152928301828280156171835780601f1061715857610100808354040283529160200191617183565b820191906000526020600020905b81548152906001019060200180831161716657829003601f168201915b50505050506013838154811061341857fe5b6171e857601381815481106171a657fe5b90600052602060002001601282815481106171bd57fe5b9060005260206000200190805460018160011615610100020316600290046171e6929190617b7e565b505b6001016170dd565b5082821115610e3257825b8281101561725e5760126013828154811061721257fe5b6000918252602080832084546001818101875595855291909320929091018054617255949390920192909160026101009282161592909202600019011604617b7e565b506001016171fb565b50505050565b601354600b54808211156172af57805b828110156172ad57601380548061728757fe5b6001900381819060005260206000200160006172a39190617b1a565b9055600101617274565b505b60008183106172be57816172c0565b825b905060005b818110156173df5761737d601382815481106172dd57fe5b600091825260209182902001805460408051601f600260001961010060018716150201909416939093049283018590048502810185019091528181529283018282801561736b5780601f106173405761010080835404028352916020019161736b565b820191906000526020600020905b81548152906001019060200180831161734e57829003601f168201915b5050505050600b8381548110615ecb57fe5b6173d757600b818154811061738e57fe5b9060005260206000209060160201600201601382815481106173ac57fe5b9060005260206000200190805460018160011615610100020316600290046173d5929190617b7e565b505b6001016172c5565b5082821115610e3257825b8281101561725e576013600b828154811061740157fe5b60009182526020808320845460018082018755958552919093206016929092029092016002908101805461744995939094019390926000199082161561010002011604617b7e565b506001016173ea565b600081848411156174765760405162461bcd60e51b8152600401610e12919061837e565b505050900390565b6000818361749f5760405162461bcd60e51b8152600401610e12919061837e565b5060008385816174ab57fe5b0495945050505050565b80516000906174c657506000611d15565b6020820151805160001a9060c08210156174e557600092505050611d15565b5060019392505050565b8051600090811a6080811015617509576000915050611d15565b60b8811080617524575060c08110801590617524575060f881105b15617533576001915050611d15565b60c08110156175475760b519019050611d15565b60f519019050611d15565b80516000908190811a608081101561756d576001915061762c565b60b881101561758257607e198101915061762c565b60c08110156175d357600060b78203600186019550806020036101000a8651049150600181018201935050808310156175cd5760405162461bcd60e51b8152600401610e129061892f565b5061762c565b60f88110156175e85760be198101915061762c565b600060f78203600186019550806020036101000a86510491506001810182019350508083101561762a5760405162461bcd60e51b8152600401610e129061892f565b505b5092915050565b805160009061764457506000611d15565b6000809050600061765884602001516174ef565b602085015185519181019250015b808210156176865761767782617552565b82019150826001019250617666565b50909392505050565b80516000906015146176a057600080fd5b611dc58261694c565b80516060906176b757600080fd5b60006176c683602001516174ef565b83516040805191839003808352601f19601f82011683016020019091529192506060908280156176fd576020820181803683370190505b50905060008160200190506163b58487602001510182856179a0565b604080516020808252818301909252606091829190602082018180368337505050602081018490529050600067ffffffffffffffff19841661775d57506018617781565b6fffffffffffffffffffffffffffffffff19841661777d57506010617781565b5060005b60208110156177b75781818151811061779657fe5b01602001516001600160f81b031916156177af576177b7565b600101617781565b60008160200390506060816040519080825280601f01601f1916602001820160405280156177ec576020820181803683370190505b5080830196909652508452509192915050565b6060815160011480156178315750607f60f81b8260008151811061781f57fe5b01602001516001600160f81b03191611155b1561783d575080611d15565b611dc561784f8351608060ff166178ce565b835b6060806040519050835180825260208201818101602087015b8183101561788257805183526020928301920161786a565b50855184518101855292509050808201602086015b818310156178af578051835260209283019201617897565b508651929092011591909101601f01601f191660405250905092915050565b60606801000000000000000083106178f85760405162461bcd60e51b8152600401610e129061877a565b604080516001808252818301909252606091602082018180368337019050509050603784116179525782840160f81b8160008151811061793457fe5b60200101906001600160f81b031916908160001a9053509050611dc5565b606061795d85617719565b90508381510160370160f81b8260008151811061797657fe5b60200101906001600160f81b031916908160001a9053506179978282617851565b95945050505050565b806179aa57610e32565b5b602081106179ca578251825260209283019290910190601f19016179ab565b915181516020939093036101000a6000190180199091169216919091179052565b60405180608001604052806000815260200160001515815260200160608152602001617a15617c46565b905290565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10617a5b57805160ff1916838001178555617a88565b82800160010185558215617a88579182015b82811115617a88578251825591602001919060010190617a6d565b506131e8929150617c65565b8260138101928215617a885791602002820182811115617a88578251825591602001919060010190617a6d565b6040518060600160405280600060ff16815260200160608152602001606081525090565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b50805460018160011615610100020316600290046000825580601f10617b405750611f2d565b601f016020900490600052602060002090810190611f2d9190617c65565b6040518060400160405280617b71617c2c565b8152602001600081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10617bb75780548555617a88565b82800160010185558215617a8857600052602060002091601f016020900482015b82811115617a88578254825591600101919060010190617bd8565b8260138101928215617a885791820182811115617a88578254825591600101919060010190617bd8565b50611f2d906013810190617c65565b604051806040016040528060008152602001600081525090565b6040518061026001604052806013906020820280368337509192915050565b61318c91905b808211156131e85760008155600101617c6b565b8035611dc581618faf565b60008083601f840112617c9b578182fd5b5081356001600160401b03811115617cb1578182fd5b60208301915083602080830285010111156159f357600080fd5b6000601f8381840112617cdc578182fd5b8235617cef617cea82618f64565b618f3e565b818152925060208084019085810160005b84811015617d81578135880189603f820112617d1b57600080fd5b838101356001600160401b03811115617d3357600080fd5b617d44818901601f19168601618f3e565b81815260408c81848601011115617d5a57600080fd5b82818501888401375060009181018601919091528552509282019290820190600101617d00565b50505050505092915050565b600082601f830112617d9d578081fd5b8135617dab617cea82618f64565b818152915060208083019084810181840286018201871015617dcc57600080fd5b6000805b85811015617d815782356001600160401b0381168114617dee578283fd5b85529383019391830191600101617dd0565b60008083601f840112617e11578182fd5b5081356001600160401b03811115617e27578182fd5b6020830191508360208285010111156159f357600080fd5b600060208284031215617e50578081fd5b813561115e81618faf565b600060208284031215617e6c578081fd5b815161115e81618faf565b60008060008060408587031215617e8c578283fd5b84356001600160401b0380821115617ea2578485fd5b617eae88838901617c8a565b90965094506020870135915080821115617ec6578384fd5b50617ed387828801617c8a565b95989497509550505050565b600080600060608486031215617ef3578283fd5b83356001600160401b0380821115617f09578485fd5b81860187601f820112617f1a578586fd5b80359250617f2a617cea84618f64565b80848252602080830192508084018b828389028701011115617f4a57898afd5b8994505b86851015617f7457617f608c82617c7f565b845260019490940193928101928101617f4e565b509097508801359350505080821115617f8b578384fd5b617f9787838801617d8d565b93506040860135915080821115617fac578283fd5b50617fb986828701617ccb565b9150509250925092565b600060208284031215617fd4578081fd5b8151801515811461115e578182fd5b60008060208385031215617ff5578182fd5b82356001600160401b0381111561800a578283fd5b61801685828601617e00565b90969095509350505050565b60008060008060408587031215618037578384fd5b84356001600160401b038082111561804d578586fd5b61805988838901617e00565b90965094506020870135915080821115618071578384fd5b50617ed387828801617e00565b60006020828403121561808f578081fd5b5035919050565b6000602082840312156180a7578081fd5b5051919050565b600080604083850312156180c0578182fd5b505080516020909101519092909150565b6000806000604084860312156180e5578081fd5b833560ff811681146180f5578182fd5b925060208401356001600160401b0381111561810f578182fd5b61811b86828701617e00565b9497909650939450505050565b6000815180845260208085019450808401835b838110156181605781516001600160a01b03168752958201959082019060010161813b565b509495945050505050565b60008284528282602086013780602084860101526020601f19601f85011685010190509392505050565b600081518084526181ad816020860160208601618f83565b601f01601f19169290920160200192915050565b600082516181d3818460208701618f83565b9190910192915050565b918252602082015260400190565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b03968716815294861660208601529290941660408401526001600160401b03166060830152911515608082015260a081019190915260c00190565b6001600160a01b0392909216825260ff16602082015260400190565b60006020825261115e6020830184618128565b60006040825261829c6040830185618128565b602083820381850152818551808452828401915082838202850101838801865b838110156182ea57601f198784030185526182d8838351618195565b948601949250908501906001016182bc565b50909998505050505050505050565b60006080825261830c6080830187618128565b828103602084810191909152865180835287820192820190845b8181101561834257845183529383019391830191600101618326565b505084810360408601526183568188618128565b93505050506001600160401b038316606083015295945050505050565b901515815260200190565b60006020825261115e6020830184618195565b6000604082526183a560408301868861816b565b82810360208401526183b881858761816b565b979650505050505050565b6020808252601c908201527f6c656e677468206f66206275726e526174696f206d69736d6174636800000000604082015260600190565b60208082526042908201527f746865206275726e526174696f20706c75732073797374656d5265776172645260408201527f6174696f206d757374206265206e6f2067726561746572207468616e20313030606082015261030360f41b608082015260a00190565b60208082526026908201527f6c656e677468206f66206d61784e756d4f664d61696e7461696e696e67206d696040820152650e6dac2e8c6d60d31b606082015260800190565b6020808252601b908201527f6261746368207472616e736665722072657475726e2066616c73650000000000604082015260600190565b6020808252602c908201527f6c656e677468206f66206d61784e756d4f66576f726b696e6743616e6469646160408201526b0e8cae640dad2e6dac2e8c6d60a31b606082015260800190565b60208082526025908201527f6c656e677468206f66206d61696e7461696e536c6173685363616c65206d69736040820152640dac2e8c6d60db1b606082015260800190565b6020808252818101527f6c656e677468206f66206e756d4f66436162696e657473206d69736d61746368604082015260600190565b60208082526019908201527f74686520636f6e7472616374206e6f7420696e69742079657400000000000000604082015260600190565b6020808252601f908201527f6f6e6c7920736c617368206f72207374616b6548756220636f6e747261637400604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b60208082526028908201527f746865206e756d4f66436162696e657473206d75737420626520677265617465604082015267072207468616e20360c41b606082015260800190565b60208082526039908201527f746865206e756d4f66436162696e657473206d757374206265206c657373207460408201527f68616e204d41585f4e554d5f4f465f56414c494441544f525300000000000000606082015260800190565b60208082526029908201527f746865206e756d626572206f662076616c696461746f727320657863656564206040820152681d1a19481b1a5b5a5d60ba1b606082015260800190565b60208082526022908201527f63616e206e6f7420646f207468697320747769636520696e206f6e6520626c6f604082015261636b60f01b606082015260800190565b6020808252600e908201526d696e70757420746f6f206c6f6e6760901b604082015260600190565b60208082526037908201527f746865206d61784e756d4f664d61696e7461696e696e67206d7573742062652060408201527f6c657373207468616e206e756d4f66436162696e657473000000000000000000606082015260800190565b6020808252602b908201527f6475706c696361746520636f6e73656e7375732061646472657373206f66207660408201526a185b1a59185d1bdc94d95d60aa1b606082015260800190565b60208082526027908201527f7468652065787069726554696d655365636f6e64476170206973206f7574206f604082015266662072616e676560c81b606082015260800190565b6020808252601590820152746465706f7369742076616c7565206973207a65726f60581b604082015260600190565b60208082526049908201527f746865206d61784e756d4f66576f726b696e6743616e64696461746573206d7560408201527f7374206265206e6f742067726561746572207468616e206d61784e756d4f6643606082015268616e6469646174657360b81b608082015260a00190565b6020808252601190820152706164646974696f6e206f766572666c6f7760781b604082015260600190565b60208082526023908201527f63616e206e6f7420656e7465722054656d706f72617279204d61696e74656e616040820152626e636560e81b606082015260800190565b60208082526025908201527f6c656e677468206f66206a61696c2076616c696461746f7273206d757374206260408201526465206f6e6560d81b606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252601490820152736761737072696365206973206e6f74207a65726f60601b604082015260600190565b6020808252602e908201527f746865206d6573736167652073656e646572206d75737420626520676f76657260408201526d1b985b98d94818dbdb9d1c9858dd60921b606082015260800190565b60208082526025908201527f6c656e677468206f66206d61784e756d4f6643616e64696461746573206d69736040820152640dac2e8c6d60db1b606082015260800190565b6020808252601290820152716e6f7420696e206d61696e74656e616e636560701b604082015260600190565b60208082526021908201527f666565206973206c6172676572207468616e2044555354595f494e434f4d494e6040820152604760f81b606082015260800190565b60208082526019908201527f74686520636f6e747261637420616c726561647920696e697400000000000000604082015260600190565b60208082526042908201527f7468652073797374656d526577617264526174696f20706c7573206275726e5260408201527f6174696f206d757374206265206e6f2067726561746572207468616e20313030606082015261030360f41b608082015260a00190565b6020808252601a908201527f6c656e677468206973206c657373207468616e206f6666736574000000000000604082015260600190565b60208082526026908201527f6c656e677468206f662065787069726554696d655365636f6e64476170206d696040820152650e6dac2e8c6d60d31b606082015260800190565b60208082526017908201527f6f6e6c792063757272656e742076616c696461746f7273000000000000000000604082015260600190565b60208082526021908201527f6661696c656420746f20706172736520696e69742076616c696461746f7253656040820152601d60fa1b606082015260800190565b6020808252602f908201527f746865206d6573736167652073656e646572206d7573742062652063726f737360408201526e0818da185a5b8818dbdb9d1c9858dd608a1b606082015260800190565b6020808252602d908201527f746865206d6573736167652073656e646572206d75737420626520746865206260408201526c3637b1b590383937b23ab1b2b960991b606082015260800190565b60208082526024908201527f6c656e677468206f662073797374656d526577617264526174696f206d69736d6040820152630c2e8c6d60e31b606082015260800190565b6020808252603e908201527f746865206d61696e7461696e536c6173685363616c65206d757374206265206760408201527f726561746572207468616e203020616e64206c657373207468616e2031300000606082015260800190565b6020808252600d908201526c756e6b6e6f776e20706172616d60981b604082015260600190565b60208082526029908201527f746865206d6573736167652073656e646572206d75737420626520736c6173686040820152680818dbdb9d1c9858dd60ba1b606082015260800190565b6020808252601f908201527f746865206d73672073656e646572206d757374206265207374616b6548756200604082015260600190565b61ffff91909116815260200190565b90815260200190565b60008482528315156020830152606060408301526179976060830184618195565b63ffffffff91909116815260200190565b60ff91909116815260200190565b600060ff851682526040602083015261799760408301848661816b565b6040518181016001600160401b0381118282101715618f5c57600080fd5b604052919050565b60006001600160401b03821115618f79578081fd5b5060209081020190565b60005b83811015618f9e578181015183820152602001618f86565b8381111561725e5750506000910152565b6001600160a01b0381168114611f2d57600080fdfe70e72399380dcfb0338abc03dc8d47f9f470ada8e769c9a78d644ea97385ecb20175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dbbf905ec80f905e8f846942a7cdd959bfe8d9487b2a43b33565295a698f7e294b6a7edd747c0554875d3fc531d19ba1497992c5e941ff80f3f7f110ffd8920a3ac38fdef318fe94a3f86048c27395000f846946488aa4d1955ee33403f8ccb1d4de5fb97c7ade294220f003d8bdfaadf52aa1e55ae4cc485e6794875941a87e90e440a39c99aa9cb5cea0ad6a3f0b2407b86048c27395000f846949ef9f4360c606c7ab4db26b016007d3ad0ab86a0946103af86a874b705854033438383c82575f25bc29418e2db06cbff3e3c5f856410a1838649e760175786048c27395000f84694ee01c3b1283aa067c58eab4709f85e99d46de5fe94ee4b9bfb1871c64e2bcabb1dc382dc8b7c4218a29415904ab26ab0e99d70b51c220ccdcccabee6e29786048c27395000f84694685b1ded8013785d6623cc18d214320b6bb6475994a20ef4e5e4e7e36258dbf51f4d905114cb1b34bc9413e39085dc88704f4394d35209a02b1a9520320c86048c27395000f8469478f3adfc719c99674c072166708589033e2d9afe9448a30d5eaa7b64492a160f139e2da2800ec3834e94055838358c29edf4dcc1ba1985ad58aedbb6be2b86048c27395000f84694c2be4ec20253b8642161bc3f444f53679c1f3d479466f50c616d737e60d7ca6311ff0d9c434197898a94d1d678a2506eeaa365056fe565df8bc8659f28b086048c27395000f846942f7be8361c80a4c1e7e9aaf001d0877f1cfde218945f93992ac37f3e61db2ef8a587a436a161fd210b94ecbc4fb1a97861344dad0867ca3cba2b860411f086048c27395000f84694ce2fd7544e0b2cc94692d4a704debef7bcb613289444abc67b4b2fba283c582387f54c9cba7c34bafa948acc2ab395ded08bb75ce85bf0f95ad2abc51ad586048c27395000f84694b8f7166496996a7da21cf1f1b04d9b3e26a3d077946770572763289aac606e4f327c2f6cc1aa3b3e3b94882d745ed97d4422ca8da1c22ec49d880c4c097286048c27395000f846942d4c407bbe49438ed859fe965b140dcf1aab71a9943ad0939e120f33518fbba04631afe7a3ed6327b194b2bbb170ca4e499a2b0f3cc85ebfa6e8c4dfcbea86048c27395000f846946bbad7cf34b5fa511d8e963dbba288b1960e75d694853b0f6c324d1f4e76c8266942337ac1b0af1a229442498946a51ca5924552ead6fc2af08b94fcba648601d1a94a2000f846944430b3230294d12c6ab2aac5c2cd68e80b16b581947b107f4976a252a6939b771202c28e64e03f52d694795811a7f214084116949fc4f53cedbf189eeab28601d1a94a2000f84694ea0a6e3c511bbd10f4519ece37dc24887e11b55d946811ca77acfb221a49393c193f3a22db829fcc8e9464feb7c04830dd9ace164fc5c52b3f5a29e5018a8601d1a94a2000f846947ae2f5b9e386cd1b50a4550696d957cb4900f03a94e83bcc5077e6b873995c24bac871b5ad856047e19464e48d4057a90b233e026c1041e6012ada897fe88601d1a94a2000f8469482012708dafc9e1b880fd083b32182b869be8e09948e5adc73a2d233a1b496ed3115464dd6c7b887509428b383d324bc9a37f4e276190796ba5a8947f5ed8601d1a94a2000f8469422b81f8e175ffde54d797fe11eb03f9e3bf75f1d94a1c3ef7ca38d8ba80cce3bfc53ebd2903ed21658942767f7447f7b9b70313d4147b795414aecea54718601d1a94a2000f8469468bf0b8b6fb4e317a0f9d6f03eaf8ce6675bc60d94675cfe570b7902623f47e7f59c9664b5f5065dcf94d84f0d2e50bcf00f2fc476e1c57f5ca2d57f625b8601d1a94a2000f846948c4d90829ce8f72d0163c1d5cf348a862d5506309485c42a7b34309bee2ed6a235f86d16f059deec5894cc2cedc53f0fa6d376336efb67e43d167169f3b78601d1a94a2000f8469435e7a025f4da968de7e4d7e4004197917f4070f194b1182abaeeb3b4d8eba7e6a4162eac7ace23d57394c4fd0d870da52e73de2dd8ded19fe3d26f43a1138601d1a94a2000f84694d6caa02bbebaebb5d7e581e4b66559e635f805ff94c07335cf083c1c46a487f0325769d88e163b653694efaff03b42e41f953a925fc43720e45fb61a19938601d1a94a20000175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dbaa164736f6c6343000604000a

Block Transaction Gas Used Reward
view all blocks produced
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
View All Validatorset

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Chain Token Portfolio % Price Amount Value
BSC
BNB Chain (BNB)
94.77%$696.36259.2728$180,548.24
BSC1.90%$0.000007543,696,662.5298$3,617.11
BSC1.47%$0.0003168,836,000$2,791.36
BSC0.59%$0.9979561,118.2861$1,116
BSC0.48%<$0.0000013,000,002,004.6432$917.7
BSC0.13%$0.02563310,000$256.33
BSC0.06%$1.1699.5$115.58
BSC0.05%$0.86932113.0589$98.28
BSC0.01%<$0.000001200,000,000$26.68
BSC<0.01%<$0.0000014,772,629,056.1795$11.93
BSC<0.01%$0.0007512,700$9.53
BSC<0.01%<$0.000001296,137,155,953,485,630$9.48
BSC<0.01%$0.50010410$5
BSC<0.01%$0.38344611.2975$4.33
BSC<0.01%$3.631$3.63
BSC<0.01%$0.0019821,800.003$3.57
BSC<0.01%$0.00031110,154.4234$3.16
BSC<0.01%$11.927$1.93
BSC<0.01%<$0.00000112,154,909,481.4719$1.22
BSC<0.01%$2.070.441$0.9137
BSC<0.01%$0.1903824$0.7615
BSC<0.01%$0.7881090.8$0.6304
BSC<0.01%$50.107$0.5344
BSC<0.01%$0.5565060.833$0.4635
BSC<0.01%$0.447980.615$0.2755
BSC<0.01%$0.1384271.8356$0.254
BSC<0.01%$0.2455871$0.2455
BSC<0.01%<$0.00000137,132,404.5886$0.2408
BSC<0.01%<$0.000001355,028,038,988.7721$0.2239
BSC<0.01%$0.1515230.75$0.1136
ETH0.50%$0.997956950$948.06
ETH<0.01%$3,407.220.00236071$8.04
OP<0.01%$3,407.690.001$3.41
BASE<0.01%$3,407.720.00071627$2.44
OPBNB<0.01%$696.390.000002$0.001393
ARB<0.01%$3,407.730.0000003$0.001022
LINEA<0.01%$3,408.350.0000002$0.000682
[ Download: CSV Export  ]
[ Download: CSV Export  ]

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