Address Details
contract

0xBa6525D55084A1563D14F6Ac0216D1A588484fB7

Contract Name
GoodGhosting
Creator
0xdbb021–173662 at 0x77f511–2cbba9
Balance
0 CELO ( )
Locked CELO Balance
0.00 CELO
Voting CELO Balance
0.00 CELO
Pending Unlocked Gold
0.00 CELO
Tokens
Fetching tokens...
Transactions
6 Transactions
Transfers
16 Transfers
Gas Used
1,656,270
Last Balance Update
10286971
This contract has been verified via Sourcify. View contract in Sourcify repository
Contract name:
GoodGhosting




Optimization enabled
false
Compiler version
v0.6.11+commit.5ef660b1




EVM Version
istanbul




Verified at
2022-08-21T09:36:30.870452Z

project:/contracts/GoodGhosting.sol

// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.6.11;

import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Pausable.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./aave/ILendingPoolAddressesProvider.sol";
import "./aave/ILendingPool.sol";
import "./aave/AToken.sol";

/// @title GoodGhosting Game Contract
/// @notice Used for games deployed on Ethereum Mainnet using Aave (v2) as the underlying pool, or for games deployed on Celo using Moola (v2) as the underlying pool
/// @author Francis Odisi & Viraz Malhotra
contract GoodGhosting is Ownable, Pausable {
    using SafeMath for uint256;

    /// @notice Ownership Control flag
    bool public allowRenouncingOwnership = false;
    /// @notice Controls if tokens were redeemed or not from the pool
    bool public redeemed;
    /// @notice controls if admin withdrew or not the performance fee.
    bool public adminWithdraw;
    /// @notice Address of the token used for depositing into the game by players (DAI)
    IERC20 public immutable daiToken;
    /// @notice Address of the interest bearing token received when funds are transferred to the external pool
    AToken public immutable adaiToken;
    /// @notice Which Aave instance we use to swap DAI to interest bearing aDAI
    ILendingPoolAddressesProvider public immutable lendingPoolAddressProvider;
    /// @notice Lending pool address
    ILendingPool public lendingPool;
    /// @notice Defines an optional token address used to provide additional incentives to users. Accepts "0x0" adresses when no incentive token exists.
    IERC20 public immutable incentiveToken;

    /// @notice total amount of incentive tokens to be distributed among winners
    uint256 public totalIncentiveAmount = 0;
    /// @notice Controls the amount of active players in the game (ignores players that early withdraw)
    uint256 public activePlayersCount = 0;
    /// @notice Stores the total amount of net interest received in the game.
    uint256 public totalGameInterest;
    /// @notice total principal amount
    uint256 public totalGamePrincipal;
    /// @notice performance fee amount allocated to the admin
    uint256 public adminFeeAmount;
    /// @notice The amount to be paid on each segment
    uint256 public immutable segmentPayment;
    /// @notice The number of segments in the game (segment count)
    uint256 public immutable lastSegment;
    /// @notice When the game started (deployed timestamp)
    uint256 public immutable firstSegmentStart;
    /// @notice The time duration (in seconds) of each segment
    uint256 public immutable segmentLength;
    /// @notice Defines the max quantity of players allowed in the game
    uint256 public immutable maxPlayersCount;
    /// @notice winner counter to track no of winners
    uint256 public winnerCount = 0;
    /// @notice The early withdrawal fee (percentage)
    uint8 public immutable earlyWithdrawalFee;
    /// @notice The performance admin fee (percentage)
    uint8 public immutable customFee;

    struct Player {
        bool withdrawn;
        bool canRejoin;
        bool isWinner;
        address addr;
        uint256 mostRecentSegmentPaid;
        uint256 amountPaid;
        uint256 winnerIndex;
    }

    /// @notice Stores info about the players in the game
    mapping(address => Player) public players;
    /// @notice controls the amount deposited in each segment that was not yet transferred to the external underlying pool
    /// @notice list of players
    address[] public iterablePlayers;
    /// @notice list of winners
    address[] public winners;

    event JoinedGame(address indexed player, uint256 amount);
    event Deposit(
        address indexed player,
        uint256 indexed segment,
        uint256 amount
    );
    event Withdrawal(
        address indexed player,
        uint256 amount,
        uint256 playerReward,
        uint256 playerIncentive
    );
    event FundsRedeemedFromExternalPool(
        uint256 totalAmount,
        uint256 totalGamePrincipal,
        uint256 totalGameInterest,
        uint256 rewards,
        uint256 totalIncentiveAmount
    );
    event WinnersAnnouncement(address[] winners);
    event EarlyWithdrawal(
        address indexed player,
        uint256 amount,
        uint256 totalGamePrincipal
    );
    event AdminWithdrawal(
        address indexed admin,
        uint256 totalGameInterest,
        uint256 adminFeeAmount,
        uint256 adminIncentiveAmount
    );

    modifier whenGameIsCompleted() {
        require(isGameCompleted(), "Game is not completed");
        _;
    }

    modifier whenGameIsNotCompleted() {
        require(!isGameCompleted(), "Game is already completed");
        _;
    }

    /**
        Creates a new instance of GoodGhosting game
        @param _inboundCurrency Smart contract address of inbound currency used for the game.
        @param _lendingPoolAddressProvider Smart contract address of the lending pool adddress provider.
        @param _segmentCount Number of segments in the game.
        @param _segmentLength Lenght of each segment, in seconds (i.e., 180 (sec) => 3 minutes).
        @param _segmentPayment Amount of tokens each player needs to contribute per segment (i.e. 10*10**18 equals to 10 DAI - note that DAI uses 18 decimal places).
        @param _earlyWithdrawalFee Fee paid by users on early withdrawals (before the game completes). Used as an integer percentage (i.e., 10 represents 10%).
        @param _customFee performance fee charged by admin. Used as an integer percentage (i.e., 10 represents 10%). Does not accept "decimal" fees like "0.5".
        @param _dataProvider id for getting the data provider contract address 0x1 to be passed.
        @param _maxPlayersCount max quantity of players allowed to join the game
        @param _incentiveToken optional token address used to provide additional incentives to users. Accepts "0x0" adresses when no incentive token exists.
     */
    constructor(
        IERC20 _inboundCurrency,
        ILendingPoolAddressesProvider _lendingPoolAddressProvider,
        uint256 _segmentCount,
        uint256 _segmentLength,
        uint256 _segmentPayment,
        uint8 _earlyWithdrawalFee,
        uint8 _customFee,
        address _dataProvider,
        uint256 _maxPlayersCount,
        IERC20 _incentiveToken
    ) public {
        require(_customFee <= 20, "_customFee must be less than or equal to 20%");
        require(_earlyWithdrawalFee <= 10, "_earlyWithdrawalFee must be less than or equal to 10%");
        require(_earlyWithdrawalFee > 0,  "_earlyWithdrawalFee must be greater than zero");
        require(_maxPlayersCount > 0, "_maxPlayersCount must be greater than zero");
        require(address(_inboundCurrency) != address(0), "invalid _inboundCurrency address");
        require(address(_lendingPoolAddressProvider) != address(0), "invalid _lendingPoolAddressProvider address");
        require(_segmentCount > 0, "_segmentCount must be greater than zero");
        require(_segmentLength > 0, "_segmentLength must be greater than zero");
        require(_segmentPayment > 0, "_segmentPayment must be greater than zero");
        require(_dataProvider != address(0), "invalid _dataProvider address");
        // Initializes default variables
        firstSegmentStart = block.timestamp; //gets current time
        lastSegment = _segmentCount;
        segmentLength = _segmentLength;
        segmentPayment = _segmentPayment;
        earlyWithdrawalFee = _earlyWithdrawalFee;
        customFee = _customFee;
        daiToken = _inboundCurrency;
        lendingPoolAddressProvider = _lendingPoolAddressProvider;
        AaveProtocolDataProvider dataProvider =
            AaveProtocolDataProvider(_dataProvider);
        // lending pool needs to be approved in v2 since it is the core contract in v2 and not lending pool core
        lendingPool = ILendingPool(
            _lendingPoolAddressProvider.getLendingPool()
        );
        // atoken address in v2 is fetched from data provider contract
        (address adaiTokenAddress, , ) =
            dataProvider.getReserveTokensAddresses(address(_inboundCurrency));
        adaiToken = AToken(adaiTokenAddress);
        maxPlayersCount = _maxPlayersCount;
        incentiveToken = _incentiveToken;
    }

    /// @notice pauses the game. This function can be called only by the contract's admin.
    function pause() external onlyOwner whenNotPaused {
        _pause();
    }

    /// @notice unpauses the game. This function can be called only by the contract's admin.
    function unpause() external onlyOwner whenPaused {
        _unpause();
    }

    /// @notice Renounces Ownership.
    function renounceOwnership() public override onlyOwner {
        require(allowRenouncingOwnership, "Not allowed");
        super.renounceOwnership();
    }

    /// @notice Unlocks renounceOwnership.
    function unlockRenounceOwnership() external onlyOwner {
        allowRenouncingOwnership = true;
    }

    /// @notice Allows the admin to withdraw the performance fee, if applicable. This function can be called only by the contract's admin.
    /// @dev Cannot be called before the game ends.
    function adminFeeWithdraw() external virtual onlyOwner whenGameIsCompleted {
        require(redeemed, "Funds not redeemed from external pool");
        require(!adminWithdraw, "Admin has already withdrawn");
        adminWithdraw = true;

        // when there are no winners, admin will be able to withdraw the
        // additional incentives sent to the pool, avoiding locking the funds.
        uint256 adminIncentiveAmount = 0;
        if (winnerCount == 0 && totalIncentiveAmount > 0) {
            adminIncentiveAmount = totalIncentiveAmount;
        }

        emit AdminWithdrawal(owner(), totalGameInterest, adminFeeAmount, adminIncentiveAmount);

        if (adminFeeAmount > 0) {
            require(
                IERC20(daiToken).transfer(owner(), adminFeeAmount),
                "Fail to transfer ER20 tokens to admin"
            );
        }

        if (adminIncentiveAmount > 0) {
            require(
                IERC20(incentiveToken).transfer(owner(), adminIncentiveAmount),
                "Fail to transfer ER20 incentive tokens to admin"
            );
        }
    }

    /// @notice Allows a player to join the game
    function joinGame()
        external
        virtual
        whenNotPaused
    {
        _joinGame();
    }

    /// @notice Allows a player to withdraw funds before the game ends. An early withdrawal fee is charged.
    /// @dev Cannot be called after the game is completed.
    function earlyWithdraw() external whenNotPaused whenGameIsNotCompleted {
        Player storage player = players[msg.sender];
        require(player.amountPaid > 0, "Player does not exist");
        require(!player.withdrawn, "Player has already withdrawn");
        player.withdrawn = true;
        activePlayersCount = activePlayersCount.sub(1);
        if (winnerCount > 0 && player.isWinner) {
            winnerCount = winnerCount.sub(uint(1));
            player.isWinner = false;
            winners[player.winnerIndex] = address(0);
        }

        // In an early withdraw, users get their principal minus the earlyWithdrawalFee % defined in the constructor.
        uint256 withdrawAmount =
            player.amountPaid.sub(
                player.amountPaid.mul(earlyWithdrawalFee).div(100)
            );
        // Decreases the totalGamePrincipal on earlyWithdraw
        totalGamePrincipal = totalGamePrincipal.sub(player.amountPaid);
        uint256 currentSegment = getCurrentSegment();

        // Users that early withdraw during the first segment, are allowed to rejoin.
        if (currentSegment == 0) {
            player.canRejoin = true;
        }

        emit EarlyWithdrawal(msg.sender, withdrawAmount, totalGamePrincipal);

        lendingPool.withdraw(address(daiToken), withdrawAmount, address(this));
        require(
            IERC20(daiToken).transfer(msg.sender, withdrawAmount),
            "Fail to transfer ERC20 tokens on early withdraw"
        );
    }

    /// @notice Allows player to withdraw their funds after the game ends with no loss (fee). Winners get a share of the interest earned.
    function withdraw() external virtual {
        Player storage player = players[msg.sender];
        require(player.amountPaid > 0, "Player does not exist");
        require(!player.withdrawn, "Player has already withdrawn");
        player.withdrawn = true;

        // First player to withdraw redeems everyone's funds
        if (!redeemed) {
            redeemFromExternalPool();
        }

        uint256 payout = player.amountPaid;
        uint256 playerIncentive = 0;
        if (player.mostRecentSegmentPaid == lastSegment.sub(1)) {
            // Player is a winner and gets a bonus!
            payout = payout.add(totalGameInterest.div(winnerCount));
            // If there's additional incentives, distributes them to winners
            if (totalIncentiveAmount > 0) {
                playerIncentive = totalIncentiveAmount.div(winnerCount);
            }
        }
        emit Withdrawal(msg.sender, payout, 0, playerIncentive);

        require(
            IERC20(daiToken).transfer(msg.sender, payout),
            "Fail to transfer ERC20 tokens on withdraw"
        );

        if (playerIncentive > 0) {
            require(
                IERC20(incentiveToken).transfer(msg.sender, playerIncentive),
                "Fail to transfer ERC20 incentive tokens on withdraw"
            );
        }
    }

    /// @notice Allows players to make deposits for the game segments, after joining the game.
    function makeDeposit() external whenNotPaused {
        Player storage player = players[msg.sender];
        require(
            !player.withdrawn,
            "Player already withdraw from game"
        );
        // only registered players can deposit
        require(
            player.addr == msg.sender,
            "Sender is not a player"
        );

        uint256 currentSegment = getCurrentSegment();
        // User can only deposit between segment 1 and segment n-1 (where n is the number of segments for the game).
        // Details:
        // Segment 0 is paid when user joins the game (the first deposit window).
        // Last segment doesn't accept payments, because the payment window for the last
        // segment happens on segment n-1 (penultimate segment).
        // Any segment greater than the last segment means the game is completed, and cannot
        // receive payments
        require(
            currentSegment > 0 && currentSegment < lastSegment,
            "Deposit available only between segment 1 and segment n-1 (penultimate)"
        );

        //check if current segment is currently unpaid
        require(
            player.mostRecentSegmentPaid != currentSegment,
            "Player already paid current segment"
        );

        // check if player has made payments up to the previous segment
        require(
            player.mostRecentSegmentPaid == currentSegment.sub(1),
            "Player didn't pay the previous segment - game over!"
        );
 
        emit Deposit(msg.sender, currentSegment, segmentPayment);
        _transferDaiToContract();
    }

    /// @notice gets the number of players in the game
    /// @return number of players
    function getNumberOfPlayers() external view returns (uint256) {
        return iterablePlayers.length;
    }

    /// @notice Redeems funds from the external pool and updates the internal accounting controls related to the game stats.
    /// @dev Can only be called after the game is completed.
    function redeemFromExternalPool() public virtual whenGameIsCompleted {
        require(!redeemed, "Redeem operation already happened for the game");
        redeemed = true;
        // Withdraws funds (principal + interest + rewards) from external pool
        if (adaiToken.balanceOf(address(this)) > 0) {
            lendingPool.withdraw(
                address(daiToken),
                type(uint256).max,
                address(this)
            );
        }
        uint256 totalBalance = IERC20(daiToken).balanceOf(address(this));
        // If there's an incentive token address defined, sets the total incentive amount to be distributed among winners.
        if (address(incentiveToken) != address(0)) {
            totalIncentiveAmount = IERC20(incentiveToken).balanceOf(address(this));
        }

        // calculates gross interest
        uint256 grossInterest = 0;

        // Sanity check to avoid reverting due to overflow in the "subtraction" below.
        // This could only happen in case Aave changes the 1:1 ratio between
        // aToken vs. Token in the future (i.e., 1 aDAI is worth less than 1 DAI)
        if (totalBalance > totalGamePrincipal) {
            grossInterest = totalBalance.sub(totalGamePrincipal);
        }
        // calculates the performance/admin fee (takes a cut - the admin percentage fee - from the pool's interest).
        // calculates the "gameInterest" (net interest) that will be split among winners in the game
        uint256 _adminFeeAmount;
        if (customFee > 0) {
            _adminFeeAmount = (grossInterest.mul(customFee)).div(100);
            totalGameInterest = grossInterest.sub(_adminFeeAmount);
        } else {
            _adminFeeAmount = 0;
            totalGameInterest = grossInterest;
        }

        // when there's no winners, admin takes all the interest + rewards
        if (winnerCount == 0) {
            adminFeeAmount = grossInterest;
        } else {
            adminFeeAmount = _adminFeeAmount;
        }

        emit FundsRedeemedFromExternalPool(
            totalBalance,
            totalGamePrincipal,
            totalGameInterest,
            0,
            totalIncentiveAmount
        );
        emit WinnersAnnouncement(winners);
    }

    /// @notice Calculates the current segment of the game.
    /// @return current game segment
    function getCurrentSegment() public view returns (uint256) {
        return block.timestamp.sub(firstSegmentStart).div(segmentLength);
    }

    /// @notice Checks if the game is completed or not.
    /// @return "true" if completeted; otherwise, "false".
    function isGameCompleted() public view returns (bool) {
        // Game is completed when the current segment is greater than "lastSegment" of the game.
        return getCurrentSegment() > lastSegment;
    }

    /**
        @dev Manages the transfer of funds from the player to the contract, recording
        the required accounting operations to control the user's position in the pool.
     */
    function _transferDaiToContract() internal {
        require(
            daiToken.allowance(msg.sender, address(this)) >= segmentPayment,
            "You need to have allowance to do transfer DAI on the smart contract"
        );

        uint256 currentSegment = getCurrentSegment();
        players[msg.sender].mostRecentSegmentPaid = currentSegment;
        players[msg.sender].amountPaid = players[msg.sender].amountPaid.add(
            segmentPayment
        );
        // check if this is deposit for the last segment. If yes, the player is a winner.
        // since both join game and deposit method call this method so having it here
        if (currentSegment == lastSegment.sub(1)) {
            winners.push(msg.sender);
            // array indexes start from 0
            players[msg.sender].winnerIndex = winners.length.sub(uint(1));
            winnerCount = winnerCount.add(uint(1));
            players[msg.sender].isWinner = true;
        }
        
        totalGamePrincipal = totalGamePrincipal.add(segmentPayment);
        require(
            daiToken.transferFrom(msg.sender, address(this), segmentPayment),
            "Transfer failed"
        );


        // Allows the lending pool to convert DAI deposited on this contract to aDAI on lending pool
        uint256 contractBalance = daiToken.balanceOf(address(this));
        require(
            daiToken.approve(address(lendingPool), contractBalance),
            "Fail to approve allowance to lending pool"
        );

        lendingPool.deposit(address(daiToken), contractBalance, address(this), 155);
    }

    /// @notice Allows a player to join the game and controls
    function _joinGame() internal {
        require(getCurrentSegment() == 0, "Game has already started");
        require(
            players[msg.sender].addr != msg.sender ||
                players[msg.sender].canRejoin,
            "Cannot join the game more than once"
        );

        activePlayersCount = activePlayersCount.add(1);
        require(activePlayersCount <= maxPlayersCount, "Reached max quantity of players allowed");

        bool canRejoin = players[msg.sender].canRejoin;
        Player memory newPlayer =
            Player({
                addr: msg.sender,
                mostRecentSegmentPaid: 0,
                amountPaid: 0,
                withdrawn: false,
                canRejoin: false,
                isWinner: false,
                winnerIndex: 0
            });
        players[msg.sender] = newPlayer;
        if (!canRejoin) {
            iterablePlayers.push(msg.sender);
        }
        emit JoinedGame(msg.sender, segmentPayment);
        _transferDaiToContract();
    }
}
        

/_openzeppelin/contracts/access/Ownable.sol

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "../utils/Context.sol";
/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor () internal {
        address msgSender = _msgSender();
        _owner = msgSender;
        emit OwnershipTransferred(address(0), msgSender);
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        emit OwnershipTransferred(_owner, address(0));
        _owner = address(0);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
    }
}
          

/_openzeppelin/contracts/math/SafeMath.sol

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        uint256 c = a + b;
        if (c < a) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the substraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b > a) return (false, 0);
        return (true, a - b);
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) return (true, 0);
        uint256 c = a * b;
        if (c / a != b) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b == 0) return (false, 0);
        return (true, a / b);
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b == 0) return (false, 0);
        return (true, a % b);
    }

    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");
        return c;
    }

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

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        if (a == 0) return 0;
        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");
        return c;
    }

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

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

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        return a - b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryDiv}.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        return a % b;
    }
}
          

/_openzeppelin/contracts/token/ERC20/IERC20.sol

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <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 `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, 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 `sender` to `recipient` 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 sender, address recipient, 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);
}
          

/_openzeppelin/contracts/utils/Context.sol

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/*
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with GSN meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address payable) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes memory) {
        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
        return msg.data;
    }
}
          

/_openzeppelin/contracts/utils/Pausable.sol

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "./Context.sol";

/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
abstract contract Pausable is Context {
    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by `account`.
     */
    event Unpaused(address account);

    bool private _paused;

    /**
     * @dev Initializes the contract in unpaused state.
     */
    constructor () internal {
        _paused = false;
    }

    /**
     * @dev Returns true if the contract is paused, and false otherwise.
     */
    function paused() public view virtual returns (bool) {
        return _paused;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    modifier whenNotPaused() {
        require(!paused(), "Pausable: paused");
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    modifier whenPaused() {
        require(paused(), "Pausable: not paused");
        _;
    }

    /**
     * @dev Triggers stopped state.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    function _pause() internal virtual whenNotPaused {
        _paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    function _unpause() internal virtual whenPaused {
        _paused = false;
        emit Unpaused(_msgSender());
    }
}
          

/project_/contracts/aave/AToken.sol

// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.6.11;

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

/project_/contracts/aave/ILendingPool.sol

// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.6.11;

interface ILendingPool {
    function deposit(address _reserve, uint256 _amount, address onBehalfOf, uint16 _referralCode) external;
    //see: https://github.com/aave/aave-protocol/blob/1ff8418eb5c73ce233ac44bfb7541d07828b273f/contracts/tokenization/AToken.sol#L218
    function withdraw(address asset, uint amount, address to) external;
}

interface AaveProtocolDataProvider {
    function getReserveTokensAddresses(address asset) external view returns(address, address, address);
}
          

/project_/contracts/aave/ILendingPoolAddressesProvider.sol

// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.6.11;

/**
@title ILendingPoolAddressesProvider interface
@notice provides the interface to fetch the LendingPoolCore address
 */

abstract contract ILendingPoolAddressesProvider {

    function getLendingPool() public virtual view returns (address);
    function setLendingPoolImpl(address _pool) public virtual;
    function getAddress(bytes32 id) public virtual view returns (address);

    function getLendingPoolCore() public virtual view returns (address payable);
    function setLendingPoolCoreImpl(address _lendingPoolCore) public virtual;

    function getLendingPoolConfigurator() public virtual view returns (address);
    function setLendingPoolConfiguratorImpl(address _configurator) public virtual;

    function getLendingPoolDataProvider() public virtual view returns (address);
    function setLendingPoolDataProviderImpl(address _provider) public virtual;

    function getLendingPoolParametersProvider() public virtual view returns (address);
    function setLendingPoolParametersProviderImpl(address _parametersProvider) public virtual;

    function getTokenDistributor() public virtual view returns (address);
    function setTokenDistributor(address _tokenDistributor) public virtual;


    function getFeeProvider() public virtual view returns (address);
    function setFeeProviderImpl(address _feeProvider) public virtual;

    function getLendingPoolLiquidationManager() public virtual view returns (address);
    function setLendingPoolLiquidationManager(address _manager) public virtual;

    function getLendingPoolManager() public virtual view returns (address);
    function setLendingPoolManager(address _lendingPoolManager) public virtual;

    function getPriceOracle() public virtual view returns (address);
    function setPriceOracle(address _priceOracle) public virtual;

    function getLendingRateOracle() public virtual view returns (address);
    function setLendingRateOracle(address _lendingRateOracle) public virtual;

}
          

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_inboundCurrency","internalType":"contract IERC20"},{"type":"address","name":"_lendingPoolAddressProvider","internalType":"contract ILendingPoolAddressesProvider"},{"type":"uint256","name":"_segmentCount","internalType":"uint256"},{"type":"uint256","name":"_segmentLength","internalType":"uint256"},{"type":"uint256","name":"_segmentPayment","internalType":"uint256"},{"type":"uint8","name":"_earlyWithdrawalFee","internalType":"uint8"},{"type":"uint8","name":"_customFee","internalType":"uint8"},{"type":"address","name":"_dataProvider","internalType":"address"},{"type":"uint256","name":"_maxPlayersCount","internalType":"uint256"},{"type":"address","name":"_incentiveToken","internalType":"contract IERC20"}]},{"type":"event","name":"AdminWithdrawal","inputs":[{"type":"address","name":"admin","internalType":"address","indexed":true},{"type":"uint256","name":"totalGameInterest","internalType":"uint256","indexed":false},{"type":"uint256","name":"adminFeeAmount","internalType":"uint256","indexed":false},{"type":"uint256","name":"adminIncentiveAmount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Deposit","inputs":[{"type":"address","name":"player","internalType":"address","indexed":true},{"type":"uint256","name":"segment","internalType":"uint256","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"EarlyWithdrawal","inputs":[{"type":"address","name":"player","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false},{"type":"uint256","name":"totalGamePrincipal","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"FundsRedeemedFromExternalPool","inputs":[{"type":"uint256","name":"totalAmount","internalType":"uint256","indexed":false},{"type":"uint256","name":"totalGamePrincipal","internalType":"uint256","indexed":false},{"type":"uint256","name":"totalGameInterest","internalType":"uint256","indexed":false},{"type":"uint256","name":"rewards","internalType":"uint256","indexed":false},{"type":"uint256","name":"totalIncentiveAmount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"JoinedGame","inputs":[{"type":"address","name":"player","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Paused","inputs":[{"type":"address","name":"account","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Unpaused","inputs":[{"type":"address","name":"account","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"WinnersAnnouncement","inputs":[{"type":"address[]","name":"winners","internalType":"address[]","indexed":false}],"anonymous":false},{"type":"event","name":"Withdrawal","inputs":[{"type":"address","name":"player","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false},{"type":"uint256","name":"playerReward","internalType":"uint256","indexed":false},{"type":"uint256","name":"playerIncentive","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"activePlayersCount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract AToken"}],"name":"adaiToken","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"adminFeeAmount","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"adminFeeWithdraw","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"adminWithdraw","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"allowRenouncingOwnership","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"customFee","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IERC20"}],"name":"daiToken","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"earlyWithdraw","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"earlyWithdrawalFee","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"firstSegmentStart","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getCurrentSegment","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getNumberOfPlayers","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IERC20"}],"name":"incentiveToken","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isGameCompleted","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"iterablePlayers","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"joinGame","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"lastSegment","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract ILendingPool"}],"name":"lendingPool","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract ILendingPoolAddressesProvider"}],"name":"lendingPoolAddressProvider","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"makeDeposit","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"maxPlayersCount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"pause","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"paused","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"withdrawn","internalType":"bool"},{"type":"bool","name":"canRejoin","internalType":"bool"},{"type":"bool","name":"isWinner","internalType":"bool"},{"type":"address","name":"addr","internalType":"address"},{"type":"uint256","name":"mostRecentSegmentPaid","internalType":"uint256"},{"type":"uint256","name":"amountPaid","internalType":"uint256"},{"type":"uint256","name":"winnerIndex","internalType":"uint256"}],"name":"players","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"redeemFromExternalPool","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"redeemed","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"segmentLength","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"segmentPayment","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalGameInterest","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalGamePrincipal","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalIncentiveAmount","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"unlockRenounceOwnership","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"unpause","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"winnerCount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"winners","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"withdraw","inputs":[]}]
              

Contract Creation Code

0x6101e060405260008060156101000a81548160ff0219169083151502179055506000600255600060035560006007553480156200003b57600080fd5b50604051620051e9380380620051e983398181016040526101408110156200006257600080fd5b81019080805190602001909291908051906020019092919080519060200190929190805190602001909291908051906020019092919080519060200190929190805190602001909291908051906020019092919080519060200190929190805190602001909291905050506000620000df620008cc60201b60201c565b9050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35060008060146101000a81548160ff02191690831515021790555060148460ff161115620001f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c8152602001806200508e602c913960400191505060405180910390fd5b600a8560ff16111562000255576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526035815260200180620051896035913960400191505060405180910390fd5b60008560ff1611620002b3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602d8152602001806200510c602d913960400191505060405180910390fd5b600082116200030e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180620050ba602a913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff161415620003b2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f696e76616c6964205f696e626f756e6443757272656e6379206164647265737381525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff1614156200043a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b815260200180620051be602b913960400191505060405180910390fd5b6000881162000495576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526027815260200180620051396027913960400191505060405180910390fd5b60008711620004f0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526028815260200180620050e46028913960400191505060405180910390fd5b600086116200054b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180620051606029913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415620005ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f696e76616c6964205f6461746150726f7669646572206164647265737300000081525060200191505060405180910390fd5b4261014081815250508761012081815250508661016081815250508561010081815250508460ff166101a08160ff1660f81b815250508360ff166101c08160ff1660f81b815250508973ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff1660601b815250508873ffffffffffffffffffffffffffffffffffffffff1660c08173ffffffffffffffffffffffffffffffffffffffff1660601b8152505060008390508973ffffffffffffffffffffffffffffffffffffffff16630261bf8b6040518163ffffffff1660e01b815260040160206040518083038186803b158015620006f157600080fd5b505afa15801562000706573d6000803e3d6000fd5b505050506040513d60208110156200071d57600080fd5b8101908080519060200190929190505050600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008173ffffffffffffffffffffffffffffffffffffffff1663d2493b6c8d6040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060606040518083038186803b158015620007ee57600080fd5b505afa15801562000803573d6000803e3d6000fd5b505050506040513d60608110156200081a57600080fd5b81019080805190602001909291908051906020019092919080519060200190929190505050505090508073ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff1660601b815250508361018081815250508273ffffffffffffffffffffffffffffffffffffffff1660e08173ffffffffffffffffffffffffffffffffffffffff1660601b81525050505050505050505050505050620008d4565b600033905090565b60805160601c60a05160601c60c05160601c60e05160601c61010051610120516101405161016051610180516101a05160f81c6101c05160f81c61468c62000a02600039806119e55280612d725280612da4525080610c415280610f96525080611b9e5280613ffa525080611e5552806127c15250806114b652806127e55250806108e5528061114f528061180f5280611e2052806135055250806108c1528061198d528061326e5280613448528061367852806136ee52806142d15250806113795280611a33528061230c5280612c2d5280612c69525080611a0f525080611d9a5280612925525080610d835280610e5a52806112395280611dfa52806121c25280612a415280612b3b528061328f52806136b0528061385a52806139345280613acb525061468c6000f3fe608060405234801561001057600080fd5b50600436106102485760003560e01c80638da5cb5b1161013b578063d4f77b1c116100b8578063f2fde38b1161007c578063f2fde38b1461082b578063f4ceab1c1461086f578063f5c9786714610879578063f8dd5ad314610897578063fd6673f5146108a157610248565b8063d4f77b1c14610719578063e0236a1814610723578063e231bff01461072d578063e2eb41ff1461074f578063f18d20be1461080957610248565b8063aad739f5116100ff578063aad739f514610603578063be22f54614610671578063c39b583c146106bb578063caa02e08146106dd578063d013666e146106fb57610248565b80638da5cb5b1461049957806395224b33146104e3578063a2fb117514610501578063a59a99731461056f578063a98a5c94146105b957610248565b80635edafd5a116101c9578063715018a61161018d578063715018a6146104275780637a23032c146104315780637c80e6da1461044f5780637e5f84761461046d5780638456cb591461048f57610248565b80635edafd5a146103335780635faeea37146103575780636338030014610375578063638126f8146103bf5780636a79328a1461040957610248565b80633ccfd60b116102105780633ccfd60b146102d55780633e7433eb146102df5780633f4ba83a146102fd57806340732c89146103075780635c975abb1461031157610248565b80630c8ac6451461024d57806311b2e2d91461026b57806315d74bb31461028957806316330d4014610293578063250a2b0d146102b7575b600080fd5b6102556108bf565b6040518082815260200191505060405180910390f35b6102736108e3565b6040518082815260200191505060405180910390f35b610291610907565b005b61029b610f94565b604051808260ff1660ff16815260200191505060405180910390f35b6102bf610fb8565b6040518082815260200191505060405180910390f35b6102dd610fbe565b005b6102e76114b4565b6040518082815260200191505060405180910390f35b6103056114d8565b005b61030f61160b565b005b6103196119cd565b604051808215151515815260200191505060405180910390f35b61033b6119e3565b604051808260ff1660ff16815260200191505060405180910390f35b61035f611a07565b6040518082815260200191505060405180910390f35b61037d611a0d565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6103c7611a31565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610411611a55565b6040518082815260200191505060405180910390f35b61042f611a5b565b005b610439611b96565b6040518082815260200191505060405180910390f35b610457611b9c565b6040518082815260200191505060405180910390f35b610475611bc0565b604051808215151515815260200191505060405180910390f35b610497611bd3565b005b6104a1611d07565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6104eb611d30565b6040518082815260200191505060405180910390f35b61052d6004803603602081101561051757600080fd5b8101908080359060200190929190505050611d36565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610577611d72565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6105c1611d98565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61062f6004803603602081101561061957600080fd5b8101908080359060200190929190505050611dbc565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610679611df8565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6106c3611e1c565b604051808215151515815260200191505060405180910390f35b6106e5611e4d565b6040518082815260200191505060405180910390f35b610703611e53565b6040518082815260200191505060405180910390f35b610721611e77565b005b61072b611efc565b005b61073561244c565b604051808215151515815260200191505060405180910390f35b6107916004803603602081101561076557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061245f565b604051808815151515815260200187151515158152602001861515151581526020018573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200184815260200183815260200182815260200197505050505050505060405180910390f35b6108116124e8565b604051808215151515815260200191505060405180910390f35b61086d6004803603602081101561084157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506124fb565b005b6108776126ee565b005b6108816127ba565b6040518082815260200191505060405180910390f35b61089f612826565b005b6108a9612f3d565b6040518082815260200191505060405180910390f35b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b61090f6119cd565b15610982576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f5061757361626c653a207061757365640000000000000000000000000000000081525060200191505060405180910390fd5b61098a611e1c565b156109fd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f47616d6520697320616c726561647920636f6d706c657465640000000000000081525060200191505060405180910390fd5b6000600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000816002015411610aba576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f506c6179657220646f6573206e6f74206578697374000000000000000000000081525060200191505060405180910390fd5b8060000160009054906101000a900460ff1615610b3f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f506c617965722068617320616c72656164792077697468647261776e0000000081525060200191505060405180910390fd5b60018160000160006101000a81548160ff021916908315150217905550610b726001600354612f4a90919063ffffffff16565b6003819055506000600754118015610b9857508060000160029054906101000a900460ff165b15610c3257610bb36001600754612f4a90919063ffffffff16565b60078190555060008160000160026101000a81548160ff0219169083151502179055506000600a826003015481548110610be957fe5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b6000610c97610c846064610c767f000000000000000000000000000000000000000000000000000000000000000060ff168660020154612fcd90919063ffffffff16565b61305390919063ffffffff16565b8360020154612f4a90919063ffffffff16565b9050610cb28260020154600554612f4a90919063ffffffff16565b6005819055506000610cc26127ba565b90506000811415610ceb5760018360000160016101000a81548160ff0219169083151502179055505b3373ffffffffffffffffffffffffffffffffffffffff167f1670585e36568ede58d159518ce92cad99f75ad41c7d8281df3dd4eaa0c855d083600554604051808381526020018281526020019250505060405180910390a2600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166369328dec7f000000000000000000000000000000000000000000000000000000000000000084306040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019350505050600060405180830381600087803b158015610e4057600080fd5b505af1158015610e54573d6000803e3d6000fd5b505050507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33846040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b158015610eff57600080fd5b505af1158015610f13573d6000803e3d6000fd5b505050506040513d6020811015610f2957600080fd5b8101908080519060200190929190505050610f8f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f815260200180614392602f913960400191505060405180910390fd5b505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60035481565b6000600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600081600201541161107b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f506c6179657220646f6573206e6f74206578697374000000000000000000000081525060200191505060405180910390fd5b8060000160009054906101000a900460ff1615611100576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f506c617965722068617320616c72656164792077697468647261776e0000000081525060200191505060405180910390fd5b60018160000160006101000a81548160ff021916908315150217905550600060169054906101000a900460ff1661113a57611139612826565b5b600081600201549050600080905061117c60017f0000000000000000000000000000000000000000000000000000000000000000612f4a90919063ffffffff16565b836001015414156111d8576111b06111a160075460045461305390919063ffffffff16565b836130dc90919063ffffffff16565b9150600060025411156111d7576111d460075460025461305390919063ffffffff16565b90505b5b3373ffffffffffffffffffffffffffffffffffffffff167f650fdf669e93aa6c8ff3defe2da9c12b64f1548e5e1e54e803f4c1beb6466c8e8360008460405180848152602001838152602001828152602001935050505060405180910390a27f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33846040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b1580156112de57600080fd5b505af11580156112f2573d6000803e3d6000fd5b505050506040513d602081101561130857600080fd5b810190808051906020019092919050505061136e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260298152602001806144ce6029913960400191505060405180910390fd5b60008111156114af577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33836040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b15801561141e57600080fd5b505af1158015611432573d6000803e3d6000fd5b505050506040513d602081101561144857600080fd5b81019080805190602001909291905050506114ae576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260338152602001806145f16033913960400191505060405180910390fd5b5b505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6114e0613164565b73ffffffffffffffffffffffffffffffffffffffff166114fe611d07565b73ffffffffffffffffffffffffffffffffffffffff1614611587576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b61158f6119cd565b611601576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f5061757361626c653a206e6f742070617573656400000000000000000000000081525060200191505060405180910390fd5b61160961316c565b565b6116136119cd565b15611686576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f5061757361626c653a207061757365640000000000000000000000000000000081525060200191505060405180910390fd5b6000600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060000160009054906101000a900460ff1615611731576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602181526020018061458a6021913960400191505060405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff168160000160039054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146117f6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f53656e646572206973206e6f74206120706c617965720000000000000000000081525060200191505060405180910390fd5b60006118006127ba565b905060008111801561183157507f000000000000000000000000000000000000000000000000000000000000000081105b611886576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252604681526020018061443a6046913960600191505060405180910390fd5b80826001015414156118e3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806145ce6023913960400191505060405180910390fd5b6118f7600182612f4a90919063ffffffff16565b826001015414611952576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260338152602001806146246033913960400191505060405180910390fd5b803373ffffffffffffffffffffffffffffffffffffffff167f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a157f00000000000000000000000000000000000000000000000000000000000000006040518082815260200191505060405180910390a36119c961326c565b5050565b60008060149054906101000a900460ff16905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b60055481565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60025481565b611a63613164565b73ffffffffffffffffffffffffffffffffffffffff16611a81611d07565b73ffffffffffffffffffffffffffffffffffffffff1614611b0a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600060159054906101000a900460ff16611b8c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600b8152602001807f4e6f7420616c6c6f77656400000000000000000000000000000000000000000081525060200191505060405180910390fd5b611b94613bb1565b565b60065481565b7f000000000000000000000000000000000000000000000000000000000000000081565b600060159054906101000a900460ff1681565b611bdb613164565b73ffffffffffffffffffffffffffffffffffffffff16611bf9611d07565b73ffffffffffffffffffffffffffffffffffffffff1614611c82576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b611c8a6119cd565b15611cfd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f5061757361626c653a207061757365640000000000000000000000000000000081525060200191505060405180910390fd5b611d05613d1f565b565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60045481565b600a8181548110611d4357fe5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b7f000000000000000000000000000000000000000000000000000000000000000081565b60098181548110611dc957fe5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f0000000000000000000000000000000000000000000000000000000000000000611e476127ba565b11905090565b60075481565b7f000000000000000000000000000000000000000000000000000000000000000081565b611e7f6119cd565b15611ef2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f5061757361626c653a207061757365640000000000000000000000000000000081525060200191505060405180910390fd5b611efa613e21565b565b611f04613164565b73ffffffffffffffffffffffffffffffffffffffff16611f22611d07565b73ffffffffffffffffffffffffffffffffffffffff1614611fab576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b611fb3611e1c565b612025576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f47616d65206973206e6f7420636f6d706c65746564000000000000000000000081525060200191505060405180910390fd5b600060169054906101000a900460ff1661208a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806144806025913960400191505060405180910390fd5b600060179054906101000a900460ff161561210d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f41646d696e2068617320616c72656164792077697468647261776e000000000081525060200191505060405180910390fd5b6001600060176101000a81548160ff0219169083151502179055506000809050600060075414801561214157506000600254115b1561214c5760025490505b612154611d07565b73ffffffffffffffffffffffffffffffffffffffff167f80ebcacc706983394bb8fcc88ea7b9241338fb4617fffbea411b68b40ed5627e6004546006548460405180848152602001838152602001828152602001935050505060405180910390a260006006541115612301577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb612204611d07565b6006546040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b15801561227057600080fd5b505af1158015612284573d6000803e3d6000fd5b505050506040513d602081101561229a57600080fd5b8101908080519060200190929190505050612300576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806144156025913960400191505060405180910390fd5b5b6000811115612449577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb61234e611d07565b836040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b1580156123b857600080fd5b505af11580156123cc573d6000803e3d6000fd5b505050506040513d60208110156123e257600080fd5b8101908080519060200190929190505050612448576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f815260200180614518602f913960400191505060405180910390fd5b5b50565b600060169054906101000a900460ff1681565b60086020528060005260406000206000915090508060000160009054906101000a900460ff16908060000160019054906101000a900460ff16908060000160029054906101000a900460ff16908060000160039054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060010154908060020154908060030154905087565b600060179054906101000a900460ff1681565b612503613164565b73ffffffffffffffffffffffffffffffffffffffff16612521611d07565b73ffffffffffffffffffffffffffffffffffffffff16146125aa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612630576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806143ef6026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6126f6613164565b73ffffffffffffffffffffffffffffffffffffffff16612714611d07565b73ffffffffffffffffffffffffffffffffffffffff161461279d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6001600060156101000a81548160ff021916908315150217905550565b60006128217f00000000000000000000000000000000000000000000000000000000000000006128137f000000000000000000000000000000000000000000000000000000000000000042612f4a90919063ffffffff16565b61305390919063ffffffff16565b905090565b61282e611e1c565b6128a0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f47616d65206973206e6f7420636f6d706c65746564000000000000000000000081525060200191505060405180910390fd5b600060169054906101000a900460ff1615612906576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e8152602001806143c1602e913960400191505060405180910390fd5b6001600060166101000a81548160ff02191690831515021790555060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156129c057600080fd5b505afa1580156129d4573d6000803e3d6000fd5b505050506040513d60208110156129ea57600080fd5b81019080805190602001909291905050501115612b3757600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166369328dec7f00000000000000000000000000000000000000000000000000000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff306040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019350505050600060405180830381600087803b158015612b1e57600080fd5b505af1158015612b32573d6000803e3d6000fd5b505050505b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015612bd657600080fd5b505afa158015612bea573d6000803e3d6000fd5b505050506040513d6020811015612c0057600080fd5b81019080805190602001909291905050509050600073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1614612d46577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015612d0457600080fd5b505afa158015612d18573d6000803e3d6000fd5b505050506040513d6020811015612d2e57600080fd5b81019080805190602001909291905050506002819055505b6000809050600554821115612d6d57612d6a60055483612f4a90919063ffffffff16565b90505b6000807f000000000000000000000000000000000000000000000000000000000000000060ff161115612e0357612de36064612dd57f000000000000000000000000000000000000000000000000000000000000000060ff1685612fcd90919063ffffffff16565b61305390919063ffffffff16565b9050612df88183612f4a90919063ffffffff16565b600481905550612e0f565b60009050816004819055505b60006007541415612e265781600681905550612e2e565b806006819055505b7f28d72925fdcea205b246c820015bd35812a740d1ec1a5cdc84f7784b50940fbb836005546004546000600254604051808681526020018581526020018481526020018381526020018281526020019550505050505060405180910390a17fdbb9607e18553d40c255226e09883b48f92a108f6f895b0f37db6ae0d7fd56e6600a60405180806020018281038252838181548152602001915080548015612f2a57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311612ee0575b50509250505060405180910390a1505050565b6000600980549050905090565b600082821115612fc2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525060200191505060405180910390fd5b818303905092915050565b600080831415612fe0576000905061304d565b6000828402905082848281612ff157fe5b0414613048576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806144f76021913960400191505060405180910390fd5b809150505b92915050565b60008082116130ca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525060200191505060405180910390fd5b8183816130d357fe5b04905092915050565b60008082840190508381101561315a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b600033905090565b6131746119cd565b6131e6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f5061757361626c653a206e6f742070617573656400000000000000000000000081525060200191505060405180910390fd5b60008060146101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa613229613164565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1565b7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e33306040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060206040518083038186803b15801561335e57600080fd5b505afa158015613372573d6000803e3d6000fd5b505050506040513d602081101561338857600080fd5b810190808051906020019092919050505010156133f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260438152602001806145476043913960600191505060405180910390fd5b60006133fa6127ba565b905080600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101819055506134b87f0000000000000000000000000000000000000000000000000000000000000000600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600201546130dc90919063ffffffff16565b600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206002018190555061353260017f0000000000000000000000000000000000000000000000000000000000000000612f4a90919063ffffffff16565b81141561367357600a339080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506135b56001600a80549050612f4a90919063ffffffff16565b600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206003018190555061361160016007546130dc90919063ffffffff16565b6007819055506001600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160026101000a81548160ff0219169083151502179055505b6136a87f00000000000000000000000000000000000000000000000000000000000000006005546130dc90919063ffffffff16565b6005819055507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166323b872dd33307f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050602060405180830381600087803b1580156137a957600080fd5b505af11580156137bd573d6000803e3d6000fd5b505050506040513d60208110156137d357600080fd5b8101908080519060200190929190505050613856576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f5472616e73666572206661696c6564000000000000000000000000000000000081525060200191505060405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156138f557600080fd5b505afa158015613909573d6000803e3d6000fd5b505050506040513d602081101561391f57600080fd5b810190808051906020019092919050505090507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663095ea7b3600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b1580156139fb57600080fd5b505af1158015613a0f573d6000803e3d6000fd5b505050506040513d6020811015613a2557600080fd5b8101908080519060200190929190505050613a8b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260298152602001806144a56029913960400191505060405180910390fd5b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e8eda9df7f00000000000000000000000000000000000000000000000000000000000000008330609b6040518563ffffffff1660e01b8152600401808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018481526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018261ffff168152602001945050505050600060405180830381600087803b158015613b9557600080fd5b505af1158015613ba9573d6000803e3d6000fd5b505050505050565b613bb9613164565b73ffffffffffffffffffffffffffffffffffffffff16613bd7611d07565b73ffffffffffffffffffffffffffffffffffffffff1614613c60576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b613d276119cd565b15613d9a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f5061757361626c653a207061757365640000000000000000000000000000000081525060200191505060405180910390fd5b6001600060146101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258613dde613164565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1565b6000613e2b6127ba565b14613e9e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f47616d652068617320616c72656164792073746172746564000000000000000081525060200191505060405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff16600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160039054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141580613f875750600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160019054906101000a900460ff165b613fdc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806145ab6023913960400191505060405180910390fd5b613ff260016003546130dc90919063ffffffff16565b6003819055507f00000000000000000000000000000000000000000000000000000000000000006003541115614073576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018061436b6027913960400191505060405180910390fd5b6000600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160019054906101000a900460ff1690506140cf614311565b6040518060e001604052806000151581526020016000151581526020016000151581526020013373ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001600081526020016000815250905080600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548160ff02191690831515021790555060408201518160000160026101000a81548160ff02191690831515021790555060608201518160000160036101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506080820151816001015560a0820151816002015560c0820151816003015590505081614297576009339080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b3373ffffffffffffffffffffffffffffffffffffffff167f485fd86c2a7d2d9ca3bf02e2ba776ea24271bc62274265b0bd5f478b3b7a1ca47f00000000000000000000000000000000000000000000000000000000000000006040518082815260200191505060405180910390a261430d61326c565b5050565b6040518060e00160405280600015158152602001600015158152602001600015158152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600081526020016000815260200160008152509056fe52656163686564206d6178207175616e74697479206f6620706c617965727320616c6c6f7765644661696c20746f207472616e7366657220455243323020746f6b656e73206f6e206561726c7920776974686472617752656465656d206f7065726174696f6e20616c72656164792068617070656e656420666f72207468652067616d654f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573734661696c20746f207472616e73666572204552323020746f6b656e7320746f2061646d696e4465706f73697420617661696c61626c65206f6e6c79206265747765656e207365676d656e74203120616e64207365676d656e74206e2d31202870656e756c74696d6174652946756e6473206e6f742072656465656d65642066726f6d2065787465726e616c20706f6f6c4661696c20746f20617070726f766520616c6c6f77616e636520746f206c656e64696e6720706f6f6c4661696c20746f207472616e7366657220455243323020746f6b656e73206f6e207769746864726177536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774661696c20746f207472616e73666572204552323020696e63656e7469766520746f6b656e7320746f2061646d696e596f75206e65656420746f206861766520616c6c6f77616e636520746f20646f207472616e7366657220444149206f6e2074686520736d61727420636f6e7472616374506c6179657220616c72656164792077697468647261772066726f6d2067616d6543616e6e6f74206a6f696e207468652067616d65206d6f7265207468616e206f6e6365506c6179657220616c726561647920706169642063757272656e74207365676d656e744661696c20746f207472616e7366657220455243323020696e63656e7469766520746f6b656e73206f6e207769746864726177506c61796572206469646e277420706179207468652070726576696f7573207365676d656e74202d2067616d65206f76657221a264697066735822122083fae1a594582de23ccaaa1148cb2251932884cd0a6a5aa2a63f2ae5029c716464736f6c634300060b00335f637573746f6d466565206d757374206265206c657373207468616e206f7220657175616c20746f203230255f6d6178506c6179657273436f756e74206d7573742062652067726561746572207468616e207a65726f5f7365676d656e744c656e677468206d7573742062652067726561746572207468616e207a65726f5f6561726c795769746864726177616c466565206d7573742062652067726561746572207468616e207a65726f5f7365676d656e74436f756e74206d7573742062652067726561746572207468616e207a65726f5f7365676d656e745061796d656e74206d7573742062652067726561746572207468616e207a65726f5f6561726c795769746864726177616c466565206d757374206265206c657373207468616e206f7220657175616c20746f20313025696e76616c6964205f6c656e64696e67506f6f6c4164647265737350726f76696465722061646472657373000000000000000000000000765de816845861e75a25fca122bb6898b8b1282a000000000000000000000000d1088091a174d33412a968fa34cb67131188b33200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000258000000000000000000000000000000000000000000000000002386f26fc100000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000043d067ed784d9dd2ffeda73775e2cc4c560103a1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000

Deployed ByteCode

0x608060405234801561001057600080fd5b50600436106102485760003560e01c80638da5cb5b1161013b578063d4f77b1c116100b8578063f2fde38b1161007c578063f2fde38b1461082b578063f4ceab1c1461086f578063f5c9786714610879578063f8dd5ad314610897578063fd6673f5146108a157610248565b8063d4f77b1c14610719578063e0236a1814610723578063e231bff01461072d578063e2eb41ff1461074f578063f18d20be1461080957610248565b8063aad739f5116100ff578063aad739f514610603578063be22f54614610671578063c39b583c146106bb578063caa02e08146106dd578063d013666e146106fb57610248565b80638da5cb5b1461049957806395224b33146104e3578063a2fb117514610501578063a59a99731461056f578063a98a5c94146105b957610248565b80635edafd5a116101c9578063715018a61161018d578063715018a6146104275780637a23032c146104315780637c80e6da1461044f5780637e5f84761461046d5780638456cb591461048f57610248565b80635edafd5a146103335780635faeea37146103575780636338030014610375578063638126f8146103bf5780636a79328a1461040957610248565b80633ccfd60b116102105780633ccfd60b146102d55780633e7433eb146102df5780633f4ba83a146102fd57806340732c89146103075780635c975abb1461031157610248565b80630c8ac6451461024d57806311b2e2d91461026b57806315d74bb31461028957806316330d4014610293578063250a2b0d146102b7575b600080fd5b6102556108bf565b6040518082815260200191505060405180910390f35b6102736108e3565b6040518082815260200191505060405180910390f35b610291610907565b005b61029b610f94565b604051808260ff1660ff16815260200191505060405180910390f35b6102bf610fb8565b6040518082815260200191505060405180910390f35b6102dd610fbe565b005b6102e76114b4565b6040518082815260200191505060405180910390f35b6103056114d8565b005b61030f61160b565b005b6103196119cd565b604051808215151515815260200191505060405180910390f35b61033b6119e3565b604051808260ff1660ff16815260200191505060405180910390f35b61035f611a07565b6040518082815260200191505060405180910390f35b61037d611a0d565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6103c7611a31565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610411611a55565b6040518082815260200191505060405180910390f35b61042f611a5b565b005b610439611b96565b6040518082815260200191505060405180910390f35b610457611b9c565b6040518082815260200191505060405180910390f35b610475611bc0565b604051808215151515815260200191505060405180910390f35b610497611bd3565b005b6104a1611d07565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6104eb611d30565b6040518082815260200191505060405180910390f35b61052d6004803603602081101561051757600080fd5b8101908080359060200190929190505050611d36565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610577611d72565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6105c1611d98565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61062f6004803603602081101561061957600080fd5b8101908080359060200190929190505050611dbc565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610679611df8565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6106c3611e1c565b604051808215151515815260200191505060405180910390f35b6106e5611e4d565b6040518082815260200191505060405180910390f35b610703611e53565b6040518082815260200191505060405180910390f35b610721611e77565b005b61072b611efc565b005b61073561244c565b604051808215151515815260200191505060405180910390f35b6107916004803603602081101561076557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061245f565b604051808815151515815260200187151515158152602001861515151581526020018573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200184815260200183815260200182815260200197505050505050505060405180910390f35b6108116124e8565b604051808215151515815260200191505060405180910390f35b61086d6004803603602081101561084157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506124fb565b005b6108776126ee565b005b6108816127ba565b6040518082815260200191505060405180910390f35b61089f612826565b005b6108a9612f3d565b6040518082815260200191505060405180910390f35b7f000000000000000000000000000000000000000000000000002386f26fc1000081565b7f000000000000000000000000000000000000000000000000000000000000000281565b61090f6119cd565b15610982576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f5061757361626c653a207061757365640000000000000000000000000000000081525060200191505060405180910390fd5b61098a611e1c565b156109fd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f47616d6520697320616c726561647920636f6d706c657465640000000000000081525060200191505060405180910390fd5b6000600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000816002015411610aba576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f506c6179657220646f6573206e6f74206578697374000000000000000000000081525060200191505060405180910390fd5b8060000160009054906101000a900460ff1615610b3f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f506c617965722068617320616c72656164792077697468647261776e0000000081525060200191505060405180910390fd5b60018160000160006101000a81548160ff021916908315150217905550610b726001600354612f4a90919063ffffffff16565b6003819055506000600754118015610b9857508060000160029054906101000a900460ff165b15610c3257610bb36001600754612f4a90919063ffffffff16565b60078190555060008160000160026101000a81548160ff0219169083151502179055506000600a826003015481548110610be957fe5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b6000610c97610c846064610c767f000000000000000000000000000000000000000000000000000000000000000160ff168660020154612fcd90919063ffffffff16565b61305390919063ffffffff16565b8360020154612f4a90919063ffffffff16565b9050610cb28260020154600554612f4a90919063ffffffff16565b6005819055506000610cc26127ba565b90506000811415610ceb5760018360000160016101000a81548160ff0219169083151502179055505b3373ffffffffffffffffffffffffffffffffffffffff167f1670585e36568ede58d159518ce92cad99f75ad41c7d8281df3dd4eaa0c855d083600554604051808381526020018281526020019250505060405180910390a2600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166369328dec7f000000000000000000000000765de816845861e75a25fca122bb6898b8b1282a84306040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019350505050600060405180830381600087803b158015610e4057600080fd5b505af1158015610e54573d6000803e3d6000fd5b505050507f000000000000000000000000765de816845861e75a25fca122bb6898b8b1282a73ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33846040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b158015610eff57600080fd5b505af1158015610f13573d6000803e3d6000fd5b505050506040513d6020811015610f2957600080fd5b8101908080519060200190929190505050610f8f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f815260200180614392602f913960400191505060405180910390fd5b505050565b7f000000000000000000000000000000000000000000000000000000000000000181565b60035481565b6000600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600081600201541161107b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f506c6179657220646f6573206e6f74206578697374000000000000000000000081525060200191505060405180910390fd5b8060000160009054906101000a900460ff1615611100576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f506c617965722068617320616c72656164792077697468647261776e0000000081525060200191505060405180910390fd5b60018160000160006101000a81548160ff021916908315150217905550600060169054906101000a900460ff1661113a57611139612826565b5b600081600201549050600080905061117c60017f0000000000000000000000000000000000000000000000000000000000000002612f4a90919063ffffffff16565b836001015414156111d8576111b06111a160075460045461305390919063ffffffff16565b836130dc90919063ffffffff16565b9150600060025411156111d7576111d460075460025461305390919063ffffffff16565b90505b5b3373ffffffffffffffffffffffffffffffffffffffff167f650fdf669e93aa6c8ff3defe2da9c12b64f1548e5e1e54e803f4c1beb6466c8e8360008460405180848152602001838152602001828152602001935050505060405180910390a27f000000000000000000000000765de816845861e75a25fca122bb6898b8b1282a73ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33846040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b1580156112de57600080fd5b505af11580156112f2573d6000803e3d6000fd5b505050506040513d602081101561130857600080fd5b810190808051906020019092919050505061136e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260298152602001806144ce6029913960400191505060405180910390fd5b60008111156114af577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33836040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b15801561141e57600080fd5b505af1158015611432573d6000803e3d6000fd5b505050506040513d602081101561144857600080fd5b81019080805190602001909291905050506114ae576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260338152602001806145f16033913960400191505060405180910390fd5b5b505050565b7f0000000000000000000000000000000000000000000000000000000061b14cc981565b6114e0613164565b73ffffffffffffffffffffffffffffffffffffffff166114fe611d07565b73ffffffffffffffffffffffffffffffffffffffff1614611587576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b61158f6119cd565b611601576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f5061757361626c653a206e6f742070617573656400000000000000000000000081525060200191505060405180910390fd5b61160961316c565b565b6116136119cd565b15611686576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f5061757361626c653a207061757365640000000000000000000000000000000081525060200191505060405180910390fd5b6000600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060000160009054906101000a900460ff1615611731576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602181526020018061458a6021913960400191505060405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff168160000160039054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146117f6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f53656e646572206973206e6f74206120706c617965720000000000000000000081525060200191505060405180910390fd5b60006118006127ba565b905060008111801561183157507f000000000000000000000000000000000000000000000000000000000000000281105b611886576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252604681526020018061443a6046913960600191505060405180910390fd5b80826001015414156118e3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806145ce6023913960400191505060405180910390fd5b6118f7600182612f4a90919063ffffffff16565b826001015414611952576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260338152602001806146246033913960400191505060405180910390fd5b803373ffffffffffffffffffffffffffffffffffffffff167f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a157f000000000000000000000000000000000000000000000000002386f26fc100006040518082815260200191505060405180910390a36119c961326c565b5050565b60008060149054906101000a900460ff16905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b60055481565b7f000000000000000000000000d1088091a174d33412a968fa34cb67131188b33281565b7f000000000000000000000000000000000000000000000000000000000000000081565b60025481565b611a63613164565b73ffffffffffffffffffffffffffffffffffffffff16611a81611d07565b73ffffffffffffffffffffffffffffffffffffffff1614611b0a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600060159054906101000a900460ff16611b8c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600b8152602001807f4e6f7420616c6c6f77656400000000000000000000000000000000000000000081525060200191505060405180910390fd5b611b94613bb1565b565b60065481565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81565b600060159054906101000a900460ff1681565b611bdb613164565b73ffffffffffffffffffffffffffffffffffffffff16611bf9611d07565b73ffffffffffffffffffffffffffffffffffffffff1614611c82576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b611c8a6119cd565b15611cfd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f5061757361626c653a207061757365640000000000000000000000000000000081525060200191505060405180910390fd5b611d05613d1f565b565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60045481565b600a8181548110611d4357fe5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b7f000000000000000000000000918146359264c492bd6934071c6bd31c854edbc381565b60098181548110611dc957fe5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b7f000000000000000000000000765de816845861e75a25fca122bb6898b8b1282a81565b60007f0000000000000000000000000000000000000000000000000000000000000002611e476127ba565b11905090565b60075481565b7f000000000000000000000000000000000000000000000000000000000000025881565b611e7f6119cd565b15611ef2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f5061757361626c653a207061757365640000000000000000000000000000000081525060200191505060405180910390fd5b611efa613e21565b565b611f04613164565b73ffffffffffffffffffffffffffffffffffffffff16611f22611d07565b73ffffffffffffffffffffffffffffffffffffffff1614611fab576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b611fb3611e1c565b612025576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f47616d65206973206e6f7420636f6d706c65746564000000000000000000000081525060200191505060405180910390fd5b600060169054906101000a900460ff1661208a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806144806025913960400191505060405180910390fd5b600060179054906101000a900460ff161561210d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f41646d696e2068617320616c72656164792077697468647261776e000000000081525060200191505060405180910390fd5b6001600060176101000a81548160ff0219169083151502179055506000809050600060075414801561214157506000600254115b1561214c5760025490505b612154611d07565b73ffffffffffffffffffffffffffffffffffffffff167f80ebcacc706983394bb8fcc88ea7b9241338fb4617fffbea411b68b40ed5627e6004546006548460405180848152602001838152602001828152602001935050505060405180910390a260006006541115612301577f000000000000000000000000765de816845861e75a25fca122bb6898b8b1282a73ffffffffffffffffffffffffffffffffffffffff1663a9059cbb612204611d07565b6006546040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b15801561227057600080fd5b505af1158015612284573d6000803e3d6000fd5b505050506040513d602081101561229a57600080fd5b8101908080519060200190929190505050612300576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806144156025913960400191505060405180910390fd5b5b6000811115612449577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb61234e611d07565b836040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b1580156123b857600080fd5b505af11580156123cc573d6000803e3d6000fd5b505050506040513d60208110156123e257600080fd5b8101908080519060200190929190505050612448576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f815260200180614518602f913960400191505060405180910390fd5b5b50565b600060169054906101000a900460ff1681565b60086020528060005260406000206000915090508060000160009054906101000a900460ff16908060000160019054906101000a900460ff16908060000160029054906101000a900460ff16908060000160039054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060010154908060020154908060030154905087565b600060179054906101000a900460ff1681565b612503613164565b73ffffffffffffffffffffffffffffffffffffffff16612521611d07565b73ffffffffffffffffffffffffffffffffffffffff16146125aa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612630576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806143ef6026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6126f6613164565b73ffffffffffffffffffffffffffffffffffffffff16612714611d07565b73ffffffffffffffffffffffffffffffffffffffff161461279d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6001600060156101000a81548160ff021916908315150217905550565b60006128217f00000000000000000000000000000000000000000000000000000000000002586128137f0000000000000000000000000000000000000000000000000000000061b14cc942612f4a90919063ffffffff16565b61305390919063ffffffff16565b905090565b61282e611e1c565b6128a0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f47616d65206973206e6f7420636f6d706c65746564000000000000000000000081525060200191505060405180910390fd5b600060169054906101000a900460ff1615612906576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e8152602001806143c1602e913960400191505060405180910390fd5b6001600060166101000a81548160ff02191690831515021790555060007f000000000000000000000000918146359264c492bd6934071c6bd31c854edbc373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156129c057600080fd5b505afa1580156129d4573d6000803e3d6000fd5b505050506040513d60208110156129ea57600080fd5b81019080805190602001909291905050501115612b3757600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166369328dec7f000000000000000000000000765de816845861e75a25fca122bb6898b8b1282a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff306040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019350505050600060405180830381600087803b158015612b1e57600080fd5b505af1158015612b32573d6000803e3d6000fd5b505050505b60007f000000000000000000000000765de816845861e75a25fca122bb6898b8b1282a73ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015612bd657600080fd5b505afa158015612bea573d6000803e3d6000fd5b505050506040513d6020811015612c0057600080fd5b81019080805190602001909291905050509050600073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1614612d46577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015612d0457600080fd5b505afa158015612d18573d6000803e3d6000fd5b505050506040513d6020811015612d2e57600080fd5b81019080805190602001909291905050506002819055505b6000809050600554821115612d6d57612d6a60055483612f4a90919063ffffffff16565b90505b6000807f000000000000000000000000000000000000000000000000000000000000000060ff161115612e0357612de36064612dd57f000000000000000000000000000000000000000000000000000000000000000060ff1685612fcd90919063ffffffff16565b61305390919063ffffffff16565b9050612df88183612f4a90919063ffffffff16565b600481905550612e0f565b60009050816004819055505b60006007541415612e265781600681905550612e2e565b806006819055505b7f28d72925fdcea205b246c820015bd35812a740d1ec1a5cdc84f7784b50940fbb836005546004546000600254604051808681526020018581526020018481526020018381526020018281526020019550505050505060405180910390a17fdbb9607e18553d40c255226e09883b48f92a108f6f895b0f37db6ae0d7fd56e6600a60405180806020018281038252838181548152602001915080548015612f2a57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311612ee0575b50509250505060405180910390a1505050565b6000600980549050905090565b600082821115612fc2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525060200191505060405180910390fd5b818303905092915050565b600080831415612fe0576000905061304d565b6000828402905082848281612ff157fe5b0414613048576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806144f76021913960400191505060405180910390fd5b809150505b92915050565b60008082116130ca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525060200191505060405180910390fd5b8183816130d357fe5b04905092915050565b60008082840190508381101561315a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b600033905090565b6131746119cd565b6131e6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f5061757361626c653a206e6f742070617573656400000000000000000000000081525060200191505060405180910390fd5b60008060146101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa613229613164565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1565b7f000000000000000000000000000000000000000000000000002386f26fc100007f000000000000000000000000765de816845861e75a25fca122bb6898b8b1282a73ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e33306040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060206040518083038186803b15801561335e57600080fd5b505afa158015613372573d6000803e3d6000fd5b505050506040513d602081101561338857600080fd5b810190808051906020019092919050505010156133f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260438152602001806145476043913960600191505060405180910390fd5b60006133fa6127ba565b905080600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101819055506134b87f000000000000000000000000000000000000000000000000002386f26fc10000600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600201546130dc90919063ffffffff16565b600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206002018190555061353260017f0000000000000000000000000000000000000000000000000000000000000002612f4a90919063ffffffff16565b81141561367357600a339080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506135b56001600a80549050612f4a90919063ffffffff16565b600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206003018190555061361160016007546130dc90919063ffffffff16565b6007819055506001600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160026101000a81548160ff0219169083151502179055505b6136a87f000000000000000000000000000000000000000000000000002386f26fc100006005546130dc90919063ffffffff16565b6005819055507f000000000000000000000000765de816845861e75a25fca122bb6898b8b1282a73ffffffffffffffffffffffffffffffffffffffff166323b872dd33307f000000000000000000000000000000000000000000000000002386f26fc100006040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050602060405180830381600087803b1580156137a957600080fd5b505af11580156137bd573d6000803e3d6000fd5b505050506040513d60208110156137d357600080fd5b8101908080519060200190929190505050613856576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f5472616e73666572206661696c6564000000000000000000000000000000000081525060200191505060405180910390fd5b60007f000000000000000000000000765de816845861e75a25fca122bb6898b8b1282a73ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156138f557600080fd5b505afa158015613909573d6000803e3d6000fd5b505050506040513d602081101561391f57600080fd5b810190808051906020019092919050505090507f000000000000000000000000765de816845861e75a25fca122bb6898b8b1282a73ffffffffffffffffffffffffffffffffffffffff1663095ea7b3600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b1580156139fb57600080fd5b505af1158015613a0f573d6000803e3d6000fd5b505050506040513d6020811015613a2557600080fd5b8101908080519060200190929190505050613a8b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260298152602001806144a56029913960400191505060405180910390fd5b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e8eda9df7f000000000000000000000000765de816845861e75a25fca122bb6898b8b1282a8330609b6040518563ffffffff1660e01b8152600401808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018481526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018261ffff168152602001945050505050600060405180830381600087803b158015613b9557600080fd5b505af1158015613ba9573d6000803e3d6000fd5b505050505050565b613bb9613164565b73ffffffffffffffffffffffffffffffffffffffff16613bd7611d07565b73ffffffffffffffffffffffffffffffffffffffff1614613c60576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b613d276119cd565b15613d9a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f5061757361626c653a207061757365640000000000000000000000000000000081525060200191505060405180910390fd5b6001600060146101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258613dde613164565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1565b6000613e2b6127ba565b14613e9e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f47616d652068617320616c72656164792073746172746564000000000000000081525060200191505060405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff16600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160039054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141580613f875750600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160019054906101000a900460ff165b613fdc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806145ab6023913960400191505060405180910390fd5b613ff260016003546130dc90919063ffffffff16565b6003819055507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6003541115614073576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018061436b6027913960400191505060405180910390fd5b6000600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160019054906101000a900460ff1690506140cf614311565b6040518060e001604052806000151581526020016000151581526020016000151581526020013373ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001600081526020016000815250905080600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548160ff02191690831515021790555060408201518160000160026101000a81548160ff02191690831515021790555060608201518160000160036101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506080820151816001015560a0820151816002015560c0820151816003015590505081614297576009339080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b3373ffffffffffffffffffffffffffffffffffffffff167f485fd86c2a7d2d9ca3bf02e2ba776ea24271bc62274265b0bd5f478b3b7a1ca47f000000000000000000000000000000000000000000000000002386f26fc100006040518082815260200191505060405180910390a261430d61326c565b5050565b6040518060e00160405280600015158152602001600015158152602001600015158152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600081526020016000815260200160008152509056fe52656163686564206d6178207175616e74697479206f6620706c617965727320616c6c6f7765644661696c20746f207472616e7366657220455243323020746f6b656e73206f6e206561726c7920776974686472617752656465656d206f7065726174696f6e20616c72656164792068617070656e656420666f72207468652067616d654f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573734661696c20746f207472616e73666572204552323020746f6b656e7320746f2061646d696e4465706f73697420617661696c61626c65206f6e6c79206265747765656e207365676d656e74203120616e64207365676d656e74206e2d31202870656e756c74696d6174652946756e6473206e6f742072656465656d65642066726f6d2065787465726e616c20706f6f6c4661696c20746f20617070726f766520616c6c6f77616e636520746f206c656e64696e6720706f6f6c4661696c20746f207472616e7366657220455243323020746f6b656e73206f6e207769746864726177536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774661696c20746f207472616e73666572204552323020696e63656e7469766520746f6b656e7320746f2061646d696e596f75206e65656420746f206861766520616c6c6f77616e636520746f20646f207472616e7366657220444149206f6e2074686520736d61727420636f6e7472616374506c6179657220616c72656164792077697468647261772066726f6d2067616d6543616e6e6f74206a6f696e207468652067616d65206d6f7265207468616e206f6e6365506c6179657220616c726561647920706169642063757272656e74207365676d656e744661696c20746f207472616e7366657220455243323020696e63656e7469766520746f6b656e73206f6e207769746864726177506c61796572206469646e277420706179207468652070726576696f7573207365676d656e74202d2067616d65206f76657221a264697066735822122083fae1a594582de23ccaaa1148cb2251932884cd0a6a5aa2a63f2ae5029c716464736f6c634300060b0033