Contract Address Details

0x1c5A78dc93B644D7375527888a0aB5dcf1250C74

Contract Name
MultiSigVesting
Creator
0x90c9ea–1d787d at 0x66d8ec–630181
Balance
0 REI
Tokens
Fetching tokens...
Transactions
2 Transactions
Transfers
1 Transfers
Gas Used
295,220
Last Balance Update
34084345
Contract name:
MultiSigVesting




Optimization enabled
true
Compiler version
v0.8.7+commit.e28d00a7




Optimization runs
200
Verified at
2022-12-01T07:19:30.104746Z

Contract source code

// Sources flattened with hardhat v2.9.3 https://hardhat.org

// File @openzeppelin/contracts/token/ERC20/[email protected]

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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


// File @openzeppelin/contracts/utils/[email protected]


// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)

pragma solidity ^0.8.1;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        require(isContract(target), "Address: call to non-contract");

        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");

        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}


// File @openzeppelin/contracts/token/ERC20/utils/[email protected]


// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.0;


/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using Address for address;

    function safeTransfer(
        IERC20 token,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(
        IERC20 token,
        address from,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        require(
            (value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        uint256 newAllowance = token.allowance(address(this), spender) + value;
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        unchecked {
            uint256 oldAllowance = token.allowance(address(this), spender);
            require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
            uint256 newAllowance = oldAllowance - value;
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        if (returndata.length > 0) {
            // Return data is optional
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}


// File contracts/VestingWallet.sol


pragma solidity 0.8.7;


/**
 * @title VestingWallet
 * @dev This contract handles the vesting of Eth and ERC20 tokens for a given beneficiary. Custody of multiple tokens
 * can be given to this contract, which will release the token to the beneficiary following a given vesting schedule.
 * The vesting schedule is customizable through the {vestedAmount} function.
 *
 * Any token transferred to this contract will follow the vesting schedule as if they were locked from the beginning.
 * Consequently, if the vesting has already started, any amount of tokens sent to this contract will (at least partly)
 * be immediately releasable.
 */
contract VestingWallet  {
    event EtherReleased(uint256 amount);
    event ERC20Released(address indexed token, uint256 amount);

    address private  _beneficiary;
    uint64 private  _start;
    uint64 private  _duration;

    /**
     * @dev Set the beneficiary, start timestamp and vesting duration of the vesting wallet.
     */
    function VestingWallet_initialize(
        address beneficiaryAddress,
        uint64 startTimestamp,
        uint64 durationSeconds
    ) internal {
        require(beneficiaryAddress != address(0), "VestingWallet: beneficiary is zero address");
        _beneficiary = beneficiaryAddress;
        _start = startTimestamp;
        _duration = durationSeconds;
    }

    /**
     * @dev Getter for the beneficiary address.
     */
    function beneficiary() public view virtual returns (address) {
        return _beneficiary;
    }

    /**
     * @dev Getter for the start timestamp.
     */
    function start() public view virtual returns (uint256) {
        return _start;
    }

    /**
     * @dev Getter for the vesting duration.
     */
    function duration() public view virtual returns (uint256) {
        return _duration;
    }

    /**
     * @dev Calculates the amount of ether that has already vested. Default implementation is a linear vesting curve.
     */
    function vestedAmount(uint64 timestamp) public view virtual returns (uint256) {
        return _vestingSchedule(address(this).balance, timestamp);
    }

    /**
     * @dev Calculates the amount of tokens that has already vested. Default implementation is a linear vesting curve.
     */
    function vestedAmount(address token, uint64 timestamp) public view virtual returns (uint256) {
        return _vestingSchedule(IERC20(token).balanceOf(address(this)), timestamp);
    }

    /**
     * @dev Virtual implementation of the vesting formula. This returns the amout vested, as a function of time, for
     * an asset given its total historical allocation.
     */
    function _vestingSchedule(uint256 totalAllocation, uint64 timestamp) internal view virtual returns (uint256) {
       if (timestamp >= start() + duration()) {
            return totalAllocation;
        }else{
            return 0;
        }
    }
}


// File contracts/MultiSigWallet.sol


pragma solidity 0.8.7;

contract MultiSigWallet {
    /*
     *  Events
     */
    event Confirmation(address indexed sender, uint indexed transactionId);
    event Revocation(address indexed sender, uint indexed transactionId);
    event Submission(uint indexed transactionId);
    event Execution(uint indexed transactionId);
    event ExecutionFailure(uint indexed transactionId);
    event Deposit(address indexed sender, uint value);
    event OwnerAddition(address indexed owner);
    event OwnerRemoval(address indexed owner);
    event RequirementChange(uint required);

    /*
     *  Constants
     */
    uint constant public MAX_OWNER_COUNT = 50;

    /*
     *  Storage
     */
    mapping (uint => Transaction) public transactions;
    mapping (uint => mapping (address => bool)) public confirmations;
    mapping (address => bool) public isOwner;
    address[] public owners;
    uint public required;
    uint public transactionCount;

    struct Transaction {
        address destination;
        uint value;
        bytes data;
        bool executed;
    }

    /*
     *  Modifiers
     */
    modifier onlyWallet() {
        require(msg.sender == address(this));
        _;
    }

    modifier ownerDoesNotExist(address owner) {
        require(!isOwner[owner]);
        _;
    }

    modifier ownerExists(address owner) {
        require(isOwner[owner]);
        _;
    }

    modifier transactionExists(uint transactionId) {
        require(transactions[transactionId].destination != address(0));
        _;
    }

    modifier confirmed(uint transactionId, address owner) {
        require(confirmations[transactionId][owner]);
        _;
    }

    modifier notConfirmed(uint transactionId, address owner) {
        require(!confirmations[transactionId][owner]);
        _;
    }

    modifier notExecuted(uint transactionId) {
        require(!transactions[transactionId].executed);
        _;
    }

    modifier notNull(address _address) {
        require(_address != address(0));
        _;
    }

    modifier validRequirement(uint ownerCount, uint _required) {
        require(ownerCount <= MAX_OWNER_COUNT
            && _required <= ownerCount
            && _required != 0
            && ownerCount != 0);
        _;
    }

    /// @dev Fallback function allows to deposit ether.
    fallback()
        external
        payable
    {
        if (msg.value > 0)
            emit Deposit(msg.sender, msg.value);
    }

    receive()
        external
        payable
    {
        if (msg.value > 0)
            emit Deposit(msg.sender, msg.value);
    }

    /*
     * Public functions
     */
    /// @dev Contract constructor sets initial owners and required number of confirmations.
    /// @param _owners List of initial owners.
    /// @param _required Number of required confirmations.
    function MultiSigWallet_initialize(address[] memory _owners, uint _required)
        validRequirement(_owners.length, _required) internal
    {
        for (uint i=0; i<_owners.length; i++) {
            require(!isOwner[_owners[i]] && _owners[i] != address(0));
            isOwner[_owners[i]] = true;
        }
        owners = _owners;
        required = _required;
    }

    /// @dev Allows to add a new owner. Transaction has to be sent by wallet.
    /// @param owner Address of new owner.
    function addOwner(address owner)
        public
        onlyWallet
        ownerDoesNotExist(owner)
        notNull(owner)
        validRequirement(owners.length + 1, required)
    {
        isOwner[owner] = true;
        owners.push(owner);
        emit OwnerAddition(owner);
    }

    /// @dev Allows to remove an owner. Transaction has to be sent by wallet.
    /// @param owner Address of owner.
    function removeOwner(address owner)
        public
        onlyWallet
        ownerExists(owner)
    {
        isOwner[owner] = false;
        for (uint i=0; i<owners.length - 1; i++)
            if (owners[i] == owner) {
                owners[i] = owners[owners.length - 1];
                break;
            }
        owners.pop();
        if (required > owners.length)
            changeRequirement(owners.length);
        emit OwnerRemoval(owner);
    }

    /// @dev Allows to replace an owner with a new owner. Transaction has to be sent by wallet.
    /// @param owner Address of owner to be replaced.
    /// @param newOwner Address of new owner.
    function replaceOwner(address owner, address newOwner)
        public
        onlyWallet
        ownerExists(owner)
        ownerDoesNotExist(newOwner)
    {
        for (uint i=0; i<owners.length; i++)
            if (owners[i] == owner) {
                owners[i] = newOwner;
                break;
            }
        isOwner[owner] = false;
        isOwner[newOwner] = true;
        emit OwnerRemoval(owner);
        emit OwnerAddition(newOwner);
    }

    /// @dev Allows to change the number of required confirmations. Transaction has to be sent by wallet.
    /// @param _required Number of required confirmations.
    function changeRequirement(uint _required)
        public
        onlyWallet
        validRequirement(owners.length, _required)
    {
        required = _required;
        emit RequirementChange(_required);
    }

    /// @dev Allows an owner to submit and confirm a transaction.
    /// @param destination Transaction target address.
    /// @param value Transaction ether value.
    /// @param data Transaction data payload.
    /// @return transactionId Returns transaction ID.
    function submitTransaction(address destination, uint value, bytes memory data)
        public
        returns (uint transactionId)
    {
        transactionId = addTransaction(destination, value, data);
        confirmTransaction(transactionId);
    }

    /// @dev Allows an owner to confirm a transaction.
    /// @param transactionId Transaction ID.
    function confirmTransaction(uint transactionId)
        public
        virtual
        ownerExists(msg.sender)
        transactionExists(transactionId)
        notConfirmed(transactionId, msg.sender)
    {
        confirmations[transactionId][msg.sender] = true;
        emit Confirmation(msg.sender, transactionId);
        executeTransaction(transactionId);
    }

    /// @dev Allows an owner to revoke a confirmation for a transaction.
    /// @param transactionId Transaction ID.
    function revokeConfirmation(uint transactionId)
        public
        ownerExists(msg.sender)
        confirmed(transactionId, msg.sender)
        notExecuted(transactionId)
    {
        confirmations[transactionId][msg.sender] = false;
        emit Revocation(msg.sender, transactionId);
    }

    /// @dev Allows anyone to execute a confirmed transaction.
    /// @param transactionId Transaction ID.
    function executeTransaction(uint transactionId)
        public
        virtual
        ownerExists(msg.sender)
        confirmed(transactionId, msg.sender)
        notExecuted(transactionId)
    {
        if (isConfirmed(transactionId)) {
            Transaction storage txn = transactions[transactionId];
            txn.executed = true;
            if (external_call(txn.destination, txn.value, txn.data.length, txn.data))
                emit Execution(transactionId);
            else {
                emit ExecutionFailure(transactionId);
                txn.executed = false;
            }
        }
    }

    // call has been separated into its own function in order to take advantage
    // of the Solidity's code generator to produce a loop that copies tx.data into memory.
    function external_call(address destination, uint value, uint dataLength, bytes memory data) internal returns (bool) {
        bool result;
        assembly {
            let x := mload(0x40)   // "Allocate" memory for output (0x40 is where "free memory" pointer is stored by convention)
            let d := add(data, 32) // First 32 bytes are the padded length of data, so exclude that
            result := call(
                sub(gas(), 34710),   // 34710 is the value that solidity is currently emitting
                                   // It includes callGas (700) + callVeryLow (3, to pay for SUB) + callValueTransferGas (9000) +
                                   // callNewAccountGas (25000, in case the destination address does not exist and needs creating)
                destination,
                value,
                d,
                dataLength,        // Size of the input (in bytes) - this is what fixes the padding problem
                x,
                0                  // Output is ignored, therefore the output size is zero
            )
        }
        return result;
    }

    /// @dev Returns the confirmation status of a transaction.
    /// @param transactionId Transaction ID.
    /// @return Confirmation status.
    function isConfirmed(uint transactionId)
        public
        view
        returns (bool)
    {
        uint count = 0;
        for (uint i=0; i<owners.length; i++) {
            if (confirmations[transactionId][owners[i]])
                count += 1;
            if (count == required)
                return true;
        }

        return false;
    }

    /*
     * Internal functions
     */
    /// @dev Adds a new transaction to the transaction mapping, if transaction does not exist yet.
    /// @param destination Transaction target address.
    /// @param value Transaction ether value.
    /// @param data Transaction data payload.
    /// @return transactionId Returns transaction ID.
    function addTransaction(address destination, uint value, bytes memory data)
        internal
        notNull(destination)
        returns (uint transactionId)
    {
        transactionId = transactionCount;
        transactions[transactionId] = Transaction({
            destination: destination,
            value: value,
            data: data,
            executed: false
        });
        transactionCount += 1;
        emit Submission(transactionId);
    }

    /*
     * Web3 call functions
     */
    /// @dev Returns number of confirmations of a transaction.
    /// @param transactionId Transaction ID.
    /// @return count Number of confirmations.
    function getConfirmationCount(uint transactionId)
        public
        view
        returns (uint count)
    {
        for (uint i=0; i<owners.length; i++)
            if (confirmations[transactionId][owners[i]])
                count += 1;
    }

    /// @dev Returns total number of transactions after filers are applied.
    /// @param pending Include pending transactions.
    /// @param executed Include executed transactions.
    /// @return count Total number of transactions after filters are applied.
    function getTransactionCount(bool pending, bool executed)
        public
        view
        returns (uint count)
    {
        for (uint i=0; i<transactionCount; i++)
            if (   pending && !transactions[i].executed
                || executed && transactions[i].executed)
                count += 1;
    }

    /// @dev Returns list of owners.
    /// @return List of owner addresses.
    function getOwners()
        public
        view
        returns (address[] memory)
    {
        return owners;
    }

    /// @dev Returns array with owner addresses, which confirmed transaction.
    /// @param transactionId Transaction ID.
    /// @return _confirmations Returns array of owner addresses.
    function getConfirmations(uint transactionId)
        public
        view
        returns (address[] memory _confirmations)
    {
        address[] memory confirmationsTemp = new address[](owners.length);
        uint count = 0;
        uint i;
        for (i=0; i<owners.length; i++)
            if (confirmations[transactionId][owners[i]]) {
                confirmationsTemp[count] = owners[i];
                count += 1;
            }
        _confirmations = new address[](count);
        for (i=0; i<count; i++)
            _confirmations[i] = confirmationsTemp[i];
    }

    /// @dev Returns list of transaction IDs in defined range.
    /// @param from Index start position of transaction array.
    /// @param to Index end position of transaction array.
    /// @param pending Include pending transactions.
    /// @param executed Include executed transactions.
    /// @return _transactionIds Returns array of transaction IDs.
    function getTransactionIds(uint from, uint to, bool pending, bool executed)
        public
        view
        returns (uint[] memory _transactionIds)
    {
        uint[] memory transactionIdsTemp = new uint[](transactionCount);
        uint count = 0;
        uint i;
        for (i=0; i<transactionCount; i++)
            if (   pending && !transactions[i].executed
                || executed && transactions[i].executed)
            {
                transactionIdsTemp[count] = i;
                count += 1;
            }
        _transactionIds = new uint[](to - from);
        for (i=from; i<to; i++)
            _transactionIds[i - from] = transactionIdsTemp[i];
    }
}


// File contracts/MultiSigVesting.sol


pragma solidity 0.8.7;


contract MultiSigVesting  is MultiSigWallet,VestingWallet{

    address public  _tokenLp;
    address public  _token;

    address private  _wrei;

    // address private  _pool;

    address private immutable _idopool;

    constructor() {
         _idopool = msg.sender;
    }

    function initialize(
        address[] memory _owners,
        uint256 _required,
        uint64 _durationSeconds,
        address _benefit,
        uint64 _time,
        address token,
        address _lpAddr,
        address wrei
       
    ) external {
        require(msg.sender == _idopool,"only pool");

        MultiSigWallet_initialize(_owners, _required);
        VestingWallet_initialize(_benefit,_time,_durationSeconds);

       _token = token;
       _wrei = wrei;
        _tokenLp = _lpAddr;
    }

    function releaseLp() public onlyWallet {
        uint256 releasable = vestedAmount(_tokenLp, uint64(block.timestamp));
        emit ERC20Released(_tokenLp, releasable);
        SafeERC20.safeTransfer(IERC20(_tokenLp), beneficiary(), releasable);
    }

    function release(uint256 _amount) public onlyWallet {
         uint256 value;
         require(start() < block.timestamp,"end!");
        
        if(_token == _wrei) {
            value = address(this).balance;
            
            require(_amount <= value,"amount lt balanceOf");

            payable(beneficiary()).transfer(_amount);
        }else{
            value = IERC20(_token).balanceOf(address(this));
            
            require(_amount <= value,"amount lt balanceOf");

            IERC20(_token).transfer(beneficiary(), _amount);
        }   

        emit EtherReleased(_amount);
    }
}
        
>

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[]},{"type":"event","name":"Confirmation","inputs":[{"type":"address","name":"sender","internalType":"address","indexed":true},{"type":"uint256","name":"transactionId","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"Deposit","inputs":[{"type":"address","name":"sender","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"ERC20Released","inputs":[{"type":"address","name":"token","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"EtherReleased","inputs":[{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Execution","inputs":[{"type":"uint256","name":"transactionId","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"ExecutionFailure","inputs":[{"type":"uint256","name":"transactionId","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"OwnerAddition","inputs":[{"type":"address","name":"owner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"OwnerRemoval","inputs":[{"type":"address","name":"owner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"RequirementChange","inputs":[{"type":"uint256","name":"required","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Revocation","inputs":[{"type":"address","name":"sender","internalType":"address","indexed":true},{"type":"uint256","name":"transactionId","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"Submission","inputs":[{"type":"uint256","name":"transactionId","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"fallback","stateMutability":"payable"},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"MAX_OWNER_COUNT","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"_token","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"_tokenLp","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"addOwner","inputs":[{"type":"address","name":"owner","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"beneficiary","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"changeRequirement","inputs":[{"type":"uint256","name":"_required","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"confirmTransaction","inputs":[{"type":"uint256","name":"transactionId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"confirmations","inputs":[{"type":"uint256","name":"","internalType":"uint256"},{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"duration","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"executeTransaction","inputs":[{"type":"uint256","name":"transactionId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"count","internalType":"uint256"}],"name":"getConfirmationCount","inputs":[{"type":"uint256","name":"transactionId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address[]","name":"_confirmations","internalType":"address[]"}],"name":"getConfirmations","inputs":[{"type":"uint256","name":"transactionId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address[]","name":"","internalType":"address[]"}],"name":"getOwners","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"count","internalType":"uint256"}],"name":"getTransactionCount","inputs":[{"type":"bool","name":"pending","internalType":"bool"},{"type":"bool","name":"executed","internalType":"bool"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256[]","name":"_transactionIds","internalType":"uint256[]"}],"name":"getTransactionIds","inputs":[{"type":"uint256","name":"from","internalType":"uint256"},{"type":"uint256","name":"to","internalType":"uint256"},{"type":"bool","name":"pending","internalType":"bool"},{"type":"bool","name":"executed","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"initialize","inputs":[{"type":"address[]","name":"_owners","internalType":"address[]"},{"type":"uint256","name":"_required","internalType":"uint256"},{"type":"uint64","name":"_durationSeconds","internalType":"uint64"},{"type":"address","name":"_benefit","internalType":"address"},{"type":"uint64","name":"_time","internalType":"uint64"},{"type":"address","name":"token","internalType":"address"},{"type":"address","name":"_lpAddr","internalType":"address"},{"type":"address","name":"wrei","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isConfirmed","inputs":[{"type":"uint256","name":"transactionId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isOwner","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owners","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"release","inputs":[{"type":"uint256","name":"_amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"releaseLp","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"removeOwner","inputs":[{"type":"address","name":"owner","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"replaceOwner","inputs":[{"type":"address","name":"owner","internalType":"address"},{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"required","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"revokeConfirmation","inputs":[{"type":"uint256","name":"transactionId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"start","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"transactionId","internalType":"uint256"}],"name":"submitTransaction","inputs":[{"type":"address","name":"destination","internalType":"address"},{"type":"uint256","name":"value","internalType":"uint256"},{"type":"bytes","name":"data","internalType":"bytes"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"transactionCount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"destination","internalType":"address"},{"type":"uint256","name":"value","internalType":"uint256"},{"type":"bytes","name":"data","internalType":"bytes"},{"type":"bool","name":"executed","internalType":"bool"}],"name":"transactions","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"vestedAmount","inputs":[{"type":"uint64","name":"timestamp","internalType":"uint64"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"vestedAmount","inputs":[{"type":"address","name":"token","internalType":"address"},{"type":"uint64","name":"timestamp","internalType":"uint64"}]},{"type":"receive","stateMutability":"payable"}]
              

Contract Creation Code

0x60a060405234801561001057600080fd5b5033606081901b6080526126fe61003260003960006115ce01526126fe6000f3fe6080604052600436106101dc5760003560e01c80639ace38c211610102578063c642747411610095578063dc8452cd11610064578063dc8452cd14610625578063e20056e61461063b578063ecd0c0c31461065b578063ee22610b1461067b57610220565b8063c6427474146105a9578063cf5bf23f146105c9578063d6c3179d146105e9578063d74f8edd1461061057610220565b8063b77bf600116100d1578063b77bf6001461052e578063ba51a6df14610544578063be9a655514610564578063c01a8c841461058957610220565b80639ace38c21461048f578063a0e67e2b146104bf578063a8abe69a146104e1578063b5dc40c31461050e57610220565b806337bdc99b1161017a5780637065cb48116101495780637065cb481461040f578063784547a71461042f578063810ec23b1461044f5780638b51d13f1461046f57610220565b806337bdc99b1461039c57806338af3eed146103bc57806343ad92d5146103da57806354741525146103ef57610220565b8063173825d9116101b6578063173825d9146102e157806320ea8d86146103015780632f54bf6e146103215780633411c81c1461036157610220565b8063025e7c27146102585780630a17b06b146102955780630fb5a6b4146102c357610220565b3661022057341561021e5760405134815233907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c906020015b60405180910390a25b005b341561021e5760405134815233907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c90602001610215565b34801561026457600080fd5b506102786102733660046123af565b61069b565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156102a157600080fd5b506102b56102b036600461244e565b6106c5565b60405190815260200161028c565b3480156102cf57600080fd5b506007546001600160401b03166102b5565b3480156102ed57600080fd5b5061021e6102fc36600461210e565b6106d7565b34801561030d57600080fd5b5061021e61031c3660046123af565b61088e565b34801561032d57600080fd5b5061035161033c36600461210e565b60026020526000908152604090205460ff1681565b604051901515815260200161028c565b34801561036d57600080fd5b5061035161037c3660046123e1565b600160209081526000928352604080842090915290825290205460ff1681565b3480156103a857600080fd5b5061021e6103b73660046123af565b610944565b3480156103c857600080fd5b506006546001600160a01b0316610278565b3480156103e657600080fd5b5061021e610bec565b3480156103fb57600080fd5b506102b561040a366004612376565b610c95565b34801561041b57600080fd5b5061021e61042a36600461210e565b610d12565b34801561043b57600080fd5b5061035161044a3660046123af565b610e2b565b34801561045b57600080fd5b506102b561046a36600461220a565b610eca565b34801561047b57600080fd5b506102b561048a3660046123af565b610f55565b34801561049b57600080fd5b506104af6104aa3660046123af565b610fdb565b60405161028c94939291906124b1565b3480156104cb57600080fd5b506104d4611099565b60405161028c91906124eb565b3480156104ed57600080fd5b506105016104fc366004612404565b6110fb565b60405161028c9190612538565b34801561051a57600080fd5b506104d46105293660046123af565b611291565b34801561053a57600080fd5b506102b560055481565b34801561055057600080fd5b5061021e61055f3660046123af565b611467565b34801561057057600080fd5b50600654600160a01b90046001600160401b03166102b5565b34801561059557600080fd5b5061021e6105a43660046123af565b6114e4565b3480156105b557600080fd5b506102b56105c436600461215c565b6115ab565b3480156105d557600080fd5b5061021e6105e4366004612234565b6115c3565b3480156105f557600080fd5b5060075461027890600160401b90046001600160a01b031681565b34801561061c57600080fd5b506102b5603281565b34801561063157600080fd5b506102b560045481565b34801561064757600080fd5b5061021e610656366004612129565b611698565b34801561066757600080fd5b50600854610278906001600160a01b031681565b34801561068757600080fd5b5061021e6106963660046123af565b61182b565b600381815481106106ab57600080fd5b6000918252602090912001546001600160a01b0316905081565b60006106d147836119ee565b92915050565b3330146106e357600080fd5b6001600160a01b038116600090815260026020526040902054819060ff1661070a57600080fd5b6001600160a01b0382166000908152600260205260408120805460ff191690555b60035461073a906001906125cb565b81101561080a57826001600160a01b03166003828154811061075e5761075e61268e565b6000918252602090912001546001600160a01b031614156107f85760038054610789906001906125cb565b815481106107995761079961268e565b600091825260209091200154600380546001600160a01b0390921691839081106107c5576107c561268e565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555061080a565b8061080281612647565b91505061072b565b50600380548061081c5761081c612678565b600082815260209020810160001990810180546001600160a01b031916905501905560035460045411156108565760035461085690611467565b6040516001600160a01b038316907f8001553a916ef2f495d26a907cc54d96ed840d7bda71e73194bf5a9df7a76b9090600090a25050565b3360008181526002602052604090205460ff166108aa57600080fd5b60008281526001602090815260408083203380855292529091205483919060ff166108d457600080fd5b600084815260208190526040902060030154849060ff16156108f557600080fd5b6000858152600160209081526040808320338085529252808320805460ff191690555187927ff6a317157440607f36269043eb55f1287a5a19ba2216afeab88cd46cbcfb88e991a35050505050565b33301461095057600080fd5b60004261096d6006546001600160401b03600160a01b9091041690565b106109ac5760405162461bcd60e51b81526004016109a390602080825260049082015263656e642160e01b604082015260600190565b60405180910390fd5b6009546008546001600160a01b0390811691161415610a4d57504780821115610a0d5760405162461bcd60e51b815260206004820152601360248201527230b6b7bab73a10363a103130b630b731b2a7b360691b60448201526064016109a3565b6006546040516001600160a01b039091169083156108fc029084906000818181858888f19350505050158015610a47573d6000803e3d6000fd5b50610bb5565b6008546040516370a0823160e01b81523060048201526001600160a01b03909116906370a082319060240160206040518083038186803b158015610a9057600080fd5b505afa158015610aa4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ac891906123c8565b905080821115610b105760405162461bcd60e51b815260206004820152601360248201527230b6b7bab73a10363a103130b630b731b2a7b360691b60448201526064016109a3565b6008546001600160a01b031663a9059cbb610b336006546001600160a01b031690565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101859052604401602060405180830381600087803b158015610b7b57600080fd5b505af1158015610b8f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bb39190612359565b505b6040518281527fda9d4e5f101b8b9b1c5b76d0c5a9f7923571acfc02376aa076b75a8c080c956b9060200160405180910390a15050565b333014610bf857600080fd5b600754600090610c1890600160401b90046001600160a01b031642610eca565b600754604051828152919250600160401b90046001600160a01b0316907fc0e523490dd523c33b1878c9eb14ff46991e3f5b2cd33710918618f2a39cba1b9060200160405180910390a2600754610c92906001600160a01b03600160401b90910416610c8c6006546001600160a01b031690565b83611a3d565b50565b6000805b600554811015610d0b57838015610cc2575060008181526020819052604090206003015460ff16155b80610ce65750828015610ce6575060008181526020819052604090206003015460ff165b15610cf957610cf66001836125b3565b91505b80610d0381612647565b915050610c99565b5092915050565b333014610d1e57600080fd5b6001600160a01b038116600090815260026020526040902054819060ff1615610d4657600080fd5b816001600160a01b038116610d5a57600080fd5b600354610d689060016125b3565b60045460328211158015610d7c5750818111155b8015610d8757508015155b8015610d9257508115155b610d9b57600080fd5b6001600160a01b038516600081815260026020526040808220805460ff1916600190811790915560038054918201815583527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b0180546001600160a01b03191684179055517ff39e6e1eb0edcf53c221607b54b00cd28f3196fed0a24994dc308b8f611b682d9190a25050505050565b600080805b600354811015610ec05760008481526001602052604081206003805491929184908110610e5f57610e5f61268e565b60009182526020808320909101546001600160a01b0316835282019290925260400190205460ff1615610e9a57610e976001836125b3565b91505b600454821415610eae575060019392505050565b80610eb881612647565b915050610e30565b5060009392505050565b6040516370a0823160e01b8152306004820152600090610f4e906001600160a01b038516906370a082319060240160206040518083038186803b158015610f1057600080fd5b505afa158015610f24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4891906123c8565b836119ee565b9392505050565b6000805b600354811015610fd55760008381526001602052604081206003805491929184908110610f8857610f8861268e565b60009182526020808320909101546001600160a01b0316835282019290925260400190205460ff1615610fc357610fc06001836125b3565b91505b80610fcd81612647565b915050610f59565b50919050565b6000602081905290815260409020805460018201546002830180546001600160a01b0390931693919261100d90612612565b80601f016020809104026020016040519081016040528092919081815260200182805461103990612612565b80156110865780601f1061105b57610100808354040283529160200191611086565b820191906000526020600020905b81548152906001019060200180831161106957829003601f168201915b5050506003909301549192505060ff1684565b606060038054806020026020016040519081016040528092919081815260200182805480156110f157602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116110d3575b5050505050905090565b606060006005546001600160401b03811115611119576111196126a4565b604051908082528060200260200182016040528015611142578160200160208202803683370190505b5090506000805b6005548110156111d957858015611172575060008181526020819052604090206003015460ff16155b806111965750848015611196575060008181526020819052604090206003015460ff165b156111c757808383815181106111ae576111ae61268e565b60209081029190910101526111c46001836125b3565b91505b806111d181612647565b915050611149565b6111e388886125cb565b6001600160401b038111156111fa576111fa6126a4565b604051908082528060200260200182016040528015611223578160200160208202803683370190505b5093508790505b86811015611286578281815181106112445761124461268e565b602002602001015184898361125991906125cb565b815181106112695761126961268e565b60209081029190910101528061127e81612647565b91505061122a565b505050949350505050565b6003546060906000906001600160401b038111156112b1576112b16126a4565b6040519080825280602002602001820160405280156112da578160200160208202803683370190505b5090506000805b6003548110156113b857600085815260016020526040812060038054919291849081106113105761131061268e565b60009182526020808320909101546001600160a01b0316835282019290925260400190205460ff16156113a657600381815481106113505761135061268e565b9060005260206000200160009054906101000a90046001600160a01b03168383815181106113805761138061268e565b6001600160a01b03909216602092830291909101909101526113a36001836125b3565b91505b806113b081612647565b9150506112e1565b816001600160401b038111156113d0576113d06126a4565b6040519080825280602002602001820160405280156113f9578160200160208202803683370190505b509350600090505b8181101561145f5782818151811061141b5761141b61268e565b60200260200101518482815181106114355761143561268e565b6001600160a01b03909216602092830291909101909101528061145781612647565b915050611401565b505050919050565b33301461147357600080fd5b60035481603282118015906114885750818111155b801561149357508015155b801561149e57508115155b6114a757600080fd5b60048390556040518381527fa3f1ee9126a074d9326c682f561767f710e927faa811f7a99829d49dc421797a9060200160405180910390a1505050565b3360008181526002602052604090205460ff1661150057600080fd5b60008281526020819052604090205482906001600160a01b031661152357600080fd5b60008381526001602090815260408083203380855292529091205484919060ff161561154e57600080fd5b6000858152600160208181526040808420338086529252808420805460ff1916909317909255905187927f4a504a94899432a9846e1aa406dceb1bcfd538bb839071d49d1e5e23f5be30ef91a36115a48561182b565b5050505050565b60006115b8848484611a94565b9050610f4e816114e4565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146116275760405162461bcd60e51b81526020600482015260096024820152681bdb9b1e481c1bdbdb60ba1b60448201526064016109a3565b6116318888611b87565b61163c858588611cbe565b600880546001600160a01b039485166001600160a01b03199182161790915560098054928516929091169190911790556007805491909216600160401b0268010000000000000000600160e01b03199091161790555050505050565b3330146116a457600080fd5b6001600160a01b038216600090815260026020526040902054829060ff166116cb57600080fd5b6001600160a01b038216600090815260026020526040902054829060ff16156116f357600080fd5b60005b60035481101561179157846001600160a01b03166003828154811061171d5761171d61268e565b6000918252602090912001546001600160a01b0316141561177f57836003828154811061174c5761174c61268e565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550611791565b8061178981612647565b9150506116f6565b506001600160a01b03808516600081815260026020526040808220805460ff1990811690915593871682528082208054909416600117909355915190917f8001553a916ef2f495d26a907cc54d96ed840d7bda71e73194bf5a9df7a76b9091a26040516001600160a01b038416907ff39e6e1eb0edcf53c221607b54b00cd28f3196fed0a24994dc308b8f611b682d90600090a250505050565b3360008181526002602052604090205460ff1661184757600080fd5b60008281526001602090815260408083203380855292529091205483919060ff1661187157600080fd5b600084815260208190526040902060030154849060ff161561189257600080fd5b61189b85610e2b565b156115a457600085815260208190526040902060038101805460ff19166001908117909155815490820154600283018054611979936001600160a01b03169291906118e590612612565b90508460020180546118f690612612565b80601f016020809104026020016040519081016040528092919081815260200182805461192290612612565b801561196f5780601f106119445761010080835404028352916020019161196f565b820191906000526020600020905b81548152906001019060200180831161195257829003601f168201915b5050505050611d77565b156119ae5760405186907f33e13ecb54c3076d8e8bb8c2881800a4d972b792045ffae98fdf46df365fed7590600090a26119e6565b60405186907f526441bb6c1aba3c9a4a6ca1d6545da9c2333c8c48343ef398eb858d72b7923690600090a260038101805460ff191690555b505050505050565b6000611a026007546001600160401b031690565b600654600160a01b90046001600160401b0316611a1f91906125b3565b826001600160401b031610611a355750816106d1565b5060006106d1565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611a8f908490611d9a565b505050565b6000836001600160a01b038116611aaa57600080fd5b600554604080516080810182526001600160a01b038881168252602080830189815283850189815260006060860181905287815280845295909520845181546001600160a01b03191694169390931783555160018301559251805194965091939092611b1d926002850192910190611fed565b50606091909101516003909101805460ff19169115159190911790556005805460019190600090611b4f9084906125b3565b909155505060405182907fc0ba8fe4b176c1714197d43b9cc6bcf797a4a7461c5fe8d0ef6e184ae7601e5190600090a2509392505050565b81518160328211158015611b9b5750818111155b8015611ba657508015155b8015611bb157508115155b611bba57600080fd5b60005b8451811015611ca15760026000868381518110611bdc57611bdc61268e565b6020908102919091018101516001600160a01b031682528101919091526040016000205460ff16158015611c3c575060006001600160a01b0316858281518110611c2857611c2861268e565b60200260200101516001600160a01b031614155b611c4557600080fd5b600160026000878481518110611c5d57611c5d61268e565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580611c9981612647565b915050611bbd565b508351611cb5906003906020870190612071565b50505060045550565b6001600160a01b038316611d275760405162461bcd60e51b815260206004820152602a60248201527f56657374696e6757616c6c65743a2062656e6566696369617279206973207a65604482015269726f206164647265737360b01b60648201526084016109a3565b600680546001600160a01b03949094166001600160e01b031990941693909317600160a01b6001600160401b0393841602179092556007805467ffffffffffffffff191692909116919091179055565b6000806040516020840160008287838a8c6187965a03f198975050505050505050565b6000611def826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611e6c9092919063ffffffff16565b805190915015611a8f5780806020019051810190611e0d9190612359565b611a8f5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016109a3565b6060611e7b8484600085611e83565b949350505050565b606082471015611ee45760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109a3565b6001600160a01b0385163b611f3b5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109a3565b600080866001600160a01b03168587604051611f579190612495565b60006040518083038185875af1925050503d8060008114611f94576040519150601f19603f3d011682016040523d82523d6000602084013e611f99565b606091505b5091509150611fa9828286611fb4565b979650505050505050565b60608315611fc3575081610f4e565b825115611fd35782518084602001fd5b8160405162461bcd60e51b81526004016109a39190612570565b828054611ff990612612565b90600052602060002090601f01602090048101928261201b5760008555612061565b82601f1061203457805160ff1916838001178555612061565b82800160010185558215612061579182015b82811115612061578251825591602001919060010190612046565b5061206d9291506120c6565b5090565b828054828255906000526020600020908101928215612061579160200282015b8281111561206157825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190612091565b5b8082111561206d57600081556001016120c7565b80356001600160a01b03811681146120f257600080fd5b919050565b80356001600160401b03811681146120f257600080fd5b60006020828403121561212057600080fd5b610f4e826120db565b6000806040838503121561213c57600080fd5b612145836120db565b9150612153602084016120db565b90509250929050565b60008060006060848603121561217157600080fd5b61217a846120db565b9250602080850135925060408501356001600160401b038082111561219e57600080fd5b818701915087601f8301126121b257600080fd5b8135818111156121c4576121c46126a4565b6121d6601f8201601f19168501612583565b915080825288848285010111156121ec57600080fd5b80848401858401376000848284010152508093505050509250925092565b6000806040838503121561221d57600080fd5b612226836120db565b9150612153602084016120f7565b600080600080600080600080610100898b03121561225157600080fd5b6001600160401b03808a35111561226757600080fd5b89358a018b601f82011261227a57600080fd5b80358281111561228c5761228c6126a4565b8060051b925061229e60208401612583565b80828252602082019150602084018f60208787010111156122be57600080fd5b600095505b838610156122e9576122d4816120db565b835260019590950194602092830192016122c3565b509b5050505060208a01359750612304905060408a016120f7565b955061231260608a016120db565b945061232060808a016120f7565b935061232e60a08a016120db565b925061233c60c08a016120db565b915061234a60e08a016120db565b90509295985092959890939650565b60006020828403121561236b57600080fd5b8151610f4e816126ba565b6000806040838503121561238957600080fd5b8235612394816126ba565b915060208301356123a4816126ba565b809150509250929050565b6000602082840312156123c157600080fd5b5035919050565b6000602082840312156123da57600080fd5b5051919050565b600080604083850312156123f457600080fd5b82359150612153602084016120db565b6000806000806080858703121561241a57600080fd5b84359350602085013592506040850135612433816126ba565b91506060850135612443816126ba565b939692955090935050565b60006020828403121561246057600080fd5b610f4e826120f7565b600081518084526124818160208601602086016125e2565b601f01601f19169290920160200192915050565b600082516124a78184602087016125e2565b9190910192915050565b60018060a01b03851681528360208201526080604082015260006124d86080830185612469565b9050821515606083015295945050505050565b6020808252825182820181905260009190848201906040850190845b8181101561252c5783516001600160a01b031683529284019291840191600101612507565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561252c57835183529284019291840191600101612554565b602081526000610f4e6020830184612469565b604051601f8201601f191681016001600160401b03811182821017156125ab576125ab6126a4565b604052919050565b600082198211156125c6576125c6612662565b500190565b6000828210156125dd576125dd612662565b500390565b60005b838110156125fd5781810151838201526020016125e5565b8381111561260c576000848401525b50505050565b600181811c9082168061262657607f821691505b60208210811415610fd557634e487b7160e01b600052602260045260246000fd5b600060001982141561265b5761265b612662565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b8015158114610c9257600080fdfea2646970667358221220ad5f1b47d2adf92bad4533ffe2cbf7d6d45660df712721af9b5b08a8d8a1354664736f6c63430008070033

Deployed ByteCode

0x6080604052600436106101dc5760003560e01c80639ace38c211610102578063c642747411610095578063dc8452cd11610064578063dc8452cd14610625578063e20056e61461063b578063ecd0c0c31461065b578063ee22610b1461067b57610220565b8063c6427474146105a9578063cf5bf23f146105c9578063d6c3179d146105e9578063d74f8edd1461061057610220565b8063b77bf600116100d1578063b77bf6001461052e578063ba51a6df14610544578063be9a655514610564578063c01a8c841461058957610220565b80639ace38c21461048f578063a0e67e2b146104bf578063a8abe69a146104e1578063b5dc40c31461050e57610220565b806337bdc99b1161017a5780637065cb48116101495780637065cb481461040f578063784547a71461042f578063810ec23b1461044f5780638b51d13f1461046f57610220565b806337bdc99b1461039c57806338af3eed146103bc57806343ad92d5146103da57806354741525146103ef57610220565b8063173825d9116101b6578063173825d9146102e157806320ea8d86146103015780632f54bf6e146103215780633411c81c1461036157610220565b8063025e7c27146102585780630a17b06b146102955780630fb5a6b4146102c357610220565b3661022057341561021e5760405134815233907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c906020015b60405180910390a25b005b341561021e5760405134815233907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c90602001610215565b34801561026457600080fd5b506102786102733660046123af565b61069b565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156102a157600080fd5b506102b56102b036600461244e565b6106c5565b60405190815260200161028c565b3480156102cf57600080fd5b506007546001600160401b03166102b5565b3480156102ed57600080fd5b5061021e6102fc36600461210e565b6106d7565b34801561030d57600080fd5b5061021e61031c3660046123af565b61088e565b34801561032d57600080fd5b5061035161033c36600461210e565b60026020526000908152604090205460ff1681565b604051901515815260200161028c565b34801561036d57600080fd5b5061035161037c3660046123e1565b600160209081526000928352604080842090915290825290205460ff1681565b3480156103a857600080fd5b5061021e6103b73660046123af565b610944565b3480156103c857600080fd5b506006546001600160a01b0316610278565b3480156103e657600080fd5b5061021e610bec565b3480156103fb57600080fd5b506102b561040a366004612376565b610c95565b34801561041b57600080fd5b5061021e61042a36600461210e565b610d12565b34801561043b57600080fd5b5061035161044a3660046123af565b610e2b565b34801561045b57600080fd5b506102b561046a36600461220a565b610eca565b34801561047b57600080fd5b506102b561048a3660046123af565b610f55565b34801561049b57600080fd5b506104af6104aa3660046123af565b610fdb565b60405161028c94939291906124b1565b3480156104cb57600080fd5b506104d4611099565b60405161028c91906124eb565b3480156104ed57600080fd5b506105016104fc366004612404565b6110fb565b60405161028c9190612538565b34801561051a57600080fd5b506104d46105293660046123af565b611291565b34801561053a57600080fd5b506102b560055481565b34801561055057600080fd5b5061021e61055f3660046123af565b611467565b34801561057057600080fd5b50600654600160a01b90046001600160401b03166102b5565b34801561059557600080fd5b5061021e6105a43660046123af565b6114e4565b3480156105b557600080fd5b506102b56105c436600461215c565b6115ab565b3480156105d557600080fd5b5061021e6105e4366004612234565b6115c3565b3480156105f557600080fd5b5060075461027890600160401b90046001600160a01b031681565b34801561061c57600080fd5b506102b5603281565b34801561063157600080fd5b506102b560045481565b34801561064757600080fd5b5061021e610656366004612129565b611698565b34801561066757600080fd5b50600854610278906001600160a01b031681565b34801561068757600080fd5b5061021e6106963660046123af565b61182b565b600381815481106106ab57600080fd5b6000918252602090912001546001600160a01b0316905081565b60006106d147836119ee565b92915050565b3330146106e357600080fd5b6001600160a01b038116600090815260026020526040902054819060ff1661070a57600080fd5b6001600160a01b0382166000908152600260205260408120805460ff191690555b60035461073a906001906125cb565b81101561080a57826001600160a01b03166003828154811061075e5761075e61268e565b6000918252602090912001546001600160a01b031614156107f85760038054610789906001906125cb565b815481106107995761079961268e565b600091825260209091200154600380546001600160a01b0390921691839081106107c5576107c561268e565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555061080a565b8061080281612647565b91505061072b565b50600380548061081c5761081c612678565b600082815260209020810160001990810180546001600160a01b031916905501905560035460045411156108565760035461085690611467565b6040516001600160a01b038316907f8001553a916ef2f495d26a907cc54d96ed840d7bda71e73194bf5a9df7a76b9090600090a25050565b3360008181526002602052604090205460ff166108aa57600080fd5b60008281526001602090815260408083203380855292529091205483919060ff166108d457600080fd5b600084815260208190526040902060030154849060ff16156108f557600080fd5b6000858152600160209081526040808320338085529252808320805460ff191690555187927ff6a317157440607f36269043eb55f1287a5a19ba2216afeab88cd46cbcfb88e991a35050505050565b33301461095057600080fd5b60004261096d6006546001600160401b03600160a01b9091041690565b106109ac5760405162461bcd60e51b81526004016109a390602080825260049082015263656e642160e01b604082015260600190565b60405180910390fd5b6009546008546001600160a01b0390811691161415610a4d57504780821115610a0d5760405162461bcd60e51b815260206004820152601360248201527230b6b7bab73a10363a103130b630b731b2a7b360691b60448201526064016109a3565b6006546040516001600160a01b039091169083156108fc029084906000818181858888f19350505050158015610a47573d6000803e3d6000fd5b50610bb5565b6008546040516370a0823160e01b81523060048201526001600160a01b03909116906370a082319060240160206040518083038186803b158015610a9057600080fd5b505afa158015610aa4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ac891906123c8565b905080821115610b105760405162461bcd60e51b815260206004820152601360248201527230b6b7bab73a10363a103130b630b731b2a7b360691b60448201526064016109a3565b6008546001600160a01b031663a9059cbb610b336006546001600160a01b031690565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101859052604401602060405180830381600087803b158015610b7b57600080fd5b505af1158015610b8f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bb39190612359565b505b6040518281527fda9d4e5f101b8b9b1c5b76d0c5a9f7923571acfc02376aa076b75a8c080c956b9060200160405180910390a15050565b333014610bf857600080fd5b600754600090610c1890600160401b90046001600160a01b031642610eca565b600754604051828152919250600160401b90046001600160a01b0316907fc0e523490dd523c33b1878c9eb14ff46991e3f5b2cd33710918618f2a39cba1b9060200160405180910390a2600754610c92906001600160a01b03600160401b90910416610c8c6006546001600160a01b031690565b83611a3d565b50565b6000805b600554811015610d0b57838015610cc2575060008181526020819052604090206003015460ff16155b80610ce65750828015610ce6575060008181526020819052604090206003015460ff165b15610cf957610cf66001836125b3565b91505b80610d0381612647565b915050610c99565b5092915050565b333014610d1e57600080fd5b6001600160a01b038116600090815260026020526040902054819060ff1615610d4657600080fd5b816001600160a01b038116610d5a57600080fd5b600354610d689060016125b3565b60045460328211158015610d7c5750818111155b8015610d8757508015155b8015610d9257508115155b610d9b57600080fd5b6001600160a01b038516600081815260026020526040808220805460ff1916600190811790915560038054918201815583527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b0180546001600160a01b03191684179055517ff39e6e1eb0edcf53c221607b54b00cd28f3196fed0a24994dc308b8f611b682d9190a25050505050565b600080805b600354811015610ec05760008481526001602052604081206003805491929184908110610e5f57610e5f61268e565b60009182526020808320909101546001600160a01b0316835282019290925260400190205460ff1615610e9a57610e976001836125b3565b91505b600454821415610eae575060019392505050565b80610eb881612647565b915050610e30565b5060009392505050565b6040516370a0823160e01b8152306004820152600090610f4e906001600160a01b038516906370a082319060240160206040518083038186803b158015610f1057600080fd5b505afa158015610f24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4891906123c8565b836119ee565b9392505050565b6000805b600354811015610fd55760008381526001602052604081206003805491929184908110610f8857610f8861268e565b60009182526020808320909101546001600160a01b0316835282019290925260400190205460ff1615610fc357610fc06001836125b3565b91505b80610fcd81612647565b915050610f59565b50919050565b6000602081905290815260409020805460018201546002830180546001600160a01b0390931693919261100d90612612565b80601f016020809104026020016040519081016040528092919081815260200182805461103990612612565b80156110865780601f1061105b57610100808354040283529160200191611086565b820191906000526020600020905b81548152906001019060200180831161106957829003601f168201915b5050506003909301549192505060ff1684565b606060038054806020026020016040519081016040528092919081815260200182805480156110f157602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116110d3575b5050505050905090565b606060006005546001600160401b03811115611119576111196126a4565b604051908082528060200260200182016040528015611142578160200160208202803683370190505b5090506000805b6005548110156111d957858015611172575060008181526020819052604090206003015460ff16155b806111965750848015611196575060008181526020819052604090206003015460ff165b156111c757808383815181106111ae576111ae61268e565b60209081029190910101526111c46001836125b3565b91505b806111d181612647565b915050611149565b6111e388886125cb565b6001600160401b038111156111fa576111fa6126a4565b604051908082528060200260200182016040528015611223578160200160208202803683370190505b5093508790505b86811015611286578281815181106112445761124461268e565b602002602001015184898361125991906125cb565b815181106112695761126961268e565b60209081029190910101528061127e81612647565b91505061122a565b505050949350505050565b6003546060906000906001600160401b038111156112b1576112b16126a4565b6040519080825280602002602001820160405280156112da578160200160208202803683370190505b5090506000805b6003548110156113b857600085815260016020526040812060038054919291849081106113105761131061268e565b60009182526020808320909101546001600160a01b0316835282019290925260400190205460ff16156113a657600381815481106113505761135061268e565b9060005260206000200160009054906101000a90046001600160a01b03168383815181106113805761138061268e565b6001600160a01b03909216602092830291909101909101526113a36001836125b3565b91505b806113b081612647565b9150506112e1565b816001600160401b038111156113d0576113d06126a4565b6040519080825280602002602001820160405280156113f9578160200160208202803683370190505b509350600090505b8181101561145f5782818151811061141b5761141b61268e565b60200260200101518482815181106114355761143561268e565b6001600160a01b03909216602092830291909101909101528061145781612647565b915050611401565b505050919050565b33301461147357600080fd5b60035481603282118015906114885750818111155b801561149357508015155b801561149e57508115155b6114a757600080fd5b60048390556040518381527fa3f1ee9126a074d9326c682f561767f710e927faa811f7a99829d49dc421797a9060200160405180910390a1505050565b3360008181526002602052604090205460ff1661150057600080fd5b60008281526020819052604090205482906001600160a01b031661152357600080fd5b60008381526001602090815260408083203380855292529091205484919060ff161561154e57600080fd5b6000858152600160208181526040808420338086529252808420805460ff1916909317909255905187927f4a504a94899432a9846e1aa406dceb1bcfd538bb839071d49d1e5e23f5be30ef91a36115a48561182b565b5050505050565b60006115b8848484611a94565b9050610f4e816114e4565b336001600160a01b037f00000000000000000000000090c9ea90db9e924b5e4f705b5edd04d0ad1d787d16146116275760405162461bcd60e51b81526020600482015260096024820152681bdb9b1e481c1bdbdb60ba1b60448201526064016109a3565b6116318888611b87565b61163c858588611cbe565b600880546001600160a01b039485166001600160a01b03199182161790915560098054928516929091169190911790556007805491909216600160401b0268010000000000000000600160e01b03199091161790555050505050565b3330146116a457600080fd5b6001600160a01b038216600090815260026020526040902054829060ff166116cb57600080fd5b6001600160a01b038216600090815260026020526040902054829060ff16156116f357600080fd5b60005b60035481101561179157846001600160a01b03166003828154811061171d5761171d61268e565b6000918252602090912001546001600160a01b0316141561177f57836003828154811061174c5761174c61268e565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550611791565b8061178981612647565b9150506116f6565b506001600160a01b03808516600081815260026020526040808220805460ff1990811690915593871682528082208054909416600117909355915190917f8001553a916ef2f495d26a907cc54d96ed840d7bda71e73194bf5a9df7a76b9091a26040516001600160a01b038416907ff39e6e1eb0edcf53c221607b54b00cd28f3196fed0a24994dc308b8f611b682d90600090a250505050565b3360008181526002602052604090205460ff1661184757600080fd5b60008281526001602090815260408083203380855292529091205483919060ff1661187157600080fd5b600084815260208190526040902060030154849060ff161561189257600080fd5b61189b85610e2b565b156115a457600085815260208190526040902060038101805460ff19166001908117909155815490820154600283018054611979936001600160a01b03169291906118e590612612565b90508460020180546118f690612612565b80601f016020809104026020016040519081016040528092919081815260200182805461192290612612565b801561196f5780601f106119445761010080835404028352916020019161196f565b820191906000526020600020905b81548152906001019060200180831161195257829003601f168201915b5050505050611d77565b156119ae5760405186907f33e13ecb54c3076d8e8bb8c2881800a4d972b792045ffae98fdf46df365fed7590600090a26119e6565b60405186907f526441bb6c1aba3c9a4a6ca1d6545da9c2333c8c48343ef398eb858d72b7923690600090a260038101805460ff191690555b505050505050565b6000611a026007546001600160401b031690565b600654600160a01b90046001600160401b0316611a1f91906125b3565b826001600160401b031610611a355750816106d1565b5060006106d1565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611a8f908490611d9a565b505050565b6000836001600160a01b038116611aaa57600080fd5b600554604080516080810182526001600160a01b038881168252602080830189815283850189815260006060860181905287815280845295909520845181546001600160a01b03191694169390931783555160018301559251805194965091939092611b1d926002850192910190611fed565b50606091909101516003909101805460ff19169115159190911790556005805460019190600090611b4f9084906125b3565b909155505060405182907fc0ba8fe4b176c1714197d43b9cc6bcf797a4a7461c5fe8d0ef6e184ae7601e5190600090a2509392505050565b81518160328211158015611b9b5750818111155b8015611ba657508015155b8015611bb157508115155b611bba57600080fd5b60005b8451811015611ca15760026000868381518110611bdc57611bdc61268e565b6020908102919091018101516001600160a01b031682528101919091526040016000205460ff16158015611c3c575060006001600160a01b0316858281518110611c2857611c2861268e565b60200260200101516001600160a01b031614155b611c4557600080fd5b600160026000878481518110611c5d57611c5d61268e565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580611c9981612647565b915050611bbd565b508351611cb5906003906020870190612071565b50505060045550565b6001600160a01b038316611d275760405162461bcd60e51b815260206004820152602a60248201527f56657374696e6757616c6c65743a2062656e6566696369617279206973207a65604482015269726f206164647265737360b01b60648201526084016109a3565b600680546001600160a01b03949094166001600160e01b031990941693909317600160a01b6001600160401b0393841602179092556007805467ffffffffffffffff191692909116919091179055565b6000806040516020840160008287838a8c6187965a03f198975050505050505050565b6000611def826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611e6c9092919063ffffffff16565b805190915015611a8f5780806020019051810190611e0d9190612359565b611a8f5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016109a3565b6060611e7b8484600085611e83565b949350505050565b606082471015611ee45760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109a3565b6001600160a01b0385163b611f3b5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109a3565b600080866001600160a01b03168587604051611f579190612495565b60006040518083038185875af1925050503d8060008114611f94576040519150601f19603f3d011682016040523d82523d6000602084013e611f99565b606091505b5091509150611fa9828286611fb4565b979650505050505050565b60608315611fc3575081610f4e565b825115611fd35782518084602001fd5b8160405162461bcd60e51b81526004016109a39190612570565b828054611ff990612612565b90600052602060002090601f01602090048101928261201b5760008555612061565b82601f1061203457805160ff1916838001178555612061565b82800160010185558215612061579182015b82811115612061578251825591602001919060010190612046565b5061206d9291506120c6565b5090565b828054828255906000526020600020908101928215612061579160200282015b8281111561206157825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190612091565b5b8082111561206d57600081556001016120c7565b80356001600160a01b03811681146120f257600080fd5b919050565b80356001600160401b03811681146120f257600080fd5b60006020828403121561212057600080fd5b610f4e826120db565b6000806040838503121561213c57600080fd5b612145836120db565b9150612153602084016120db565b90509250929050565b60008060006060848603121561217157600080fd5b61217a846120db565b9250602080850135925060408501356001600160401b038082111561219e57600080fd5b818701915087601f8301126121b257600080fd5b8135818111156121c4576121c46126a4565b6121d6601f8201601f19168501612583565b915080825288848285010111156121ec57600080fd5b80848401858401376000848284010152508093505050509250925092565b6000806040838503121561221d57600080fd5b612226836120db565b9150612153602084016120f7565b600080600080600080600080610100898b03121561225157600080fd5b6001600160401b03808a35111561226757600080fd5b89358a018b601f82011261227a57600080fd5b80358281111561228c5761228c6126a4565b8060051b925061229e60208401612583565b80828252602082019150602084018f60208787010111156122be57600080fd5b600095505b838610156122e9576122d4816120db565b835260019590950194602092830192016122c3565b509b5050505060208a01359750612304905060408a016120f7565b955061231260608a016120db565b945061232060808a016120f7565b935061232e60a08a016120db565b925061233c60c08a016120db565b915061234a60e08a016120db565b90509295985092959890939650565b60006020828403121561236b57600080fd5b8151610f4e816126ba565b6000806040838503121561238957600080fd5b8235612394816126ba565b915060208301356123a4816126ba565b809150509250929050565b6000602082840312156123c157600080fd5b5035919050565b6000602082840312156123da57600080fd5b5051919050565b600080604083850312156123f457600080fd5b82359150612153602084016120db565b6000806000806080858703121561241a57600080fd5b84359350602085013592506040850135612433816126ba565b91506060850135612443816126ba565b939692955090935050565b60006020828403121561246057600080fd5b610f4e826120f7565b600081518084526124818160208601602086016125e2565b601f01601f19169290920160200192915050565b600082516124a78184602087016125e2565b9190910192915050565b60018060a01b03851681528360208201526080604082015260006124d86080830185612469565b9050821515606083015295945050505050565b6020808252825182820181905260009190848201906040850190845b8181101561252c5783516001600160a01b031683529284019291840191600101612507565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561252c57835183529284019291840191600101612554565b602081526000610f4e6020830184612469565b604051601f8201601f191681016001600160401b03811182821017156125ab576125ab6126a4565b604052919050565b600082198211156125c6576125c6612662565b500190565b6000828210156125dd576125dd612662565b500390565b60005b838110156125fd5781810151838201526020016125e5565b8381111561260c576000848401525b50505050565b600181811c9082168061262657607f821691505b60208210811415610fd557634e487b7160e01b600052602260045260246000fd5b600060001982141561265b5761265b612662565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b8015158114610c9257600080fdfea2646970667358221220ad5f1b47d2adf92bad4533ffe2cbf7d6d45660df712721af9b5b08a8d8a1354664736f6c63430008070033