Contract Address Details

0x2CD6eA7DE6B33C663a669158c70800BAba17a951

Contract Name
ProxyAdminMultisig
Creator
0xe01c8dā€“e085f7 at 0xe3272fā€“426147
Balance
0 CSB
Tokens
Fetching tokens...
Transactions
70 Transactions
Transfers
0 Transfers
Gas Used
8,385,640
Last Balance Update
64505744
Contract name:
ProxyAdminMultisig




Optimization enabled
true
Compiler version
v0.8.10+commit.fc410830




Optimization runs
200
EVM Version
default




Verified at
2022-11-03T14:17:25.023343Z

Constructor Arguments

000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000561293bc75993bbd53f63fdfdb43847f91cfd079000000000000000000000000742408a71603159b3074fa83e52e9c37ca1a6810000000000000000000000000f8f67ba5b24ceb288b48a8cfbd878f7b2c057d7a

Arg [0] (address[]) : [0x561293bc75993bbd53f63fdfdb43847f91cfd079, 0x742408a71603159b3074fa83e52e9c37ca1a6810, 0xf8f67ba5b24ceb288b48a8cfbd878f7b2c057d7a]
Arg [1] (uint256) : 2

              

Contract source code

// SPDX-License-Identifier: MIT

pragma solidity 0.8.10;

// OpenZeppelin Contracts (last updated v4.7.0) (utils/math/Math.sol)

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    enum Rounding {
        Down, // Toward negative infinity
        Up, // Toward infinity
        Zero // Toward zero
    }

    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a >= b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds up instead
     * of rounding down.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a == 0 ? 0 : (a - 1) / b + 1;
    }

    /**
     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
     * with further edits by Uniswap Labs also under MIT license.
     */
    function mulDiv(
        uint256 x,
        uint256 y,
        uint256 denominator
    ) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2^256 + prod0.
            uint256 prod0; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod0 := mul(x, y)
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            require(denominator > prod1);

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
            // See https://cs.stackexchange.com/q/138556/92363.

            // Does not overflow because the denominator cannot be zero at this stage in the function.
            uint256 twos = denominator & (~denominator + 1);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
            // in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /**
     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(
        uint256 x,
        uint256 y,
        uint256 denominator,
        Rounding rounding
    ) internal pure returns (uint256) {
        uint256 result = mulDiv(x, y, denominator);
        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
            result += 1;
        }
        return result;
    }

    /**
     * @dev Returns the square root of a number. It the number is not a perfect square, the value is rounded down.
     *
     * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
        // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
        // `msb(a) <= a < 2*msb(a)`.
        // We also know that `k`, the position of the most significant bit, is such that `msb(a) = 2**k`.
        // This gives `2**k < a <= 2**(k+1)` ā†’ `2**(k/2) <= sqrt(a) < 2 ** (k/2+1)`.
        // Using an algorithm similar to the msb conmputation, we are able to compute `result = 2**(k/2)` which is a
        // good first aproximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1;
        uint256 x = a;
        if (x >> 128 > 0) {
            x >>= 128;
            result <<= 64;
        }
        if (x >> 64 > 0) {
            x >>= 64;
            result <<= 32;
        }
        if (x >> 32 > 0) {
            x >>= 32;
            result <<= 16;
        }
        if (x >> 16 > 0) {
            x >>= 16;
            result <<= 8;
        }
        if (x >> 8 > 0) {
            x >>= 8;
            result <<= 4;
        }
        if (x >> 4 > 0) {
            x >>= 4;
            result <<= 2;
        }
        if (x >> 2 > 0) {
            result <<= 1;
        }

        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
        // into the expected uint128 result.
        unchecked {
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            return min(result, a / result);
        }
    }

    /**
     * @notice Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        uint256 result = sqrt(a);
        if (rounding == Rounding.Up && result * result < a) {
            result += 1;
        }
        return result;
    }
}

library Constants {
    string internal constant PROPOSAL_STATUS_PENDING = "Pending";
    string internal constant PROPOSAL_STATUS_DELETED = "Deleted";
    string internal constant PROPOSAL_STATUS_EXECUTED = "Executed";
    address internal constant SENTINEL_OWNER = address(0x1);
    string internal constant PROPOSAL_TYPE_UPGRADE = "Upgrade";
    string internal constant PROPOSAL_TYPE_CHANGE_ADMIN = "ChangeAdmin";
}

interface ITransparentUpgradeableProxy {
    function changeAdmin(address newAdmin) external;

    function upgradeTo(address newImplementation) external;
}

error NotOwner();
error ThresholdIsZero();
error ThresholdExceedsOwnersCount(uint256 threshold, uint256 ownersCount);
error InvalidOwner();
error OwnerExists();
error UnexpectedProposalType();
error NotPendingProposal();
error AlreadyApproved();
error NotEnoughApproval();

contract ProxyAdminMultisig {
    // events
    event Setup(
        address indexed initiator,
        address[] owners,
        uint256 indexed ownerCount,
        uint256 indexed threshold
    );

    event Propose(
        uint256 indexed proposalId,
        address target,
        string proposalType, // "ChangeAdmin" or "Upgrade"
        address data
    );
    event Approval(address indexed owner, uint256 indexed proposalId);
    event Delete(address indexed owner, uint256 indexed proposalId);
    event Execution(
        uint256 indexed proposalId,
        address target,
        string proposalType, // "ChangeAdmin" or "Upgrade"
        address data
    );
    event Upgrade(address target, address implementation);
    event ChangeAdmin(address target, address newAdmin);

    modifier onlyMember() {
        if (owners[msg.sender] == address(0)) {
            revert NotOwner();
        }
        _;
    }

    mapping(address => address) internal owners;
    uint256 internal ownersCount;
    uint256 internal threshold;

    struct Proposal {
        uint256 proposalId;
        address target;
        string proposalType; // "ChangeAdmin" or "Upgrade"
        address data;
        uint256 approvalCount;
        address[] approvals;
        string status;
    }
    uint256 internal proposalCount;
    mapping(uint256 => Proposal) internal proposals;
    uint256[] internal pendingProposalIds;

    constructor(address[] memory _owners, uint256 _threshold) {
        if (_threshold == 0) {
            revert ThresholdIsZero();
        }
        if (_threshold > _owners.length) {
            revert ThresholdExceedsOwnersCount(_threshold, _owners.length);
        }

        // initialize owners
        address currentOwner = Constants.SENTINEL_OWNER;
        for (uint256 i = 0; i < _owners.length; i++) {
            address owner = _owners[i];
            if (owner == address(0) || owner == Constants.SENTINEL_OWNER || currentOwner == owner) {
                revert InvalidOwner();
            }
            if (owners[owner] != address(0)) {
                revert OwnerExists();
            }
            owners[currentOwner] = owner;
            currentOwner = owner;
        }
        owners[currentOwner] = Constants.SENTINEL_OWNER;
        ownersCount = _owners.length;
        threshold = _threshold;

        emit Setup(msg.sender, _owners, ownersCount, threshold);
    }

    function propose(
        address target,
        string calldata proposalType,
        address data
    ) external onlyMember {
        if (
            keccak256(bytes(proposalType)) !=
            keccak256(bytes(Constants.PROPOSAL_TYPE_CHANGE_ADMIN)) &&
            keccak256(bytes(proposalType)) != keccak256(bytes(Constants.PROPOSAL_TYPE_UPGRADE))
        ) {
            revert UnexpectedProposalType();
        }
        proposalCount++;
        uint256 proposalId = proposalCount;
        // create proposal
        proposals[proposalId].proposalId = proposalId;
        proposals[proposalId].target = target;
        proposals[proposalId].proposalType = proposalType;
        proposals[proposalId].data = data;
        proposals[proposalId].approvalCount = 0;
        proposals[proposalId].status = Constants.PROPOSAL_STATUS_PENDING;
        pendingProposalIds.push(proposalId);

        emit Propose(proposalId, target, proposalType, data);
    }

    function approveProposal(uint256 proposalId) external onlyMember {
        if (!_isPendingProposal(proposalId)) {
            revert NotPendingProposal();
        }
        if (_hasApproved(msg.sender, proposalId)) {
            revert AlreadyApproved();
        }

        // approve proposal
        proposals[proposalId].approvalCount++;
        proposals[proposalId].approvals.push(msg.sender);

        emit Approval(msg.sender, proposalId);

        if (proposals[proposalId].approvalCount >= threshold) {
            _executeProposal(proposalId);
        }
    }

    // reject and delete a pending proposal
    function deleteProposal(uint256 proposalId) external onlyMember {
        if (!_isPendingProposal(proposalId)) {
            revert NotPendingProposal();
        }

        _deletePendingProposalId(proposalId);
        proposals[proposalId].status = Constants.PROPOSAL_STATUS_DELETED;

        emit Delete(msg.sender, proposalId);
    }

    function getPendingProposals() external view returns (Proposal[] memory results) {
        uint256 len = pendingProposalIds.length;

        results = new Proposal[](len);
        for (uint256 i = 0; i < len; i++) {
            uint256 pid = pendingProposalIds[i];
            results[i] = proposals[pid];
        }
    }

    function getAllProposals(uint256 offset, uint256 limit)
        external
        view
        returns (Proposal[] memory results)
    {
        if (offset >= proposalCount) return results;

        uint256 len = Math.min(limit, proposalCount - offset);

        results = new Proposal[](len);
        for (uint256 i = offset; i < offset + len; i++) {
            // plus 1 because proposalId starts from 1
            results[i - offset] = proposals[i + 1];
        }
    }

    function getWalletDetail()
        external
        view
        returns (
            uint256 _threshold,
            uint256 _ownersCount,
            address[] memory _owners
        )
    {
        _threshold = threshold;
        _ownersCount = ownersCount;
        _owners = _getOwners();
    }

    function getProposalCount() external view returns (uint256) {
        return proposalCount;
    }

    function isOwner(address owner) external view returns (bool) {
        return owner != Constants.SENTINEL_OWNER && owners[owner] != address(0);
    }

    function _getOwners() internal view returns (address[] memory) {
        address[] memory array = new address[](ownersCount);

        uint256 index = 0;
        address currentOwner = owners[Constants.SENTINEL_OWNER];
        while (currentOwner != Constants.SENTINEL_OWNER) {
            array[index] = currentOwner;
            currentOwner = owners[currentOwner];
            index++;
        }
        return array;
    }

    function _executeProposal(uint256 proposalId) internal {
        Proposal storage proposal = proposals[proposalId];
        if (proposal.approvalCount < threshold) {
            revert NotEnoughApproval();
        }

        if (
            keccak256(bytes(proposal.proposalType)) ==
            keccak256(bytes(Constants.PROPOSAL_TYPE_CHANGE_ADMIN))
        ) {
            ITransparentUpgradeableProxy(proposal.target).changeAdmin(proposal.data);
            emit ChangeAdmin(proposal.target, proposal.data);
        } else if (
            keccak256(bytes(proposal.proposalType)) ==
            keccak256(bytes(Constants.PROPOSAL_TYPE_UPGRADE))
        ) {
            ITransparentUpgradeableProxy(proposal.target).upgradeTo(proposal.data);
            emit Upgrade(proposal.target, proposal.data);
        } else {
            revert("Unexpected proposal type");
        }

        // update proposal
        _deletePendingProposalId(proposalId);
        proposals[proposalId].status = Constants.PROPOSAL_STATUS_EXECUTED;
    }

    function _deletePendingProposalId(uint256 proposalId) internal {
        // find index to be deleted
        uint256 valueIndex = 0;
        for (uint256 i = 0; i < pendingProposalIds.length; i++) {
            if (proposalId == pendingProposalIds[i]) {
                // plus 1 because index 0
                // means a value is not in the array.
                valueIndex = i + 1;
                break;
            }
        }

        if (valueIndex != 0) {
            uint256 toDeleteIndex = valueIndex - 1;
            uint256 lastIndex = pendingProposalIds.length - 1;
            if (lastIndex != toDeleteIndex) {
                pendingProposalIds[toDeleteIndex] = pendingProposalIds[lastIndex];
            }

            // delete the slot
            pendingProposalIds.pop();
        }
    }

    function _hasApproved(address owner, uint256 proposalId) internal view returns (bool) {
        uint256 valueIndex;
        Proposal memory proposal = proposals[proposalId];
        for (uint256 i = 0; i < proposal.approvals.length; i++) {
            if (owner == proposal.approvals[i]) {
                // plus 1 because index 0
                // means a value is not in the array.
                valueIndex = i + 1;
                break;
            }
        }
        return valueIndex != 0;
    }

    function _isPendingProposal(uint256 proposalId) internal view returns (bool) {
        uint256 valueIndex;
        for (uint256 i = 0; i < pendingProposalIds.length; i++) {
            if (proposalId == pendingProposalIds[i]) {
                // plus 1 because index 0
                // means a value is not in the array.
                valueIndex = i + 1;
                break;
            }
        }

        return valueIndex != 0;
    }
}

        

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address[]","name":"_owners","internalType":"address[]"},{"type":"uint256","name":"_threshold","internalType":"uint256"}]},{"type":"error","name":"AlreadyApproved","inputs":[]},{"type":"error","name":"InvalidOwner","inputs":[]},{"type":"error","name":"NotEnoughApproval","inputs":[]},{"type":"error","name":"NotOwner","inputs":[]},{"type":"error","name":"NotPendingProposal","inputs":[]},{"type":"error","name":"OwnerExists","inputs":[]},{"type":"error","name":"ThresholdExceedsOwnersCount","inputs":[{"type":"uint256","name":"threshold","internalType":"uint256"},{"type":"uint256","name":"ownersCount","internalType":"uint256"}]},{"type":"error","name":"ThresholdIsZero","inputs":[]},{"type":"error","name":"UnexpectedProposalType","inputs":[]},{"type":"event","name":"Approval","inputs":[{"type":"address","name":"owner","internalType":"address","indexed":true},{"type":"uint256","name":"proposalId","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"ChangeAdmin","inputs":[{"type":"address","name":"target","internalType":"address","indexed":false},{"type":"address","name":"newAdmin","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Delete","inputs":[{"type":"address","name":"owner","internalType":"address","indexed":true},{"type":"uint256","name":"proposalId","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"Execution","inputs":[{"type":"uint256","name":"proposalId","internalType":"uint256","indexed":true},{"type":"address","name":"target","internalType":"address","indexed":false},{"type":"string","name":"proposalType","internalType":"string","indexed":false},{"type":"address","name":"data","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Propose","inputs":[{"type":"uint256","name":"proposalId","internalType":"uint256","indexed":true},{"type":"address","name":"target","internalType":"address","indexed":false},{"type":"string","name":"proposalType","internalType":"string","indexed":false},{"type":"address","name":"data","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Setup","inputs":[{"type":"address","name":"initiator","internalType":"address","indexed":true},{"type":"address[]","name":"owners","internalType":"address[]","indexed":false},{"type":"uint256","name":"ownerCount","internalType":"uint256","indexed":true},{"type":"uint256","name":"threshold","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"Upgrade","inputs":[{"type":"address","name":"target","internalType":"address","indexed":false},{"type":"address","name":"implementation","internalType":"address","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"approveProposal","inputs":[{"type":"uint256","name":"proposalId","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"deleteProposal","inputs":[{"type":"uint256","name":"proposalId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple[]","name":"results","internalType":"struct ProxyAdminMultisig.Proposal[]","components":[{"type":"uint256","name":"proposalId","internalType":"uint256"},{"type":"address","name":"target","internalType":"address"},{"type":"string","name":"proposalType","internalType":"string"},{"type":"address","name":"data","internalType":"address"},{"type":"uint256","name":"approvalCount","internalType":"uint256"},{"type":"address[]","name":"approvals","internalType":"address[]"},{"type":"string","name":"status","internalType":"string"}]}],"name":"getAllProposals","inputs":[{"type":"uint256","name":"offset","internalType":"uint256"},{"type":"uint256","name":"limit","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple[]","name":"results","internalType":"struct ProxyAdminMultisig.Proposal[]","components":[{"type":"uint256","name":"proposalId","internalType":"uint256"},{"type":"address","name":"target","internalType":"address"},{"type":"string","name":"proposalType","internalType":"string"},{"type":"address","name":"data","internalType":"address"},{"type":"uint256","name":"approvalCount","internalType":"uint256"},{"type":"address[]","name":"approvals","internalType":"address[]"},{"type":"string","name":"status","internalType":"string"}]}],"name":"getPendingProposals","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getProposalCount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"_threshold","internalType":"uint256"},{"type":"uint256","name":"_ownersCount","internalType":"uint256"},{"type":"address[]","name":"_owners","internalType":"address[]"}],"name":"getWalletDetail","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isOwner","inputs":[{"type":"address","name":"owner","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"propose","inputs":[{"type":"address","name":"target","internalType":"address"},{"type":"string","name":"proposalType","internalType":"string"},{"type":"address","name":"data","internalType":"address"}]}]
              

Contract Creation Code

0x60806040523480156200001157600080fd5b5060405162001d1838038062001d18833981016040819052620000349162000256565b806200005357604051631fc460bf60e11b815260040160405180910390fd5b81518111156200008d57815160405163c9745ceb60e01b815262000084918391600401918252602082015260400190565b60405180910390fd5b600160005b8351811015620001a2576000848281518110620000b357620000b362000330565b6020026020010151905060006001600160a01b0316816001600160a01b03161480620000e857506001600160a01b0381166001145b80620001055750806001600160a01b0316836001600160a01b0316145b1562000124576040516349e27cff60e01b815260040160405180910390fd5b6001600160a01b0381811660009081526020819052604090205416156200015e576040516315d7cf2960e31b815260040160405180910390fd5b6001600160a01b03928316600090815260208190526040902080546001600160a01b0319169382169390931790925580620001998162000346565b91505062000092565b506001600160a01b0381166000908152602081905260409081902080546001600160a01b03191660019081179091558451908190556002849055905183919033907f9ef8de4d179f3fe64ea3a0574dbfe6a3f869ee559b34bf42d25b7ac41ef1c213906200021290889062000370565b60405180910390a4505050620003bf565b634e487b7160e01b600052604160045260246000fd5b80516001600160a01b03811681146200025157600080fd5b919050565b600080604083850312156200026a57600080fd5b82516001600160401b03808211156200028257600080fd5b818501915085601f8301126200029757600080fd5b8151602082821115620002ae57620002ae62000223565b8160051b604051601f19603f83011681018181108682111715620002d657620002d662000223565b604052928352818301935084810182019289841115620002f557600080fd5b948201945b838610156200031e576200030e8662000239565b85529482019493820193620002fa565b97909101519698969750505050505050565b634e487b7160e01b600052603260045260246000fd5b60006000198214156200036957634e487b7160e01b600052601160045260246000fd5b5060010190565b6020808252825182820181905260009190848201906040850190845b81811015620003b35783516001600160a01b0316835292840192918401916001016200038c565b50909695505050505050565b61194980620003cf6000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c8063a3c393f71161005b578063a3c393f714610101578063a80db6fc14610118578063c08cc02d14610120578063e49422051461013157600080fd5b80632376efbc1461008d5780632f54bf6e146100b65780638259d553146100d957806398951b56146100ee575b600080fd5b6100a061009b36600461149f565b610144565b6040516100ad9190611552565b60405180910390f35b6100c96100c436600461164c565b610421565b60405190151581526020016100ad565b6100ec6100e7366004611667565b610459565b005b6100ec6100fc366004611667565b61052f565b61010961065b565b6040516100ad93929190611680565b6100a0610672565b6003546040519081526020016100ad565b6100ec61013f3660046116a8565b610928565b606060035483106101545761041b565b600061016d83856003546101689190611752565b610b74565b90508067ffffffffffffffff81111561018857610188611769565b6040519080825280602002602001820160405280156101c157816020015b6101ae611343565b8152602001906001900390816101a65790505b509150835b6101d0828661177f565b81101561041857600460006101e683600161177f565b81526020808201929092526040908101600020815160e0810183528154815260018201546001600160a01b031693810193909352600281018054919284019161022e90611797565b80601f016020809104026020016040519081016040528092919081815260200182805461025a90611797565b80156102a75780601f1061027c576101008083540402835291602001916102a7565b820191906000526020600020905b81548152906001019060200180831161028a57829003601f168201915b505050505081526020016003820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b03168152602001600482015481526020016005820180548060200260200160405190810160405280929190818152602001828054801561034257602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610324575b5050505050815260200160068201805461035b90611797565b80601f016020809104026020016040519081016040528092919081815260200182805461038790611797565b80156103d45780601f106103a9576101008083540402835291602001916103d4565b820191906000526020600020905b8154815290600101906020018083116103b757829003601f168201915b5050505050815250508386836103ea9190611752565b815181106103fa576103fa6117d2565b60200260200101819052508080610410906117e8565b9150506101c6565b50505b92915050565b60006001600160a01b03821660011480159061041b5750506001600160a01b0390811660009081526020819052604090205416151590565b336000908152602081905260409020546001600160a01b031661048f576040516330cd747160e01b815260040160405180910390fd5b61049881610b8c565b6104b557604051631fc0cfbb60e11b815260040160405180910390fd5b6104be81610bee565b604080518082018252600781526611195b195d195960ca1b6020808301918252600085815260049091529290922090516104fe9260069092019190611392565b50604051819033907fd5f8e8e971a13eefd39d2b144a79e89a46c05e862e0e165e058de3bbedb27b6090600090a350565b336000908152602081905260409020546001600160a01b0316610565576040516330cd747160e01b815260040160405180910390fd5b61056e81610b8c565b61058b57604051631fc0cfbb60e11b815260040160405180910390fd5b6105953382610ce3565b156105b35760405163080fc0bd60e11b815260040160405180910390fd5b60008181526004602081905260408220018054916105d0836117e8565b90915550506000818152600460209081526040808320600501805460018101825590845291832090910180546001600160a01b03191633908117909155905183927f1e4109814b4fb1210f81ef6540a9bf7e5834ff79536859d16d6398f0e417c44f91a360025460008281526004602081905260409091200154106106585761065881610f56565b50565b600254600154606061066b611253565b9050909192565b6005546060908067ffffffffffffffff81111561069157610691611769565b6040519080825280602002602001820160405280156106ca57816020015b6106b7611343565b8152602001906001900390816106af5790505b50915060005b81811015610923576000600582815481106106ed576106ed6117d2565b600091825260208083209091015480835260048252604092839020835160e0810185528154815260018201546001600160a01b031693810193909352600281018054929550929390929084019161074390611797565b80601f016020809104026020016040519081016040528092919081815260200182805461076f90611797565b80156107bc5780601f10610791576101008083540402835291602001916107bc565b820191906000526020600020905b81548152906001019060200180831161079f57829003601f168201915b505050505081526020016003820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b03168152602001600482015481526020016005820180548060200260200160405190810160405280929190818152602001828054801561085757602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610839575b5050505050815260200160068201805461087090611797565b80601f016020809104026020016040519081016040528092919081815260200182805461089c90611797565b80156108e95780601f106108be576101008083540402835291602001916108e9565b820191906000526020600020905b8154815290600101906020018083116108cc57829003601f168201915b505050505081525050848381518110610904576109046117d2565b602002602001018190525050808061091b906117e8565b9150506106d0565b505090565b336000908152602081905260409020546001600160a01b031661095e576040516330cd747160e01b815260040160405180910390fd5b604080518082018252600b81526a21b430b733b2a0b236b4b760a91b602090910152517fefd55ed9dfbf676b0ab91f0770a93483a7071f13b003dcc371938f7d0c600788906109b09085908590611803565b604051809103902014158015610a1a575060408051808201825260078152665570677261646560c81b602090910152517f19add3273ac31967a744b01bbed9306f6881ceaa67df8aea5b8977e6da9b97bc90610a0f9085908590611803565b604051809103902014155b15610a38576040516359a2579b60e11b815260040160405180910390fd5b60038054906000610a48836117e8565b909155505060035460008181526004602052604090208181556001810180546001600160a01b0319166001600160a01b038816179055610a8c906002018585611416565b5060008181526004602081815260408084206003810180546001600160a01b0319166001600160a01b0389161790558084018590558151808301909252600782526650656e64696e6760c81b828401908152948690529290915251610af79260069092019190611392565b50600580546001810182556000919091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00181905560405181907feb99a8f3715db0a65e28b58a1738e840c9538a24ff9c0b2cd6e5c94f3b2321f290610b65908890889088908890611813565b60405180910390a25050505050565b6000818310610b835781610b85565b825b9392505050565b60008060005b600554811015610be55760058181548110610baf57610baf6117d2565b9060005260206000200154841415610bd357610bcc81600161177f565b9150610be5565b80610bdd816117e8565b915050610b92565b50151592915050565b6000805b600554811015610c455760058181548110610c0f57610c0f6117d2565b9060005260206000200154831415610c3357610c2c81600161177f565b9150610c45565b80610c3d816117e8565b915050610bf2565b508015610cdf576000610c59600183611752565b600554909150600090610c6e90600190611752565b9050818114610cb55760058181548110610c8a57610c8a6117d2565b906000526020600020015460058381548110610ca857610ca86117d2565b6000918252602090912001555b6005805480610cc657610cc6611861565b6001900381819060005260206000200160009055905550505b5050565b6000818152600460209081526040808320815160e0810183528154815260018201546001600160a01b0316938101939093526002810180548594859490939290840191610d2f90611797565b80601f0160208091040260200160405190810160405280929190818152602001828054610d5b90611797565b8015610da85780601f10610d7d57610100808354040283529160200191610da8565b820191906000526020600020905b815481529060010190602001808311610d8b57829003601f168201915b505050505081526020016003820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016004820154815260200160058201805480602002602001604051908101604052809291908181526020018280548015610e4357602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610e25575b50505050508152602001600682018054610e5c90611797565b80601f0160208091040260200160405190810160405280929190818152602001828054610e8890611797565b8015610ed55780601f10610eaa57610100808354040283529160200191610ed5565b820191906000526020600020905b815481529060010190602001808311610eb857829003601f168201915b505050505081525050905060005b8160a0015151811015610f4b578160a001518181518110610f0657610f066117d2565b60200260200101516001600160a01b0316866001600160a01b03161415610f3957610f3281600161177f565b9250610f4b565b80610f43816117e8565b915050610ee3565b505015159392505050565b60008181526004602081905260409091206002549181015490911115610f8f576040516323cf61af60e21b815260040160405180910390fd5b604080518082018252600b81526a21b430b733b2a0b236b4b760a91b602090910152517fefd55ed9dfbf676b0ab91f0770a93483a7071f13b003dcc371938f7d0c60078890610fe2906002840190611877565b604051809103902014156110aa57600181015460038201546040516308f2839760e41b81526001600160a01b039182166004820152911690638f28397090602401600060405180830381600087803b15801561103d57600080fd5b505af1158015611051573d6000803e3d6000fd5b5050505060018101546003820154604080516001600160a01b0393841681529290911660208301527fcf9b665e0639e0b81a8db37b60ac7ddf45aeb1b484e11adeb7dff4bf4a3a625891015b60405180910390a1611204565b60408051808201825260078152665570677261646560c81b602090910152517f19add3273ac31967a744b01bbed9306f6881ceaa67df8aea5b8977e6da9b97bc906110f9906002840190611877565b604051809103902014156111b85760018101546003820154604051631b2ce7f360e11b81526001600160a01b039182166004820152911690633659cfe690602401600060405180830381600087803b15801561115457600080fd5b505af1158015611168573d6000803e3d6000fd5b5050505060018101546003820154604080516001600160a01b0393841681529290911660208301527fd23ce5645530506727523fe6d7939e72bb49102454460bc72f0f5baec60ac718910161109d565b60405162461bcd60e51b815260206004820152601860248201527f556e65787065637465642070726f706f73616c20747970650000000000000000604482015260640160405180910390fd5b61120d82610bee565b6040805180820182526008815267115e1958dd5d195960c21b60208083019182526000868152600490915292909220905161124e9260069092019190611392565b505050565b6060600060015467ffffffffffffffff81111561127257611272611769565b60405190808252806020026020018201604052801561129b578160200160208202803683370190505b506001600090815260208190527fada5013122d395ba3c54772283fb069b10426056ef8ca54750cb9bb552a59e7d54919250906001600160a01b03165b6001600160a01b03811660011461133b57808383815181106112fc576112fc6117d2565b6001600160a01b039283166020918202929092018101919091529181166000908152918290526040909120541681611333816117e8565b9250506112d8565b509092915050565b6040518060e001604052806000815260200160006001600160a01b031681526020016060815260200160006001600160a01b031681526020016000815260200160608152602001606081525090565b82805461139e90611797565b90600052602060002090601f0160209004810192826113c05760008555611406565b82601f106113d957805160ff1916838001178555611406565b82800160010185558215611406579182015b828111156114065782518255916020019190600101906113eb565b5061141292915061148a565b5090565b82805461142290611797565b90600052602060002090601f0160209004810192826114445760008555611406565b82601f1061145d5782800160ff19823516178555611406565b82800160010185558215611406579182015b8281111561140657823582559160200191906001019061146f565b5b80821115611412576000815560010161148b565b600080604083850312156114b257600080fd5b50508035926020909101359150565b6000815180845260005b818110156114e7576020818501810151868301820152016114cb565b818111156114f9576000602083870101525b50601f01601f19169290920160200192915050565b600081518084526020808501945080840160005b838110156115475781516001600160a01b031687529582019590820190600101611522565b509495945050505050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b8381101561162257888303603f19018552815180518452878101516001600160a01b03908116898601528782015160e0898701819052916115bc838801836114c1565b925060609150808285015116828801525050608080830151818701525060a080830151868303828801526115f0838261150e565b9250505060c0808301519250858203818701525061160e81836114c1565b968901969450505090860190600101611579565b509098975050505050505050565b80356001600160a01b038116811461164757600080fd5b919050565b60006020828403121561165e57600080fd5b610b8582611630565b60006020828403121561167957600080fd5b5035919050565b83815282602082015260606040820152600061169f606083018461150e565b95945050505050565b600080600080606085870312156116be57600080fd5b6116c785611630565b9350602085013567ffffffffffffffff808211156116e457600080fd5b818701915087601f8301126116f857600080fd5b81358181111561170757600080fd5b88602082850101111561171957600080fd5b60208301955080945050505061173160408601611630565b905092959194509250565b634e487b7160e01b600052601160045260246000fd5b6000828210156117645761176461173c565b500390565b634e487b7160e01b600052604160045260246000fd5b600082198211156117925761179261173c565b500190565b600181811c908216806117ab57607f821691505b602082108114156117cc57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b60006000198214156117fc576117fc61173c565b5060010190565b8183823760009101908152919050565b6001600160a01b03858116825260606020830181905282018490526000908486608085013760008386016080908101919091529316604083015250601f909201601f19169091010192915050565b634e487b7160e01b600052603160045260246000fd5b600080835481600182811c91508083168061189357607f831692505b60208084108214156118b357634e487b7160e01b86526022600452602486fd5b8180156118c757600181146118d857611905565b60ff19861689528489019650611905565b60008a81526020902060005b868110156118fd5781548b8201529085019083016118e4565b505084890196505b50949897505050505050505056fea2646970667358221220bfcce50368ce1fc716d33f637a8c26f3b661763814b8021c7d0136021cf0dcc664736f6c634300080a0033000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000561293bc75993bbd53f63fdfdb43847f91cfd079000000000000000000000000742408a71603159b3074fa83e52e9c37ca1a6810000000000000000000000000f8f67ba5b24ceb288b48a8cfbd878f7b2c057d7a

Deployed ByteCode

0x608060405234801561001057600080fd5b50600436106100885760003560e01c8063a3c393f71161005b578063a3c393f714610101578063a80db6fc14610118578063c08cc02d14610120578063e49422051461013157600080fd5b80632376efbc1461008d5780632f54bf6e146100b65780638259d553146100d957806398951b56146100ee575b600080fd5b6100a061009b36600461149f565b610144565b6040516100ad9190611552565b60405180910390f35b6100c96100c436600461164c565b610421565b60405190151581526020016100ad565b6100ec6100e7366004611667565b610459565b005b6100ec6100fc366004611667565b61052f565b61010961065b565b6040516100ad93929190611680565b6100a0610672565b6003546040519081526020016100ad565b6100ec61013f3660046116a8565b610928565b606060035483106101545761041b565b600061016d83856003546101689190611752565b610b74565b90508067ffffffffffffffff81111561018857610188611769565b6040519080825280602002602001820160405280156101c157816020015b6101ae611343565b8152602001906001900390816101a65790505b509150835b6101d0828661177f565b81101561041857600460006101e683600161177f565b81526020808201929092526040908101600020815160e0810183528154815260018201546001600160a01b031693810193909352600281018054919284019161022e90611797565b80601f016020809104026020016040519081016040528092919081815260200182805461025a90611797565b80156102a75780601f1061027c576101008083540402835291602001916102a7565b820191906000526020600020905b81548152906001019060200180831161028a57829003601f168201915b505050505081526020016003820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b03168152602001600482015481526020016005820180548060200260200160405190810160405280929190818152602001828054801561034257602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610324575b5050505050815260200160068201805461035b90611797565b80601f016020809104026020016040519081016040528092919081815260200182805461038790611797565b80156103d45780601f106103a9576101008083540402835291602001916103d4565b820191906000526020600020905b8154815290600101906020018083116103b757829003601f168201915b5050505050815250508386836103ea9190611752565b815181106103fa576103fa6117d2565b60200260200101819052508080610410906117e8565b9150506101c6565b50505b92915050565b60006001600160a01b03821660011480159061041b5750506001600160a01b0390811660009081526020819052604090205416151590565b336000908152602081905260409020546001600160a01b031661048f576040516330cd747160e01b815260040160405180910390fd5b61049881610b8c565b6104b557604051631fc0cfbb60e11b815260040160405180910390fd5b6104be81610bee565b604080518082018252600781526611195b195d195960ca1b6020808301918252600085815260049091529290922090516104fe9260069092019190611392565b50604051819033907fd5f8e8e971a13eefd39d2b144a79e89a46c05e862e0e165e058de3bbedb27b6090600090a350565b336000908152602081905260409020546001600160a01b0316610565576040516330cd747160e01b815260040160405180910390fd5b61056e81610b8c565b61058b57604051631fc0cfbb60e11b815260040160405180910390fd5b6105953382610ce3565b156105b35760405163080fc0bd60e11b815260040160405180910390fd5b60008181526004602081905260408220018054916105d0836117e8565b90915550506000818152600460209081526040808320600501805460018101825590845291832090910180546001600160a01b03191633908117909155905183927f1e4109814b4fb1210f81ef6540a9bf7e5834ff79536859d16d6398f0e417c44f91a360025460008281526004602081905260409091200154106106585761065881610f56565b50565b600254600154606061066b611253565b9050909192565b6005546060908067ffffffffffffffff81111561069157610691611769565b6040519080825280602002602001820160405280156106ca57816020015b6106b7611343565b8152602001906001900390816106af5790505b50915060005b81811015610923576000600582815481106106ed576106ed6117d2565b600091825260208083209091015480835260048252604092839020835160e0810185528154815260018201546001600160a01b031693810193909352600281018054929550929390929084019161074390611797565b80601f016020809104026020016040519081016040528092919081815260200182805461076f90611797565b80156107bc5780601f10610791576101008083540402835291602001916107bc565b820191906000526020600020905b81548152906001019060200180831161079f57829003601f168201915b505050505081526020016003820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b03168152602001600482015481526020016005820180548060200260200160405190810160405280929190818152602001828054801561085757602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610839575b5050505050815260200160068201805461087090611797565b80601f016020809104026020016040519081016040528092919081815260200182805461089c90611797565b80156108e95780601f106108be576101008083540402835291602001916108e9565b820191906000526020600020905b8154815290600101906020018083116108cc57829003601f168201915b505050505081525050848381518110610904576109046117d2565b602002602001018190525050808061091b906117e8565b9150506106d0565b505090565b336000908152602081905260409020546001600160a01b031661095e576040516330cd747160e01b815260040160405180910390fd5b604080518082018252600b81526a21b430b733b2a0b236b4b760a91b602090910152517fefd55ed9dfbf676b0ab91f0770a93483a7071f13b003dcc371938f7d0c600788906109b09085908590611803565b604051809103902014158015610a1a575060408051808201825260078152665570677261646560c81b602090910152517f19add3273ac31967a744b01bbed9306f6881ceaa67df8aea5b8977e6da9b97bc90610a0f9085908590611803565b604051809103902014155b15610a38576040516359a2579b60e11b815260040160405180910390fd5b60038054906000610a48836117e8565b909155505060035460008181526004602052604090208181556001810180546001600160a01b0319166001600160a01b038816179055610a8c906002018585611416565b5060008181526004602081815260408084206003810180546001600160a01b0319166001600160a01b0389161790558084018590558151808301909252600782526650656e64696e6760c81b828401908152948690529290915251610af79260069092019190611392565b50600580546001810182556000919091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00181905560405181907feb99a8f3715db0a65e28b58a1738e840c9538a24ff9c0b2cd6e5c94f3b2321f290610b65908890889088908890611813565b60405180910390a25050505050565b6000818310610b835781610b85565b825b9392505050565b60008060005b600554811015610be55760058181548110610baf57610baf6117d2565b9060005260206000200154841415610bd357610bcc81600161177f565b9150610be5565b80610bdd816117e8565b915050610b92565b50151592915050565b6000805b600554811015610c455760058181548110610c0f57610c0f6117d2565b9060005260206000200154831415610c3357610c2c81600161177f565b9150610c45565b80610c3d816117e8565b915050610bf2565b508015610cdf576000610c59600183611752565b600554909150600090610c6e90600190611752565b9050818114610cb55760058181548110610c8a57610c8a6117d2565b906000526020600020015460058381548110610ca857610ca86117d2565b6000918252602090912001555b6005805480610cc657610cc6611861565b6001900381819060005260206000200160009055905550505b5050565b6000818152600460209081526040808320815160e0810183528154815260018201546001600160a01b0316938101939093526002810180548594859490939290840191610d2f90611797565b80601f0160208091040260200160405190810160405280929190818152602001828054610d5b90611797565b8015610da85780601f10610d7d57610100808354040283529160200191610da8565b820191906000526020600020905b815481529060010190602001808311610d8b57829003601f168201915b505050505081526020016003820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016004820154815260200160058201805480602002602001604051908101604052809291908181526020018280548015610e4357602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610e25575b50505050508152602001600682018054610e5c90611797565b80601f0160208091040260200160405190810160405280929190818152602001828054610e8890611797565b8015610ed55780601f10610eaa57610100808354040283529160200191610ed5565b820191906000526020600020905b815481529060010190602001808311610eb857829003601f168201915b505050505081525050905060005b8160a0015151811015610f4b578160a001518181518110610f0657610f066117d2565b60200260200101516001600160a01b0316866001600160a01b03161415610f3957610f3281600161177f565b9250610f4b565b80610f43816117e8565b915050610ee3565b505015159392505050565b60008181526004602081905260409091206002549181015490911115610f8f576040516323cf61af60e21b815260040160405180910390fd5b604080518082018252600b81526a21b430b733b2a0b236b4b760a91b602090910152517fefd55ed9dfbf676b0ab91f0770a93483a7071f13b003dcc371938f7d0c60078890610fe2906002840190611877565b604051809103902014156110aa57600181015460038201546040516308f2839760e41b81526001600160a01b039182166004820152911690638f28397090602401600060405180830381600087803b15801561103d57600080fd5b505af1158015611051573d6000803e3d6000fd5b5050505060018101546003820154604080516001600160a01b0393841681529290911660208301527fcf9b665e0639e0b81a8db37b60ac7ddf45aeb1b484e11adeb7dff4bf4a3a625891015b60405180910390a1611204565b60408051808201825260078152665570677261646560c81b602090910152517f19add3273ac31967a744b01bbed9306f6881ceaa67df8aea5b8977e6da9b97bc906110f9906002840190611877565b604051809103902014156111b85760018101546003820154604051631b2ce7f360e11b81526001600160a01b039182166004820152911690633659cfe690602401600060405180830381600087803b15801561115457600080fd5b505af1158015611168573d6000803e3d6000fd5b5050505060018101546003820154604080516001600160a01b0393841681529290911660208301527fd23ce5645530506727523fe6d7939e72bb49102454460bc72f0f5baec60ac718910161109d565b60405162461bcd60e51b815260206004820152601860248201527f556e65787065637465642070726f706f73616c20747970650000000000000000604482015260640160405180910390fd5b61120d82610bee565b6040805180820182526008815267115e1958dd5d195960c21b60208083019182526000868152600490915292909220905161124e9260069092019190611392565b505050565b6060600060015467ffffffffffffffff81111561127257611272611769565b60405190808252806020026020018201604052801561129b578160200160208202803683370190505b506001600090815260208190527fada5013122d395ba3c54772283fb069b10426056ef8ca54750cb9bb552a59e7d54919250906001600160a01b03165b6001600160a01b03811660011461133b57808383815181106112fc576112fc6117d2565b6001600160a01b039283166020918202929092018101919091529181166000908152918290526040909120541681611333816117e8565b9250506112d8565b509092915050565b6040518060e001604052806000815260200160006001600160a01b031681526020016060815260200160006001600160a01b031681526020016000815260200160608152602001606081525090565b82805461139e90611797565b90600052602060002090601f0160209004810192826113c05760008555611406565b82601f106113d957805160ff1916838001178555611406565b82800160010185558215611406579182015b828111156114065782518255916020019190600101906113eb565b5061141292915061148a565b5090565b82805461142290611797565b90600052602060002090601f0160209004810192826114445760008555611406565b82601f1061145d5782800160ff19823516178555611406565b82800160010185558215611406579182015b8281111561140657823582559160200191906001019061146f565b5b80821115611412576000815560010161148b565b600080604083850312156114b257600080fd5b50508035926020909101359150565b6000815180845260005b818110156114e7576020818501810151868301820152016114cb565b818111156114f9576000602083870101525b50601f01601f19169290920160200192915050565b600081518084526020808501945080840160005b838110156115475781516001600160a01b031687529582019590820190600101611522565b509495945050505050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b8381101561162257888303603f19018552815180518452878101516001600160a01b03908116898601528782015160e0898701819052916115bc838801836114c1565b925060609150808285015116828801525050608080830151818701525060a080830151868303828801526115f0838261150e565b9250505060c0808301519250858203818701525061160e81836114c1565b968901969450505090860190600101611579565b509098975050505050505050565b80356001600160a01b038116811461164757600080fd5b919050565b60006020828403121561165e57600080fd5b610b8582611630565b60006020828403121561167957600080fd5b5035919050565b83815282602082015260606040820152600061169f606083018461150e565b95945050505050565b600080600080606085870312156116be57600080fd5b6116c785611630565b9350602085013567ffffffffffffffff808211156116e457600080fd5b818701915087601f8301126116f857600080fd5b81358181111561170757600080fd5b88602082850101111561171957600080fd5b60208301955080945050505061173160408601611630565b905092959194509250565b634e487b7160e01b600052601160045260246000fd5b6000828210156117645761176461173c565b500390565b634e487b7160e01b600052604160045260246000fd5b600082198211156117925761179261173c565b500190565b600181811c908216806117ab57607f821691505b602082108114156117cc57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b60006000198214156117fc576117fc61173c565b5060010190565b8183823760009101908152919050565b6001600160a01b03858116825260606020830181905282018490526000908486608085013760008386016080908101919091529316604083015250601f909201601f19169091010192915050565b634e487b7160e01b600052603160045260246000fd5b600080835481600182811c91508083168061189357607f831692505b60208084108214156118b357634e487b7160e01b86526022600452602486fd5b8180156118c757600181146118d857611905565b60ff19861689528489019650611905565b60008a81526020902060005b868110156118fd5781548b8201529085019083016118e4565b505084890196505b50949897505050505050505056fea2646970667358221220bfcce50368ce1fc716d33f637a8c26f3b661763814b8021c7d0136021cf0dcc664736f6c634300080a0033