BNB Price: $616.27 (-3.04%)
 

Overview

BNB Balance

BNB Smart Chain LogoBNB Smart Chain LogoBNB Smart Chain Logo51.105805341425047302 BNB

BNB Value

$31,494.85 (@ $616.27/BNB)

Token Holdings

More Info

Private Name Tags

ContractCreator

N/A (Genesis Contract)

Multichain Info

Transaction Hash
Block
From
To
Deposit814918232026-02-16 4:43:563 secs ago1771217036IN
BSC: Validator Set
0.0005342 BNB00
Deposit814918222026-02-16 4:43:563 secs ago1771217036IN
BSC: Validator Set
0.00122771 BNB00
Deposit814918212026-02-16 4:43:554 secs ago1771217035IN
BSC: Validator Set
0.00076087 BNB00
Deposit814918202026-02-16 4:43:554 secs ago1771217035IN
BSC: Validator Set
0.00168159 BNB00
Deposit814918192026-02-16 4:43:554 secs ago1771217035IN
BSC: Validator Set
0.00070536 BNB00
Deposit814918182026-02-16 4:43:545 secs ago1771217034IN
BSC: Validator Set
0.00163514 BNB00
Deposit814918172026-02-16 4:43:545 secs ago1771217034IN
BSC: Validator Set
0.00053135 BNB00
Deposit814918162026-02-16 4:43:536 secs ago1771217033IN
BSC: Validator Set
0.00048777 BNB00
Deposit814918152026-02-16 4:43:536 secs ago1771217033IN
BSC: Validator Set
0.00066123 BNB00
Deposit814918142026-02-16 4:43:527 secs ago1771217032IN
BSC: Validator Set
0.00229852 BNB00
Deposit814918132026-02-16 4:43:527 secs ago1771217032IN
BSC: Validator Set
0.00105989 BNB00
Deposit814918122026-02-16 4:43:518 secs ago1771217031IN
BSC: Validator Set
0.00109656 BNB00
Deposit814918112026-02-16 4:43:518 secs ago1771217031IN
BSC: Validator Set
0.00066406 BNB00
Deposit814918102026-02-16 4:43:518 secs ago1771217031IN
BSC: Validator Set
0.00114093 BNB00
Deposit814918092026-02-16 4:43:509 secs ago1771217030IN
BSC: Validator Set
0.00156753 BNB00
Deposit814918082026-02-16 4:43:509 secs ago1771217030IN
BSC: Validator Set
0.00124657 BNB00
Deposit814918072026-02-16 4:43:4910 secs ago1771217029IN
BSC: Validator Set
0.00115711 BNB00
Deposit814918062026-02-16 4:43:4910 secs ago1771217029IN
BSC: Validator Set
0.0006004 BNB00
Deposit814918052026-02-16 4:43:4811 secs ago1771217028IN
BSC: Validator Set
0.00152275 BNB00
Deposit814918042026-02-16 4:43:4811 secs ago1771217028IN
BSC: Validator Set
0.00096706 BNB00
Deposit814918032026-02-16 4:43:4712 secs ago1771217027IN
BSC: Validator Set
0.00056052 BNB00
Deposit814918022026-02-16 4:43:4712 secs ago1771217027IN
BSC: Validator Set
0.00073703 BNB00
Deposit814918012026-02-16 4:43:4613 secs ago1771217026IN
BSC: Validator Set
0.00057913 BNB00
Distribute Final...814918002026-02-16 4:43:4613 secs ago1771217026IN
BSC: Validator Set
0 BNB00
Deposit814918002026-02-16 4:43:4613 secs ago1771217026IN
BSC: Validator Set
0.00310673 BNB00
View all transactions

Latest 25 internal transactions (View All)

Parent Transaction Hash Block From To
814918212026-02-16 4:43:554 secs ago1771217035
BSC: Validator Set
0.00007608 BNB
814918212026-02-16 4:43:554 secs ago1771217035
BSC: Validator Set
0.00004755 BNB
814918202026-02-16 4:43:554 secs ago1771217035
BSC: Validator Set
0.00016815 BNB
814918202026-02-16 4:43:554 secs ago1771217035
BSC: Validator Set
0.00010509 BNB
814918192026-02-16 4:43:554 secs ago1771217035
BSC: Validator Set
0.00007053 BNB
814918192026-02-16 4:43:554 secs ago1771217035
BSC: Validator Set
0.00004408 BNB
814918182026-02-16 4:43:545 secs ago1771217034
BSC: Validator Set
0.00016351 BNB
814918182026-02-16 4:43:545 secs ago1771217034
BSC: Validator Set
0.00010219 BNB
814918172026-02-16 4:43:545 secs ago1771217034
BSC: Validator Set
0.00005313 BNB
814918172026-02-16 4:43:545 secs ago1771217034
BSC: Validator Set
0.0000332 BNB
814918162026-02-16 4:43:536 secs ago1771217033
BSC: Validator Set
0.00004877 BNB
814918162026-02-16 4:43:536 secs ago1771217033
BSC: Validator Set
0.00003048 BNB
814918152026-02-16 4:43:536 secs ago1771217033
BSC: Validator Set
0.00006612 BNB
814918152026-02-16 4:43:536 secs ago1771217033
BSC: Validator Set
0.00004132 BNB
814918142026-02-16 4:43:527 secs ago1771217032
BSC: Validator Set
0.00022985 BNB
814918142026-02-16 4:43:527 secs ago1771217032
BSC: Validator Set
0.00014365 BNB
814918132026-02-16 4:43:527 secs ago1771217032
BSC: Validator Set
0.00010598 BNB
814918132026-02-16 4:43:527 secs ago1771217032
BSC: Validator Set
0.00006624 BNB
814918122026-02-16 4:43:518 secs ago1771217031
BSC: Validator Set
0.00010965 BNB
814918122026-02-16 4:43:518 secs ago1771217031
BSC: Validator Set
0.00006853 BNB
814918112026-02-16 4:43:518 secs ago1771217031
BSC: Validator Set
0.0000664 BNB
814918112026-02-16 4:43:518 secs ago1771217031
BSC: Validator Set
0.0000415 BNB
814918102026-02-16 4:43:518 secs ago1771217031
BSC: Validator Set
0.00011409 BNB
814918102026-02-16 4:43:518 secs ago1771217031
BSC: Validator Set
0.0000713 BNB
814918092026-02-16 4:43:509 secs ago1771217030
BSC: Validator Set
0.00015675 BNB
View All Internal Transactions
Cross-Chain 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, Apache-2.0 license
/**
 *Submitted for verification at BscScan.com on 2020-09-02
*/

pragma solidity =0.6.4;
pragma experimental ABIEncoderV2;

// contracts/lib/0.6.x/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/0.6.x/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/interface/0.6.x/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/0.6.x/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/0.6.x/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/0.6.x/IParamSubscriber.sol

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

// contracts/interface/0.6.x/IRelayerHub.sol

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

// contracts/interface/0.6.x/ISlashIndicator.sol

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

// contracts/interface/0.6.x/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/0.6.x/ISystemReward.sol

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

// contracts/lib/0.6.x/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/0.6.x/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)

            // shift to the correct location if necessary
            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/0.6.x/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/System.sol

contract System {
    bool public alreadyInit;

    uint32 public constant CODE_OK = 0;
    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

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

    using RLPDecode for *;

    bytes public constant INIT_VALIDATORSET_BYTES =
        hex"f905ec80f905e8f846942a7cdd959bfe8d9487b2a43b33565295a698f7e294b6a7edd747c0554875d3fc531d19ba1497992c5e941ff80f3f7f110ffd8920a3ac38fdef318fe94a3f86048c27395000f846946488aa4d1955ee33403f8ccb1d4de5fb97c7ade294220f003d8bdfaadf52aa1e55ae4cc485e6794875941a87e90e440a39c99aa9cb5cea0ad6a3f0b2407b86048c27395000f846949ef9f4360c606c7ab4db26b016007d3ad0ab86a0946103af86a874b705854033438383c82575f25bc29418e2db06cbff3e3c5f856410a1838649e760175786048c27395000f84694ee01c3b1283aa067c58eab4709f85e99d46de5fe94ee4b9bfb1871c64e2bcabb1dc382dc8b7c4218a29415904ab26ab0e99d70b51c220ccdcccabee6e29786048c27395000f84694685b1ded8013785d6623cc18d214320b6bb6475994a20ef4e5e4e7e36258dbf51f4d905114cb1b34bc9413e39085dc88704f4394d35209a02b1a9520320c86048c27395000f8469478f3adfc719c99674c072166708589033e2d9afe9448a30d5eaa7b64492a160f139e2da2800ec3834e94055838358c29edf4dcc1ba1985ad58aedbb6be2b86048c27395000f84694c2be4ec20253b8642161bc3f444f53679c1f3d479466f50c616d737e60d7ca6311ff0d9c434197898a94d1d678a2506eeaa365056fe565df8bc8659f28b086048c27395000f846942f7be8361c80a4c1e7e9aaf001d0877f1cfde218945f93992ac37f3e61db2ef8a587a436a161fd210b94ecbc4fb1a97861344dad0867ca3cba2b860411f086048c27395000f84694ce2fd7544e0b2cc94692d4a704debef7bcb613289444abc67b4b2fba283c582387f54c9cba7c34bafa948acc2ab395ded08bb75ce85bf0f95ad2abc51ad586048c27395000f84694b8f7166496996a7da21cf1f1b04d9b3e26a3d077946770572763289aac606e4f327c2f6cc1aa3b3e3b94882d745ed97d4422ca8da1c22ec49d880c4c097286048c27395000f846942d4c407bbe49438ed859fe965b140dcf1aab71a9943ad0939e120f33518fbba04631afe7a3ed6327b194b2bbb170ca4e499a2b0f3cc85ebfa6e8c4dfcbea86048c27395000f846946bbad7cf34b5fa511d8e963dbba288b1960e75d694853b0f6c324d1f4e76c8266942337ac1b0af1a229442498946a51ca5924552ead6fc2af08b94fcba648601d1a94a2000f846944430b3230294d12c6ab2aac5c2cd68e80b16b581947b107f4976a252a6939b771202c28e64e03f52d694795811a7f214084116949fc4f53cedbf189eeab28601d1a94a2000f84694ea0a6e3c511bbd10f4519ece37dc24887e11b55d946811ca77acfb221a49393c193f3a22db829fcc8e9464feb7c04830dd9ace164fc5c52b3f5a29e5018a8601d1a94a2000f846947ae2f5b9e386cd1b50a4550696d957cb4900f03a94e83bcc5077e6b873995c24bac871b5ad856047e19464e48d4057a90b233e026c1041e6012ada897fe88601d1a94a2000f8469482012708dafc9e1b880fd083b32182b869be8e09948e5adc73a2d233a1b496ed3115464dd6c7b887509428b383d324bc9a37f4e276190796ba5a8947f5ed8601d1a94a2000f8469422b81f8e175ffde54d797fe11eb03f9e3bf75f1d94a1c3ef7ca38d8ba80cce3bfc53ebd2903ed21658942767f7447f7b9b70313d4147b795414aecea54718601d1a94a2000f8469468bf0b8b6fb4e317a0f9d6f03eaf8ce6675bc60d94675cfe570b7902623f47e7f59c9664b5f5065dcf94d84f0d2e50bcf00f2fc476e1c57f5ca2d57f625b8601d1a94a2000f846948c4d90829ce8f72d0163c1d5cf348a862d5506309485c42a7b34309bee2ed6a235f86d16f059deec5894cc2cedc53f0fa6d376336efb67e43d167169f3b78601d1a94a2000f8469435e7a025f4da968de7e4d7e4004197917f4070f194b1182abaeeb3b4d8eba7e6a4162eac7ace23d57394c4fd0d870da52e73de2dd8ded19fe3d26f43a1138601d1a94a2000f84694d6caa02bbebaebb5d7e581e4b66559e635f805ff94c07335cf083c1c46a487f0325769d88e163b653694efaff03b42e41f953a925fc43720e45fb61a19938601d1a94a2000";

    uint256 public constant INIT_NUM_OF_CABINETS = 21;

    /*----------------- state of the contract -----------------*/
    Validator[] public currentValidatorSet;
    uint256 public expireTimeSecondGap;  // @dev deprecated
    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; // @dev deprecated

    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; // @dev 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 systemRewardBaseRatio;
    uint256 public previousHeight;
    uint256 public previousBalanceOfSystemReward; // @dev deprecated
    bytes[] public previousVoteAddrFullSet;
    bytes[] public currentVoteAddrFullSet;
    bool public isSystemRewardIncluded;

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

    // BEP-341 Validators can produce consecutive blocks
    uint256 public turnLength; // Consecutive number of blocks a validator receives priority for block production
    uint256 public systemRewardAntiMEVRatio;

    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;
    }

    struct ValidatorSetPackage {
        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 systemTransfer(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 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 validatorJailed(address indexed validator);  // @dev deprecated
    event validatorEmptyJailed(address indexed validator);  // @dev deprecated
    event batchTransfer(uint256 amount);  // @dev deprecated
    event batchTransferFailed(uint256 indexed amount, string reason);  // @dev deprecated
    event batchTransferLowerFailed(uint256 indexed amount, bytes reason);  // @dev deprecated
    event directTransfer(address payable indexed validator, uint256 amount);  // @dev deprecated
    event directTransferFail(address payable indexed validator, uint256 amount);  // @dev deprecated
    event failReasonWithStr(string message);  // @dev deprecated
    event unexpectedPackage(uint8 channelId, bytes msgBytes);  // @dev deprecated
    event tmpValidatorSetUpdated(uint256 validatorsNum);  // @dev deprecated

    /*----------------- init -----------------*/
    function init() external onlyNotInit {
        (ValidatorSetPackage memory validatorSetPkg, bool valid) =
            decodeValidatorSet(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;
        }
        alreadyInit = true;
    }

    receive() external payable { }

    /*----------------- Cross Chain App Implement -----------------*/
    function handleSynPackage(
        uint8,
        bytes calldata msgBytes
    ) external override onlyInit onlyCrossChainContract initValidatorExtraSet returns (bytes memory responsePayload) {
        revert("deprecated");
    }

    function handleAckPackage(uint8 channelId, bytes calldata msgBytes) external override onlyCrossChainContract {
        revert("deprecated");
    }

    function handleFailAckPackage(uint8 channelId, bytes calldata msgBytes) external override onlyCrossChainContract {
        revert("deprecated");
    }

    /*----------------- 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
            });
        }

        // 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;
        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) {
            systemRewardBaseRatio = INIT_SYSTEM_REWARD_RATIO;
            burnRatio = INIT_BURN_RATIO;
            isSystemRewardIncluded = true;
        }

        uint256 systemRewardRatio = systemRewardBaseRatio;
        if (turnLength > 1 && systemRewardAntiMEVRatio > 0) {
            systemRewardRatio += systemRewardAntiMEVRatio * (block.number % turnLength) / (turnLength - 1);
        }

        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 finalityReward intervals,
            // 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;
        uint256 _shuffleInterval = 200;

        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 shuffleNumber = block.number / _shuffleInterval;
            shuffle(
                validators,
                voteAddrs,
                shuffleNumber,
                _numOfCabinets - _maxNumOfWorkingCandidates,
                0,
                _maxNumOfWorkingCandidates,
                _numOfCabinets
            );
            shuffle(
                validators,
                voteAddrs,
                shuffleNumber,
                _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 {
        revert("deprecated");
    }

    /*----------------- 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, true);
    }

    /*----------------- Param update -----------------*/
    function updateParam(string calldata key, bytes calldata value) external override onlyInit onlyGov {
        if (Memory.compareStrings(key, "burnRatio")) {
            require(value.length == 32, "length of burnRatio mismatch");
            uint256 newBurnRatio = BytesToTypes.bytesToUint256(32, value);
            require(
                newBurnRatio.add(systemRewardBaseRatio).add(systemRewardAntiMEVRatio) <= BLOCK_FEES_RATIO_SCALE,
                "the burnRatio plus systemRewardBaseRatio and systemRewardAntiMEVRatio 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");

            uint256 maxElectedValidators = IStakeHub(STAKE_HUB_ADDR).maxElectedValidators();
            require(
                newNumOfCabinets <= maxElectedValidators, "the numOfCabinets must be less than maxElectedValidators"
            );

            numOfCabinets = newNumOfCabinets;
        } else if (Memory.compareStrings(key, "systemRewardBaseRatio")) {
            require(value.length == 32, "length of systemRewardBaseRatio mismatch");
            uint256 newSystemRewardBaseRatio = BytesToTypes.bytesToUint256(32, value);
            require(
                newSystemRewardBaseRatio.add(burnRatio).add(systemRewardAntiMEVRatio) <= BLOCK_FEES_RATIO_SCALE,
                "the systemRewardBaseRatio plus burnRatio and systemRewardAntiMEVRatio must be no greater than 10000"
            );
            systemRewardBaseRatio = newSystemRewardBaseRatio;
        } else if (Memory.compareStrings(key, "systemRewardAntiMEVRatio")) {
            require(value.length == 32, "length of systemRewardAntiMEVRatio mismatch");
            uint256 newSystemRewardAntiMEVRatio = BytesToTypes.bytesToUint256(32, value);
            require(
                newSystemRewardAntiMEVRatio.add(burnRatio).add(systemRewardBaseRatio) <= BLOCK_FEES_RATIO_SCALE,
                "the systemRewardAntiMEVRatio plus burnRatio and systemRewardBaseRatio must be no greater than 10000"
            );
            systemRewardAntiMEVRatio = newSystemRewardAntiMEVRatio;
        } else if (Memory.compareStrings(key, "turnLength")) {
            require(value.length == 32, "length of turnLength mismatch");
            uint256 newTurnLength = BytesToTypes.bytesToUint256(32, value);
            require(
                newTurnLength >= 3 && newTurnLength <= 64 || newTurnLength == 1,
                "the turnLength should be in [3,64] or equal to 1"
            );
            turnLength = newTurnLength;
        } else {
            require(false, "unknown param");
        }
        emit paramChange(key, value);
    }

    /*----------------- Internal Functions -----------------*/
    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 shuffle interval blocks, 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 shuffleNumber,
        uint256 startIdx,
        uint256 offset,
        uint256 limit,
        uint256 modNumber
    ) internal pure {
        for (uint256 i; i < limit; ++i) {
            uint256 random = uint256(keccak256(abi.encodePacked(shuffleNumber, 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 getTurnLength() external view returns (uint256) {
        if (turnLength == 0) {
            return 1;
        }
        return turnLength;
    }

    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, false);
            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,
        bool shouldRevert
    ) private returns (bool isFelony) {
        if (maintainSlashScale == 0 || miningValidatorCount == 0 || numOfMaintaining == 0) {
            // should not happen, still protect
            return false;
        }

        // step 0: modify numOfMaintaining
        --numOfMaintaining;

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

        // step 2: clear isMaintaining info
        validatorExtraSet[index].isMaintaining = false;

        // step 3: slash the validator
        (uint256 misdemeanorThreshold, uint256 felonyThreshold) =
            ISlashIndicator(SLASH_CONTRACT_ADDR).getSlashThresholds();
        isFelony = false;
        if (slashCount >= felonyThreshold) {
            _felony(validator, index);
            ISlashIndicator(SLASH_CONTRACT_ADDR).downtimeSlash(validator, slashCount, shouldRevert);
            isFelony = true;
        } else if (slashCount >= misdemeanorThreshold) {
            _misdemeanor(validator);
        }

        emit validatorExitMaintenance(validator);
    }

    function decodeValidatorSet(bytes memory msgBytes)
        internal
        pure
        returns (ValidatorSetPackage memory, bool)
    {
        ValidatorSetPackage 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

API
[{"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": "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": "GOVERNOR_ADDR","outputs": [{"internalType": "address","name": "","type": "address"}],"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": "LIGHT_CLIENT_ADDR","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "MAX_SYSTEM_REWARD_BALANCE","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_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_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": "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": "getTurnLength","outputs": [{"internalType": "uint256","name": "","type": "uint256"}],"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": "systemRewardAntiMEVRatio","outputs": [{"internalType": "uint256","name": "","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "systemRewardBaseRatio","outputs": [{"internalType": "uint256","name": "","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "totalInComing","outputs": [{"internalType": "uint256","name": "","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "turnLength","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"}]

6080604052600436106104405760003560e01c80638b5ad0c911610234578063c81b16621161012e578063e1c7392a116100b6578063f92eb86b1161007a578063f92eb86b14610b3f578063f9a2bbc714610b54578063fccc281314610b69578063fd4ad81f14610b7e578063fd6a687914610bad57610447565b8063e1c7392a14610ac2578063e40716a114610ad7578063ea321e4914610aec578063eb57e20214610b0c578063f340fa0114610b2c57610447565b8063d58918ae116100fd578063d58918ae14610a59578063d68fb56a14610a6e578063daacdb6614610a83578063dc927faf14610a98578063df8079e914610aad57610447565b8063c81b166214610a0f578063c8509d81146107e6578063cb75a59214610a24578063ce910b0c14610a3957610447565b8063aa82dce1116101bc578063aef198a911610180578063aef198a914610999578063b7ab4db5146109ae578063b8cf4ef1146109d0578063c466689d146109e5578063c6d33945146109fa57610447565b8063aa82dce11461090d578063aad5606314610922578063ab51bb9614610937578063ac43175114610959578063ad3c9da61461097957610447565b80639dc09262116102035780639dc09262146108a45780639fe0f816146108b9578063a1a11bf5146108ce578063a5422d5c146108e3578063a78abc16146108f857610447565b80638b5ad0c9146108455780638c5d749d1461085a5780638d19a4101461086f5780639369d7de1461088f57610447565b80634df6e0c3116103455780636e47b482116102cd578063820dcaa811610291578063820dcaa8146107d1578063831d65d1146107e6578063862498821461080657806388b32f111461081b5780638a7beb011461083057610447565b80636e47b4821461076857806375d47a0a1461077d57806378dfed4a146107925780637a84ca2a146107a75780637e434d54146107bc57610447565b806355614fcc1161031457806355614fcc146106c1578063565c56b3146106e157806360eba4fe1461070157806362b72cf5146107215780636969a25c1461073657610447565b80634df6e0c31461066d5780635192c82c1461068257806351b4dce31461069757806351e80672146106ac57610447565b80632a0ffb6e116103c857806335409f7f1161039757806335409f7f146105de5780633b071dcc146105fe57806343756e5c1461062157806345cf9daf14610636578063493279b11461064b57610447565b80632a0ffb6e1461055e578063300c35671461057e578063321d398a1461059e5780633365af3a146105be57610447565b8063152ad3b81161040f578063152ad3b8146104dd5780631bd14ed8146104ff5780631e4c1524146105145780631ff1806914610534578063280870281461054957610447565b806304c4fec61461044c57806307a56847146104635780630e2374a51461048e5780631182b875146104b057610447565b3661044757005b600080fd5b34801561045857600080fd5b50610461610bc2565b005b34801561046f57600080fd5b50610478610c36565b6040516104859190616d89565b60405180910390f35b34801561049a57600080fd5b506104a3610c3c565b604051610485919061613e565b3480156104bc57600080fd5b506104d06104cb366004616024565b610c42565b604051610485919061625e565b3480156104e957600080fd5b506104f2610d5e565b6040516104859190616253565b34801561050b57600080fd5b50610478610d67565b34801561052057600080fd5b5061046161052f366004615e52565b610d6d565b34801561054057600080fd5b506104786110a1565b34801561055557600080fd5b506104a36110a7565b34801561056a57600080fd5b50610461610579366004615db2565b6110ad565b34801561058a57600080fd5b50610461610599366004615dea565b6110ce565b3480156105aa57600080fd5b506104f26105b9366004615fd1565b611417565b3480156105ca57600080fd5b506104f26105d9366004615fd1565b6114e6565b3480156105ea57600080fd5b506104616105f9366004615db2565b611597565b34801561060a57600080fd5b506106136116fc565b6040516104859291906161e3565b34801561062d57600080fd5b506104a36119d8565b34801561064257600080fd5b506104786119de565b34801561065757600080fd5b506106606119e4565b6040516104859190616d7a565b34801561067957600080fd5b506106136119e9565b34801561068e57600080fd5b50610478611b83565b3480156106a357600080fd5b506104a3611b89565b3480156106b857600080fd5b506104a3611b8f565b3480156106cd57600080fd5b506104f26106dc366004615db2565b611b95565b3480156106ed57600080fd5b506104786106fc366004615db2565b611bd1565b34801561070d57600080fd5b506104d061071c366004615fd1565b611c22565b34801561072d57600080fd5b50610478611cc8565b34801561074257600080fd5b50610756610751366004615fd1565b611cce565b6040516104859695949392919061616b565b34801561077457600080fd5b506104a3611d32565b34801561078957600080fd5b506104a3611d38565b34801561079e57600080fd5b50610478611d3e565b3480156107b357600080fd5b50610478611d44565b3480156107c857600080fd5b506104a3611d4a565b3480156107dd57600080fd5b50610478611d50565b3480156107f257600080fd5b50610461610801366004616024565b611d56565b34801561081257600080fd5b50610478611d77565b34801561082757600080fd5b50610478611d7d565b34801561083c57600080fd5b506104f2611d83565b34801561085157600080fd5b50610478611d8c565b34801561086657600080fd5b50610478611d92565b34801561087b57600080fd5b5061047861088a366004615db2565b611daf565b34801561089b57600080fd5b50610461611def565b3480156108b057600080fd5b506104a3611f03565b3480156108c557600080fd5b50610478611f09565b3480156108da57600080fd5b506104a3611f0e565b3480156108ef57600080fd5b506104d0611f14565b34801561090457600080fd5b506104f2611f33565b34801561091957600080fd5b506104a3611f3c565b34801561092e57600080fd5b506104a3611f42565b34801561094357600080fd5b5061094c611f48565b6040516104859190616dbc565b34801561096557600080fd5b50610461610974366004615f75565b611f4d565b34801561098557600080fd5b50610478610994366004615db2565b6129b6565b3480156109a557600080fd5b506104786129c8565b3480156109ba57600080fd5b506109c36129d5565b60405161048591906161d0565b3480156109dc57600080fd5b50610478612ac0565b3480156109f157600080fd5b50610478612ac5565b348015610a0657600080fd5b50610478612acb565b348015610a1b57600080fd5b506104a3612ad0565b348015610a3057600080fd5b50610478612ad6565b348015610a4557600080fd5b506104d0610a54366004615fd1565b612adc565b348015610a6557600080fd5b50610478612ae9565b348015610a7a57600080fd5b50610478612aef565b348015610a8f57600080fd5b50610478612b2e565b348015610aa457600080fd5b506104a3612b34565b348015610ab957600080fd5b506104a3612b3a565b348015610ace57600080fd5b50610461612b40565b348015610ae357600080fd5b50610478612ce9565b348015610af857600080fd5b506104f2610b07366004615f36565b612cef565b348015610b1857600080fd5b50610461610b27366004615db2565b612e75565b610461610b3a366004615db2565b612f7d565b348015610b4b57600080fd5b50610478613333565b348015610b6057600080fd5b506104a3613339565b348015610b7557600080fd5b506104a361333f565b348015610b8a57600080fd5b50610b9e610b99366004615fd1565b613345565b60405161048593929190616d92565b348015610bb957600080fd5b506104a3613407565b6000610bcd33611daf565b9050600b8181548110610bdc57fe5b600091825260209091206001601690920201015460ff16610c185760405162461bcd60e51b8152600401610c0f90616a30565b60405180910390fd5b6000610c22612aef565b9050610c31338383600161340d565b505050565b60095481565b61200181565b60005460609060ff16610c675760405162461bcd60e51b8152600401610c0f90616443565b3361200014610c885760405162461bcd60e51b8152600401610c0f90616b42565b600b54610d4657610c9761595e565b60015460005b81811015610d4257600b80546001810182556000919091528351600080516020616e5483398151915260169092029182019081556020808601516000805160206174838339815191528401805460ff1916911515919091179055604086015180518794610d1e93600080516020616e7483398151915290910192019061598d565b506060820151610d349060038301906013615a07565b505050806001019050610c9d565b5050505b60405162461bcd60e51b8152600401610c0f90616695565b60075460ff1681565b600f5481565b334114610d8c5760405162461bcd60e51b8152600401610c0f90616b91565b3a15610daa5760405162461bcd60e51b8152600401610c0f9061696f565b8251604080518281526020808402820101909152606090828015610de857816020015b610dd5615a34565b815260200190600190039081610dcd5790505b50905060005b82811015610e92576040518060c00160405280878381518110610e0d57fe5b60200260200101516001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b03168152602001868381518110610e4f57fe5b60200260200101516001600160401b031681526020016000151581526020016000815250828281518110610e7f57fe5b6020908102919091010152600101610dee565b50606080610ea083866135ff565b9150915060005b600154811015610f9657600060018281548110610ec057fe5b906000526020600020906004020160030154905080600014610f8d57600060018381548110610eeb57fe5b9060005260206000209060040201600301819055506120026001600160a01b031663092193ab8260018581548110610f1f57fe5b60009182526020909120600491820201546040516001600160e01b031960e086901b168152610f5a926001600160a01b03909216910161613e565b6000604051808303818588803b158015610f7357600080fd5b505af1158015610f87573d6000803e3d6000fd5b50505050505b50600101610ea7565b504715611004577f6ecc855f9440a9282c90913bbc91619fd44f5ec0b462af28d127b116f130aa4d47604051610fcc9190616d89565b60405180910390a1604051611002904780156108fc02916000818181858888f19350505050158015611002573d6000803e3d6000fd5b505b600060035581511561101a5761101a8282613ae9565b6110016001600160a01b031663fc4333cd6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561105757600080fd5b505af115801561106b573d6000803e3d6000fd5b50506040517fedd8d7296956dd970ab4de3f2fc03be2b0ffc615d20cd4c72c6e44f928630ebf925060009150a150505050505050565b60035481565b61200581565b3361200214610d465760405162461bcd60e51b8152600401610c0f90616d43565b3341146110ed5760405162461bcd60e51b8152600401610c0f90616b91565b601054431161110e5760405162461bcd60e51b8152600401610c0f906165bf565b3a1561112c5760405162461bcd60e51b8152600401610c0f9061696f565b60005460ff1661114e5760405162461bcd60e51b8152600401610c0f90616443565b60006110023168056bc75e2d631000008111156111855761117e8168056bc75e2d6310000063ffffffff6142d816565b915061118c565b505061140d565b6040516309a99b4f60e41b815261100290639a99b4f0906111b39030908690600401616152565b602060405180830381600087803b1580156111cd57600080fd5b505af11580156111e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112059190615fe9565b91508161121357505061140d565b6000805b848110156112415785858281811061122b57fe5b9050602002013582019150806001019050611217565b508061124f5750505061140d565b6000806000805b89811015611405578489898381811061126b57fe5b9050602002013588028161127b57fe5b0493508a8a8281811061128a57fe5b905060200201602081019061129f9190615db2565b6001600160a01b038116600090815260046020526040902054909350915081156113bb5760006001808403815481106112d457fe5b9060005260206000209060040201905080600201601c9054906101000a900460ff161561134157836001600160a01b03167fb9c75cbbfde137c4281689580799ef5f52144e78858f776a5979b2b212137d85866040516113349190616d89565b60405180910390a26113b5565b600354611354908663ffffffff61431a16565b600390815581015461136c908663ffffffff61431a16565b60038201556040516001600160a01b038516907fcb0aad6cf9cd03bdf6137e359f541c42f38b39f007cae8e89e88aa7d8c6617b2906113ac908890616d89565b60405180910390a25b506113fd565b826001600160a01b03167fb9c75cbbfde137c4281689580799ef5f52144e78858f776a5979b2b212137d85856040516113f49190616d89565b60405180910390a25b600101611256565b505050505050505b5050436010555050565b600154600090821061142b575060006114e1565b60006001600160a01b03166001838154811061144357fe5b60009182526020909120600490910201546001600160a01b03161480611473575060085415806114735750600a54155b80611482575060085460095410155b806114935750611491826114e6565b155b806114bc57506000600b83815481106114a857fe5b906000526020600020906016020160000154115b806114d0575060016114cc6129d5565b5111155b156114dd575060006114e1565b5060015b919050565b60015460009082106114fa575060006114e1565b600b548210611537576001828154811061151057fe5b9060005260206000209060040201600201601c9054906101000a900460ff161590506114e1565b6001828154811061154457fe5b9060005260206000209060040201600201601c9054906101000a900460ff161580156115915750600b828154811061157857fe5b600091825260209091206001601690920201015460ff16155b92915050565b600b54611655576115a661595e565b60015460005b8181101561165157600b80546001810182556000919091528351600080516020616e5483398151915260169092029182019081556020808601516000805160206174838339815191528401805460ff191691151591909117905560408601518051879461162d93600080516020616e7483398151915290910192019061598d565b5060608201516116439060038301906013615a07565b5050508060010190506115ac565b5050505b336110011480611666575033612002145b6116825760405162461bcd60e51b8152600401610c0f9061647a565b6001600160a01b038116600090815260046020526040902054806116a657506116f9565b6001810390506000600b82815481106116bb57fe5b600091825260209091206001601690920201015460ff1690506116de838361433f565b80156116e75750805b15610c31576009805460001901905550505b50565b60015460609081906000805b8281101561174f576001818154811061171d57fe5b9060005260206000209060040201600201601c9054906101000a900460ff16611747576001909101905b600101611708565b5060608160405190808252806020026020018201604052801561177c578160200160208202803683370190505b5090506060826040519080825280602002602001820160405280156117b557816020015b60608152602001906001900390816117a05790505b50600b54600094509091508414156119305760005b8481101561192a57600181815481106117df57fe5b9060005260206000209060040201600201601c9054906101000a900460ff16611922576001818154811061180f57fe5b600091825260209091206004909102015483516001600160a01b039091169084908690811061183a57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050600b818154811061186757fe5b600091825260209182902060026016909202018101805460408051601f6000196101006001861615020190931694909404918201859004850284018501905280835291929091908301828280156118ff5780601f106118d4576101008083540402835291602001916118ff565b820191906000526020600020905b8154815290600101906020018083116118e257829003601f168201915b505050505082858151811061191057fe5b60209081029190910101526001909301925b6001016117ca565b506119cc565b60005b848110156119ca576001818154811061194857fe5b9060005260206000209060040201600201601c9054906101000a900460ff166119c2576001818154811061197857fe5b600091825260209091206004909102015483516001600160a01b03909116908490869081106119a357fe5b6001600160a01b03909216602092830291909101909101526001909301925b600101611933565b505b909450925050505b9091565b61100181565b60085481565b603881565b6060806000600e549050600080600c5411611a05576015611a09565b600c545b905060c86060611a176129d5565b90506060611a2482614702565b905083825111611a3c5790955093506119d492505050565b84848351031015611a4e578382510394505b8415611a8e576000834381611a5f57fe5b049050611a7483838389890360008b8b614870565b611a8c8383838989038a8a038b8c8c8b510301614870565b505b606084604051908082528060200260200182016040528015611aba578160200160208202803683370190505b509050606085604051908082528060200260200182016040528015611af357816020015b6060815260200190600190039081611ade5790505b50905060005b86811015611b7457848181518110611b0d57fe5b6020026020010151838281518110611b2157fe5b60200260200101906001600160a01b031690816001600160a01b031681525050838181518110611b4d57fe5b6020026020010151828281518110611b6157fe5b6020908102919091010152600101611af9565b50909750955050505050509091565b60065481565b61200681565b61200081565b6001600160a01b03811660009081526004602052604081205480611bbd5760009150506114e1565b60001901611bca816114e6565b9392505050565b6001600160a01b03811660009081526004602052604081205480611bf95760009150506114e1565b600180820381548110611c0857fe5b906000526020600020906004020160030154915050919050565b60128181548110611c2f57fe5b600091825260209182902001805460408051601f6002600019610100600187161502019094169390930492830185900485028101850190915281815293509091830182828015611cc05780601f10611c9557610100808354040283529160200191611cc0565b820191906000526020600020905b815481529060010190602001808311611ca357829003601f168201915b505050505081565b60105481565b60018181548110611cdb57fe5b600091825260209091206004909102018054600182015460028301546003909301546001600160a01b0392831694509082169291821691600160a01b81046001600160401b031691600160e01b90910460ff169086565b61100581565b61100881565b6103e881565b600c5481565b61200381565b61271081565b3361200014610d465760405162461bcd60e51b8152600401610c0f90616b42565b60025481565b60115481565b60145460ff1681565b600a5481565b600060175460001415611da757506001611dac565b506017545b90565b6001600160a01b03811660009081526004602052604081205480611de55760405162461bcd60e51b8152600401610c0f90616aca565b6000190192915050565b600b54611ead57611dfe61595e565b60015460005b81811015611ea957600b80546001810182556000919091528351600080516020616e5483398151915260169092029182019081556020808601516000805160206174838339815191528401805460ff1916911515919091179055604086015180518794611e8593600080516020616e7483398151915290910192019061598d565b506060820151611e9b9060038301906013615a07565b505050806001019050611e04565b5050505b600854611eba5760036008555b600a54611ec7576002600a555b6000611ed233611daf565b9050611edd81611417565b611ef95760405162461bcd60e51b8152600401610c0f906168eb565b6116f933826149c7565b61100781565b600381565b61100681565b6040518061062001604052806105ef8152602001616e946105ef913981565b60005460ff1681565b61200281565b61300081565b600081565b60005460ff16611f6f5760405162461bcd60e51b8152600401610c0f90616443565b3361100714611f905760405162461bcd60e51b8152600401610c0f9061699d565b611ff084848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260098152686275726e526174696f60b81b60208201529150614a5f9050565b156120a557602081146120155760405162461bcd60e51b8152600401610c0f906162a3565b604080516020601f840181900481028201810190925282815260009161205391858580838501838280828437600092019190915250614ab892505050565b905061271061207f601854612073600f548561431a90919063ffffffff16565b9063ffffffff61431a16565b111561209d5760405162461bcd60e51b8152600401610c0f906166b9565b600655612973565b61210f84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260138152726d61784e756d4f664d61696e7461696e696e6760681b60208201529150614a5f9050565b156121a957602081146121345760405162461bcd60e51b8152600401610c0f906162da565b604080516020601f840181900481028201810190925282815260009161217291858580838501838280828437600092019190915250614ab892505050565b600c5490915080612181575060155b8082106121a05760405162461bcd60e51b8152600401610c0f90616601565b50600855612973565b61221284848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260128152716d61696e7461696e536c6173685363616c6560701b60208201529150614a5f9050565b156122ab57602081146122375760405162461bcd60e51b8152600401610c0f906163c9565b604080516020601f840181900481028201810190925282815260009161227591858580838501838280828437600092019190915250614ab892505050565b90506000811180156122875750600a81105b6122a35760405162461bcd60e51b8152600401610c0f90616c26565b600a55612973565b61231f84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601981527f6d61784e756d4f66576f726b696e6743616e646964617465730000000000000060208201529150614a5f9050565b156123ae57602081146123445760405162461bcd60e51b8152600401610c0f9061637d565b604080516020601f840181900481028201810190925282815260009161238291858580838501838280828437600092019190915250614ab892505050565b9050600d548111156123a65760405162461bcd60e51b8152600401610c0f906167c2565b600e55612973565b61241784848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260128152716d61784e756d4f6643616e6469646174657360701b60208201529150614a5f9050565b15612499576020811461243c5760405162461bcd60e51b8152600401610c0f906169eb565b604080516020601f840181900481028201810190925282815260009161247a91858580838501838280828437600092019190915250614ab892505050565b600d819055600e5490915081101561249357600d54600e555b50612973565b6124fd84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600d81526c6e756d4f66436162696e65747360981b60208201529150614a5f9050565b1561262257602081146125225760405162461bcd60e51b8152600401610c0f9061640e565b604080516020601f840181900481028201810190925282815260009161256091858580838501838280828437600092019190915250614ab892505050565b9050600081116125825760405162461bcd60e51b8152600401610c0f90616577565b60006120026001600160a01b031663c473318f6040518163ffffffff1660e01b815260040160206040518083038186803b1580156125bf57600080fd5b505afa1580156125d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125f79190615fe9565b9050808211156126195760405162461bcd60e51b8152600401610c0f90616320565b50600c55612973565b61268e84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601581527473797374656d52657761726442617365526174696f60581b60208201529150614a5f9050565b1561273757602081146126b35760405162461bcd60e51b8152600401610c0f90616bde565b604080516020601f84018190048102820181019092528281526000916126f191858580838501838280828437600092019190915250614ab892505050565b90506127106127116018546120736006548561431a90919063ffffffff16565b111561272f5760405162461bcd60e51b8152600401610c0f906164e8565b600f55612973565b6127ab84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601881527f73797374656d526577617264416e74694d4556526174696f000000000000000060208201529150614a5f9050565b1561285457602081146127d05760405162461bcd60e51b8152600401610c0f90616748565b604080516020601f840181900481028201810190925282815260009161280e91858580838501838280828437600092019190915250614ab892505050565b905061271061282e600f546120736006548561431a90919063ffffffff16565b111561284c5760405162461bcd60e51b8152600401610c0f9061685c565b601855612973565b6128b584848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600a8152690e8eae4dc98cadccee8d60b31b60208201529150614a5f9050565b1561295b57602081146128da5760405162461bcd60e51b8152600401610c0f9061665e565b604080516020601f840181900481028201810190925282815260009161291891858580838501838280828437600092019190915250614ab892505050565b90506003811015801561292c575060408111155b806129375750806001145b6129535760405162461bcd60e51b8152600401610c0f90616c83565b601755612973565b60405162461bcd60e51b8152600401610c0f90616cd3565b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a848484846040516129a89493929190616271565b60405180910390a150505050565b60046020526000908152604090205481565b68056bc75e2d6310000081565b6001546060906000805b82811015612a04576129f0816114e6565b156129fc578160010191505b6001016129df565b50606081604051908082528060200260200182016040528015612a31578160200160208202803683370190505b5090506000915060005b83811015612ab857612a4c816114e6565b15612ab05760018181548110612a5e57fe5b600091825260209091206004909102015482516001600160a01b0390911690839085908110612a8957fe5b60200260200101906001600160a01b031690816001600160a01b0316815250508260010192505b600101612a3b565b509250505090565b601581565b61027181565b600281565b61100281565b60175481565b60138181548110611c2f57fe5b60185481565b6000612af96129d5565b519050600080600c5411612b0e576015612b12565b600c545b905080821115612b20578091505b81612b2a57600191505b5090565b60055481565b61100381565b61200481565b60005460ff1615612b635760405162461bcd60e51b8152600401610c0f90616a5c565b612b6b615a69565b6000612b916040518061062001604052806105ef8152602001616e946105ef9139614abd565b9150915080612bb25760405162461bcd60e51b8152600401610c0f90616b01565b60005b826020015151811015612cd757600183602001518281518110612bd457fe5b60209081029190910181015182546001818101855560009485528385208351600493840290910180546001600160a01b039283166001600160a01b03199182161782558587015182850180549185169183169190911790556040860151600283018054606089015160808a01511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b199590981692909516919091179290921694909417161790915560a090930151600390930192909255918601518051918501939185908110612caa57fe5b602090810291909101810151516001600160a01b0316825281019190915260400160002055600101612bb5565b50506000805460ff1916600117905550565b600d5481565b601354600090815b81811015612df857612de085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050601380549092508591508110612d4857fe5b600091825260209182902001805460408051601f6002600019610100600187161502019094169390930492830185900485028101850190915281815292830182828015612dd65780601f10612dab57610100808354040283529160200191612dd6565b820191906000526020600020905b815481529060010190602001808311612db957829003601f168201915b5050505050614c79565b15612df057600192505050611591565b600101612cf7565b5060125460005b81811015612e6957612e5086868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050601280549092508591508110612d4857fe5b15612e615760019350505050611591565b600101612dff565b50600095945050505050565b3361100114612e965760405162461bcd60e51b8152600401610c0f90616cfa565b600b54612f5457612ea561595e565b60015460005b81811015612f5057600b80546001810182556000919091528351600080516020616e5483398151915260169092029182019081556020808601516000805160206174838339815191528401805460ff1916911515919091179055604086015180518794612f2c93600080516020616e7483398151915290910192019061598d565b506060820151612f429060038301906013615a07565b505050806001019050612eab565b5050505b6000612f5f82614cdd565b9050612f6a81611417565b15612f7957612f7982826149c7565b5050565b334114612f9c5760405162461bcd60e51b8152600401610c0f90616b91565b60005460ff16612fbe5760405162461bcd60e51b8152600401610c0f90616443565b60003411612fde5760405162461bcd60e51b8152600401610c0f90616793565b3a15612ffc5760405162461bcd60e51b8152600401610c0f9061696f565b6001600160a01b03811660009081526004602052604090205460145434919060ff1661303c57610271600f556103e86006556014805460ff191660011790555b600f54601754600110801561305357506000601854115b1561307857600160175403601754438161306957fe5b06601854028161307557fe5b04015b6000831180156130885750600081115b156131355760006130b16127106130a5348563ffffffff614e6016565b9063ffffffff614e9a16565b90508015613133576040516110029082156108fc029083906000818181858888f193505050501580156130e8573d6000803e3d6000fd5b507f6ecc855f9440a9282c90913bbc91619fd44f5ec0b462af28d127b116f130aa4d816040516131189190616d89565b60405180910390a1613130848263ffffffff6142d816565b93505b505b60008311801561314757506000600654115b156131ed5760006131696127106130a560065434614e6090919063ffffffff16565b905080156131eb5760405161dead9082156108fc029083906000818181858888f193505050501580156131a0573d6000803e3d6000fd5b507f627059660ea01c4733a328effb2294d2f86905bf806da763a89cee254de8bee5816040516131d09190616d89565b60405180910390a16131e8848263ffffffff6142d816565b93505b505b81156132eb57600060018084038154811061320457fe5b9060005260206000209060040201905080600201601c9054906101000a900460ff161561327157846001600160a01b03167ff177e5d6c5764d79c32883ed824111d9b13f5668cf6ab1cc12dd36791dd955b4856040516132649190616d89565b60405180910390a26132e5565b600354613284908563ffffffff61431a16565b600390815581015461329c908563ffffffff61431a16565b60038201556040516001600160a01b038616907f93a090ecc682c002995fad3c85b30c5651d7fd29b0be5da9d784a3302aedc055906132dc908790616d89565b60405180910390a25b5061332d565b836001600160a01b03167ff177e5d6c5764d79c32883ed824111d9b13f5668cf6ab1cc12dd36791dd955b4846040516133249190616d89565b60405180910390a25b50505050565b600e5481565b61100081565b61dead81565b600b818154811061335257fe5b6000918252602091829020601691909102018054600180830154600280850180546040805161010096831615969096026000190190911692909204601f810188900488028501880190925281845293965060ff909116949192918301828280156133fd5780601f106133d2576101008083540402835291602001916133fd565b820191906000526020600020905b8154815290600101906020018083116133e057829003601f168201915b5050505050905083565b61100481565b6000600a546000148061341e575082155b806134295750600954155b15613436575060006135f7565b60096000815460019003919050819055506000613481600a546130a5866130a5600b8a8154811061346357fe5b6000918252602090912060169091020154439063ffffffff6142d816565b90506000600b868154811061349257fe5b906000526020600020906016020160010160006101000a81548160ff0219169083151502179055506000806110016001600160a01b0316638256ace66040518163ffffffff1660e01b8152600401604080518083038186803b1580156134f757600080fd5b505afa15801561350b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061352f9190616001565b91509150600093508083106135ad57613548888861433f565b506040516328aa02b160e01b8152611001906328aa02b190613572908b9087908a906004016161ad565b600060405180830381600087803b15801561358c57600080fd5b505af11580156135a0573d6000803e3d6000fd5b50505050600193506135bf565b8183106135bf576135bd88614cdd565b505b6040516001600160a01b038916907fb9d38178dc641ff1817967a63c9078cbcd955a9f1fcd75e0e3636de615d44d3b90600090a25050505b949350505050565b606080600080808080613610612aef565b6001549091505b801561384257600181039250600b838154811061363057fe5b600091825260209091206001601690920201015460ff1661365057613839565b6001838154811061365d57fe5b600091825260208220600490910201546001600160a01b031695506136879086908590859061340d565b93508361369357613839565b60405163436aa28360e11b81526000908190612002906386d54506906136bd908a9060040161613e565b60206040518083038186803b1580156136d557600080fd5b505afa1580156136e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061370d9190615dce565b90506001600160a01b03811615613796576040516302ceee9160e11b81526120029063059ddd229061374390849060040161613e565b60206040518083038186803b15801561375b57600080fd5b505afa15801561376f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137939190615dce565b91505b60005b8c5181101561383557876001600160a01b03168d82815181106137b857fe5b6020026020010151600001516001600160a01b031614806138015750826001600160a01b03168d82815181106137ea57fe5b6020026020010151600001516001600160a01b0316145b1561382d5760018d828151811061381457fe5b6020908102919091010151901515608090910152613835565b600101613799565b5050505b60001901613617565b5060005b89518110156138af5789818151811061385b57fe5b6020026020010151608001518061389b575060006001600160a01b03168a828151811061388457fe5b6020026020010151600001516001600160a01b0316145b156138a7578560010195505b600101613846565b50885185106139975760408051600180825281830190925290816020015b6138d5615a34565b8152602001906001900390816138cd575050604080516001808252818301909252919850602082015b60608152602001906001900390816138fe5790505095508860008151811061392257fe5b60200260200101518760008151811061393757fe5b60200260200101819052508760008151811061394f57fe5b60200260200101518660008151811061396457fe5b602002602001018190525060008760008151811061397e57fe5b6020908102919091010151901515608090910152613adc565b848951036040519080825280602002602001820160405280156139d457816020015b6139c1615a34565b8152602001906001900390816139b95790505b50965084895103604051908082528060200260200182016040528015613a0e57816020015b60608152602001906001900390816139f95790505b5095506000915060005b8951811015613ada57898181518110613a2d57fe5b602002602001015160800151158015613a70575060006001600160a01b03168a8281518110613a5857fe5b6020026020010151600001516001600160a01b031614155b15613ad257898181518110613a8157fe5b6020026020010151888481518110613a9557fe5b6020026020010181905250888181518110613aac57fe5b6020026020010151878481518110613ac057fe5b60200260200101819052508260010192505b600101613a18565b505b50505050505b9250929050565b600154825160005b82811015613c06576001613b03615a34565b60018381548110613b1057fe5b600091825260208083206040805160c08101825260049490940290910180546001600160a01b0390811685526001820154811693850193909352600281015492831691840191909152600160a01b82046001600160401b03166060840152600160e01b90910460ff16151560808301526003015460a082015291505b84811015613bda57878181518110613ba057fe5b6020026020010151600001516001600160a01b031682600001516001600160a01b03161415613bd25760009250613bda565b600101613b8c565b508115613bfc5780516001600160a01b03166000908152600460205260408120555b5050600101613af1565b5080821115613cc557805b82811015613cc3576001805480613c2457fe5b60008281526020812060046000199093019283020180546001600160a01b0319908116825560018201805490911690556002810180546001600160e81b0319169055600301559055600b805480613c7757fe5b60008281526020812060166000199093019283020181815560018101805460ff1916905590613ca96002830182615a8d565b613cb7600383016000615ad1565b50509055600101613c11565b505b6000818310613cd45781613cd6565b825b905060005b8181101561407a57613d88868281518110613cf257fe5b602002602001015160018381548110613d0757fe5b60009182526020918290206040805160c08101825260049390930290910180546001600160a01b0390811684526001820154811694840194909452600281015493841691830191909152600160a01b83046001600160401b03166060830152600160e01b90920460ff161515608082015260039091015460a0820152614edc565b613f3c578060010160046000888481518110613da057fe5b6020026020010151600001516001600160a01b03166001600160a01b0316815260200190815260200160002081905550858181518110613ddc57fe5b602002602001015160018281548110613df157fe5b6000918252602091829020835160049092020180546001600160a01b039283166001600160a01b0319918216178255928401516001820180549184169185169190911790556040840151600282018054606087015160808801511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b1995909716929097169190911792909216939093171692909217905560a0909101516003909101558451859082908110613eac57fe5b6020026020010151600b8281548110613ec157fe5b90600052602060002090601602016002019080519060200190613ee592919061598d565b506000600b8281548110613ef557fe5b60009182526020822060169190910201600101805460ff191692151592909217909155600b805483908110613f2657fe5b6000918252602090912060169091020155614072565b858181518110613f4857fe5b60200260200101516060015160018281548110613f6157fe5b906000526020600020906004020160020160146101000a8154816001600160401b0302191690836001600160401b03160217905550614027858281518110613fa557fe5b6020026020010151600b8381548110613fba57fe5b600091825260209182902060026016909202018101805460408051601f600019610100600186161502019093169490940491820185900485028401850190528083529192909190830182828015612dd65780601f10612dab57610100808354040283529160200191612dd6565b6140725784818151811061403757fe5b6020026020010151600b828154811061404c57fe5b9060005260206000209060160201600201908051906020019061407092919061598d565b505b600101613cdb565b50828211156142525761408b61595e565b835b8381101561424f578581815181106140a157fe5b6020026020010151826040018190525060018782815181106140bf57fe5b6020908102919091018101518254600181810185556000948552838520835160049093020180546001600160a01b039384166001600160a01b0319918216178255848601518284018054918616918316919091179055604080860151600284018054606089015160808a01511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b1995909a1692909616919091179290921696909617169190911790935560a090930151600390930192909255600b8054928301815590935284516016909102600080516020616e548339815191528101918255858301516000805160206174838339815191528201805491151560ff19909216919091179055928501518051869492936141f593600080516020616e748339815191520192019061598d565b50606082015161420b9060038301906013615a07565b505050806001016004600089848151811061422257fe5b602090810291909101810151516001600160a01b031682528101919091526040016000205560010161408d565b50505b61425a614f38565b61426261511a565b6000600981905560015493505b838110156142d0576000600b828154811061428657fe5b60009182526020822060169190910201600101805460ff191692151592909217909155600b8054839081106142b757fe5b600091825260209091206016909102015560010161426f565b505050505050565b6000611bca83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250615308565b600082820183811015611bca5760405162461bcd60e51b8152600401610c0f906164b1565b6000806001838154811061434f57fe5b906000526020600020906004020160030154905060006001808054905003905060016143796129d5565b51116143ae5760006001858154811061438e57fe5b906000526020600020906004020160030181905550600092505050611591565b846001600160a01b03167f3b6f9ef90462b512a1293ecec018670bf7b7f1876fb727590a8a6d7643130a70836040516143e79190616d89565b60405180910390a26001600160a01b038516600090815260046020526040812055835b600154600019018110156145d4576001816001018154811061442857fe5b90600052602060002090600402016001828154811061444357fe5b60009182526020909120825460049092020180546001600160a01b03199081166001600160a01b0393841617825560018085015481840180548416918616919091179055600280860180549185018054909416919095161780835584546001600160401b03600160a01b91829004160267ffffffffffffffff60a01b1990911617808355935460ff600160e01b918290041615150260ff60e01b19909416939093179055600392830154920191909155600b80549091830190811061450457fe5b9060005260206000209060160201600b828154811061451f57fe5b600091825260209091208254601690920201908155600180830154818301805460ff909216151560ff1990921691909117905560028084018054614576938386019390821615610100026000190190911604615ae0565b5061458960038281019084016013615b55565b509050508060010160046000600184815481106145a257fe5b600091825260208083206004909202909101546001600160a01b0316835282019290925260400190205560010161440a565b5060018054806145e057fe5b60008281526020812060046000199093019283020180546001600160a01b0319908116825560018201805490911690556002810180546001600160e81b0319169055600301559055600b80548061463357fe5b60008281526020812060166000199093019283020181815560018101805460ff19169055906146656002830182615a8d565b614673600383016000615ad1565b50509055600081838161468257fe5b04905080156146f65760015460005b818110156146f3576146ca83600183815481106146aa57fe5b90600052602060002090600402016003015461431a90919063ffffffff16565b600182815481106146d757fe5b6000918252602090912060036004909202010155600101614691565b50505b50600195945050505050565b60015481516040805182815260208084028201019091526060929190839082801561474157816020015b606081526020019060019003908161472c5790505b50600b5490915083146147585792506114e1915050565b60005b8281101561486757600b60016004600089858151811061477757fe5b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205403815481106147ab57fe5b600091825260209182902060026016909202018101805460408051601f6000196101006001861615020190931694909404918201859004850284018501905280835291929091908301828280156148435780601f1061481857610100808354040283529160200191614843565b820191906000526020600020905b81548152906001019060200180831161482657829003601f168201915b505050505082828151811061485457fe5b602090810291909101015260010161475b565b50949350505050565b60005b828110156149bd5760008287838801604051602001614893929190616130565b6040516020818303038152906040528051906020012060001c816148b357fe5b069050808501828701146149b457600089838801815181106148d157fe5b60200260200101519050606089848901815181106148eb57fe5b602002602001015190508a8388018151811061490357fe5b60200260200101518b858a018151811061491957fe5b60200260200101906001600160a01b031690816001600160a01b031681525050818b8489018151811061494857fe5b60200260200101906001600160a01b031690816001600160a01b031681525050898388018151811061497657fe5b60200260200101518a858a018151811061498c57fe5b6020026020010181905250808a848901815181106149a657fe5b602002602001018190525050505b50600101614873565b5050505050505050565b600980546001908101909155600b8054839081106149e157fe5b906000526020600020906016020160010160006101000a81548160ff02191690831515021790555043600b8281548110614a1757fe5b600091825260208220601690910201919091556040516001600160a01b038416917ff62981a567ec3cec866c6fa93c55bcdf841d6292d18b8d522ececa769375d82d91a25050565b600081604051602001614a729190616114565b6040516020818303038152906040528051906020012083604051602001614a999190616114565b6040516020818303038152906040528051906020012014905092915050565b015190565b614ac5615a69565b6000614acf615a69565b614ad7615b7f565b614ae8614ae386615334565b615359565b90506000805b614af7836153a3565b15614c6b5780614b1c57614b12614b0d846153c4565b615412565b60ff168452614c63565b8060011415614c5e576060614b38614b33856153c4565b615492565b90508051604051908082528060200260200182016040528015614b7557816020015b614b62615a34565b815260200190600190039081614b5a5790505b5085602001819052508051604051908082528060200260200182016040528015614bb357816020015b6060815260200190600190039081614b9e5790505b50604086015260005b8151811015614c5357614bcd615a34565b60606000614bed858581518110614be057fe5b6020026020010151615563565b92509250925080614c0d578860009a509a50505050505050505050614c74565b8289602001518581518110614c1e57fe5b60200260200101819052508189604001518581518110614c3a57fe5b6020026020010181905250505050806001019050614bbc565b506001925050614c63565b614c6b565b600101614aee565b50919350909150505b915091565b815181516000916001918114808314614c955760009250614cd3565b600160208701838101602088015b600284838510011415614cce578051835114614cc25760009650600093505b60209283019201614ca3565b505050505b5090949350505050565b6001600160a01b03811660009081526004602052604081205480614d06575060001990506114e1565b600181039050600060018281548110614d1b57fe5b9060005260206000209060040201600301549050600060018381548110614d3e57fe5b6000918252602090912060036004909202010155600154604051600019909101906001600160a01b038616907f8cd4e147d8af98a9e3b6724021b8bf6aed2e5dac71c38f2dce8161b82585b25d90614d97908590616d89565b60405180910390a280614daf578293505050506114e1565b6000818381614dba57fe5b0490508015614e565760005b84811015614e0857614ddf82600183815481106146aa57fe5b60018281548110614dec57fe5b6000918252602090912060036004909202010155600101614dc6565b50600180549085015b81811015614e5357614e2a83600183815481106146aa57fe5b60018281548110614e3757fe5b6000918252602090912060036004909202010155600101614e11565b50505b5091949350505050565b600082614e6f57506000611591565b82820282848281614e7c57fe5b0414611bca5760405162461bcd60e51b8152600401610c0f9061692e565b6000611bca83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061567d565b805182516000916001600160a01b039182169116148015614f16575081602001516001600160a01b031683602001516001600160a01b0316145b8015611bca5750506040908101519101516001600160a01b0390811691161490565b60125460135480821115614f8357805b82811015614f81576012805480614f5b57fe5b600190038181906000526020600020016000614f779190615a8d565b9055600101614f48565b505b6000818310614f925781614f94565b825b905060005b818110156150ac5761505160128281548110614fb157fe5b600091825260209182902001805460408051601f600260001961010060018716150201909416939093049283018590048502810185019091528181529283018282801561503f5780601f106150145761010080835404028352916020019161503f565b820191906000526020600020905b81548152906001019060200180831161502257829003601f168201915b505050505060138381548110612d4857fe5b6150a4576013818154811061506257fe5b906000526020600020016012828154811061507957fe5b9060005260206000200190805460018160011615610100020316600290046150a2929190615ae0565b505b600101614f99565b5082821115610c3157825b8281101561332d576012601382815481106150ce57fe5b6000918252602080832084546001818101875595855291909320929091018054615111949390920192909160026101009282161592909202600019011604615ae0565b506001016150b7565b601354600b548082111561516557805b8281101561516357601380548061513d57fe5b6001900381819060005260206000200160006151599190615a8d565b905560010161512a565b505b60008183106151745781615176565b825b905060005b81811015615295576152336013828154811061519357fe5b600091825260209182902001805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152928301828280156152215780601f106151f657610100808354040283529160200191615221565b820191906000526020600020905b81548152906001019060200180831161520457829003601f168201915b5050505050600b8381548110613fba57fe5b61528d57600b818154811061524457fe5b90600052602060002090601602016002016013828154811061526257fe5b90600052602060002001908054600181600116156101000203166002900461528b929190615ae0565b505b60010161517b565b5082821115610c3157825b8281101561332d576013600b82815481106152b757fe5b6000918252602080832084546001808201875595855291909320601692909202909201600290810180546152ff95939094019390926000199082161561010002011604615ae0565b506001016152a0565b6000818484111561532c5760405162461bcd60e51b8152600401610c0f919061625e565b505050900390565b61533c615b9f565b506040805180820190915281518152602082810190820152919050565b615361615b7f565b61536a826156b4565b61537357600080fd5b600061538283602001516156ee565b60208085015160408051808201909152868152920190820152915050919050565b60006153ad615b9f565b505080518051602091820151919092015191011190565b6153cc615b9f565b6153d5826153a3565b6153de57600080fd5b602082015160006153ee82615751565b80830160209586015260408051808201909152908152938401919091525090919050565b80516000901580159061542757508151602110155b61543057600080fd5b600061543f83602001516156ee565b905080836000015110156154655760405162461bcd60e51b8152600401610c0f90616a93565b82516020808501518301805192849003929183101561486757506020919091036101000a90049392505050565b606061549d826156b4565b6154a657600080fd5b60006154b183615832565b90506060816040519080825280602002602001820160405280156154ef57816020015b6154dc615b9f565b8152602001906001900390816154d45790505b509050600061550185602001516156ee565b60208601510190506000805b848110156155585761551e83615751565b915060405180604001604052808381526020018481525084828151811061554157fe5b60209081029190910101529181019160010161550d565b509195945050505050565b61556b615a34565b60606000615577615a34565b6060615581615b7f565b61558a87615359565b90506000805b615599836153a3565b1561566e57806155c4576155b46155af846153c4565b61588e565b6001600160a01b03168552615666565b80600114156155ec576155d96155af846153c4565b6001600160a01b03166020860152615666565b8060021415615614576156016155af846153c4565b6001600160a01b03166040860152615666565b806003141561564057615629614b0d846153c4565b6001600160401b0316606086015260019150615666565b80600414156156615761565a615655846153c4565b6158a8565b9350615666565b61566e565b600101615590565b50929791965091945092505050565b6000818361569e5760405162461bcd60e51b8152600401610c0f919061625e565b5060008385816156aa57fe5b0495945050505050565b80516000906156c5575060006114e1565b6020820151805160001a9060c08210156156e4576000925050506114e1565b5060019392505050565b8051600090811a60808110156157085760009150506114e1565b60b8811080615723575060c08110801590615723575060f881105b156157325760019150506114e1565b60c08110156157465760b5190190506114e1565b60f5190190506114e1565b80516000908190811a608081101561576c576001915061582b565b60b881101561578157607e198101915061582b565b60c08110156157d257600060b78203600186019550806020036101000a8651049150600181018201935050808310156157cc5760405162461bcd60e51b8152600401610c0f90616831565b5061582b565b60f88110156157e75760be198101915061582b565b600060f78203600186019550806020036101000a8651049150600181018201935050808310156158295760405162461bcd60e51b8152600401610c0f90616831565b505b5092915050565b8051600090615843575060006114e1565b6000809050600061585784602001516156ee565b602085015185519181019250015b808210156158855761587682615751565b82019150826001019250615865565b50909392505050565b805160009060151461589f57600080fd5b61159182615412565b80516060906158b657600080fd5b60006158c583602001516156ee565b83516040805191839003808352601f19601f82011683016020019091529192506060908280156158fc576020820181803683370190505b50905060008160200190506148678487602001510182858061591d57610c31565b5b6020811061593d578251825260209283019290910190601f190161591e565b915181516020939093036101000a6000190180199091169216919091179052565b60405180608001604052806000815260200160001515815260200160608152602001615988615bb9565b905290565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106159ce57805160ff19168380011785556159fb565b828001600101855582156159fb579182015b828111156159fb5782518255916020019190600101906159e0565b50612b2a929150615bd8565b82601381019282156159fb57916020028201828111156159fb5782518255916020019190600101906159e0565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b6040518060600160405280600060ff16815260200160608152602001606081525090565b50805460018160011615610100020316600290046000825580601f10615ab357506116f9565b601f0160209004906000526020600020908101906116f99190615bd8565b506116f9906013810190615bd8565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10615b1957805485556159fb565b828001600101855582156159fb57600052602060002091601f016020900482015b828111156159fb578254825591600101919060010190615b3a565b82601381019282156159fb57918201828111156159fb578254825591600101919060010190615b3a565b6040518060400160405280615b92615b9f565b8152602001600081525090565b604051806040016040528060008152602001600081525090565b6040518061026001604052806013906020820280368337509192915050565b611dac91905b80821115612b2a5760008155600101615bde565b803561159181616e3e565b60008083601f840112615c0e578182fd5b5081356001600160401b03811115615c24578182fd5b6020830191508360208083028501011115613ae257600080fd5b6000601f8381840112615c4f578182fd5b8235615c62615c5d82616df3565b616dcd565b818152925060208084019085810160005b84811015615cf4578135880189603f820112615c8e57600080fd5b838101356001600160401b03811115615ca657600080fd5b615cb7818901601f19168601616dcd565b81815260408c81848601011115615ccd57600080fd5b82818501888401375060009181018601919091528552509282019290820190600101615c73565b50505050505092915050565b600082601f830112615d10578081fd5b8135615d1e615c5d82616df3565b818152915060208083019084810181840286018201871015615d3f57600080fd5b6000805b85811015615cf45782356001600160401b0381168114615d61578283fd5b85529383019391830191600101615d43565b60008083601f840112615d84578182fd5b5081356001600160401b03811115615d9a578182fd5b602083019150836020828501011115613ae257600080fd5b600060208284031215615dc3578081fd5b8135611bca81616e3e565b600060208284031215615ddf578081fd5b8151611bca81616e3e565b60008060008060408587031215615dff578283fd5b84356001600160401b0380821115615e15578485fd5b615e2188838901615bfd565b90965094506020870135915080821115615e39578384fd5b50615e4687828801615bfd565b95989497509550505050565b600080600060608486031215615e66578283fd5b83356001600160401b0380821115615e7c578485fd5b81860187601f820112615e8d578586fd5b80359250615e9d615c5d84616df3565b80848252602080830192508084018b828389028701011115615ebd57898afd5b8994505b86851015615ee757615ed38c82615bf2565b845260019490940193928101928101615ec1565b509097508801359350505080821115615efe578384fd5b615f0a87838801615d00565b93506040860135915080821115615f1f578283fd5b50615f2c86828701615c3e565b9150509250925092565b60008060208385031215615f48578182fd5b82356001600160401b03811115615f5d578283fd5b615f6985828601615d73565b90969095509350505050565b60008060008060408587031215615f8a578384fd5b84356001600160401b0380821115615fa0578586fd5b615fac88838901615d73565b90965094506020870135915080821115615fc4578384fd5b50615e4687828801615d73565b600060208284031215615fe2578081fd5b5035919050565b600060208284031215615ffa578081fd5b5051919050565b60008060408385031215616013578182fd5b505080516020909101519092909150565b600080600060408486031215616038578081fd5b833560ff81168114616048578182fd5b925060208401356001600160401b03811115616062578182fd5b61606e86828701615d73565b9497909650939450505050565b6000815180845260208085019450808401835b838110156160b35781516001600160a01b03168752958201959082019060010161608e565b509495945050505050565b60008284528282602086013780602084860101526020601f19601f85011685010190509392505050565b60008151808452616100816020860160208601616e12565b601f01601f19169290920160200192915050565b60008251616126818460208701616e12565b9190910192915050565b918252602082015260400190565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b03968716815294861660208601529290941660408401526001600160401b03166060830152911515608082015260a081019190915260c00190565b6001600160a01b0393909316835260208301919091521515604082015260600190565b600060208252611bca602083018461607b565b6000604082526161f6604083018561607b565b602083820381850152818551808452828401915082838202850101838801865b8381101561624457601f198784030185526162328383516160e8565b94860194925090850190600101616216565b50909998505050505050505050565b901515815260200190565b600060208252611bca60208301846160e8565b6000604082526162856040830186886160be565b82810360208401526162988185876160be565b979650505050505050565b6020808252601c908201527f6c656e677468206f66206275726e526174696f206d69736d6174636800000000604082015260600190565b60208082526026908201527f6c656e677468206f66206d61784e756d4f664d61696e7461696e696e67206d696040820152650e6dac2e8c6d60d31b606082015260800190565b60208082526038908201527f746865206e756d4f66436162696e657473206d757374206265206c657373207460408201527f68616e206d6178456c656374656456616c696461746f72730000000000000000606082015260800190565b6020808252602c908201527f6c656e677468206f66206d61784e756d4f66576f726b696e6743616e6469646160408201526b0e8cae640dad2e6dac2e8c6d60a31b606082015260800190565b60208082526025908201527f6c656e677468206f66206d61696e7461696e536c6173685363616c65206d69736040820152640dac2e8c6d60db1b606082015260800190565b6020808252818101527f6c656e677468206f66206e756d4f66436162696e657473206d69736d61746368604082015260600190565b60208082526019908201527f74686520636f6e7472616374206e6f7420696e69742079657400000000000000604082015260600190565b6020808252601f908201527f6f6e6c7920736c617368206f72207374616b6548756220636f6e747261637400604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b60208082526063908201527f7468652073797374656d52657761726442617365526174696f20706c7573206260408201527f75726e526174696f20616e642073797374656d526577617264416e74694d455660608201527f526174696f206d757374206265206e6f2067726561746572207468616e20313060808201526203030360ec1b60a082015260c00190565b60208082526028908201527f746865206e756d4f66436162696e657473206d75737420626520677265617465604082015267072207468616e20360c41b606082015260800190565b60208082526022908201527f63616e206e6f7420646f207468697320747769636520696e206f6e6520626c6f604082015261636b60f01b606082015260800190565b60208082526037908201527f746865206d61784e756d4f664d61696e7461696e696e67206d7573742062652060408201527f6c657373207468616e206e756d4f66436162696e657473000000000000000000606082015260800190565b6020808252601d908201527f6c656e677468206f66207475726e4c656e677468206d69736d61746368000000604082015260600190565b6020808252600a908201526919195c1c9958d85d195960b21b604082015260600190565b60208082526063908201527f746865206275726e526174696f20706c75732073797374656d5265776172644260408201527f617365526174696f20616e642073797374656d526577617264416e74694d455660608201527f526174696f206d757374206265206e6f2067726561746572207468616e20313060808201526203030360ec1b60a082015260c00190565b6020808252602b908201527f6c656e677468206f662073797374656d526577617264416e74694d455652617460408201526a0d2de40dad2e6dac2e8c6d60ab1b606082015260800190565b6020808252601590820152746465706f7369742076616c7565206973207a65726f60581b604082015260600190565b60208082526049908201527f746865206d61784e756d4f66576f726b696e6743616e64696461746573206d7560408201527f7374206265206e6f742067726561746572207468616e206d61784e756d4f6643606082015268616e6469646174657360b81b608082015260a00190565b6020808252601190820152706164646974696f6e206f766572666c6f7760781b604082015260600190565b60208082526063908201527f7468652073797374656d526577617264416e74694d4556526174696f20706c7560408201527f73206275726e526174696f20616e642073797374656d5265776172644261736560608201527f526174696f206d757374206265206e6f2067726561746572207468616e20313060808201526203030360ec1b60a082015260c00190565b60208082526023908201527f63616e206e6f7420656e7465722054656d706f72617279204d61696e74656e616040820152626e636560e81b606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252601490820152736761737072696365206973206e6f74207a65726f60601b604082015260600190565b6020808252602e908201527f746865206d6573736167652073656e646572206d75737420626520676f76657260408201526d1b985b98d94818dbdb9d1c9858dd60921b606082015260800190565b60208082526025908201527f6c656e677468206f66206d61784e756d4f6643616e64696461746573206d69736040820152640dac2e8c6d60db1b606082015260800190565b6020808252601290820152716e6f7420696e206d61696e74656e616e636560701b604082015260600190565b60208082526019908201527f74686520636f6e747261637420616c726561647920696e697400000000000000604082015260600190565b6020808252601a908201527f6c656e677468206973206c657373207468616e206f6666736574000000000000604082015260600190565b60208082526017908201527f6f6e6c792063757272656e742076616c696461746f7273000000000000000000604082015260600190565b60208082526021908201527f6661696c656420746f20706172736520696e69742076616c696461746f7253656040820152601d60fa1b606082015260800190565b6020808252602f908201527f746865206d6573736167652073656e646572206d7573742062652063726f737360408201526e0818da185a5b8818dbdb9d1c9858dd608a1b606082015260800190565b6020808252602d908201527f746865206d6573736167652073656e646572206d75737420626520746865206260408201526c3637b1b590383937b23ab1b2b960991b606082015260800190565b60208082526028908201527f6c656e677468206f662073797374656d52657761726442617365526174696f206040820152670dad2e6dac2e8c6d60c31b606082015260800190565b6020808252603e908201527f746865206d61696e7461696e536c6173685363616c65206d757374206265206760408201527f726561746572207468616e203020616e64206c657373207468616e2031300000606082015260800190565b60208082526030908201527f746865207475726e4c656e6774682073686f756c6420626520696e205b332c3660408201526f345d206f7220657175616c20746f203160801b606082015260800190565b6020808252600d908201526c756e6b6e6f776e20706172616d60981b604082015260600190565b60208082526029908201527f746865206d6573736167652073656e646572206d75737420626520736c6173686040820152680818dbdb9d1c9858dd60ba1b606082015260800190565b6020808252601f908201527f746865206d73672073656e646572206d757374206265207374616b6548756200604082015260600190565b61ffff91909116815260200190565b90815260200190565b6000848252831515602083015260606040830152616db360608301846160e8565b95945050505050565b63ffffffff91909116815260200190565b6040518181016001600160401b0381118282101715616deb57600080fd5b604052919050565b60006001600160401b03821115616e08578081fd5b5060209081020190565b60005b83811015616e2d578181015183820152602001616e15565b8381111561332d5750506000910152565b6001600160a01b03811681146116f957600080fdfe0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dbbf905ec80f905e8f846942a7cdd959bfe8d9487b2a43b33565295a698f7e294b6a7edd747c0554875d3fc531d19ba1497992c5e941ff80f3f7f110ffd8920a3ac38fdef318fe94a3f86048c27395000f846946488aa4d1955ee33403f8ccb1d4de5fb97c7ade294220f003d8bdfaadf52aa1e55ae4cc485e6794875941a87e90e440a39c99aa9cb5cea0ad6a3f0b2407b86048c27395000f846949ef9f4360c606c7ab4db26b016007d3ad0ab86a0946103af86a874b705854033438383c82575f25bc29418e2db06cbff3e3c5f856410a1838649e760175786048c27395000f84694ee01c3b1283aa067c58eab4709f85e99d46de5fe94ee4b9bfb1871c64e2bcabb1dc382dc8b7c4218a29415904ab26ab0e99d70b51c220ccdcccabee6e29786048c27395000f84694685b1ded8013785d6623cc18d214320b6bb6475994a20ef4e5e4e7e36258dbf51f4d905114cb1b34bc9413e39085dc88704f4394d35209a02b1a9520320c86048c27395000f8469478f3adfc719c99674c072166708589033e2d9afe9448a30d5eaa7b64492a160f139e2da2800ec3834e94055838358c29edf4dcc1ba1985ad58aedbb6be2b86048c27395000f84694c2be4ec20253b8642161bc3f444f53679c1f3d479466f50c616d737e60d7ca6311ff0d9c434197898a94d1d678a2506eeaa365056fe565df8bc8659f28b086048c27395000f846942f7be8361c80a4c1e7e9aaf001d0877f1cfde218945f93992ac37f3e61db2ef8a587a436a161fd210b94ecbc4fb1a97861344dad0867ca3cba2b860411f086048c27395000f84694ce2fd7544e0b2cc94692d4a704debef7bcb613289444abc67b4b2fba283c582387f54c9cba7c34bafa948acc2ab395ded08bb75ce85bf0f95ad2abc51ad586048c27395000f84694b8f7166496996a7da21cf1f1b04d9b3e26a3d077946770572763289aac606e4f327c2f6cc1aa3b3e3b94882d745ed97d4422ca8da1c22ec49d880c4c097286048c27395000f846942d4c407bbe49438ed859fe965b140dcf1aab71a9943ad0939e120f33518fbba04631afe7a3ed6327b194b2bbb170ca4e499a2b0f3cc85ebfa6e8c4dfcbea86048c27395000f846946bbad7cf34b5fa511d8e963dbba288b1960e75d694853b0f6c324d1f4e76c8266942337ac1b0af1a229442498946a51ca5924552ead6fc2af08b94fcba648601d1a94a2000f846944430b3230294d12c6ab2aac5c2cd68e80b16b581947b107f4976a252a6939b771202c28e64e03f52d694795811a7f214084116949fc4f53cedbf189eeab28601d1a94a2000f84694ea0a6e3c511bbd10f4519ece37dc24887e11b55d946811ca77acfb221a49393c193f3a22db829fcc8e9464feb7c04830dd9ace164fc5c52b3f5a29e5018a8601d1a94a2000f846947ae2f5b9e386cd1b50a4550696d957cb4900f03a94e83bcc5077e6b873995c24bac871b5ad856047e19464e48d4057a90b233e026c1041e6012ada897fe88601d1a94a2000f8469482012708dafc9e1b880fd083b32182b869be8e09948e5adc73a2d233a1b496ed3115464dd6c7b887509428b383d324bc9a37f4e276190796ba5a8947f5ed8601d1a94a2000f8469422b81f8e175ffde54d797fe11eb03f9e3bf75f1d94a1c3ef7ca38d8ba80cce3bfc53ebd2903ed21658942767f7447f7b9b70313d4147b795414aecea54718601d1a94a2000f8469468bf0b8b6fb4e317a0f9d6f03eaf8ce6675bc60d94675cfe570b7902623f47e7f59c9664b5f5065dcf94d84f0d2e50bcf00f2fc476e1c57f5ca2d57f625b8601d1a94a2000f846948c4d90829ce8f72d0163c1d5cf348a862d5506309485c42a7b34309bee2ed6a235f86d16f059deec5894cc2cedc53f0fa6d376336efb67e43d167169f3b78601d1a94a2000f8469435e7a025f4da968de7e4d7e4004197917f4070f194b1182abaeeb3b4d8eba7e6a4162eac7ace23d57394c4fd0d870da52e73de2dd8ded19fe3d26f43a1138601d1a94a2000f84694d6caa02bbebaebb5d7e581e4b66559e635f805ff94c07335cf083c1c46a487f0325769d88e163b653694efaff03b42e41f953a925fc43720e45fb61a19938601d1a94a20000175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dbaa164736f6c6343000604000a

Deployed Bytecode

0x6080604052600436106104405760003560e01c80638b5ad0c911610234578063c81b16621161012e578063e1c7392a116100b6578063f92eb86b1161007a578063f92eb86b14610b3f578063f9a2bbc714610b54578063fccc281314610b69578063fd4ad81f14610b7e578063fd6a687914610bad57610447565b8063e1c7392a14610ac2578063e40716a114610ad7578063ea321e4914610aec578063eb57e20214610b0c578063f340fa0114610b2c57610447565b8063d58918ae116100fd578063d58918ae14610a59578063d68fb56a14610a6e578063daacdb6614610a83578063dc927faf14610a98578063df8079e914610aad57610447565b8063c81b166214610a0f578063c8509d81146107e6578063cb75a59214610a24578063ce910b0c14610a3957610447565b8063aa82dce1116101bc578063aef198a911610180578063aef198a914610999578063b7ab4db5146109ae578063b8cf4ef1146109d0578063c466689d146109e5578063c6d33945146109fa57610447565b8063aa82dce11461090d578063aad5606314610922578063ab51bb9614610937578063ac43175114610959578063ad3c9da61461097957610447565b80639dc09262116102035780639dc09262146108a45780639fe0f816146108b9578063a1a11bf5146108ce578063a5422d5c146108e3578063a78abc16146108f857610447565b80638b5ad0c9146108455780638c5d749d1461085a5780638d19a4101461086f5780639369d7de1461088f57610447565b80634df6e0c3116103455780636e47b482116102cd578063820dcaa811610291578063820dcaa8146107d1578063831d65d1146107e6578063862498821461080657806388b32f111461081b5780638a7beb011461083057610447565b80636e47b4821461076857806375d47a0a1461077d57806378dfed4a146107925780637a84ca2a146107a75780637e434d54146107bc57610447565b806355614fcc1161031457806355614fcc146106c1578063565c56b3146106e157806360eba4fe1461070157806362b72cf5146107215780636969a25c1461073657610447565b80634df6e0c31461066d5780635192c82c1461068257806351b4dce31461069757806351e80672146106ac57610447565b80632a0ffb6e116103c857806335409f7f1161039757806335409f7f146105de5780633b071dcc146105fe57806343756e5c1461062157806345cf9daf14610636578063493279b11461064b57610447565b80632a0ffb6e1461055e578063300c35671461057e578063321d398a1461059e5780633365af3a146105be57610447565b8063152ad3b81161040f578063152ad3b8146104dd5780631bd14ed8146104ff5780631e4c1524146105145780631ff1806914610534578063280870281461054957610447565b806304c4fec61461044c57806307a56847146104635780630e2374a51461048e5780631182b875146104b057610447565b3661044757005b600080fd5b34801561045857600080fd5b50610461610bc2565b005b34801561046f57600080fd5b50610478610c36565b6040516104859190616d89565b60405180910390f35b34801561049a57600080fd5b506104a3610c3c565b604051610485919061613e565b3480156104bc57600080fd5b506104d06104cb366004616024565b610c42565b604051610485919061625e565b3480156104e957600080fd5b506104f2610d5e565b6040516104859190616253565b34801561050b57600080fd5b50610478610d67565b34801561052057600080fd5b5061046161052f366004615e52565b610d6d565b34801561054057600080fd5b506104786110a1565b34801561055557600080fd5b506104a36110a7565b34801561056a57600080fd5b50610461610579366004615db2565b6110ad565b34801561058a57600080fd5b50610461610599366004615dea565b6110ce565b3480156105aa57600080fd5b506104f26105b9366004615fd1565b611417565b3480156105ca57600080fd5b506104f26105d9366004615fd1565b6114e6565b3480156105ea57600080fd5b506104616105f9366004615db2565b611597565b34801561060a57600080fd5b506106136116fc565b6040516104859291906161e3565b34801561062d57600080fd5b506104a36119d8565b34801561064257600080fd5b506104786119de565b34801561065757600080fd5b506106606119e4565b6040516104859190616d7a565b34801561067957600080fd5b506106136119e9565b34801561068e57600080fd5b50610478611b83565b3480156106a357600080fd5b506104a3611b89565b3480156106b857600080fd5b506104a3611b8f565b3480156106cd57600080fd5b506104f26106dc366004615db2565b611b95565b3480156106ed57600080fd5b506104786106fc366004615db2565b611bd1565b34801561070d57600080fd5b506104d061071c366004615fd1565b611c22565b34801561072d57600080fd5b50610478611cc8565b34801561074257600080fd5b50610756610751366004615fd1565b611cce565b6040516104859695949392919061616b565b34801561077457600080fd5b506104a3611d32565b34801561078957600080fd5b506104a3611d38565b34801561079e57600080fd5b50610478611d3e565b3480156107b357600080fd5b50610478611d44565b3480156107c857600080fd5b506104a3611d4a565b3480156107dd57600080fd5b50610478611d50565b3480156107f257600080fd5b50610461610801366004616024565b611d56565b34801561081257600080fd5b50610478611d77565b34801561082757600080fd5b50610478611d7d565b34801561083c57600080fd5b506104f2611d83565b34801561085157600080fd5b50610478611d8c565b34801561086657600080fd5b50610478611d92565b34801561087b57600080fd5b5061047861088a366004615db2565b611daf565b34801561089b57600080fd5b50610461611def565b3480156108b057600080fd5b506104a3611f03565b3480156108c557600080fd5b50610478611f09565b3480156108da57600080fd5b506104a3611f0e565b3480156108ef57600080fd5b506104d0611f14565b34801561090457600080fd5b506104f2611f33565b34801561091957600080fd5b506104a3611f3c565b34801561092e57600080fd5b506104a3611f42565b34801561094357600080fd5b5061094c611f48565b6040516104859190616dbc565b34801561096557600080fd5b50610461610974366004615f75565b611f4d565b34801561098557600080fd5b50610478610994366004615db2565b6129b6565b3480156109a557600080fd5b506104786129c8565b3480156109ba57600080fd5b506109c36129d5565b60405161048591906161d0565b3480156109dc57600080fd5b50610478612ac0565b3480156109f157600080fd5b50610478612ac5565b348015610a0657600080fd5b50610478612acb565b348015610a1b57600080fd5b506104a3612ad0565b348015610a3057600080fd5b50610478612ad6565b348015610a4557600080fd5b506104d0610a54366004615fd1565b612adc565b348015610a6557600080fd5b50610478612ae9565b348015610a7a57600080fd5b50610478612aef565b348015610a8f57600080fd5b50610478612b2e565b348015610aa457600080fd5b506104a3612b34565b348015610ab957600080fd5b506104a3612b3a565b348015610ace57600080fd5b50610461612b40565b348015610ae357600080fd5b50610478612ce9565b348015610af857600080fd5b506104f2610b07366004615f36565b612cef565b348015610b1857600080fd5b50610461610b27366004615db2565b612e75565b610461610b3a366004615db2565b612f7d565b348015610b4b57600080fd5b50610478613333565b348015610b6057600080fd5b506104a3613339565b348015610b7557600080fd5b506104a361333f565b348015610b8a57600080fd5b50610b9e610b99366004615fd1565b613345565b60405161048593929190616d92565b348015610bb957600080fd5b506104a3613407565b6000610bcd33611daf565b9050600b8181548110610bdc57fe5b600091825260209091206001601690920201015460ff16610c185760405162461bcd60e51b8152600401610c0f90616a30565b60405180910390fd5b6000610c22612aef565b9050610c31338383600161340d565b505050565b60095481565b61200181565b60005460609060ff16610c675760405162461bcd60e51b8152600401610c0f90616443565b3361200014610c885760405162461bcd60e51b8152600401610c0f90616b42565b600b54610d4657610c9761595e565b60015460005b81811015610d4257600b80546001810182556000919091528351600080516020616e5483398151915260169092029182019081556020808601516000805160206174838339815191528401805460ff1916911515919091179055604086015180518794610d1e93600080516020616e7483398151915290910192019061598d565b506060820151610d349060038301906013615a07565b505050806001019050610c9d565b5050505b60405162461bcd60e51b8152600401610c0f90616695565b60075460ff1681565b600f5481565b334114610d8c5760405162461bcd60e51b8152600401610c0f90616b91565b3a15610daa5760405162461bcd60e51b8152600401610c0f9061696f565b8251604080518281526020808402820101909152606090828015610de857816020015b610dd5615a34565b815260200190600190039081610dcd5790505b50905060005b82811015610e92576040518060c00160405280878381518110610e0d57fe5b60200260200101516001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b03168152602001868381518110610e4f57fe5b60200260200101516001600160401b031681526020016000151581526020016000815250828281518110610e7f57fe5b6020908102919091010152600101610dee565b50606080610ea083866135ff565b9150915060005b600154811015610f9657600060018281548110610ec057fe5b906000526020600020906004020160030154905080600014610f8d57600060018381548110610eeb57fe5b9060005260206000209060040201600301819055506120026001600160a01b031663092193ab8260018581548110610f1f57fe5b60009182526020909120600491820201546040516001600160e01b031960e086901b168152610f5a926001600160a01b03909216910161613e565b6000604051808303818588803b158015610f7357600080fd5b505af1158015610f87573d6000803e3d6000fd5b50505050505b50600101610ea7565b504715611004577f6ecc855f9440a9282c90913bbc91619fd44f5ec0b462af28d127b116f130aa4d47604051610fcc9190616d89565b60405180910390a1604051611002904780156108fc02916000818181858888f19350505050158015611002573d6000803e3d6000fd5b505b600060035581511561101a5761101a8282613ae9565b6110016001600160a01b031663fc4333cd6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561105757600080fd5b505af115801561106b573d6000803e3d6000fd5b50506040517fedd8d7296956dd970ab4de3f2fc03be2b0ffc615d20cd4c72c6e44f928630ebf925060009150a150505050505050565b60035481565b61200581565b3361200214610d465760405162461bcd60e51b8152600401610c0f90616d43565b3341146110ed5760405162461bcd60e51b8152600401610c0f90616b91565b601054431161110e5760405162461bcd60e51b8152600401610c0f906165bf565b3a1561112c5760405162461bcd60e51b8152600401610c0f9061696f565b60005460ff1661114e5760405162461bcd60e51b8152600401610c0f90616443565b60006110023168056bc75e2d631000008111156111855761117e8168056bc75e2d6310000063ffffffff6142d816565b915061118c565b505061140d565b6040516309a99b4f60e41b815261100290639a99b4f0906111b39030908690600401616152565b602060405180830381600087803b1580156111cd57600080fd5b505af11580156111e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112059190615fe9565b91508161121357505061140d565b6000805b848110156112415785858281811061122b57fe5b9050602002013582019150806001019050611217565b508061124f5750505061140d565b6000806000805b89811015611405578489898381811061126b57fe5b9050602002013588028161127b57fe5b0493508a8a8281811061128a57fe5b905060200201602081019061129f9190615db2565b6001600160a01b038116600090815260046020526040902054909350915081156113bb5760006001808403815481106112d457fe5b9060005260206000209060040201905080600201601c9054906101000a900460ff161561134157836001600160a01b03167fb9c75cbbfde137c4281689580799ef5f52144e78858f776a5979b2b212137d85866040516113349190616d89565b60405180910390a26113b5565b600354611354908663ffffffff61431a16565b600390815581015461136c908663ffffffff61431a16565b60038201556040516001600160a01b038516907fcb0aad6cf9cd03bdf6137e359f541c42f38b39f007cae8e89e88aa7d8c6617b2906113ac908890616d89565b60405180910390a25b506113fd565b826001600160a01b03167fb9c75cbbfde137c4281689580799ef5f52144e78858f776a5979b2b212137d85856040516113f49190616d89565b60405180910390a25b600101611256565b505050505050505b5050436010555050565b600154600090821061142b575060006114e1565b60006001600160a01b03166001838154811061144357fe5b60009182526020909120600490910201546001600160a01b03161480611473575060085415806114735750600a54155b80611482575060085460095410155b806114935750611491826114e6565b155b806114bc57506000600b83815481106114a857fe5b906000526020600020906016020160000154115b806114d0575060016114cc6129d5565b5111155b156114dd575060006114e1565b5060015b919050565b60015460009082106114fa575060006114e1565b600b548210611537576001828154811061151057fe5b9060005260206000209060040201600201601c9054906101000a900460ff161590506114e1565b6001828154811061154457fe5b9060005260206000209060040201600201601c9054906101000a900460ff161580156115915750600b828154811061157857fe5b600091825260209091206001601690920201015460ff16155b92915050565b600b54611655576115a661595e565b60015460005b8181101561165157600b80546001810182556000919091528351600080516020616e5483398151915260169092029182019081556020808601516000805160206174838339815191528401805460ff191691151591909117905560408601518051879461162d93600080516020616e7483398151915290910192019061598d565b5060608201516116439060038301906013615a07565b5050508060010190506115ac565b5050505b336110011480611666575033612002145b6116825760405162461bcd60e51b8152600401610c0f9061647a565b6001600160a01b038116600090815260046020526040902054806116a657506116f9565b6001810390506000600b82815481106116bb57fe5b600091825260209091206001601690920201015460ff1690506116de838361433f565b80156116e75750805b15610c31576009805460001901905550505b50565b60015460609081906000805b8281101561174f576001818154811061171d57fe5b9060005260206000209060040201600201601c9054906101000a900460ff16611747576001909101905b600101611708565b5060608160405190808252806020026020018201604052801561177c578160200160208202803683370190505b5090506060826040519080825280602002602001820160405280156117b557816020015b60608152602001906001900390816117a05790505b50600b54600094509091508414156119305760005b8481101561192a57600181815481106117df57fe5b9060005260206000209060040201600201601c9054906101000a900460ff16611922576001818154811061180f57fe5b600091825260209091206004909102015483516001600160a01b039091169084908690811061183a57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050600b818154811061186757fe5b600091825260209182902060026016909202018101805460408051601f6000196101006001861615020190931694909404918201859004850284018501905280835291929091908301828280156118ff5780601f106118d4576101008083540402835291602001916118ff565b820191906000526020600020905b8154815290600101906020018083116118e257829003601f168201915b505050505082858151811061191057fe5b60209081029190910101526001909301925b6001016117ca565b506119cc565b60005b848110156119ca576001818154811061194857fe5b9060005260206000209060040201600201601c9054906101000a900460ff166119c2576001818154811061197857fe5b600091825260209091206004909102015483516001600160a01b03909116908490869081106119a357fe5b6001600160a01b03909216602092830291909101909101526001909301925b600101611933565b505b909450925050505b9091565b61100181565b60085481565b603881565b6060806000600e549050600080600c5411611a05576015611a09565b600c545b905060c86060611a176129d5565b90506060611a2482614702565b905083825111611a3c5790955093506119d492505050565b84848351031015611a4e578382510394505b8415611a8e576000834381611a5f57fe5b049050611a7483838389890360008b8b614870565b611a8c8383838989038a8a038b8c8c8b510301614870565b505b606084604051908082528060200260200182016040528015611aba578160200160208202803683370190505b509050606085604051908082528060200260200182016040528015611af357816020015b6060815260200190600190039081611ade5790505b50905060005b86811015611b7457848181518110611b0d57fe5b6020026020010151838281518110611b2157fe5b60200260200101906001600160a01b031690816001600160a01b031681525050838181518110611b4d57fe5b6020026020010151828281518110611b6157fe5b6020908102919091010152600101611af9565b50909750955050505050509091565b60065481565b61200681565b61200081565b6001600160a01b03811660009081526004602052604081205480611bbd5760009150506114e1565b60001901611bca816114e6565b9392505050565b6001600160a01b03811660009081526004602052604081205480611bf95760009150506114e1565b600180820381548110611c0857fe5b906000526020600020906004020160030154915050919050565b60128181548110611c2f57fe5b600091825260209182902001805460408051601f6002600019610100600187161502019094169390930492830185900485028101850190915281815293509091830182828015611cc05780601f10611c9557610100808354040283529160200191611cc0565b820191906000526020600020905b815481529060010190602001808311611ca357829003601f168201915b505050505081565b60105481565b60018181548110611cdb57fe5b600091825260209091206004909102018054600182015460028301546003909301546001600160a01b0392831694509082169291821691600160a01b81046001600160401b031691600160e01b90910460ff169086565b61100581565b61100881565b6103e881565b600c5481565b61200381565b61271081565b3361200014610d465760405162461bcd60e51b8152600401610c0f90616b42565b60025481565b60115481565b60145460ff1681565b600a5481565b600060175460001415611da757506001611dac565b506017545b90565b6001600160a01b03811660009081526004602052604081205480611de55760405162461bcd60e51b8152600401610c0f90616aca565b6000190192915050565b600b54611ead57611dfe61595e565b60015460005b81811015611ea957600b80546001810182556000919091528351600080516020616e5483398151915260169092029182019081556020808601516000805160206174838339815191528401805460ff1916911515919091179055604086015180518794611e8593600080516020616e7483398151915290910192019061598d565b506060820151611e9b9060038301906013615a07565b505050806001019050611e04565b5050505b600854611eba5760036008555b600a54611ec7576002600a555b6000611ed233611daf565b9050611edd81611417565b611ef95760405162461bcd60e51b8152600401610c0f906168eb565b6116f933826149c7565b61100781565b600381565b61100681565b6040518061062001604052806105ef8152602001616e946105ef913981565b60005460ff1681565b61200281565b61300081565b600081565b60005460ff16611f6f5760405162461bcd60e51b8152600401610c0f90616443565b3361100714611f905760405162461bcd60e51b8152600401610c0f9061699d565b611ff084848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260098152686275726e526174696f60b81b60208201529150614a5f9050565b156120a557602081146120155760405162461bcd60e51b8152600401610c0f906162a3565b604080516020601f840181900481028201810190925282815260009161205391858580838501838280828437600092019190915250614ab892505050565b905061271061207f601854612073600f548561431a90919063ffffffff16565b9063ffffffff61431a16565b111561209d5760405162461bcd60e51b8152600401610c0f906166b9565b600655612973565b61210f84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260138152726d61784e756d4f664d61696e7461696e696e6760681b60208201529150614a5f9050565b156121a957602081146121345760405162461bcd60e51b8152600401610c0f906162da565b604080516020601f840181900481028201810190925282815260009161217291858580838501838280828437600092019190915250614ab892505050565b600c5490915080612181575060155b8082106121a05760405162461bcd60e51b8152600401610c0f90616601565b50600855612973565b61221284848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260128152716d61696e7461696e536c6173685363616c6560701b60208201529150614a5f9050565b156122ab57602081146122375760405162461bcd60e51b8152600401610c0f906163c9565b604080516020601f840181900481028201810190925282815260009161227591858580838501838280828437600092019190915250614ab892505050565b90506000811180156122875750600a81105b6122a35760405162461bcd60e51b8152600401610c0f90616c26565b600a55612973565b61231f84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601981527f6d61784e756d4f66576f726b696e6743616e646964617465730000000000000060208201529150614a5f9050565b156123ae57602081146123445760405162461bcd60e51b8152600401610c0f9061637d565b604080516020601f840181900481028201810190925282815260009161238291858580838501838280828437600092019190915250614ab892505050565b9050600d548111156123a65760405162461bcd60e51b8152600401610c0f906167c2565b600e55612973565b61241784848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260128152716d61784e756d4f6643616e6469646174657360701b60208201529150614a5f9050565b15612499576020811461243c5760405162461bcd60e51b8152600401610c0f906169eb565b604080516020601f840181900481028201810190925282815260009161247a91858580838501838280828437600092019190915250614ab892505050565b600d819055600e5490915081101561249357600d54600e555b50612973565b6124fd84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600d81526c6e756d4f66436162696e65747360981b60208201529150614a5f9050565b1561262257602081146125225760405162461bcd60e51b8152600401610c0f9061640e565b604080516020601f840181900481028201810190925282815260009161256091858580838501838280828437600092019190915250614ab892505050565b9050600081116125825760405162461bcd60e51b8152600401610c0f90616577565b60006120026001600160a01b031663c473318f6040518163ffffffff1660e01b815260040160206040518083038186803b1580156125bf57600080fd5b505afa1580156125d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125f79190615fe9565b9050808211156126195760405162461bcd60e51b8152600401610c0f90616320565b50600c55612973565b61268e84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601581527473797374656d52657761726442617365526174696f60581b60208201529150614a5f9050565b1561273757602081146126b35760405162461bcd60e51b8152600401610c0f90616bde565b604080516020601f84018190048102820181019092528281526000916126f191858580838501838280828437600092019190915250614ab892505050565b90506127106127116018546120736006548561431a90919063ffffffff16565b111561272f5760405162461bcd60e51b8152600401610c0f906164e8565b600f55612973565b6127ab84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601881527f73797374656d526577617264416e74694d4556526174696f000000000000000060208201529150614a5f9050565b1561285457602081146127d05760405162461bcd60e51b8152600401610c0f90616748565b604080516020601f840181900481028201810190925282815260009161280e91858580838501838280828437600092019190915250614ab892505050565b905061271061282e600f546120736006548561431a90919063ffffffff16565b111561284c5760405162461bcd60e51b8152600401610c0f9061685c565b601855612973565b6128b584848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600a8152690e8eae4dc98cadccee8d60b31b60208201529150614a5f9050565b1561295b57602081146128da5760405162461bcd60e51b8152600401610c0f9061665e565b604080516020601f840181900481028201810190925282815260009161291891858580838501838280828437600092019190915250614ab892505050565b90506003811015801561292c575060408111155b806129375750806001145b6129535760405162461bcd60e51b8152600401610c0f90616c83565b601755612973565b60405162461bcd60e51b8152600401610c0f90616cd3565b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a848484846040516129a89493929190616271565b60405180910390a150505050565b60046020526000908152604090205481565b68056bc75e2d6310000081565b6001546060906000805b82811015612a04576129f0816114e6565b156129fc578160010191505b6001016129df565b50606081604051908082528060200260200182016040528015612a31578160200160208202803683370190505b5090506000915060005b83811015612ab857612a4c816114e6565b15612ab05760018181548110612a5e57fe5b600091825260209091206004909102015482516001600160a01b0390911690839085908110612a8957fe5b60200260200101906001600160a01b031690816001600160a01b0316815250508260010192505b600101612a3b565b509250505090565b601581565b61027181565b600281565b61100281565b60175481565b60138181548110611c2f57fe5b60185481565b6000612af96129d5565b519050600080600c5411612b0e576015612b12565b600c545b905080821115612b20578091505b81612b2a57600191505b5090565b60055481565b61100381565b61200481565b60005460ff1615612b635760405162461bcd60e51b8152600401610c0f90616a5c565b612b6b615a69565b6000612b916040518061062001604052806105ef8152602001616e946105ef9139614abd565b9150915080612bb25760405162461bcd60e51b8152600401610c0f90616b01565b60005b826020015151811015612cd757600183602001518281518110612bd457fe5b60209081029190910181015182546001818101855560009485528385208351600493840290910180546001600160a01b039283166001600160a01b03199182161782558587015182850180549185169183169190911790556040860151600283018054606089015160808a01511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b199590981692909516919091179290921694909417161790915560a090930151600390930192909255918601518051918501939185908110612caa57fe5b602090810291909101810151516001600160a01b0316825281019190915260400160002055600101612bb5565b50506000805460ff1916600117905550565b600d5481565b601354600090815b81811015612df857612de085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050601380549092508591508110612d4857fe5b600091825260209182902001805460408051601f6002600019610100600187161502019094169390930492830185900485028101850190915281815292830182828015612dd65780601f10612dab57610100808354040283529160200191612dd6565b820191906000526020600020905b815481529060010190602001808311612db957829003601f168201915b5050505050614c79565b15612df057600192505050611591565b600101612cf7565b5060125460005b81811015612e6957612e5086868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050601280549092508591508110612d4857fe5b15612e615760019350505050611591565b600101612dff565b50600095945050505050565b3361100114612e965760405162461bcd60e51b8152600401610c0f90616cfa565b600b54612f5457612ea561595e565b60015460005b81811015612f5057600b80546001810182556000919091528351600080516020616e5483398151915260169092029182019081556020808601516000805160206174838339815191528401805460ff1916911515919091179055604086015180518794612f2c93600080516020616e7483398151915290910192019061598d565b506060820151612f429060038301906013615a07565b505050806001019050612eab565b5050505b6000612f5f82614cdd565b9050612f6a81611417565b15612f7957612f7982826149c7565b5050565b334114612f9c5760405162461bcd60e51b8152600401610c0f90616b91565b60005460ff16612fbe5760405162461bcd60e51b8152600401610c0f90616443565b60003411612fde5760405162461bcd60e51b8152600401610c0f90616793565b3a15612ffc5760405162461bcd60e51b8152600401610c0f9061696f565b6001600160a01b03811660009081526004602052604090205460145434919060ff1661303c57610271600f556103e86006556014805460ff191660011790555b600f54601754600110801561305357506000601854115b1561307857600160175403601754438161306957fe5b06601854028161307557fe5b04015b6000831180156130885750600081115b156131355760006130b16127106130a5348563ffffffff614e6016565b9063ffffffff614e9a16565b90508015613133576040516110029082156108fc029083906000818181858888f193505050501580156130e8573d6000803e3d6000fd5b507f6ecc855f9440a9282c90913bbc91619fd44f5ec0b462af28d127b116f130aa4d816040516131189190616d89565b60405180910390a1613130848263ffffffff6142d816565b93505b505b60008311801561314757506000600654115b156131ed5760006131696127106130a560065434614e6090919063ffffffff16565b905080156131eb5760405161dead9082156108fc029083906000818181858888f193505050501580156131a0573d6000803e3d6000fd5b507f627059660ea01c4733a328effb2294d2f86905bf806da763a89cee254de8bee5816040516131d09190616d89565b60405180910390a16131e8848263ffffffff6142d816565b93505b505b81156132eb57600060018084038154811061320457fe5b9060005260206000209060040201905080600201601c9054906101000a900460ff161561327157846001600160a01b03167ff177e5d6c5764d79c32883ed824111d9b13f5668cf6ab1cc12dd36791dd955b4856040516132649190616d89565b60405180910390a26132e5565b600354613284908563ffffffff61431a16565b600390815581015461329c908563ffffffff61431a16565b60038201556040516001600160a01b038616907f93a090ecc682c002995fad3c85b30c5651d7fd29b0be5da9d784a3302aedc055906132dc908790616d89565b60405180910390a25b5061332d565b836001600160a01b03167ff177e5d6c5764d79c32883ed824111d9b13f5668cf6ab1cc12dd36791dd955b4846040516133249190616d89565b60405180910390a25b50505050565b600e5481565b61100081565b61dead81565b600b818154811061335257fe5b6000918252602091829020601691909102018054600180830154600280850180546040805161010096831615969096026000190190911692909204601f810188900488028501880190925281845293965060ff909116949192918301828280156133fd5780601f106133d2576101008083540402835291602001916133fd565b820191906000526020600020905b8154815290600101906020018083116133e057829003601f168201915b5050505050905083565b61100481565b6000600a546000148061341e575082155b806134295750600954155b15613436575060006135f7565b60096000815460019003919050819055506000613481600a546130a5866130a5600b8a8154811061346357fe5b6000918252602090912060169091020154439063ffffffff6142d816565b90506000600b868154811061349257fe5b906000526020600020906016020160010160006101000a81548160ff0219169083151502179055506000806110016001600160a01b0316638256ace66040518163ffffffff1660e01b8152600401604080518083038186803b1580156134f757600080fd5b505afa15801561350b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061352f9190616001565b91509150600093508083106135ad57613548888861433f565b506040516328aa02b160e01b8152611001906328aa02b190613572908b9087908a906004016161ad565b600060405180830381600087803b15801561358c57600080fd5b505af11580156135a0573d6000803e3d6000fd5b50505050600193506135bf565b8183106135bf576135bd88614cdd565b505b6040516001600160a01b038916907fb9d38178dc641ff1817967a63c9078cbcd955a9f1fcd75e0e3636de615d44d3b90600090a25050505b949350505050565b606080600080808080613610612aef565b6001549091505b801561384257600181039250600b838154811061363057fe5b600091825260209091206001601690920201015460ff1661365057613839565b6001838154811061365d57fe5b600091825260208220600490910201546001600160a01b031695506136879086908590859061340d565b93508361369357613839565b60405163436aa28360e11b81526000908190612002906386d54506906136bd908a9060040161613e565b60206040518083038186803b1580156136d557600080fd5b505afa1580156136e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061370d9190615dce565b90506001600160a01b03811615613796576040516302ceee9160e11b81526120029063059ddd229061374390849060040161613e565b60206040518083038186803b15801561375b57600080fd5b505afa15801561376f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137939190615dce565b91505b60005b8c5181101561383557876001600160a01b03168d82815181106137b857fe5b6020026020010151600001516001600160a01b031614806138015750826001600160a01b03168d82815181106137ea57fe5b6020026020010151600001516001600160a01b0316145b1561382d5760018d828151811061381457fe5b6020908102919091010151901515608090910152613835565b600101613799565b5050505b60001901613617565b5060005b89518110156138af5789818151811061385b57fe5b6020026020010151608001518061389b575060006001600160a01b03168a828151811061388457fe5b6020026020010151600001516001600160a01b0316145b156138a7578560010195505b600101613846565b50885185106139975760408051600180825281830190925290816020015b6138d5615a34565b8152602001906001900390816138cd575050604080516001808252818301909252919850602082015b60608152602001906001900390816138fe5790505095508860008151811061392257fe5b60200260200101518760008151811061393757fe5b60200260200101819052508760008151811061394f57fe5b60200260200101518660008151811061396457fe5b602002602001018190525060008760008151811061397e57fe5b6020908102919091010151901515608090910152613adc565b848951036040519080825280602002602001820160405280156139d457816020015b6139c1615a34565b8152602001906001900390816139b95790505b50965084895103604051908082528060200260200182016040528015613a0e57816020015b60608152602001906001900390816139f95790505b5095506000915060005b8951811015613ada57898181518110613a2d57fe5b602002602001015160800151158015613a70575060006001600160a01b03168a8281518110613a5857fe5b6020026020010151600001516001600160a01b031614155b15613ad257898181518110613a8157fe5b6020026020010151888481518110613a9557fe5b6020026020010181905250888181518110613aac57fe5b6020026020010151878481518110613ac057fe5b60200260200101819052508260010192505b600101613a18565b505b50505050505b9250929050565b600154825160005b82811015613c06576001613b03615a34565b60018381548110613b1057fe5b600091825260208083206040805160c08101825260049490940290910180546001600160a01b0390811685526001820154811693850193909352600281015492831691840191909152600160a01b82046001600160401b03166060840152600160e01b90910460ff16151560808301526003015460a082015291505b84811015613bda57878181518110613ba057fe5b6020026020010151600001516001600160a01b031682600001516001600160a01b03161415613bd25760009250613bda565b600101613b8c565b508115613bfc5780516001600160a01b03166000908152600460205260408120555b5050600101613af1565b5080821115613cc557805b82811015613cc3576001805480613c2457fe5b60008281526020812060046000199093019283020180546001600160a01b0319908116825560018201805490911690556002810180546001600160e81b0319169055600301559055600b805480613c7757fe5b60008281526020812060166000199093019283020181815560018101805460ff1916905590613ca96002830182615a8d565b613cb7600383016000615ad1565b50509055600101613c11565b505b6000818310613cd45781613cd6565b825b905060005b8181101561407a57613d88868281518110613cf257fe5b602002602001015160018381548110613d0757fe5b60009182526020918290206040805160c08101825260049390930290910180546001600160a01b0390811684526001820154811694840194909452600281015493841691830191909152600160a01b83046001600160401b03166060830152600160e01b90920460ff161515608082015260039091015460a0820152614edc565b613f3c578060010160046000888481518110613da057fe5b6020026020010151600001516001600160a01b03166001600160a01b0316815260200190815260200160002081905550858181518110613ddc57fe5b602002602001015160018281548110613df157fe5b6000918252602091829020835160049092020180546001600160a01b039283166001600160a01b0319918216178255928401516001820180549184169185169190911790556040840151600282018054606087015160808801511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b1995909716929097169190911792909216939093171692909217905560a0909101516003909101558451859082908110613eac57fe5b6020026020010151600b8281548110613ec157fe5b90600052602060002090601602016002019080519060200190613ee592919061598d565b506000600b8281548110613ef557fe5b60009182526020822060169190910201600101805460ff191692151592909217909155600b805483908110613f2657fe5b6000918252602090912060169091020155614072565b858181518110613f4857fe5b60200260200101516060015160018281548110613f6157fe5b906000526020600020906004020160020160146101000a8154816001600160401b0302191690836001600160401b03160217905550614027858281518110613fa557fe5b6020026020010151600b8381548110613fba57fe5b600091825260209182902060026016909202018101805460408051601f600019610100600186161502019093169490940491820185900485028401850190528083529192909190830182828015612dd65780601f10612dab57610100808354040283529160200191612dd6565b6140725784818151811061403757fe5b6020026020010151600b828154811061404c57fe5b9060005260206000209060160201600201908051906020019061407092919061598d565b505b600101613cdb565b50828211156142525761408b61595e565b835b8381101561424f578581815181106140a157fe5b6020026020010151826040018190525060018782815181106140bf57fe5b6020908102919091018101518254600181810185556000948552838520835160049093020180546001600160a01b039384166001600160a01b0319918216178255848601518284018054918616918316919091179055604080860151600284018054606089015160808a01511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b1995909a1692909616919091179290921696909617169190911790935560a090930151600390930192909255600b8054928301815590935284516016909102600080516020616e548339815191528101918255858301516000805160206174838339815191528201805491151560ff19909216919091179055928501518051869492936141f593600080516020616e748339815191520192019061598d565b50606082015161420b9060038301906013615a07565b505050806001016004600089848151811061422257fe5b602090810291909101810151516001600160a01b031682528101919091526040016000205560010161408d565b50505b61425a614f38565b61426261511a565b6000600981905560015493505b838110156142d0576000600b828154811061428657fe5b60009182526020822060169190910201600101805460ff191692151592909217909155600b8054839081106142b757fe5b600091825260209091206016909102015560010161426f565b505050505050565b6000611bca83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250615308565b600082820183811015611bca5760405162461bcd60e51b8152600401610c0f906164b1565b6000806001838154811061434f57fe5b906000526020600020906004020160030154905060006001808054905003905060016143796129d5565b51116143ae5760006001858154811061438e57fe5b906000526020600020906004020160030181905550600092505050611591565b846001600160a01b03167f3b6f9ef90462b512a1293ecec018670bf7b7f1876fb727590a8a6d7643130a70836040516143e79190616d89565b60405180910390a26001600160a01b038516600090815260046020526040812055835b600154600019018110156145d4576001816001018154811061442857fe5b90600052602060002090600402016001828154811061444357fe5b60009182526020909120825460049092020180546001600160a01b03199081166001600160a01b0393841617825560018085015481840180548416918616919091179055600280860180549185018054909416919095161780835584546001600160401b03600160a01b91829004160267ffffffffffffffff60a01b1990911617808355935460ff600160e01b918290041615150260ff60e01b19909416939093179055600392830154920191909155600b80549091830190811061450457fe5b9060005260206000209060160201600b828154811061451f57fe5b600091825260209091208254601690920201908155600180830154818301805460ff909216151560ff1990921691909117905560028084018054614576938386019390821615610100026000190190911604615ae0565b5061458960038281019084016013615b55565b509050508060010160046000600184815481106145a257fe5b600091825260208083206004909202909101546001600160a01b0316835282019290925260400190205560010161440a565b5060018054806145e057fe5b60008281526020812060046000199093019283020180546001600160a01b0319908116825560018201805490911690556002810180546001600160e81b0319169055600301559055600b80548061463357fe5b60008281526020812060166000199093019283020181815560018101805460ff19169055906146656002830182615a8d565b614673600383016000615ad1565b50509055600081838161468257fe5b04905080156146f65760015460005b818110156146f3576146ca83600183815481106146aa57fe5b90600052602060002090600402016003015461431a90919063ffffffff16565b600182815481106146d757fe5b6000918252602090912060036004909202010155600101614691565b50505b50600195945050505050565b60015481516040805182815260208084028201019091526060929190839082801561474157816020015b606081526020019060019003908161472c5790505b50600b5490915083146147585792506114e1915050565b60005b8281101561486757600b60016004600089858151811061477757fe5b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205403815481106147ab57fe5b600091825260209182902060026016909202018101805460408051601f6000196101006001861615020190931694909404918201859004850284018501905280835291929091908301828280156148435780601f1061481857610100808354040283529160200191614843565b820191906000526020600020905b81548152906001019060200180831161482657829003601f168201915b505050505082828151811061485457fe5b602090810291909101015260010161475b565b50949350505050565b60005b828110156149bd5760008287838801604051602001614893929190616130565b6040516020818303038152906040528051906020012060001c816148b357fe5b069050808501828701146149b457600089838801815181106148d157fe5b60200260200101519050606089848901815181106148eb57fe5b602002602001015190508a8388018151811061490357fe5b60200260200101518b858a018151811061491957fe5b60200260200101906001600160a01b031690816001600160a01b031681525050818b8489018151811061494857fe5b60200260200101906001600160a01b031690816001600160a01b031681525050898388018151811061497657fe5b60200260200101518a858a018151811061498c57fe5b6020026020010181905250808a848901815181106149a657fe5b602002602001018190525050505b50600101614873565b5050505050505050565b600980546001908101909155600b8054839081106149e157fe5b906000526020600020906016020160010160006101000a81548160ff02191690831515021790555043600b8281548110614a1757fe5b600091825260208220601690910201919091556040516001600160a01b038416917ff62981a567ec3cec866c6fa93c55bcdf841d6292d18b8d522ececa769375d82d91a25050565b600081604051602001614a729190616114565b6040516020818303038152906040528051906020012083604051602001614a999190616114565b6040516020818303038152906040528051906020012014905092915050565b015190565b614ac5615a69565b6000614acf615a69565b614ad7615b7f565b614ae8614ae386615334565b615359565b90506000805b614af7836153a3565b15614c6b5780614b1c57614b12614b0d846153c4565b615412565b60ff168452614c63565b8060011415614c5e576060614b38614b33856153c4565b615492565b90508051604051908082528060200260200182016040528015614b7557816020015b614b62615a34565b815260200190600190039081614b5a5790505b5085602001819052508051604051908082528060200260200182016040528015614bb357816020015b6060815260200190600190039081614b9e5790505b50604086015260005b8151811015614c5357614bcd615a34565b60606000614bed858581518110614be057fe5b6020026020010151615563565b92509250925080614c0d578860009a509a50505050505050505050614c74565b8289602001518581518110614c1e57fe5b60200260200101819052508189604001518581518110614c3a57fe5b6020026020010181905250505050806001019050614bbc565b506001925050614c63565b614c6b565b600101614aee565b50919350909150505b915091565b815181516000916001918114808314614c955760009250614cd3565b600160208701838101602088015b600284838510011415614cce578051835114614cc25760009650600093505b60209283019201614ca3565b505050505b5090949350505050565b6001600160a01b03811660009081526004602052604081205480614d06575060001990506114e1565b600181039050600060018281548110614d1b57fe5b9060005260206000209060040201600301549050600060018381548110614d3e57fe5b6000918252602090912060036004909202010155600154604051600019909101906001600160a01b038616907f8cd4e147d8af98a9e3b6724021b8bf6aed2e5dac71c38f2dce8161b82585b25d90614d97908590616d89565b60405180910390a280614daf578293505050506114e1565b6000818381614dba57fe5b0490508015614e565760005b84811015614e0857614ddf82600183815481106146aa57fe5b60018281548110614dec57fe5b6000918252602090912060036004909202010155600101614dc6565b50600180549085015b81811015614e5357614e2a83600183815481106146aa57fe5b60018281548110614e3757fe5b6000918252602090912060036004909202010155600101614e11565b50505b5091949350505050565b600082614e6f57506000611591565b82820282848281614e7c57fe5b0414611bca5760405162461bcd60e51b8152600401610c0f9061692e565b6000611bca83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061567d565b805182516000916001600160a01b039182169116148015614f16575081602001516001600160a01b031683602001516001600160a01b0316145b8015611bca5750506040908101519101516001600160a01b0390811691161490565b60125460135480821115614f8357805b82811015614f81576012805480614f5b57fe5b600190038181906000526020600020016000614f779190615a8d565b9055600101614f48565b505b6000818310614f925781614f94565b825b905060005b818110156150ac5761505160128281548110614fb157fe5b600091825260209182902001805460408051601f600260001961010060018716150201909416939093049283018590048502810185019091528181529283018282801561503f5780601f106150145761010080835404028352916020019161503f565b820191906000526020600020905b81548152906001019060200180831161502257829003601f168201915b505050505060138381548110612d4857fe5b6150a4576013818154811061506257fe5b906000526020600020016012828154811061507957fe5b9060005260206000200190805460018160011615610100020316600290046150a2929190615ae0565b505b600101614f99565b5082821115610c3157825b8281101561332d576012601382815481106150ce57fe5b6000918252602080832084546001818101875595855291909320929091018054615111949390920192909160026101009282161592909202600019011604615ae0565b506001016150b7565b601354600b548082111561516557805b8281101561516357601380548061513d57fe5b6001900381819060005260206000200160006151599190615a8d565b905560010161512a565b505b60008183106151745781615176565b825b905060005b81811015615295576152336013828154811061519357fe5b600091825260209182902001805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152928301828280156152215780601f106151f657610100808354040283529160200191615221565b820191906000526020600020905b81548152906001019060200180831161520457829003601f168201915b5050505050600b8381548110613fba57fe5b61528d57600b818154811061524457fe5b90600052602060002090601602016002016013828154811061526257fe5b90600052602060002001908054600181600116156101000203166002900461528b929190615ae0565b505b60010161517b565b5082821115610c3157825b8281101561332d576013600b82815481106152b757fe5b6000918252602080832084546001808201875595855291909320601692909202909201600290810180546152ff95939094019390926000199082161561010002011604615ae0565b506001016152a0565b6000818484111561532c5760405162461bcd60e51b8152600401610c0f919061625e565b505050900390565b61533c615b9f565b506040805180820190915281518152602082810190820152919050565b615361615b7f565b61536a826156b4565b61537357600080fd5b600061538283602001516156ee565b60208085015160408051808201909152868152920190820152915050919050565b60006153ad615b9f565b505080518051602091820151919092015191011190565b6153cc615b9f565b6153d5826153a3565b6153de57600080fd5b602082015160006153ee82615751565b80830160209586015260408051808201909152908152938401919091525090919050565b80516000901580159061542757508151602110155b61543057600080fd5b600061543f83602001516156ee565b905080836000015110156154655760405162461bcd60e51b8152600401610c0f90616a93565b82516020808501518301805192849003929183101561486757506020919091036101000a90049392505050565b606061549d826156b4565b6154a657600080fd5b60006154b183615832565b90506060816040519080825280602002602001820160405280156154ef57816020015b6154dc615b9f565b8152602001906001900390816154d45790505b509050600061550185602001516156ee565b60208601510190506000805b848110156155585761551e83615751565b915060405180604001604052808381526020018481525084828151811061554157fe5b60209081029190910101529181019160010161550d565b509195945050505050565b61556b615a34565b60606000615577615a34565b6060615581615b7f565b61558a87615359565b90506000805b615599836153a3565b1561566e57806155c4576155b46155af846153c4565b61588e565b6001600160a01b03168552615666565b80600114156155ec576155d96155af846153c4565b6001600160a01b03166020860152615666565b8060021415615614576156016155af846153c4565b6001600160a01b03166040860152615666565b806003141561564057615629614b0d846153c4565b6001600160401b0316606086015260019150615666565b80600414156156615761565a615655846153c4565b6158a8565b9350615666565b61566e565b600101615590565b50929791965091945092505050565b6000818361569e5760405162461bcd60e51b8152600401610c0f919061625e565b5060008385816156aa57fe5b0495945050505050565b80516000906156c5575060006114e1565b6020820151805160001a9060c08210156156e4576000925050506114e1565b5060019392505050565b8051600090811a60808110156157085760009150506114e1565b60b8811080615723575060c08110801590615723575060f881105b156157325760019150506114e1565b60c08110156157465760b5190190506114e1565b60f5190190506114e1565b80516000908190811a608081101561576c576001915061582b565b60b881101561578157607e198101915061582b565b60c08110156157d257600060b78203600186019550806020036101000a8651049150600181018201935050808310156157cc5760405162461bcd60e51b8152600401610c0f90616831565b5061582b565b60f88110156157e75760be198101915061582b565b600060f78203600186019550806020036101000a8651049150600181018201935050808310156158295760405162461bcd60e51b8152600401610c0f90616831565b505b5092915050565b8051600090615843575060006114e1565b6000809050600061585784602001516156ee565b602085015185519181019250015b808210156158855761587682615751565b82019150826001019250615865565b50909392505050565b805160009060151461589f57600080fd5b61159182615412565b80516060906158b657600080fd5b60006158c583602001516156ee565b83516040805191839003808352601f19601f82011683016020019091529192506060908280156158fc576020820181803683370190505b50905060008160200190506148678487602001510182858061591d57610c31565b5b6020811061593d578251825260209283019290910190601f190161591e565b915181516020939093036101000a6000190180199091169216919091179052565b60405180608001604052806000815260200160001515815260200160608152602001615988615bb9565b905290565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106159ce57805160ff19168380011785556159fb565b828001600101855582156159fb579182015b828111156159fb5782518255916020019190600101906159e0565b50612b2a929150615bd8565b82601381019282156159fb57916020028201828111156159fb5782518255916020019190600101906159e0565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b6040518060600160405280600060ff16815260200160608152602001606081525090565b50805460018160011615610100020316600290046000825580601f10615ab357506116f9565b601f0160209004906000526020600020908101906116f99190615bd8565b506116f9906013810190615bd8565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10615b1957805485556159fb565b828001600101855582156159fb57600052602060002091601f016020900482015b828111156159fb578254825591600101919060010190615b3a565b82601381019282156159fb57918201828111156159fb578254825591600101919060010190615b3a565b6040518060400160405280615b92615b9f565b8152602001600081525090565b604051806040016040528060008152602001600081525090565b6040518061026001604052806013906020820280368337509192915050565b611dac91905b80821115612b2a5760008155600101615bde565b803561159181616e3e565b60008083601f840112615c0e578182fd5b5081356001600160401b03811115615c24578182fd5b6020830191508360208083028501011115613ae257600080fd5b6000601f8381840112615c4f578182fd5b8235615c62615c5d82616df3565b616dcd565b818152925060208084019085810160005b84811015615cf4578135880189603f820112615c8e57600080fd5b838101356001600160401b03811115615ca657600080fd5b615cb7818901601f19168601616dcd565b81815260408c81848601011115615ccd57600080fd5b82818501888401375060009181018601919091528552509282019290820190600101615c73565b50505050505092915050565b600082601f830112615d10578081fd5b8135615d1e615c5d82616df3565b818152915060208083019084810181840286018201871015615d3f57600080fd5b6000805b85811015615cf45782356001600160401b0381168114615d61578283fd5b85529383019391830191600101615d43565b60008083601f840112615d84578182fd5b5081356001600160401b03811115615d9a578182fd5b602083019150836020828501011115613ae257600080fd5b600060208284031215615dc3578081fd5b8135611bca81616e3e565b600060208284031215615ddf578081fd5b8151611bca81616e3e565b60008060008060408587031215615dff578283fd5b84356001600160401b0380821115615e15578485fd5b615e2188838901615bfd565b90965094506020870135915080821115615e39578384fd5b50615e4687828801615bfd565b95989497509550505050565b600080600060608486031215615e66578283fd5b83356001600160401b0380821115615e7c578485fd5b81860187601f820112615e8d578586fd5b80359250615e9d615c5d84616df3565b80848252602080830192508084018b828389028701011115615ebd57898afd5b8994505b86851015615ee757615ed38c82615bf2565b845260019490940193928101928101615ec1565b509097508801359350505080821115615efe578384fd5b615f0a87838801615d00565b93506040860135915080821115615f1f578283fd5b50615f2c86828701615c3e565b9150509250925092565b60008060208385031215615f48578182fd5b82356001600160401b03811115615f5d578283fd5b615f6985828601615d73565b90969095509350505050565b60008060008060408587031215615f8a578384fd5b84356001600160401b0380821115615fa0578586fd5b615fac88838901615d73565b90965094506020870135915080821115615fc4578384fd5b50615e4687828801615d73565b600060208284031215615fe2578081fd5b5035919050565b600060208284031215615ffa578081fd5b5051919050565b60008060408385031215616013578182fd5b505080516020909101519092909150565b600080600060408486031215616038578081fd5b833560ff81168114616048578182fd5b925060208401356001600160401b03811115616062578182fd5b61606e86828701615d73565b9497909650939450505050565b6000815180845260208085019450808401835b838110156160b35781516001600160a01b03168752958201959082019060010161608e565b509495945050505050565b60008284528282602086013780602084860101526020601f19601f85011685010190509392505050565b60008151808452616100816020860160208601616e12565b601f01601f19169290920160200192915050565b60008251616126818460208701616e12565b9190910192915050565b918252602082015260400190565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b03968716815294861660208601529290941660408401526001600160401b03166060830152911515608082015260a081019190915260c00190565b6001600160a01b0393909316835260208301919091521515604082015260600190565b600060208252611bca602083018461607b565b6000604082526161f6604083018561607b565b602083820381850152818551808452828401915082838202850101838801865b8381101561624457601f198784030185526162328383516160e8565b94860194925090850190600101616216565b50909998505050505050505050565b901515815260200190565b600060208252611bca60208301846160e8565b6000604082526162856040830186886160be565b82810360208401526162988185876160be565b979650505050505050565b6020808252601c908201527f6c656e677468206f66206275726e526174696f206d69736d6174636800000000604082015260600190565b60208082526026908201527f6c656e677468206f66206d61784e756d4f664d61696e7461696e696e67206d696040820152650e6dac2e8c6d60d31b606082015260800190565b60208082526038908201527f746865206e756d4f66436162696e657473206d757374206265206c657373207460408201527f68616e206d6178456c656374656456616c696461746f72730000000000000000606082015260800190565b6020808252602c908201527f6c656e677468206f66206d61784e756d4f66576f726b696e6743616e6469646160408201526b0e8cae640dad2e6dac2e8c6d60a31b606082015260800190565b60208082526025908201527f6c656e677468206f66206d61696e7461696e536c6173685363616c65206d69736040820152640dac2e8c6d60db1b606082015260800190565b6020808252818101527f6c656e677468206f66206e756d4f66436162696e657473206d69736d61746368604082015260600190565b60208082526019908201527f74686520636f6e7472616374206e6f7420696e69742079657400000000000000604082015260600190565b6020808252601f908201527f6f6e6c7920736c617368206f72207374616b6548756220636f6e747261637400604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b60208082526063908201527f7468652073797374656d52657761726442617365526174696f20706c7573206260408201527f75726e526174696f20616e642073797374656d526577617264416e74694d455660608201527f526174696f206d757374206265206e6f2067726561746572207468616e20313060808201526203030360ec1b60a082015260c00190565b60208082526028908201527f746865206e756d4f66436162696e657473206d75737420626520677265617465604082015267072207468616e20360c41b606082015260800190565b60208082526022908201527f63616e206e6f7420646f207468697320747769636520696e206f6e6520626c6f604082015261636b60f01b606082015260800190565b60208082526037908201527f746865206d61784e756d4f664d61696e7461696e696e67206d7573742062652060408201527f6c657373207468616e206e756d4f66436162696e657473000000000000000000606082015260800190565b6020808252601d908201527f6c656e677468206f66207475726e4c656e677468206d69736d61746368000000604082015260600190565b6020808252600a908201526919195c1c9958d85d195960b21b604082015260600190565b60208082526063908201527f746865206275726e526174696f20706c75732073797374656d5265776172644260408201527f617365526174696f20616e642073797374656d526577617264416e74694d455660608201527f526174696f206d757374206265206e6f2067726561746572207468616e20313060808201526203030360ec1b60a082015260c00190565b6020808252602b908201527f6c656e677468206f662073797374656d526577617264416e74694d455652617460408201526a0d2de40dad2e6dac2e8c6d60ab1b606082015260800190565b6020808252601590820152746465706f7369742076616c7565206973207a65726f60581b604082015260600190565b60208082526049908201527f746865206d61784e756d4f66576f726b696e6743616e64696461746573206d7560408201527f7374206265206e6f742067726561746572207468616e206d61784e756d4f6643606082015268616e6469646174657360b81b608082015260a00190565b6020808252601190820152706164646974696f6e206f766572666c6f7760781b604082015260600190565b60208082526063908201527f7468652073797374656d526577617264416e74694d4556526174696f20706c7560408201527f73206275726e526174696f20616e642073797374656d5265776172644261736560608201527f526174696f206d757374206265206e6f2067726561746572207468616e20313060808201526203030360ec1b60a082015260c00190565b60208082526023908201527f63616e206e6f7420656e7465722054656d706f72617279204d61696e74656e616040820152626e636560e81b606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252601490820152736761737072696365206973206e6f74207a65726f60601b604082015260600190565b6020808252602e908201527f746865206d6573736167652073656e646572206d75737420626520676f76657260408201526d1b985b98d94818dbdb9d1c9858dd60921b606082015260800190565b60208082526025908201527f6c656e677468206f66206d61784e756d4f6643616e64696461746573206d69736040820152640dac2e8c6d60db1b606082015260800190565b6020808252601290820152716e6f7420696e206d61696e74656e616e636560701b604082015260600190565b60208082526019908201527f74686520636f6e747261637420616c726561647920696e697400000000000000604082015260600190565b6020808252601a908201527f6c656e677468206973206c657373207468616e206f6666736574000000000000604082015260600190565b60208082526017908201527f6f6e6c792063757272656e742076616c696461746f7273000000000000000000604082015260600190565b60208082526021908201527f6661696c656420746f20706172736520696e69742076616c696461746f7253656040820152601d60fa1b606082015260800190565b6020808252602f908201527f746865206d6573736167652073656e646572206d7573742062652063726f737360408201526e0818da185a5b8818dbdb9d1c9858dd608a1b606082015260800190565b6020808252602d908201527f746865206d6573736167652073656e646572206d75737420626520746865206260408201526c3637b1b590383937b23ab1b2b960991b606082015260800190565b60208082526028908201527f6c656e677468206f662073797374656d52657761726442617365526174696f206040820152670dad2e6dac2e8c6d60c31b606082015260800190565b6020808252603e908201527f746865206d61696e7461696e536c6173685363616c65206d757374206265206760408201527f726561746572207468616e203020616e64206c657373207468616e2031300000606082015260800190565b60208082526030908201527f746865207475726e4c656e6774682073686f756c6420626520696e205b332c3660408201526f345d206f7220657175616c20746f203160801b606082015260800190565b6020808252600d908201526c756e6b6e6f776e20706172616d60981b604082015260600190565b60208082526029908201527f746865206d6573736167652073656e646572206d75737420626520736c6173686040820152680818dbdb9d1c9858dd60ba1b606082015260800190565b6020808252601f908201527f746865206d73672073656e646572206d757374206265207374616b6548756200604082015260600190565b61ffff91909116815260200190565b90815260200190565b6000848252831515602083015260606040830152616db360608301846160e8565b95945050505050565b63ffffffff91909116815260200190565b6040518181016001600160401b0381118282101715616deb57600080fd5b604052919050565b60006001600160401b03821115616e08578081fd5b5060209081020190565b60005b83811015616e2d578181015183820152602001616e15565b8381111561332d5750506000910152565b6001600160a01b03811681146116f957600080fdfe0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dbbf905ec80f905e8f846942a7cdd959bfe8d9487b2a43b33565295a698f7e294b6a7edd747c0554875d3fc531d19ba1497992c5e941ff80f3f7f110ffd8920a3ac38fdef318fe94a3f86048c27395000f846946488aa4d1955ee33403f8ccb1d4de5fb97c7ade294220f003d8bdfaadf52aa1e55ae4cc485e6794875941a87e90e440a39c99aa9cb5cea0ad6a3f0b2407b86048c27395000f846949ef9f4360c606c7ab4db26b016007d3ad0ab86a0946103af86a874b705854033438383c82575f25bc29418e2db06cbff3e3c5f856410a1838649e760175786048c27395000f84694ee01c3b1283aa067c58eab4709f85e99d46de5fe94ee4b9bfb1871c64e2bcabb1dc382dc8b7c4218a29415904ab26ab0e99d70b51c220ccdcccabee6e29786048c27395000f84694685b1ded8013785d6623cc18d214320b6bb6475994a20ef4e5e4e7e36258dbf51f4d905114cb1b34bc9413e39085dc88704f4394d35209a02b1a9520320c86048c27395000f8469478f3adfc719c99674c072166708589033e2d9afe9448a30d5eaa7b64492a160f139e2da2800ec3834e94055838358c29edf4dcc1ba1985ad58aedbb6be2b86048c27395000f84694c2be4ec20253b8642161bc3f444f53679c1f3d479466f50c616d737e60d7ca6311ff0d9c434197898a94d1d678a2506eeaa365056fe565df8bc8659f28b086048c27395000f846942f7be8361c80a4c1e7e9aaf001d0877f1cfde218945f93992ac37f3e61db2ef8a587a436a161fd210b94ecbc4fb1a97861344dad0867ca3cba2b860411f086048c27395000f84694ce2fd7544e0b2cc94692d4a704debef7bcb613289444abc67b4b2fba283c582387f54c9cba7c34bafa948acc2ab395ded08bb75ce85bf0f95ad2abc51ad586048c27395000f84694b8f7166496996a7da21cf1f1b04d9b3e26a3d077946770572763289aac606e4f327c2f6cc1aa3b3e3b94882d745ed97d4422ca8da1c22ec49d880c4c097286048c27395000f846942d4c407bbe49438ed859fe965b140dcf1aab71a9943ad0939e120f33518fbba04631afe7a3ed6327b194b2bbb170ca4e499a2b0f3cc85ebfa6e8c4dfcbea86048c27395000f846946bbad7cf34b5fa511d8e963dbba288b1960e75d694853b0f6c324d1f4e76c8266942337ac1b0af1a229442498946a51ca5924552ead6fc2af08b94fcba648601d1a94a2000f846944430b3230294d12c6ab2aac5c2cd68e80b16b581947b107f4976a252a6939b771202c28e64e03f52d694795811a7f214084116949fc4f53cedbf189eeab28601d1a94a2000f84694ea0a6e3c511bbd10f4519ece37dc24887e11b55d946811ca77acfb221a49393c193f3a22db829fcc8e9464feb7c04830dd9ace164fc5c52b3f5a29e5018a8601d1a94a2000f846947ae2f5b9e386cd1b50a4550696d957cb4900f03a94e83bcc5077e6b873995c24bac871b5ad856047e19464e48d4057a90b233e026c1041e6012ada897fe88601d1a94a2000f8469482012708dafc9e1b880fd083b32182b869be8e09948e5adc73a2d233a1b496ed3115464dd6c7b887509428b383d324bc9a37f4e276190796ba5a8947f5ed8601d1a94a2000f8469422b81f8e175ffde54d797fe11eb03f9e3bf75f1d94a1c3ef7ca38d8ba80cce3bfc53ebd2903ed21658942767f7447f7b9b70313d4147b795414aecea54718601d1a94a2000f8469468bf0b8b6fb4e317a0f9d6f03eaf8ce6675bc60d94675cfe570b7902623f47e7f59c9664b5f5065dcf94d84f0d2e50bcf00f2fc476e1c57f5ca2d57f625b8601d1a94a2000f846948c4d90829ce8f72d0163c1d5cf348a862d5506309485c42a7b34309bee2ed6a235f86d16f059deec5894cc2cedc53f0fa6d376336efb67e43d167169f3b78601d1a94a2000f8469435e7a025f4da968de7e4d7e4004197917f4070f194b1182abaeeb3b4d8eba7e6a4162eac7ace23d57394c4fd0d870da52e73de2dd8ded19fe3d26f43a1138601d1a94a2000f84694d6caa02bbebaebb5d7e581e4b66559e635f805ff94c07335cf083c1c46a487f0325769d88e163b653694efaff03b42e41f953a925fc43720e45fb61a19938601d1a94a20000175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dbaa164736f6c6343000604000a

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
0x0000000000000000000000000000000000001000
Net Worth in USD
$364,245,648.66

Net Worth in BNB
BNB Smart Chain LogoBNB Smart Chain LogoBNB Smart Chain Logo 591,051.182743

Token Allocations
MON 99.99%
BNB 0.01%
BABYAPE 0.00%
Others 0.00%
Chain Token Portfolio % Price Amount Value
MONAD99.99%$0.02363715,408,074,525.7531$364,204,326.51
BSC
BNB (BNB)
$616.3350.9609$31,408.54
BSC$0.000007543,696,662.5298$3,617.11
BSC$0.0003168,836,000$2,791.36
BSC$0.9995861,119.8403$1,119.38
BSC3,000,002,149.9083$917.7
BSC$0.0010,000$0.00
BSC$0.52963899.5$52.7
BSC$0.281277113.0589$31.8
BSC200,000,000$26.68
BSC$1.1920$23.7
BSC4,773,420,336.5833$11.93
BSC$0.00021255,060.3604$11.67
BSC30,594,611.7785$10.44
BSC$990.084$8.31
BSC296,563,535,086,066,180$7.71
BSC$0.00041112,700$5.22
BSC$0.0019821,800.003$3.57
BSC$0.3242210$3.24
BSC$0.00031110,154.5313$3.16
BSC$0.9998221.927$1.93
BSC12,158,029,036.5489$1.22
BSC$0.08469111.2975$0.9568
BSC$615.640.0013202$0.8127
BSC$1.470.441$0.6482
BSC$0.4779391$0.4779
BSC$0.2992751.0748$0.3216
BSC$68,660.220.0000041$0.2815
BSC$0.1384271.8356$0.254
BSC$0.2455871$0.2455
BSC37,146,798.1564$0.2064
BSC$0.1416970.833$0.118
BSC$0.971150.107$0.1038
ETH$0.9996961.0158$960.63
ETH$1,965.840.00237207$4.66
ETH$616.090.000672$0.414
HYPEREVM$30.251.13$34.18
OP$1,965.690.001$1.97
BASE$1,965.840.00071646$1.41
ARB$1,965.30.00038754$0.761631
OPBNB$616.180.000002$0.001233
LINEA$1,965.840.0000002$0.000393
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

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

`; } let ensZeroWidthWarningHtml = ""; if ($("#hdnIsEnsContainZeroWidthChars").val() == "true") { ensZeroWidthWarningHtml = `
${zeroWidthWarningMessage} Check the actual text at SPACE ID.
`; } const ensOnL2NoteHtml = ensOnL2Note != "" ? `
  • ${ensOnL2Note}
  • ` : ""; const contentHtml = `
    Additional Info
    Full Name:
    ${ensNameForkIconSrc}


    Note:
    • Name tag is displayed due to forward and reverse resolution. Find out more.
    • A Domain Name is not necessarily held by a person popularly associated with the name.
    • ${ensOnL2NoteHtml}
    ${ensUnicodeWarningHtml} ${ensZeroWidthWarningHtml}
    `; $('#ensName').popover({ html: true, content: contentHtml, trigger: 'manual', placement: 'right' }); $('#ensName').click(function (event) { $("#udName").popover('hide') $("#ensName").popover('toggle'); event.stopPropagation(); }); $('#ensName').on('shown.bs.popover', async () => { //disable tooltip when hovering over ens name in the main page $("[rel='tooltipEns']").each(function () { $(this).tooltip('hide'); $(this).tooltip('disable'); }); //call ajax here to get result if (!otherENSNamesHtml) { const resolvedAddressesModel = await getEnsResolvedAddress($("#hdnAddress").val(), primaryDomainNameLabel); otherENSNamesHtml = generateEnsPopoverGrid(resolvedAddressesModel.d); if (!otherENSNamesHtml) { otherENSNamesHtml = "There are no other names resolving to this address." } } $(".popOverEnsOwnedAddressTable").html(otherENSNamesHtml); $("#divENSDisplayName").html(ensDisplayName); // append more copy button for ENS let domainName = $("#hdnEnsText").val(); const copyEnsButtonHtml = ` `; $("#spanCopyENSAddress").html(copyEnsButtonHtml); $("[data-bs-toggle='tooltip']").tooltip(); }); $('#ensName').on('hidden.bs.popover', () => { $("[rel='tooltipEns']").each(function () { $(this).tooltip('enable'); }); }); $('#ensName').on('hide.bs.popover', () => { $("[data-bs-toggle='tooltip']").tooltip('hide'); }); $(document).click(function (e) { const popoverElement = document.getElementById('popover-ens-preview'); const popoverTrigger = document.getElementById('ensName'); if (!popoverTrigger.contains(e.target) && (!popoverElement || !popoverElement.contains(e.target))) { $("#ensName").popover('hide'); } }) } async function getEnsResolvedAddress(address, currentEnsText) { try { const requestModel = { "lookupAddress": address, "primaryDomainName": currentEnsText, "provider": ensNameProvider }; const response = await $.ajax({ url: "/name-lookup-search.aspx/GetOtherDomainNameForAddress", type: "POST", contentType: "application/json", dataType: "json", data: JSON.stringify({ requestModel: requestModel }) }) return response; } catch { return ""; } } function generateEnsPopoverGrid(model) { if (!model || model.DomainNames.length == 0) { return ""; } let listOtherENSNames = ""; model.DomainNames.forEach(x => listOtherENSNames += x.Name); let moreOtherENSNames = ""; if (model.Total > 5) { moreOtherENSNames = `More ` } const result = `
    Other names resolving to this address:
    ${listOtherENSNames} ${moreOtherENSNames}
    `; return result; } function removeSpecificDomain(url, domain) { return url.replace(new RegExp(domain + '$'), ''); } // ===== UD name tag const displayUDName = ''; const primaryUDName = ''; const showUDPublicNote = 'false'; let otherUDNamesHtml = ""; function initUDNamePopOver() { //required to allow bootstrap popover to support table $.fn.popover.Constructor.Default.allowList.table = []; $.fn.popover.Constructor.Default.allowList.tr = []; $.fn.popover.Constructor.Default.allowList.td = []; $.fn.popover.Constructor.Default.allowList.th = []; $.fn.popover.Constructor.Default.allowList.div = []; $.fn.popover.Constructor.Default.allowList.tbody = []; $.fn.popover.Constructor.Default.allowList.thead = []; //allowList my inline styling for bootstrap $.fn.popover.Constructor.Default.allowList['*'].push('style') let unicodeWarningHtml = ""; if ($("#hdnIsUDContainUnicodeChars").val() == "true") { unicodeWarningHtml = `
    ${unicodeWarningMessage} Check the actual text at Unstoppable Domains.
    `; } let zeroWidthWarningHtml = ""; if ($("#hdnIsUDContainZeroWidthChars").val() == "true") { zeroWidthWarningHtml = `
    ${unicodeWarningMessage} Check the actual text at Unstoppable Domains.
    `; } const contentHtml = `
    Additional Info
    Full Name:
    Unstoppable Domains Name


    Note:
    • Name tag is displayed due to forward and reverse resolution. Find out more
    • A Domain Name is not necessarily held by a person popularly associated with the name.
    ${unicodeWarningHtml} ${zeroWidthWarningHtml}
    `; $('#udName').popover({ html: true, content: contentHtml, trigger: 'manual' }); $('#udName').click(function (event) { $("#ensName").popover('hide'); $("#udName").popover('toggle'); event.stopPropagation(); }); $('#udName').on('shown.bs.popover', async () => { //disable tooltip when hovering over SID name in the main page $("[rel='tooltipUDName']").each(function () { $(this).tooltip('hide'); $(this).tooltip('disable'); }); //call ajax here to get result if (!otherUDNamesHtml) { const resolvedAddressesModel = await getUDNamesResolvedAddress($("#hdnAddress").val(), primaryUDName); //format the ajax to otherUDNamesHtml otherUDNamesHtml = generateUDPopoverGrid(resolvedAddressesModel.d); if (!otherUDNamesHtml) { otherUDNamesHtml = "There are no other names resolving to this address." } } $(".popoverUDNamesOwnedByAddress").html(otherUDNamesHtml); $("#divDisplayUDName").html(displayUDName); if (showUDPublicNote == true) { $("#noteUD").html('The Unstoppable Domains NFT is minted on the Ethereum blockchain. View and verify its details on Etherscan.'); $("#noteUD").show(); } $("[data-bs-toggle='tooltip']").tooltip(); }); $('#udName').on('hidden.bs.popover', () => { $("[rel='tooltipUDName']").each(function () { $(this).tooltip('enable'); }); }); $('#udName').on('hide.bs.popover', () => { $("[data-bs-toggle='tooltip']").tooltip('hide'); }); // Hide Unstoppable Domains Name popover when click outside the popover popup. $(document).click(function () { $("#udName").popover('hide') }); } async function getUDNamesResolvedAddress(address, primaryUDName) { try { const requestModel = { "lookupAddress": address, "primaryDomainName": primaryUDName, "provider": "UD" }; const response = await $.ajax({ url: "/name-lookup-search.aspx/GetOtherDomainNameForAddress", type: "POST", contentType: "application/json", dataType: "json", data: JSON.stringify({ requestModel: requestModel }) }) return response; } catch { return ""; } } function generateUDPopoverGrid(model) { if (!model || model.DomainNames.length == 0) { return ""; } let listOtherUDNames = ""; model.DomainNames.forEach(x => listOtherUDNames += x.Name); let moreOtherUDNames = ""; if (model.Total > 5) { moreOtherUDNames = `More `; } const result = `
    Other names resolving to this address:
    ${listOtherUDNames} ${moreOtherUDNames}
    `; return result; } // ===== end UD name tag const tooltipForTokenHolding = 'More than 112 tokens found, listing and displaying the total balance of the first 100 tokens only. Click on the Coins icon to see the full list and balance.'; var adjustPosition = 0; $(document).ready(function () { switchAmountToValue(document.getElementById("headerAmountValue"), 'Value (USD)', 'Amount', true); switchAmountToValue(document.getElementById("headerIntAmountValue"), 'Value (USD)', 'Amount', true); switchMethodColumn(document.getElementById("headerMethod"), 'Method', 'Action', true); onDocumentReady(); $("[rel='tooltip']").tooltip(); $("[data-bs-toggle-second='tooltip']").tooltip({ trigger: 'hover' }); $("[rel='tooltipEns']").each(function () { $(this).tooltip({ title: $(this).attr("tooltip-title") }); }); if (hash != '') { activaTab(hash); }; onAddressDocReady(); // Note: this is causing "Copied" tooltip not showing when copy button is clicked in V3, and seems like not applicable to v3, comment out first in case there is issue //$('[data-bs-toggle="tooltip"]').click(function () { // $('[data-bs-toggle="tooltip"]').tooltip("hide"); //}); document.getElementById("copyaddressbutton").classList.remove("disabled"); if ($("#txtSearchContract").length) { initialiseKeyupOnDocReady(); } if (!!$('#ensName')[0]) { initEnsNamePopOver(); } if (!!$("#udName")[0]) { initUDNamePopOver(); } handleToggle(); if (window.matchMedia("(max-width: 767px)").matches) { // Mobile adjustPosition = 90; } else { // Others adjustPosition = 50; } if (tooltipForTokenHolding) { const dropdownMenuBalance = document.getElementById("dropdownMenuBalance"); if (dropdownMenuBalance) { const dropdownWrapper = dropdownMenuBalance.closest(".dropdown"); if (dropdownWrapper) { dropdownWrapper.setAttribute("title", tooltipForTokenHolding); new bootstrap.Tooltip(dropdownWrapper); } } } }); function displayAudit() { $('html, body').animate({ scrollTop: $("#auditReportId").offset().top - adjustPosition }); } var cThemeMode = getCookie('displaymode'); function handleToggle() { var className = document.getElementsByClassName('editor'); var classNameCount = className.length; for (var j = 0; j t.innerWidth()) { if (mb + d > tb) { t.css('padding-bottom', ((mb + d) - tb)); } } else { t.css('overflow', 'visible'); } }).on('hidden.bs.dropdown', function () { $(this).css({ 'padding-bottom': '', 'overflow': '' }); }); var btn_ERC20_sort = { count: 0, reminder_count: 2, list: [], default_list: [], ERC20_sort_start: function (count) { if (document.getElementsByClassName('list-custom-divider-ERC20')[0]) { var self = this if (count != undefined) { self.count = count } var before_el = document.getElementsByClassName('list-custom-divider-ERC20')[0] var parent_el = before_el.parentNode var element_selector = parent_el.querySelectorAll(".list-custom-ERC20"); if (self.list.length == 0) { element_selector.forEach(function (e) { self.list.push(e); self.default_list.push(e); }); } $(".list-custom-ERC20").remove() var type = self.count % self.reminder_count self.sortList(type, parent_el, before_el); self.count++ } }, sortList: function (type, parent_el, before_el) { var self = this var sorted_list = [] var icon_el = $(before_el).find('button').find('i') switch (type) { case 1: icon_el.attr("class", "fad fa-sort-up") sorted_list = self.sortUsdAsc() break; default: icon_el.attr("class", "fad fa-sort-down") sorted_list = self.sortUsdDesc() } for (var i = sorted_list.length - 1; i >= 0; i--) { before_el.insertAdjacentElement('afterend', sorted_list[i]) } }, sortUsdAsc: function () { var self = this var sort_list = self.list sort_list.sort(function (a, b) { var target_a_value = self.formatCurrencyToNumber(a.querySelector('.list-usd-value').textContent.trim() || -1); var target_b_value = self.formatCurrencyToNumber(b.querySelector('.list-usd-value').textContent.trim() || -1); if (target_a_value == -1 || target_b_value == -1) { return 1; } if (target_a_value target_b_value) { return 1; } return 0 }); return sort_list }, sortUsdDesc: function () { var self = this var sort_list = self.list sort_list.sort(function (a, b) { var target_a_value = self.formatCurrencyToNumber(a.querySelector('.list-usd-value').textContent.trim() || -1); var target_b_value = self.formatCurrencyToNumber(b.querySelector('.list-usd-value').textContent.trim() || -1); if (target_a_value target_b_value) { return -1; } return 0 }); return sort_list }, formatCurrencyToNumber: function (strCurrency) { if (typeof strCurrency == "number") return strCurrency else return Number(strCurrency.replace(/[^0-9.-]+/g, "")); }, } function hrefTokenHolding() { var location = "/tokenholdings?a=0x0000000000000000000000000000000000001000" var queryString = $("input.form-control.form-control-xs.search.mb-3")[0].value if (queryString) { location += "&q=" + queryString } window.location.href = location } $(document).ready(function () { $("#btn_ERC20_sort").on("click", function (event) { event.preventDefault(); setTimeout(function () { btn_ERC20_sort.ERC20_sort_start() }, 10) }) btn_ERC20_sort.ERC20_sort_start() var mainAddress = $("#hdnAddress").val(); // user search for method filters var searchFuncTimeOut; $("#ContentPlaceHolder1_inputMethodName").on("keyup", function ($event) { if (searchFuncTimeOut) { clearTimeout(searchFuncTimeOut) } var searchTerm = $(this).val(); searchFuncTimeOut = setTimeout(function () { searchFunctions(searchTerm); }, 350); }); var isSearchFunctions = false; $("#dropdownMethod").on("click", function (e) { if (isSearchFunctions === false) { searchFunctions(''); isSearchFunctions = true; } }); const litDefaultMethodFilterHtml = ''; function searchFunctions(searchTerm) { if (searchTerm === '' || searchTerm.length > 3) { const curPath = encodeURIComponent(window.location.search); $.ajax({ type: 'Get', url: `/functionSearchHandler.ashx?ca=${mainAddress}&func=${searchTerm ?? ''}&curPath=${curPath}`, success: function (response) { $("#searchFunctionResult").html(''); if (response && response.length > 0) { for (var i = 0; i ${response[i].name} ${response[i].methodId} ` ); } $("[data-bs-toggle='tooltip']").tooltip(); } else { $("#searchFunctionResult").append( `` ); } $("#inputMethodSpinner").hide(); }, error: function (XMLHttpRequest, textStatus, errorThrown) { $("#searchFunctionResult").html(''); $("#inputMethodSpinner").hide(); } }); } else { $("#inputMethodSpinner").hide(); $("#searchFunctionResult").html(litDefaultMethodFilterHtml); } } // Resize window for analytic tab let isBusy = false; $(window).resize(function () { isBusy = true; if (isBusy) { let analyticFrame = document.getElementById('analytics_pageiframe'); if (analyticFrame && analyticFrame.contentWindow != undefined) { let navtab = analyticFrame.contentWindow.document.getElementsByClassName("nav_tabs1"); let hIframe = "0px"; if (navtab != null && navtab != undefined && navtab.length > 0) { let navH = Number(navtab[0].scrollHeight); hIframe = (Number(analyticFrame.contentWindow.document.getElementsByClassName("tab-content")[0].scrollHeight) + navH + 20) + 'px'; } else { hIframe = analyticFrame.contentWindow.document.body.scrollHeight + 'px'; } analyticFrame.style.height = hIframe } } }); // detect tooltip for token holding dropdown if ($(".addresses-tooltip-over").length > 0) { if (!isMobile()) { $(".addresses-tooltip-over").attr("data-bs-trigger", "hover"); let tooltip = bootstrap.Tooltip.getInstance(".addresses-tooltip-over"); if (tooltip !== null) { tooltip.dispose(); tooltip = new bootstrap.Tooltip($(".addresses-tooltip-over")); tooltip._config.trigger = 'hover'; tooltip.update(); } } } // Quick export transaction csv const quickExportCsvData = '[{"Txhash":"0xa24a8a88824c2101ebb982201ea88296f7c2c15374c199ddb3cc64ff60452c76","Status":"Success","Method":"Deposit","Blockno":"81491823","DateTime":"2026-02-16 04:43:56","Sender":"0x5cf810AB8C718ac065b45f892A5BAdAB2B2946B9","SenderLable":"Validator : zen","Receiver":"0x0000000000000000000000000000000000001000","ReceiverLable":"BSC: Validator Set","Amount":"0.0005342 BNB","Value":"$0.33","TxnFee":"0"},{"Txhash":"0x49c75039d62be19ca099f6a22847dc1d615ad555cb2362e2f503022566b8bd77","Status":"Success","Method":"Deposit","Blockno":"81491822","DateTime":"2026-02-16 04:43:56","Sender":"0x5cf810AB8C718ac065b45f892A5BAdAB2B2946B9","SenderLable":"Validator : zen","Receiver":"0x0000000000000000000000000000000000001000","ReceiverLable":"BSC: Validator Set","Amount":"0.00122771 BNB","Value":"$0.76","TxnFee":"0"},{"Txhash":"0x9b649320a2f5eaab4a6561d2a62cdacce72304482491731a2e177389d823fcc5","Status":"Success","Method":"Deposit","Blockno":"81491821","DateTime":"2026-02-16 04:43:55","Sender":"0x5cf810AB8C718ac065b45f892A5BAdAB2B2946B9","SenderLable":"Validator : zen","Receiver":"0x0000000000000000000000000000000000001000","ReceiverLable":"BSC: Validator Set","Amount":"0.00076087 BNB","Value":"$0.47","TxnFee":"0"},{"Txhash":"0xf4e26a5ff6467a72845e4604c6ca0925835fee610aa5e403ff47abf412fa3702","Status":"Success","Method":"Deposit","Blockno":"81491820","DateTime":"2026-02-16 04:43:55","Sender":"0x5cf810AB8C718ac065b45f892A5BAdAB2B2946B9","SenderLable":"Validator : zen","Receiver":"0x0000000000000000000000000000000000001000","ReceiverLable":"BSC: Validator Set","Amount":"0.00168159 BNB","Value":"$1.04","TxnFee":"0"},{"Txhash":"0x17a91cfc37af89c4a91a8265f3a9b088b042467aa79119906c0504f5a8c1f924","Status":"Success","Method":"Deposit","Blockno":"81491819","DateTime":"2026-02-16 04:43:55","Sender":"0x5cf810AB8C718ac065b45f892A5BAdAB2B2946B9","SenderLable":"Validator : zen","Receiver":"0x0000000000000000000000000000000000001000","ReceiverLable":"BSC: Validator Set","Amount":"0.00070536 BNB","Value":"$0.43","TxnFee":"0"},{"Txhash":"0xea0ba35a8f820f37cace09d10714fe2a158bc1adb9a293ac1aaf115d89b438f8","Status":"Success","Method":"Deposit","Blockno":"81491818","DateTime":"2026-02-16 04:43:54","Sender":"0x5cf810AB8C718ac065b45f892A5BAdAB2B2946B9","SenderLable":"Validator : zen","Receiver":"0x0000000000000000000000000000000000001000","ReceiverLable":"BSC: Validator Set","Amount":"0.00163514 BNB","Value":"$1.01","TxnFee":"0"},{"Txhash":"0xf940b0713d0ae2006e6378770ce765a601d3af3adad06d28bd3f0fa9fe0b0126","Status":"Success","Method":"Deposit","Blockno":"81491817","DateTime":"2026-02-16 04:43:54","Sender":"0x5cf810AB8C718ac065b45f892A5BAdAB2B2946B9","SenderLable":"Validator : zen","Receiver":"0x0000000000000000000000000000000000001000","ReceiverLable":"BSC: Validator Set","Amount":"0.00053135 BNB","Value":"$0.33","TxnFee":"0"},{"Txhash":"0x5a446a7804438e54570f1577170aef987ce14072204470cd1cfe12aa0e6b559c","Status":"Success","Method":"Deposit","Blockno":"81491816","DateTime":"2026-02-16 04:43:53","Sender":"0x5cf810AB8C718ac065b45f892A5BAdAB2B2946B9","SenderLable":"Validator : zen","Receiver":"0x0000000000000000000000000000000000001000","ReceiverLable":"BSC: Validator Set","Amount":"0.00048777 BNB","Value":"$0.30","TxnFee":"0"},{"Txhash":"0xd4bd6cc2cdb64c7afe3c961a214273429195ae05bc78506c7ff2f62986ad04c6","Status":"Success","Method":"Deposit","Blockno":"81491815","DateTime":"2026-02-16 04:43:53","Sender":"0x58567F7A51a58708C8B40ec592A38bA64C0697De","SenderLable":"Validator : Legend","Receiver":"0x0000000000000000000000000000000000001000","ReceiverLable":"BSC: Validator Set","Amount":"0.00066123 BNB","Value":"$0.41","TxnFee":"0"},{"Txhash":"0xe83015938343f7f7aef4fb0e4b51880a4a4f6aff455245039651f2b9bfa5c6c1","Status":"Success","Method":"Deposit","Blockno":"81491814","DateTime":"2026-02-16 04:43:52","Sender":"0x58567F7A51a58708C8B40ec592A38bA64C0697De","SenderLable":"Validator : Legend","Receiver":"0x0000000000000000000000000000000000001000","ReceiverLable":"BSC: Validator Set","Amount":"0.00229852 BNB","Value":"$1.42","TxnFee":"0"},{"Txhash":"0x585ac3cf8f4c3efccf13e9adbf2057974218aa4b28ff096ca9f3c8450a4c7afe","Status":"Success","Method":"Deposit","Blockno":"81491813","DateTime":"2026-02-16 04:43:52","Sender":"0x58567F7A51a58708C8B40ec592A38bA64C0697De","SenderLable":"Validator : Legend","Receiver":"0x0000000000000000000000000000000000001000","ReceiverLable":"BSC: Validator Set","Amount":"0.00105989 BNB","Value":"$0.65","TxnFee":"0"},{"Txhash":"0x742a04270ae0a07e57052410db24b278fe8a1a6fcdf9db637cd1dbbe1aa7b81f","Status":"Success","Method":"Deposit","Blockno":"81491812","DateTime":"2026-02-16 04:43:51","Sender":"0x58567F7A51a58708C8B40ec592A38bA64C0697De","SenderLable":"Validator : Legend","Receiver":"0x0000000000000000000000000000000000001000","ReceiverLable":"BSC: Validator Set","Amount":"0.00109656 BNB","Value":"$0.68","TxnFee":"0"},{"Txhash":"0x4ec24b669239e556c1a8ef59909e327aacff9790e28562659b667c11c70f46a8","Status":"Success","Method":"Deposit","Blockno":"81491811","DateTime":"2026-02-16 04:43:51","Sender":"0x58567F7A51a58708C8B40ec592A38bA64C0697De","SenderLable":"Validator : Legend","Receiver":"0x0000000000000000000000000000000000001000","ReceiverLable":"BSC: Validator Set","Amount":"0.00066406 BNB","Value":"$0.41","TxnFee":"0"},{"Txhash":"0xd118385229609388ab99379ce06c86d9c844b75229156e773c6a4ac176b21f4a","Status":"Success","Method":"Deposit","Blockno":"81491810","DateTime":"2026-02-16 04:43:51","Sender":"0x58567F7A51a58708C8B40ec592A38bA64C0697De","SenderLable":"Validator : Legend","Receiver":"0x0000000000000000000000000000000000001000","ReceiverLable":"BSC: Validator Set","Amount":"0.00114093 BNB","Value":"$0.70","TxnFee":"0"},{"Txhash":"0xf7cf9effdc5fb478b553db42268586ce769521adee0a9ecd00f64989443d9c96","Status":"Success","Method":"Deposit","Blockno":"81491809","DateTime":"2026-02-16 04:43:50","Sender":"0x58567F7A51a58708C8B40ec592A38bA64C0697De","SenderLable":"Validator : Legend","Receiver":"0x0000000000000000000000000000000000001000","ReceiverLable":"BSC: Validator Set","Amount":"0.00156753 BNB","Value":"$0.97","TxnFee":"0"},{"Txhash":"0x4293504c25a89b223d0212ff6e1fa14facc0e7e9200843283ac7f83cd1b48082","Status":"Success","Method":"Deposit","Blockno":"81491808","DateTime":"2026-02-16 04:43:50","Sender":"0x58567F7A51a58708C8B40ec592A38bA64C0697De","SenderLable":"Validator : Legend","Receiver":"0x0000000000000000000000000000000000001000","ReceiverLable":"BSC: Validator Set","Amount":"0.00124657 BNB","Value":"$0.77","TxnFee":"0"},{"Txhash":"0x57e07a3c01bebfda054e2a79321d25210d2d366f3f7c0d42f6903eec59ed6e42","Status":"Success","Method":"Deposit","Blockno":"81491807","DateTime":"2026-02-16 04:43:49","Sender":"0x502aECFE253E6AA0e8D2A06E12438FFeD0Fe16a0","SenderLable":"Validator : BscScan","Receiver":"0x0000000000000000000000000000000000001000","ReceiverLable":"BSC: Validator Set","Amount":"0.00115711 BNB","Value":"$0.71","TxnFee":"0"},{"Txhash":"0x85a0ed66bc1216501c5395cc023760ddb18666d11ab4dd780da4b2ab7d2f4a27","Status":"Success","Method":"Deposit","Blockno":"81491806","DateTime":"2026-02-16 04:43:49","Sender":"0x502aECFE253E6AA0e8D2A06E12438FFeD0Fe16a0","SenderLable":"Validator : BscScan","Receiver":"0x0000000000000000000000000000000000001000","ReceiverLable":"BSC: Validator Set","Amount":"0.0006004 BNB","Value":"$0.37","TxnFee":"0"},{"Txhash":"0x1ccfc9393cd291cd57e76d9249bf8bf614809a8e29414802ea3e8db3a7a26a71","Status":"Success","Method":"Deposit","Blockno":"81491805","DateTime":"2026-02-16 04:43:48","Sender":"0x502aECFE253E6AA0e8D2A06E12438FFeD0Fe16a0","SenderLable":"Validator : BscScan","Receiver":"0x0000000000000000000000000000000000001000","ReceiverLable":"BSC: Validator Set","Amount":"0.00152275 BNB","Value":"$0.94","TxnFee":"0"},{"Txhash":"0x1c72b49eb105fe44af34f64db797246d1d45771aef6dd0d8b1ce6e382fdb1107","Status":"Success","Method":"Deposit","Blockno":"81491804","DateTime":"2026-02-16 04:43:48","Sender":"0x502aECFE253E6AA0e8D2A06E12438FFeD0Fe16a0","SenderLable":"Validator : BscScan","Receiver":"0x0000000000000000000000000000000000001000","ReceiverLable":"BSC: Validator Set","Amount":"0.00096706 BNB","Value":"$0.60","TxnFee":"0"},{"Txhash":"0x946ce6d7d94cc86d2752d2565c287e32d38235056905b7edb20b28372e68118c","Status":"Success","Method":"Deposit","Blockno":"81491803","DateTime":"2026-02-16 04:43:47","Sender":"0x502aECFE253E6AA0e8D2A06E12438FFeD0Fe16a0","SenderLable":"Validator : BscScan","Receiver":"0x0000000000000000000000000000000000001000","ReceiverLable":"BSC: Validator Set","Amount":"0.00056052 BNB","Value":"$0.35","TxnFee":"0"},{"Txhash":"0xdb168371aa5f1aec5e5570816e823447c6f5274acd00706f9b0f8b73546d45e1","Status":"Success","Method":"Deposit","Blockno":"81491802","DateTime":"2026-02-16 04:43:47","Sender":"0x502aECFE253E6AA0e8D2A06E12438FFeD0Fe16a0","SenderLable":"Validator : BscScan","Receiver":"0x0000000000000000000000000000000000001000","ReceiverLable":"BSC: Validator Set","Amount":"0.00073703 BNB","Value":"$0.45","TxnFee":"0"},{"Txhash":"0xa691d76770a8fd0ffcc553dda5b6634de6c25c0d037c24b4e95799852bf6e9c1","Status":"Success","Method":"Deposit","Blockno":"81491801","DateTime":"2026-02-16 04:43:46","Sender":"0x502aECFE253E6AA0e8D2A06E12438FFeD0Fe16a0","SenderLable":"Validator : BscScan","Receiver":"0x0000000000000000000000000000000000001000","ReceiverLable":"BSC: Validator Set","Amount":"0.00057913 BNB","Value":"$0.36","TxnFee":"0"},{"Txhash":"0xffd65abcb0d8a0e92fc91b596777e70ac224d12cb90f2f92182bcd02f2e80e40","Status":"Success","Method":"Distribute Finality Reward","Blockno":"81491800","DateTime":"2026-02-16 04:43:46","Sender":"0x502aECFE253E6AA0e8D2A06E12438FFeD0Fe16a0","SenderLable":"Validator : BscScan","Receiver":"0x0000000000000000000000000000000000001000","ReceiverLable":"BSC: Validator Set","Amount":"0 BNB","Value":"$0.00","TxnFee":"0"},{"Txhash":"0xca508fe8915f78b473da9933a37a5dcc7286593f022992f3e9904703b2327328","Status":"Success","Method":"Deposit","Blockno":"81491800","DateTime":"2026-02-16 04:43:46","Sender":"0x502aECFE253E6AA0e8D2A06E12438FFeD0Fe16a0","SenderLable":"Validator : BscScan","Receiver":"0x0000000000000000000000000000000000001000","ReceiverLable":"BSC: Validator Set","Amount":"0.00310673 BNB","Value":"$1.91","TxnFee":"0"}]'; const quickExportCsvTitle = 'Transaction Hash,Status,Method,Blockno,"DateTime (UTC)",From,From_Nametag,To,To_Nametag,Amount,Value (USD),Txn Fee'; let isExportFinish = true; if ($("#btnExportQuickTableToCSV").length > 0 && quickExportCsvData) { $("#btnExportQuickTableToCSV").click(function () { if (isExportFinish == true) { isExportFinish = false; $("#btnExportQuickTableToCSV").append(''); let lstTxsObj = JSON.parse(quickExportCsvData); if (lstTxsObj.length > 0) { let csvRows = []; csvRows.push(quickExportCsvTitle.replace(/"/g, "")); for (let i = 0; i 0 && quickExportInternalTxsData) { $("#ContentPlaceHolder1_btnQuickExportInternalTxs").click(function () { if (isExportFinish == true) { isExportFinish = false; $("#ContentPlaceHolder1_btnQuickExportInternalTxs").append(''); let lstTxsObj = JSON.parse(quickExportInternalTxsData); if (lstTxsObj.length > 0) { let csvRows = []; csvRows.push(quickExportInternalTxsTitle.replace(/"/g, "")); for (let i = 0; i { if (x.startsWith("F")) { file = x.replace("F", ""); } else if (x.startsWith("L")) { line = x.replace("L", ""); } }) var editorId = "editor" + file var editorElem = $("#" + editorId); if (!editorElem.length) { return; } if (!line) { return; } var editor = ace.edit(editorId); editor.resize(true); editor.scrollToLine(line, true, true, function () { }); editor.gotoLine(line); var Range = ace.require('ace/range').Range $(document).scrollTop($("#" + editorId).offset().top - 95); //document.getElementById(editorId).scrollIntoView(); editor.session.addMarker(new Range(line - 1, 0, line - 1, 1), "myMarker", "fullLine"); //window.onbeforeunload = function () { $(document).scrollTop($("#" + editorId).offset().top); }; } setTimeout(function () { editorGoToLine(); }, 500); }); $("body,html").click(function (evt) { let elm = $(evt.target).attr("id"); let isClickedMode = elm === "darkModaBtn" || elm === "darkModaBtnIcon"; if (isClickedMode) { let isClickedSunMode = false; let clrBorder = "#112641"; if (elm === "darkModaBtn") isClickedSunMode = $(evt.target).find("#darkModaBtnIcon").hasClass("fa-moon"); if (elm === "darkModaBtnIcon") isClickedSunMode = $(evt.target).hasClass("fa-moon"); if (isClickedSunMode) { clrBorder = "#fff"; } let iframes = document.getElementById('analytics_pageiframe'); let heatcell = iframes.contentWindow.document.getElementsByClassName("ch-day").length; for (let i = 0; i