false
false
0

Contract Address Details

0x709E5dce1e1549d1794792F8f23D5ED1B8C36bb3

Contract Name
TwoBearsBots
Creator
0xebe894–7a24f6 at 0x95bf71–1d9fcd
Balance
0 CLO
Tokens
Fetching tokens...
Transactions
Fetching transactions...
Transfers
Fetching transfers...
Gas Used
Fetching gas used...
Last Balance Update
16286011
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
Contract name:
TwoBearsBots




Optimization enabled
false
Compiler version
v0.8.16+commit.07a7930e




EVM Version
default




Verified at
2024-09-26T15:35:02.623574Z

Contract source code

// All rights reserved.
// SPDX-License-Identifier: No License (None)

pragma solidity ^0.8.16;

interface IContractBotsHelp {
    function checkApproveAndBalance(address _owner, address _token_in, uint _value_in, uint _value_inc_balance) external view returns (uint8);
    function checkCreateBotSellBuy(address _owner, address _token_in, address _token_out, uint _value, uint _value_inc, uint _price, uint _price_step, uint _price_limit) external view returns (uint8, uint8, uint256, uint256);
    function checkCreateBotNetTrade(address _owner, address _token_in, address _token_out, uint _value_sell, uint _value_buy, uint _price, uint _price_step, uint _price_up_limit, uint _price_down_limit) external view returns (uint8, uint256, uint256);
    function checkSchemeBotSellBuy(address _owner, address _token_in, address _token_out, uint _value, uint _price, uint _price_limit) external view returns (uint8, uint256, uint256);
    function checkSchemeBotNetTrade(address _owner, address _token_in, address _token_out, uint[] memory _param, uint[] memory _order_data, uint[] memory _order_data_2) external view returns (uint8, uint[] memory);
}

interface IContractDeposits {
    function createOrderBot(address _owner, address _token_in, uint _value_in, address _token_out, uint _value_out, uint _order_position) external returns (uint256);
    function getTypeAndPriceOrder(address _token_in, uint _value_in, address _token_out, uint _value_out) external view returns (uint8, uint256);
    function getTypeAndValue(address _token_in, address _token_out, uint _value, uint _price) external view returns (uint8, uint256);
    function getWrappedAndPricelimit() external view returns (address, uint256, uint256);
    function payTheOracle(address _owner, address _oracle, uint _gasUsed) external returns (uint256);
}

interface IContractOrders {
    function cancelOrders(uint[] memory _id_arr) external returns (uint [] memory);
    function deleteCloseOrders(uint[] memory _id_arr) external returns (uint [] memory);
    function getLockedTokensForOracle(uint _id1, uint _id2) external view returns (uint [] memory);
    function getOrderDataForOracle(uint _id) external view returns (uint [] memory);
}

interface IERC20 {
    function transfer(address to, uint256 value) external returns (bool);
    function approve(address spender, uint256 value) external returns (bool);
    function transferFrom(address from, address to, uint256 value) external returns (bool);
}


contract TwoBearsBots {

    struct ListID{
        uint256 time; // время создания бота / время частичного исполнения ордера
        uint256 next; // указатель на следующий id
        uint256 prev; // указатель на предыдущий id
    }

    struct BotID{
        uint256 id_sell; // ID ордера продажи                                                // ID ордера
        uint256 id_buy; // ID ордера покупки                                                 // 0
        uint256 value_sell; // количество продажи                                            // Количество
        uint256 value_buy; // количество покупки                                             // Увеличение количества
        uint256 price; // цена исполнения                                                    // Цена
        uint256 price_step; // ценовой шаг (изменение цены после каждого успешно выполненого ордера). Зависит от типа ордера         // Ценовой шаг
        uint256 price_up_limit; // верхний предел цены при котором бот прекращает работу     // Предел цены
        uint256 price_down_limit; // нижний предел цены при котором бот прекращает работу    // 0
        uint256 paid_for_gas; // было заплачено за газ в нативной монете
        uint256 gave_1; // было отдано первого токена                                        // отдано
        uint256 received_2; // было получено второго токена                                  // получено
        uint256 commission_2; // биржевая комиссия во втором токене                          // комиссия
        uint256 gave_2; // было отдано второго токена                                        // 0
        uint256 received_1; // было получено первого токена                                  // 0
        uint256 commission_1; // биржевая комиссия в первом токене                           // 0
        address token_in; // токен который отдает владелец                                   // токена который отдает владелец
        address token_out; // токен который получает владелец                                // токена который получает владелец
        address owner; // владелец бота                                                      // владелец бота
        address oracle; // оракул что зафиксировал ошибку бота. Владелец бота должен оплатить работу оракула при снятии блокировки
        uint8 bot_type; // тип бота. 1 - распродажа, 2 - закупка, 3 - сеточная торговля      // тип бота
        uint8 bot_status; // статус бота. 100 - Активен                                      // статус бота
    }

    struct DataOracle{ // структура возврата данных для оракула, по запрошенному ордеру
        uint256 price_1; // первая цена для которой должен быть осуществен поиск позиции
        uint256 price_2; // вторая цена для которой должен быть осуществен поиск позиции
        address token_in_1; // Адрес первого входящего токена
        address token_out_1; // Адрес первого выходящего токена
        address token_in_2; // Адрес второго входящего токена
        address token_out_2; // Адрес второго выходящего токена
        uint8 bot_status; // статус бота. 100 - Активен. При других статусах оракул должен игнорировать ордера данного бота, пока владелец бота не устранит неисправность и не изменит статус на 100
    }

    uint256 public id; // уникальный идентификатор бота
    mapping(uint256 => uint256) private ids; // id_ордера => id_бота
    mapping(address => mapping(uint256 => ListID)) private bots; // список всех ботов по владельцам
    mapping(uint256 => BotID) private id_bots; // все созданные схемы ботов
    mapping(address => bool) private oracles; // доверенные оракулы

    address public owner = 0xeBE894814554c8382EA6a24CcDdf1527407A24f6; // Владелец
    address public constant contractDeposits = 0x01C81c93f38F42497b4ceBfA23eeb03f7ccFA8C7; // Контракт с депозитами
    address public constant contractOrders = 0x11d5DB9473A6E017Ba4D182987bC5aB198C04A15; // Контракт с книгами ордеров
    address public constant contractBotsHelp = 0x6F8A583c11615C7CF713A76e79131FDF8761C3fE; // Вспомогательный контракт ботов

    event CreateBot(uint indexed ID);
    event DeleteBot(uint indexed ID);
    event AddOracle(address indexed oracle);
    event DeleteOracle(address indexed oracle);

    modifier onlyOwner() {
        require(msg.sender == owner, "Only owner can call this");
        _;
    }

    modifier onlyOracle() {
        require(oracles[msg.sender] == true, "Only oracle can call this");
        _;
    }

    // Обработаем функции получения нативной монеты и любых токенов ERC223

    receive() external payable {} // принимаем нативную монету

    function tokenReceived(address _from, uint _value, bytes memory _data) public returns (bytes4) { // принимаем токены ERC223
        return this.tokenReceived.selector; // возвращаем селектор этой функции
    }

    // Работа с ботами

    function createBotSellBuy(address _token_in, address _token_out, uint _value, uint _value_inc, uint _price, uint _price_step, uint _price_limit, uint _order_position) external { // создание бота распродажи / закупа
        // _value - объем токена с наименьшим приоритетом
        // _price - цена в токене с максимальным приоритетом

        BotID memory _bot;
        _bot.value_sell = _value; // Количество
        _bot.value_buy = _value_inc; // Увеличение количества
        _bot.price = _price; // Цена
        _bot.price_step = _price_step; // Ценовой шаг
        _bot.price_up_limit = _price_limit; // Предел цены
        _bot.token_in = _token_in; // токен который отдает владелец
        _bot.token_out = _token_out; // токен который получает владелец
        _bot.owner = msg.sender; // владелец бота

        uint256 _value_in;
        uint256 _value_out;

        (_bot.bot_status, _bot.bot_type, _value_in, _value_out) = IContractBotsHelp(contractBotsHelp).checkCreateBotSellBuy(msg.sender, _token_in, _token_out, _value, _value_inc, _price, _price_step, _price_limit);
        require(_bot.bot_status == 100); // Проверка создания бота должна быть успешна

        // Создаем торгового бота с выставлением первого ордера
        _bot.id_sell = createOrderBot(msg.sender, _token_in, _value_in, _token_out, _value_out, _order_position);

        ++id; // новый ID для создаваемого бота
        uint _id = id;
        id_bots[_id] = _bot; // сохраняем схему бота
        ids[_bot.id_sell] = _id; // привязываем открытый ордер к боту
        add_ID_bot(msg.sender, _id); // добавление нового бота в список владельца
        
        emit CreateBot(_id);

    }

    function createBotNetTrade(address _token_in, address _token_out, uint _value_sell, uint _value_buy, uint _price, uint _price_step, uint _price_up_limit, uint _price_down_limit, uint _order_position_sell, uint _order_position_buy) external { // создание бота сеточной торговли
        // _value_sell и _value_buy - объем токена с наименьшим приоритетом
        // _price - цена в токене с максимальным приоритетом
        // _token_in - будет установлен токен с минимальным приоритетом (сперва идет ордер продажи, а затем ордер покупки)

        BotID memory _bot;

        uint[] memory _values = new uint[](2); // получаем токена с макс. приоритером при продаже, отдаем токен с макс. приоритером при покупке
        (_bot.bot_status, _values[0], _values[1]) = IContractBotsHelp(contractBotsHelp).checkCreateBotNetTrade(msg.sender, _token_in, _token_out, _value_sell, _value_buy, _price, _price_step, _price_up_limit, _price_down_limit);
        if(_bot.bot_status == 101){ // проверка создания бота - успешна, но входящий и выходящий токена нужно поменять местами, так как сперва мы будем создавать ордер продажи, а затем ордер покупки
            (_token_in, _token_out) = (_token_out, _token_in); // входящий и выходящий токены меняем местами
            _bot.bot_status = 100;
        }
        require(_bot.bot_status == 100); // Проверка создания бота должна быть успешна

        // Заполняем схему бота
        _bot.value_sell = _value_sell; // количество продажи
        _bot.value_buy = _value_buy; // количество покупки
        _bot.price = _price; // промежуточная цена (между ордером исполнения и ордером продажи)
        _bot.price_step = _price_step; // ценовой шаг 
        _bot.price_up_limit = _price_up_limit; // верхний предел цены при котором бот прекращает работу
        _bot.price_down_limit = _price_down_limit; // нижний предел цены при котором бот прекращает работу
        _bot.token_in = _token_in; // токен который отдает владелец
        _bot.token_out = _token_out; // токен который получает владелец
        _bot.owner = msg.sender; // владелец бота
        _bot.bot_type = 3; // тип бота. 3 - сеточная торговля 

        // Создаем торгового бота с выставлением ордеров
        ++id; // новый ID для создаваемого бота
        uint _id = id;

        if(_values[0] > 0){ // необходимо создать ордер продажи
            _bot.id_sell = createOrderBot(msg.sender, _bot.token_in, _value_sell, _bot.token_out, _values[0], _order_position_sell);
            ids[_bot.id_sell] = _id; // привязываем открытый ордер продажи к боту
        }

        if(_values[1] > 0){ // необходимо создать ордер покупки
            _bot.id_buy = createOrderBot(msg.sender, _bot.token_out, _values[1], _bot.token_in, _value_buy, _order_position_buy);
            ids[_bot.id_buy] = _id; // привязываем открытый ордер покупки к боту
        }

        id_bots[_id] = _bot; // сохраняем схему бота
        add_ID_bot(msg.sender, _id); // добавление нового бота в список владельца
        
        emit CreateBot(_id);
    }

    // Вспомогательные функции ========================================
    function createOrderBot(address _owner, address _token_in, uint _value_in, address _token_out, uint _value_out, uint _order_position) private returns (uint256){ // создание ордера от имени бота
        uint _id_ord = IContractDeposits(contractDeposits).createOrderBot(_owner, _token_in, _value_in, _token_out, _value_out, _order_position);
        return _id_ord;
    }

    function getTypeAndValue(address _token_in, address _token_out, uint _value, uint _price) private view returns (uint256) // вернуть объем токена с наивысшим приоритетом
    {
        uint256 _value_max_priority;
        (, _value_max_priority) = IContractDeposits(contractDeposits).getTypeAndValue(_token_in, _token_out, _value, _price);
        return (_value_max_priority);
    }

    function getTypeAndPriceOrder(address _token_in, uint _value_in, address _token_out, uint _value_out) private view returns (uint256) // вернуть цену ордера
    {
        uint256 _price;
        (, _price) = IContractDeposits(contractDeposits).getTypeAndPriceOrder(_token_in, _value_in, _token_out, _value_out);
        return (_price);
    }

    function payTheOracle(uint _id_bot, address _owner, address _oracle, uint _gasUsed) private { // оплатить работу оракула
        uint _value = IContractDeposits(contractDeposits).payTheOracle(_owner, _oracle, _gasUsed); // возвращаем сколько по факту получил оракул
        id_bots[_id_bot].paid_for_gas += _value; // обновляем статистику бота по газовым затратам
    }

    function transfer(address _token, address _recipient, uint _value) private { // перевод токена с баланса этого контракта 
        uint256 _size;
        assembly { _size := extcodesize(_recipient) } // проверяем является ли адрес получателя контрактом
        if(_size > 0){ // если получатель это контракт
            IERC20(_token).approve(address(this), _value); //Даем разрешение нашему контракту тратить токен на своем балансе через TransferFrom
            IERC20(_token).transferFrom(address(this), _recipient, _value);
        }
        else{ // получатель это пользователь (EOA)
            IERC20(_token).transfer(_recipient, _value);
        }
    }
    // =================================================================


    function add_ID_bot(address _owner, uint _id_bot) private { // добавление нового бота в список владельца
        uint _id_last = bots[_owner][0].prev; // получаем последнего созданного бота владельца
        bots[_owner][_id_last].next = _id_bot;
        bots[_owner][0].prev = _id_bot;
        bots[_owner][_id_bot] = ListID(block.timestamp, 0, _id_last);
    }

    function del_ID_bot(address _owner, uint _id_bot) private { // удаление бота из списка владельца
        uint _id_next = bots[_owner][_id_bot].next;
        uint _id_prev = bots[_owner][_id_bot].prev;
        bots[_owner][_id_prev].next = _id_next;
        bots[_owner][_id_next].prev = _id_prev;
        delete bots[_owner][_id_bot];
    }


    function getBotByID(uint _id_bot) public view returns (BotID memory) // Возвращаем бота по ID
    {   
        return (id_bots[_id_bot]);
    }


    function getAllBotsOwner(address _owner, uint _id_bot, uint _amount) public view returns (uint [] memory) // Возвращаем указанное количество ботов пользователя, со следующего ордера от стартового ID
    {   // если _id_bot = 0, тогда информация по ботам формируются с самого первого бота
        /* возвращаемый массив 3 - тип:             возвращаемый массив 1,2 - тип:
            [
                ID_бота,                            ID_бота,
                время_создания,                     время_создания,
                тип бота,                           тип бота,
                адрес_токена_1,                     адрес_токена_1,
                заблокированное_количество_1,       заблокированное_количество_1,
                адрес_токена_2,                     адрес_токена_2,
                заблокированное_количество_2,       заблокированное_количество_2, 
                отдано_1_токена,                    отдано,
                получено_2_токена,                  получено,
                отдано_2_токена,                    0,
                получено_1_токена,                  0,
                адрес_отдаваемого_токена,           адрес_отдаваемого_токена,
                адрес_получаемого_токена_2,         адрес_получаемого_токена,
                статус_бота,                        статус_бота,
            ...]
        */

        _id_bot = bots[_owner][_id_bot].next;

        if(_id_bot == 0) return (new uint[](1)); // если открытых ботов еще не существует, либо если это первый бот в списке, который уже был обработан, вернем [0]

        uint _index;
        uint[] memory result = new uint[](_amount * 14); // возвращаемый массив

        for(uint i; i < _amount; i++){
            if(_id_bot == 0) break;
            result[_index++] = _id_bot;
            result[_index++] = bots[_owner][_id_bot].time;
            result[_index++] = id_bots[_id_bot].bot_type;
            uint[] memory _lock_tokens = IContractOrders(contractOrders).getLockedTokensForOracle(id_bots[_id_bot].id_sell, id_bots[_id_bot].id_buy); // [токен1, количество1, токен2, количество2]
            result[_index++] = _lock_tokens[0];
            result[_index++] = _lock_tokens[1];
            result[_index++] = _lock_tokens[2];
            result[_index++] = _lock_tokens[3];
            result[_index++] = id_bots[_id_bot].gave_1;
            result[_index++] = id_bots[_id_bot].received_2;
            result[_index++] = id_bots[_id_bot].gave_2;
            result[_index++] = id_bots[_id_bot].received_1;
            result[_index++] = uint256(uint160(id_bots[_id_bot].token_in));
            result[_index++] = uint256(uint160(id_bots[_id_bot].token_out));
            result[_index++] = id_bots[_id_bot].bot_status;
            _id_bot = bots[_owner][_id_bot].next;
        }
        return (result);
    }


    // Функция проверки ордера (для получения данных оракулом)
    function checkOrderByOracle(uint _id_order) public view returns (DataOracle memory) { // Возвращаем необходимые данные по боту для поиска ценовых позиций в книгах ордеров.
        DataOracle memory _data;
        uint _id_bot = ids[_id_order]; // ID бота которому принадлежит указанный ID ордера
        _data.bot_status = id_bots[_id_bot].bot_status; // Определяем текущий статус бота
        if(_data.bot_status != 100) return (_data); // если бот неактивен или не существует

        uint[] memory _order_data = IContractOrders(contractOrders).getOrderDataForOracle(_id_order); // [статус, тип_ордера, осталось_отдать, осталось_получить, отдал, получил, комиссия]
        if(_order_data[0] == 7){ // проверяем статус ордера. Ордер полностью исполнен
            // определим цену следующего ордера согласно схеме бота (для сеточного бота это средняя цена между следующей продажей и покупкой)
            uint _price_temp = (_order_data[1] == 1) ? id_bots[_id_bot].price + id_bots[_id_bot].price_step : id_bots[_id_bot].price - id_bots[_id_bot].price_step;
            uint _value_max_priority; // объем токена с максимальным приоритетом            
            _data.token_in_1 = id_bots[_id_bot].token_in; // входящий токен из схемы бота
            _data.token_out_1 = id_bots[_id_bot].token_out; // выходящий токен из схемы бота

            if(id_bots[_id_bot].bot_type == 3){ // бот сеточной торговли
                (_data.token_in_2, _data.token_out_2) = (_data.token_out_1, _data.token_in_1); // Инвертируем токены (для покупки)
                if(_order_data[1] == 1){ // данный ордер - продажа
                    // следующий ордер продажи
                    _value_max_priority = getTypeAndValue(_data.token_in_1, _data.token_out_1, id_bots[_id_bot].value_sell, _price_temp + id_bots[_id_bot].price_step);
                    _data.price_1 = getTypeAndPriceOrder(_data.token_in_1, id_bots[_id_bot].value_sell, _data.token_out_1, _value_max_priority);
                    // следующий ордер покупки
                    uint[] memory _order_data2 = IContractOrders(contractOrders).getOrderDataForOracle(id_bots[_id_bot].id_buy); // [статус, тип_ордера, осталось_отдать, осталось_получить, отдал, получил, комиссия]
                    uint _val = ((_order_data2[0] == 1) || (_order_data2[0] == 6) || (_order_data2[0] == 9)) ? _order_data2[3] : id_bots[_id_bot].value_buy; // определяем объем покупки. Если ордер покупки был со статусом 1, 6 или 9, тогда на покупку идет оставщийся, недокупленный объем
                    _value_max_priority = getTypeAndValue(_data.token_in_2, _data.token_out_2, _val, _price_temp - id_bots[_id_bot].price_step);
                    _data.price_2 = getTypeAndPriceOrder(_data.token_in_2, _value_max_priority, _data.token_out_2, _val);
                }
                else{ // данный ордер - покупка
                    // следующий ордер покупки
                    _value_max_priority = getTypeAndValue(_data.token_in_2, _data.token_out_2, id_bots[_id_bot].value_buy, _price_temp - id_bots[_id_bot].price_step);
                    _data.price_2 = getTypeAndPriceOrder(_data.token_in_2, _value_max_priority, _data.token_out_2, id_bots[_id_bot].value_buy);
                    // следующий ордер продажи
                    uint[] memory _order_data2 = IContractOrders(contractOrders).getOrderDataForOracle(id_bots[_id_bot].id_sell); // [статус, тип_ордера, осталось_отдать, осталось_получить, отдал, получил, комиссия]
                    uint _val = ((_order_data2[0] == 1) || (_order_data2[0] == 6) || (_order_data2[0] == 9)) ? _order_data2[2] : id_bots[_id_bot].value_sell; // определяем объем продажи. Если ордер продажи был со статусом 1, 6 или 9, тогда на продажу идет оставщийся, непроданный объем
                    _value_max_priority = getTypeAndValue(_data.token_in_1, _data.token_out_1, _val, _price_temp + id_bots[_id_bot].price_step);
                    _data.price_1 = getTypeAndPriceOrder(_data.token_in_1, _val, _data.token_out_1, _value_max_priority);
                }
            }
            else{ // бот распродажи или закупа
                uint _value = id_bots[_id_bot].value_sell + id_bots[_id_bot].value_buy; // объем токена в схеме (сколько мы обмениваем)
                _value_max_priority = getTypeAndValue(_data.token_in_1, _data.token_out_1, _value, _price_temp);
                (_value, _value_max_priority) = (_order_data[1] == 1) ? (_value, _value_max_priority) : (_value_max_priority, _value);
                _data.price_1 = getTypeAndPriceOrder(_data.token_in_1, _value, _data.token_out_1, _value_max_priority);
            }

        } else if (_order_data[0] == 9) { // Ордер исполнен (достигнут максимальный лимит исполняемых ордеров)
            if(id_bots[_id_bot].id_sell == _id_order){ // если это бот распродажи, закупа, либо продажа у сеточного бота
                _data.token_in_1 = id_bots[_id_bot].token_in;
                _data.token_out_1 = id_bots[_id_bot].token_out;
            }
            else{ // это покупка у сеточного бота
                _data.token_in_1 = id_bots[_id_bot].token_out;
                _data.token_out_1 = id_bots[_id_bot].token_in;
            }
            _data.price_1 = getTypeAndPriceOrder(_data.token_in_1, _order_data[2], _data.token_out_1, _order_data[3]);         
        }
        return (_data);
    }


    function workBot(uint _id_order, uint _order_position_1, uint _order_position_2) external onlyOracle { // основная функция оракула (двигатель ботов)
        uint _gasUsed = gasleft(); // начинаем расчет газа для оракула
        uint _id_bot = ids[_id_order]; // ID бота которому принадлежит указанный ID ордера
        require(id_bots[_id_bot].bot_status == 100); // статус бота должен быть 100 - активен

        address _owner = id_bots[_id_bot].owner; // Владелец бота
        uint[] memory _order_data = IContractOrders(contractOrders).getOrderDataForOracle(_id_order); // [статус, тип_ордера, осталось_отдать, осталось_получить, отдал, получил, комиссия]
        if(_order_data[0] == 7){ // проверяем статус ордера. Ордер полностью исполнен
            // определим цену следующего ордера согласно схеме бота (для сеточного бота это средняя цена между следующей продажей и покупкой)
            uint _price_temp = (_order_data[1] == 1) ? id_bots[_id_bot].price + id_bots[_id_bot].price_step : id_bots[_id_bot].price - id_bots[_id_bot].price_step;
            DataOracle memory _data;           
            _data.token_in_1 = id_bots[_id_bot].token_in; // входящий токен из схемы бота
            _data.token_out_1 = id_bots[_id_bot].token_out; // выходящий токен из схемы бота

            if(id_bots[_id_bot].bot_type == 3){ // бот сеточной торговли
                // _data.price_2 - ID второго ордера из схемы ботов
                _data.price_2 = (id_bots[_id_bot].id_sell == _id_order) ? id_bots[_id_bot].id_buy : id_bots[_id_bot].id_sell;
                // получим данные второго ордера
                uint[] memory _order_data_2 = IContractOrders(contractOrders).getOrderDataForOracle(_data.price_2); // [статус, тип_ордера, осталось_отдать, осталось_получить, отдал, получил, комиссия]
                uint[] memory _result; // [отдаем, получаем, отдаем, получаем] - первые 2 параметра это ордер продажи, вторые 2 параметра это ордер покупки
                uint[] memory _param = new uint[](6); // [количество_продажи, количество_покупки, цена, шаг, верхний_предел_цены, нижний_предел_цены]
                _param[0] = id_bots[_id_bot].value_sell;
                _param[1] = id_bots[_id_bot].value_buy;
                _param[2] = _price_temp;
                _param[3] = id_bots[_id_bot].price_step;
                _param[4] = id_bots[_id_bot].price_up_limit;
                _param[5] = id_bots[_id_bot].price_down_limit;

                (_data.bot_status, _result) = IContractBotsHelp(contractBotsHelp).checkSchemeBotNetTrade(_owner, _data.token_in_1, _data.token_out_1, _param, _order_data, _order_data_2);
                if(_data.bot_status > 0){ // возникла ошибка при проверки апрува и баланса владельца по входящему токену или по обернутой нативной монете
                    id_bots[_id_bot].oracle = msg.sender; // оракул
                    id_bots[_id_bot].bot_status = _data.bot_status; // статус бота принимает код ошибки
                    return;
                }

                // Удаляем ордера и отвязываем их от ботов
                deleteOrder(_id_order, _order_data); // удаляем ордер со статусом 7
                if(_data.price_2 > 0){ // если второй ордер существует
                    deleteOrder(_data.price_2, _order_data_2); // удаляем второй ордер с отвязкой его от бота
                }
                id_bots[_id_bot].price = _price_temp; // текущая цена

                // Создаем новые ордера согласно схеме бота
                //uint[] memory _result; // [отдаем, получаем, отдаем, получаем] - первые 2 параметра это ордер продажи, вторые 2 параметра это ордер покупки
                if(_result[0] > 0){ // нужно создавать ордер продажи
                    uint _ord = _order_position_1; // позиция ордера продажи
                    _ord = createOrderBot(_owner, _data.token_in_1, _result[0], _data.token_out_1, _result[1], _ord);
                    ids[_ord] = _id_bot; // привязываем открытый ордер продажи к боту
                    id_bots[_id_bot].id_sell = _ord;
                }
                else{ // ордер продажи создавать не нужно, он вышел за верхний предел
                    id_bots[_id_bot].id_sell = 0;
                }

                if(_result[2] > 0){ // нужно создавать ордер покупки
                    uint _ord = _order_position_2; // позиция ордера покупки
                    _ord = createOrderBot(_owner, _data.token_out_1, _result[2], _data.token_in_1, _result[3], _ord);
                    ids[_ord] = _id_bot; // привязываем открытый ордер покупки к боту
                    id_bots[_id_bot].id_buy = _ord;
                }
                else{ // ордер продажи создавать не нужно, он вышел за верхний предел
                    id_bots[_id_bot].id_buy = 0;
                }
            }
            else{ // бот распродажи или закупа
                // _data.price_1 - количество входящего токена. _data.price_2 - количество выходящего токена
                uint _value = id_bots[_id_bot].value_sell + id_bots[_id_bot].value_buy; // объем токена в схеме (сколько мы обмениваем)
                (_data.bot_status, _data.price_1, _data.price_2) = IContractBotsHelp(contractBotsHelp).checkSchemeBotSellBuy(_owner, _data.token_in_1, _data.token_out_1, _value, _price_temp, id_bots[_id_bot].price_up_limit);
                if(_data.bot_status == 100){ // нужно создавать новый ордер. Схема активна
                    deleteOrder(_id_order, _order_data); // удаляем ордер с отвязкой его от бота
                    id_bots[_id_bot].value_sell = _value; // текущее количество токена
                    id_bots[_id_bot].price = _price_temp; // текущая цена
                    // создадим новый ордер схемы. _value - ID ордера
                    _value = createOrderBot(_owner, _data.token_in_1, _data.price_1, _data.token_out_1, _data.price_2, _order_position_1);
                    ids[_value] = _id_bot; // привязываем открытый ордер продажи к боту
                    id_bots[_id_bot].id_sell = _value;
                } else if (_data.bot_status == 200) { // Схема бота полностью отработала
                    deleteOrder(_id_order, _order_data); // удаляем ордер с отвязкой его от бота
                    id_bots[_id_bot].id_sell = 0;
                    id_bots[_id_bot].bot_status = 200; // статус бота 200 - бот полностью завершил схему
                } else{ // возникла ошибка в работе схемы бота
                    id_bots[_id_bot].oracle = msg.sender; // оракул
                    id_bots[_id_bot].bot_status = _data.bot_status; // статус бота принимает код ошибки
                    return;
                }
            }

        } else if (_order_data[0] == 9) { // Ордер исполнен (достигнут максимальный лимит исполняемых ордеров)
            uint8 _err; // Для возврата кода ошибки;
            (address _token_in, address _token_out) = (id_bots[_id_bot].id_sell == _id_order) ? (id_bots[_id_bot].token_in, id_bots[_id_bot].token_out) : (id_bots[_id_bot].token_out, id_bots[_id_bot].token_in); // входящий токен обрабатываемого ордера
            _err = IContractBotsHelp(contractBotsHelp).checkApproveAndBalance(_owner, _token_in, _order_data[2], _order_data[2]);
            if(_err > 0){ // возникла ошибка при проверки апрува и баланса владельца по входящему токену или по обернутой нативной монете
                id_bots[_id_bot].oracle = msg.sender; // оракул - создатель транзакции
                id_bots[_id_bot].bot_status = _err; // статус бота принимает код ошибки
                return;
            }
            deleteOrder(_id_order, _order_data); // удаляем ордер с отвязкой его от бота

            uint _new_order = createOrderBot(_owner, _token_in, _order_data[2], _token_out, _order_data[3], _order_position_1);
            ids[_new_order] = _id_bot; // привязываем открытый ордер продажи к боту

            if(id_bots[_id_bot].id_sell == _id_order){ // если это бот распродажи, закупа, либо продажа у сеточного бота
                id_bots[_id_bot].id_sell = _new_order;
            }
            else{ // это покупка у сеточного бота
                id_bots[_id_bot].id_buy = _new_order;
            }
        } else{ // оракул пытается обработать ордер без статуса 7 или 9. Газ такому оракулу не компенсируем
            return;
        }

        // Оплачиваем работу оракула
        payTheOracle(_id_bot, _owner, msg.sender, _gasUsed - gasleft()); // оплата работы оракула
    }


    function deleteOrder(uint _id_order, uint[] memory _order_data) private { // выплачиваем все по ордеру, обновляем статистику бота, удаляем ордер и отвязываем его от бота
        // _order_data - массив данных по ордеру [статус, тип_ордера, осталось_отдать, осталось_получить, отдал, получил, комиссия]
        uint _id_bot = ids[_id_order]; // ID бота которому принадлежит указанный ID ордера
        address _owner = id_bots[_id_bot].owner; // Владелец бота
        address _token_in; // входящий токен ордера
        address _token_out; // выходящий токен ордера

        if(id_bots[_id_bot].id_sell == _id_order){ // если это бот распродажи, закупа, либо продажа у сеточного бота
            (_token_in, _token_out) = (id_bots[_id_bot].token_in, id_bots[_id_bot].token_out);
            if(_order_data[5] > 0){ // если в ордере был обмен (частичный или полный обмен)
                id_bots[_id_bot].gave_1 += _order_data[4]; // отдал при обмене - первого токена
                id_bots[_id_bot].received_2 += _order_data[5]; // получил при обмене - второго токена
                if(_order_data[6] > 0) id_bots[_id_bot].commission_2 += _order_data[6]; // биржевая комиссия за исполнение ордера во втором токене
            }
        }
        else{ // это покупка у сеточного бота
            (_token_in, _token_out) = (id_bots[_id_bot].token_out, id_bots[_id_bot].token_in);
            if(_order_data[5] > 0){ // если в ордере был обмен (частичный или полный обмен)
                id_bots[_id_bot].gave_2 += _order_data[4]; // отдал при обмене - второго токена
                id_bots[_id_bot].received_1 += _order_data[5]; // получил при обмене - первого токена
                if(_order_data[6] > 0) id_bots[_id_bot].commission_1 += _order_data[6]; // биржевая комиссия за исполнение ордера в первом токене
            }
        }

        // статистика бота обновлена. Делаем возвраты токенов владельцу
        if(_order_data[5] > 0){ // если в ордере был обмен (частичный или полный обмен), то был получен второй токен
            transfer(_token_out, _owner, _order_data[5]); // выплачиваем владельцу бота то что было получено при обмене
        }

        uint[] memory _arr = new uint[](1); // создаем массив из 1 элемента

        if(_order_data[2] > 0){ // если есть необмененый остаток, то отменяем ордер и выплачиваем его
            _arr[0] = _id_order; // записываем в него ID ордера
            IContractOrders(contractOrders).cancelOrders(_arr); // отменяем ордер для возврата средств на адрес этого контракта
            transfer(_token_in, _owner, _order_data[2]); // выплачиваем владельцу бота то что не было обменяно
        }

        // удаляем отработанный / отмененый ордер. Данный ордер должен быть убран из книги закрытых ордеров
        _arr[0] = _id_order; // записываем в массив ID ордера
        IContractOrders(contractOrders).deleteCloseOrders(_arr);

        delete ids[_id_order]; // разрушаем связь между ордером и ботом
    }


    function restoreBot(uint _id_bot) external // Восстановление бота. Когда пользователь устранит неисправность бота, он должен вызвать эту функцию чтобы вернуть боту статус 100
    {
        uint8 _stat = id_bots[_id_bot].bot_status; // получим статус бота
        require(_stat > 0); // бот должен существовать
        require((_stat != 100) && (_stat != 200)); // Статус бота не должен быть 100 - активен и 200 - бот завершил схему
        require(msg.sender == id_bots[_id_bot].owner); // только владелец бота может разблокировать бота

        payTheOracle(_id_bot, msg.sender, id_bots[_id_bot].oracle, 0); // оплачиваем газ оракула за обнаружение неисправности бота
        id_bots[_id_bot].bot_status = 100; // возобновляем работу бота
    }


    function deleteBot(uint _id_bot) external // Удаление бота
    {
        // перед удалением бота автоматически закрываются все ордера и все токены возвращаются владельцу
        require(bots[msg.sender][_id_bot].time > 0); // удаляемый бот должен принадлежать владельцу
        uint8 _status = id_bots[_id_bot].bot_status; // получим статус бота

        if((_status != 100) && (_status != 200)){ // бот находится в состоянии ошибки
            payTheOracle(_id_bot, msg.sender, id_bots[_id_bot].oracle, 0); // оплачиваем газ оракула за обнаружение неисправности бота
        }

        if(_status != 200){ // текущая схема активна, либо бот в состоянии ошибки
            uint _id_sell = id_bots[_id_bot].id_sell;
            uint _id_buy = id_bots[_id_bot].id_buy;
            if(_id_sell > 0){ // Нужно удалять ордер
                uint[] memory _order_data = IContractOrders(contractOrders).getOrderDataForOracle(_id_sell); // [статус, тип_ордера, осталось_отдать, осталось_получить, отдал, получил, комиссия]
                deleteOrder(_id_sell, _order_data); // удаляем ордер с отвязкой его от бота
            }
            if(_id_buy > 0){ // Нужно удалять ордер
                uint[] memory _order_data = IContractOrders(contractOrders).getOrderDataForOracle(_id_buy); // [статус, тип_ордера, осталось_отдать, осталось_получить, отдал, получил, комиссия]
                deleteOrder(_id_buy, _order_data); // удаляем ордер с отвязкой его от бота
            }
        }

        del_ID_bot(msg.sender, _id_bot); // удаление бота из списка владельца
        delete id_bots[_id_bot]; // удаление схемы бота
        
        emit DeleteBot(_id_bot);
    }


    // ФУНКЦИИ ВЛАДЕЛЬЦА

    function addOracle(address _oracle) external onlyOwner // добавить доверенного оракула
    {
        oracles[_oracle] = true;
        emit AddOracle(_oracle);
    }

    function deleteOracle(address _oracle) external onlyOwner // удалить доверенного оракула
    {
        oracles[_oracle] = false;
        emit DeleteOracle(_oracle);
    }

    function isOracle(address _oracle) public view returns (bool) // проверяем является ли адрес оракулом
    {
        return (oracles[_oracle]);
    }

}
        

Contract ABI

[{"type":"event","name":"AddOracle","inputs":[{"type":"address","name":"oracle","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"CreateBot","inputs":[{"type":"uint256","name":"ID","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"DeleteBot","inputs":[{"type":"uint256","name":"ID","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"DeleteOracle","inputs":[{"type":"address","name":"oracle","internalType":"address","indexed":true}],"anonymous":false},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"addOracle","inputs":[{"type":"address","name":"_oracle","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct TwoBearsBots.DataOracle","components":[{"type":"uint256","name":"price_1","internalType":"uint256"},{"type":"uint256","name":"price_2","internalType":"uint256"},{"type":"address","name":"token_in_1","internalType":"address"},{"type":"address","name":"token_out_1","internalType":"address"},{"type":"address","name":"token_in_2","internalType":"address"},{"type":"address","name":"token_out_2","internalType":"address"},{"type":"uint8","name":"bot_status","internalType":"uint8"}]}],"name":"checkOrderByOracle","inputs":[{"type":"uint256","name":"_id_order","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"contractBotsHelp","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"contractDeposits","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"contractOrders","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"createBotNetTrade","inputs":[{"type":"address","name":"_token_in","internalType":"address"},{"type":"address","name":"_token_out","internalType":"address"},{"type":"uint256","name":"_value_sell","internalType":"uint256"},{"type":"uint256","name":"_value_buy","internalType":"uint256"},{"type":"uint256","name":"_price","internalType":"uint256"},{"type":"uint256","name":"_price_step","internalType":"uint256"},{"type":"uint256","name":"_price_up_limit","internalType":"uint256"},{"type":"uint256","name":"_price_down_limit","internalType":"uint256"},{"type":"uint256","name":"_order_position_sell","internalType":"uint256"},{"type":"uint256","name":"_order_position_buy","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"createBotSellBuy","inputs":[{"type":"address","name":"_token_in","internalType":"address"},{"type":"address","name":"_token_out","internalType":"address"},{"type":"uint256","name":"_value","internalType":"uint256"},{"type":"uint256","name":"_value_inc","internalType":"uint256"},{"type":"uint256","name":"_price","internalType":"uint256"},{"type":"uint256","name":"_price_step","internalType":"uint256"},{"type":"uint256","name":"_price_limit","internalType":"uint256"},{"type":"uint256","name":"_order_position","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"deleteBot","inputs":[{"type":"uint256","name":"_id_bot","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"deleteOracle","inputs":[{"type":"address","name":"_oracle","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256[]","name":"","internalType":"uint256[]"}],"name":"getAllBotsOwner","inputs":[{"type":"address","name":"_owner","internalType":"address"},{"type":"uint256","name":"_id_bot","internalType":"uint256"},{"type":"uint256","name":"_amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct TwoBearsBots.BotID","components":[{"type":"uint256","name":"id_sell","internalType":"uint256"},{"type":"uint256","name":"id_buy","internalType":"uint256"},{"type":"uint256","name":"value_sell","internalType":"uint256"},{"type":"uint256","name":"value_buy","internalType":"uint256"},{"type":"uint256","name":"price","internalType":"uint256"},{"type":"uint256","name":"price_step","internalType":"uint256"},{"type":"uint256","name":"price_up_limit","internalType":"uint256"},{"type":"uint256","name":"price_down_limit","internalType":"uint256"},{"type":"uint256","name":"paid_for_gas","internalType":"uint256"},{"type":"uint256","name":"gave_1","internalType":"uint256"},{"type":"uint256","name":"received_2","internalType":"uint256"},{"type":"uint256","name":"commission_2","internalType":"uint256"},{"type":"uint256","name":"gave_2","internalType":"uint256"},{"type":"uint256","name":"received_1","internalType":"uint256"},{"type":"uint256","name":"commission_1","internalType":"uint256"},{"type":"address","name":"token_in","internalType":"address"},{"type":"address","name":"token_out","internalType":"address"},{"type":"address","name":"owner","internalType":"address"},{"type":"address","name":"oracle","internalType":"address"},{"type":"uint8","name":"bot_type","internalType":"uint8"},{"type":"uint8","name":"bot_status","internalType":"uint8"}]}],"name":"getBotByID","inputs":[{"type":"uint256","name":"_id_bot","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"id","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isOracle","inputs":[{"type":"address","name":"_oracle","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"restoreBot","inputs":[{"type":"uint256","name":"_id_bot","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bytes4","name":"","internalType":"bytes4"}],"name":"tokenReceived","inputs":[{"type":"address","name":"_from","internalType":"address"},{"type":"uint256","name":"_value","internalType":"uint256"},{"type":"bytes","name":"_data","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"workBot","inputs":[{"type":"uint256","name":"_id_order","internalType":"uint256"},{"type":"uint256","name":"_order_position_1","internalType":"uint256"},{"type":"uint256","name":"_order_position_2","internalType":"uint256"}]},{"type":"receive","stateMutability":"payable"}]
              

Contract Creation Code

Verify & Publish
0x608060405273ebe894814554c8382ea6a24ccddf1527407a24f6600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555034801561006557600080fd5b50615cb180620000766000396000f3fe6080604052600436106101025760003560e01c80638da5cb5b11610095578063cada801411610064578063cada80141461033e578063caf4b41c1461037b578063df5dd1a5146103b8578063e06b4400146103e1578063e38d1a401461040c57610109565b80638da5cb5b14610282578063a97e5c93146102ad578063af640d0f146102ea578063c78f936f1461031557610109565b80632fd96ca9116100d15780632fd96ca9146101b657806330be1160146101df5780637bf02d6d146102085780638943ec021461024557610109565b80630147db0c1461010e5780630d711a9f14610139578063127e11971461016257806321c4227e1461018d57610109565b3661010957005b600080fd5b34801561011a57600080fd5b50610123610435565b6040516101309190614a65565b60405180910390f35b34801561014557600080fd5b50610160600480360381019061015b9190614ac0565b61044d565b005b34801561016e57600080fd5b5061017761057b565b6040516101849190614a65565b60405180910390f35b34801561019957600080fd5b506101b460048036038101906101af9190614b23565b610593565b005b3480156101c257600080fd5b506101dd60048036038101906101d89190614b76565b61151f565b005b3480156101eb57600080fd5b5061020660048036038101906102019190614c2c565b61198b565b005b34801561021457600080fd5b5061022f600480360381019061022a9190614d0b565b611f81565b60405161023c9190614e1c565b60405180910390f35b34801561025157600080fd5b5061026c60048036038101906102679190614f84565b612640565b604051610279919061502e565b60405180910390f35b34801561028e57600080fd5b50610297612653565b6040516102a49190614a65565b60405180910390f35b3480156102b957600080fd5b506102d460048036038101906102cf9190614ac0565b612679565b6040516102e19190615064565b60405180910390f35b3480156102f657600080fd5b506102ff6126cf565b60405161030c919061508e565b60405180910390f35b34801561032157600080fd5b5061033c600480360381019061033791906150a9565b6126d5565b005b34801561034a57600080fd5b50610365600480360381019061036091906150a9565b612ae7565b60405161037291906152b4565b60405180910390f35b34801561038757600080fd5b506103a2600480360381019061039d91906150a9565b612d3d565b6040516103af919061535e565b60405180910390f35b3480156103c457600080fd5b506103df60048036038101906103da9190614ac0565b613821565b005b3480156103ed57600080fd5b506103f661394f565b6040516104039190614a65565b60405180910390f35b34801561041857600080fd5b50610433600480360381019061042e91906150a9565b613967565b005b736f8a583c11615c7cf713a76e79131fdf8761c3fe81565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104dd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104d4906153d6565b60405180910390fd5b6000600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508073ffffffffffffffffffffffffffffffffffffffff167f8f0e1537186f631af722391ce4e08495881ee25f0d06ed39dd7e8db6ce25d3c860405160405180910390a250565b7301c81c93f38f42497b4cebfa23eeb03f7ccfa8c781565b60011515600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514610626576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161061d90615442565b60405180910390fd5b60005a905060006001600086815260200190815260200160002054905060646003600083815260200190815260200160002060120160159054906101000a900460ff1660ff161461067657600080fd5b60006003600083815260200190815260200160002060110160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060007311d5db9473a6e017ba4d182987bc5ab198c04a1573ffffffffffffffffffffffffffffffffffffffff16636da42a15886040518263ffffffff1660e01b8152600401610700919061508e565b600060405180830381865afa15801561071d573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610746919061553f565b905060078160008151811061075e5761075d615588565b5b60200260200101510361119557600060018260018151811061078357610782615588565b5b6020026020010151146107cd57600360008581526020019081526020016000206005015460036000868152602001908152602001600020600401546107c891906155e6565b610806565b60036000858152602001908152602001600020600501546003600086815260200190815260200160002060040154610805919061561a565b5b905061081061488e565b60036000868152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16816040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506003600086815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16816060019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600380600087815260200190815260200160002060120160149054906101000a900460ff1660ff1603610ed3578860036000878152602001908152602001600020600001541461095257600360008681526020019081526020016000206000015461096a565b60036000868152602001908152602001600020600101545b81602001818152505060007311d5db9473a6e017ba4d182987bc5ab198c04a1573ffffffffffffffffffffffffffffffffffffffff16636da42a1583602001516040518263ffffffff1660e01b81526004016109c6919061508e565b600060405180830381865afa1580156109e3573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610a0c919061553f565b905060606000600667ffffffffffffffff811115610a2d57610a2c614e59565b5b604051908082528060200260200182016040528015610a5b5781602001602082028036833780820191505090505b509050600360008981526020019081526020016000206002015481600081518110610a8957610a88615588565b5b602002602001018181525050600360008981526020019081526020016000206003015481600181518110610ac057610abf615588565b5b6020026020010181815250508481600281518110610ae157610ae0615588565b5b602002602001018181525050600360008981526020019081526020016000206005015481600381518110610b1857610b17615588565b5b602002602001018181525050600360008981526020019081526020016000206006015481600481518110610b4f57610b4e615588565b5b602002602001018181525050600360008981526020019081526020016000206007015481600581518110610b8657610b85615588565b5b602002602001018181525050736f8a583c11615c7cf713a76e79131fdf8761c3fe73ffffffffffffffffffffffffffffffffffffffff1663b10557348886604001518760600151858b896040518763ffffffff1660e01b8152600401610bf19695949392919061564e565b600060405180830381865afa158015610c0e573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610c3791906156f0565b8560c0018194508260ff1660ff16815250505060008460c0015160ff161115610cf05733600360008a815260200190815260200160002060120160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508360c00151600360008a815260200190815260200160002060120160156101000a81548160ff021916908360ff16021790555050505050505050505061151a565b610cfa8c87613aa5565b600084602001511115610d1657610d15846020015184613aa5565b5b84600360008a815260200190815260200160002060040181905550600082600081518110610d4757610d46615588565b5b60200260200101511115610de15760008b9050610da688866040015185600081518110610d7757610d76615588565b5b6020026020010151886060015187600181518110610d9857610d97615588565b5b6020026020010151866140c0565b905088600160008381526020019081526020016000208190555080600360008b81526020019081526020016000206000018190555050610dfe565b6000600360008a8152602001908152602001600020600001819055505b600082600281518110610e1457610e13615588565b5b60200260200101511115610eae5760008a9050610e7388866060015185600281518110610e4457610e43615588565b5b6020026020010151886040015187600381518110610e6557610e64615588565b5b6020026020010151866140c0565b905088600160008381526020019081526020016000208190555080600360008b81526020019081526020016000206001018190555050610ecb565b6000600360008a8152602001908152602001600020600101819055505b50505061118e565b600060036000878152602001908152602001600020600301546003600088815260200190815260200160002060020154610f0d919061561a565b9050736f8a583c11615c7cf713a76e79131fdf8761c3fe73ffffffffffffffffffffffffffffffffffffffff1663fe908a9c86846040015185606001518588600360008e8152602001908152602001600020600601546040518763ffffffff1660e01b8152600401610f849695949392919061574c565b606060405180830381865afa158015610fa1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc591906157ad565b8460c001856000018660200183815250838152508360ff1660ff1681525050505060648260c0015160ff160361108d57610fff8a85613aa5565b8060036000888152602001908152602001600020600201819055508260036000888152602001908152602001600020600401819055506110538583604001518460000151856060015186602001518e6140c0565b905085600160008381526020019081526020016000208190555080600360008881526020019081526020016000206000018190555061118c565b60c88260c0015160ff16036110f7576110a68a85613aa5565b6000600360008881526020019081526020016000206000018190555060c86003600088815260200190815260200160002060120160156101000a81548160ff021916908360ff16021790555061118b565b336003600088815260200190815260200160002060120160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508160c001516003600088815260200190815260200160002060120160156101000a81548160ff021916908360ff1602179055505050505050505061151a565b5b505b50506114fe565b6009816000815181106111ab576111aa615588565b5b6020026020010151036114f45760008060008960036000888152602001908152602001600020600001541461124d576003600087815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660036000888152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166112bc565b60036000878152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166003600088815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff165b91509150736f8a583c11615c7cf713a76e79131fdf8761c3fe73ffffffffffffffffffffffffffffffffffffffff1663ad148af486848760028151811061130657611305615588565b5b60200260200101518860028151811061132257611321615588565b5b60200260200101516040518563ffffffff1660e01b81526004016113499493929190615800565b602060405180830381865afa158015611366573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138a9190615845565b925060008360ff16111561142857336003600088815260200190815260200160002060120160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550826003600088815260200190815260200160002060120160156101000a81548160ff021916908360ff1602179055505050505050505061151a565b6114328a85613aa5565b600061147886848760028151811061144d5761144c615588565b5b6020026020010151858960038151811061146a57611469615588565b5b60200260200101518f6140c0565b90508660016000838152602001908152602001600020819055508a6003600089815260200190815260200160002060000154036114cf578060036000898152602001908152602001600020600001819055506114eb565b8060036000898152602001908152602001600020600101819055505b505050506114fd565b5050505061151a565b5b6115158383335a8861151091906155e6565b61416d565b505050505b505050565b611527614926565b868160400181815250508581606001818152505084816080018181525050838160a0018181525050828160c001818152505088816101e0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508781610200019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250503381610220019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600080736f8a583c11615c7cf713a76e79131fdf8761c3fe73ffffffffffffffffffffffffffffffffffffffff1663acbfa21d338d8d8d8d8d8d8d6040518963ffffffff1660e01b8152600401611662989796959493929190615872565b608060405180830381865afa15801561167f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a391906158f0565b866102800187610260018296508397508460ff1660ff168152508460ff1660ff1681525050505050606483610280015160ff16146116e057600080fd5b6116ee338c848d85896140c0565b836000018181525050600080815461170590615957565b919050819055506000805490508360036000838152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015560a0820151816005015560c0820151816006015560e082015181600701556101008201518160080155610120820151816009015561014082015181600a015561016082015181600b015561018082015181600c01556101a082015181600d01556101c082015181600e01556101e082015181600f0160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102008201518160100160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102208201518160110160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102408201518160120160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102608201518160120160146101000a81548160ff021916908360ff1602179055506102808201518160120160156101000a81548160ff021916908360ff160217905550905050806001600086600001518152602001908152602001600020819055506119503382614239565b807ff9e873657e730881eafc125ef40143f79658208a374f800d4b5b34d98432e6ea60405160405180910390a2505050505050505050505050565b611993614926565b6000600267ffffffffffffffff8111156119b0576119af614e59565b5b6040519080825280602002602001820160405280156119de5781602001602082028036833780820191505090505b509050736f8a583c11615c7cf713a76e79131fdf8761c3fe73ffffffffffffffffffffffffffffffffffffffff166390b5ef77338e8e8e8e8e8e8e8e6040518a63ffffffff1660e01b8152600401611a3e9998979695949392919061599f565b606060405180830381865afa158015611a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a7f91906157ad565b846102800184600081518110611a9857611a97615588565b5b6020026020010185600181518110611ab357611ab2615588565b5b6020026020010183815250838152508360ff1660ff16815250505050606582610280015160ff1603611afe578a8c809c50819d505050606482610280019060ff16908160ff16815250505b606482610280015160ff1614611b1357600080fd5b898260400181815250508882606001818152505087826080018181525050868260a0018181525050858260c0018181525050848260e00181815250508b826101e0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508a82610200019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250503382610220019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600382610260019060ff16908160ff16815250506000808154611c1c90615957565b91905081905550600080549050600082600081518110611c3f57611c3e615588565b5b60200260200101511115611ca657611c8033846101e001518d86610200015186600081518110611c7257611c71615588565b5b60200260200101518a6140c0565b836000018181525050806001600085600001518152602001908152602001600020819055505b600082600181518110611cbc57611cbb615588565b5b60200260200101511115611d2357611cfd3384610200015184600181518110611ce857611ce7615588565b5b6020026020010151866101e001518e896140c0565b836020018181525050806001600085602001518152602001908152602001600020819055505b8260036000838152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015560a0820151816005015560c0820151816006015560e082015181600701556101008201518160080155610120820151816009015561014082015181600a015561016082015181600b015561018082015181600c01556101a082015181600d01556101c082015181600e01556101e082015181600f0160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102008201518160100160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102208201518160110160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102408201518160120160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102608201518160120160146101000a81548160ff021916908360ff1602179055506102808201518160120160156101000a81548160ff021916908360ff160217905550905050611f453382614239565b807ff9e873657e730881eafc125ef40143f79658208a374f800d4b5b34d98432e6ea60405160405180910390a250505050505050505050505050565b6060600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008481526020019081526020016000206001015492506000830361203257600167ffffffffffffffff811115611ffc57611ffb614e59565b5b60405190808252806020026020018201604052801561202a5781602001602082028036833780820191505090505b509050612639565b600080600e846120429190615a2c565b67ffffffffffffffff81111561205b5761205a614e59565b5b6040519080825280602002602001820160405280156120895781602001602082028036833780820191505090505b50905060005b8481101561263257600086031561263257858284806120ad90615957565b9550815181106120c0576120bf615588565b5b602002602001018181525050600260008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008781526020019081526020016000206000015482848061212c90615957565b95508151811061213f5761213e615588565b5b6020026020010181815250506003600087815260200190815260200160002060120160149054906101000a900460ff1660ff1682848061217e90615957565b95508151811061219157612190615588565b5b60200260200101818152505060007311d5db9473a6e017ba4d182987bc5ab198c04a1573ffffffffffffffffffffffffffffffffffffffff166336511013600360008a815260200190815260200160002060000154600360008b8152602001908152602001600020600101546040518363ffffffff1660e01b815260040161221a929190615a86565b600060405180830381865afa158015612237573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190612260919061553f565b90508060008151811061227657612275615588565b5b602002602001015183858061228a90615957565b96508151811061229d5761229c615588565b5b602002602001018181525050806001815181106122bd576122bc615588565b5b60200260200101518385806122d190615957565b9650815181106122e4576122e3615588565b5b6020026020010181815250508060028151811061230457612303615588565b5b602002602001015183858061231890615957565b96508151811061232b5761232a615588565b5b6020026020010181815250508060038151811061234b5761234a615588565b5b602002602001015183858061235f90615957565b96508151811061237257612371615588565b5b60200260200101818152505060036000888152602001908152602001600020600901548385806123a190615957565b9650815181106123b4576123b3615588565b5b60200260200101818152505060036000888152602001908152602001600020600a01548385806123e390615957565b9650815181106123f6576123f5615588565b5b60200260200101818152505060036000888152602001908152602001600020600c015483858061242590615957565b96508151811061243857612437615588565b5b60200260200101818152505060036000888152602001908152602001600020600d015483858061246790615957565b96508151811061247a57612479615588565b5b60200260200101818152505060036000888152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168385806124df90615957565b9650815181106124f2576124f1615588565b5b6020026020010181815250506003600088815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1683858061255790615957565b96508151811061256a57612569615588565b5b6020026020010181815250506003600088815260200190815260200160002060120160159054906101000a900460ff1660ff168385806125a990615957565b9650815181106125bc576125bb615588565b5b602002602001018181525050600260008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600088815260200190815260200160002060010154965050808061262a90615957565b91505061208f565b5080925050505b9392505050565b6000638943ec0260e01b90509392505050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b60005481565b6000600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000838152602001908152602001600020600001541161273557600080fd5b60006003600083815260200190815260200160002060120160159054906101000a900460ff16905060648160ff1614158015612775575060c88160ff1614155b156127be576127bd82336003600086815260200190815260200160002060120160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600061416d565b5b60c88160ff161461295a5760006003600084815260200190815260200160002060000154905060006003600085815260200190815260200160002060010154905060008211156128ab5760007311d5db9473a6e017ba4d182987bc5ab198c04a1573ffffffffffffffffffffffffffffffffffffffff16636da42a15846040518263ffffffff1660e01b8152600401612857919061508e565b600060405180830381865afa158015612874573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061289d919061553f565b90506128a98382613aa5565b505b60008111156129575760007311d5db9473a6e017ba4d182987bc5ab198c04a1573ffffffffffffffffffffffffffffffffffffffff16636da42a15836040518263ffffffff1660e01b8152600401612903919061508e565b600060405180830381865afa158015612920573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190612949919061553f565b90506129558282613aa5565b505b50505b61296433836143d3565b60036000838152602001908152602001600020600080820160009055600182016000905560028201600090556003820160009055600482016000905560058201600090556006820160009055600782016000905560088201600090556009820160009055600a820160009055600b820160009055600c820160009055600d820160009055600e820160009055600f820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556010820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556011820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556012820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556012820160146101000a81549060ff02191690556012820160156101000a81549060ff02191690555050817fa72f695a885e7ae6c69d169d271a0fff49ed6dea3bf49329e817a3cc4666cb4560405160405180910390a25050565b612aef614926565b60036000838152602001908152602001600020604051806102a001604052908160008201548152602001600182015481526020016002820154815260200160038201548152602001600482015481526020016005820154815260200160068201548152602001600782015481526020016008820154815260200160098201548152602001600a8201548152602001600b8201548152602001600c8201548152602001600d8201548152602001600e8201548152602001600f820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016010820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016011820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016012820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016012820160149054906101000a900460ff1660ff1660ff1681526020016012820160159054906101000a900460ff1660ff1660ff16815250509050919050565b612d4561488e565b612d4d61488e565b6000600160008581526020019081526020016000205490506003600082815260200190815260200160002060120160159054906101000a900460ff168260c0019060ff16908160ff168152505060648260c0015160ff1614612db357819250505061381c565b60007311d5db9473a6e017ba4d182987bc5ab198c04a1573ffffffffffffffffffffffffffffffffffffffff16636da42a15866040518263ffffffff1660e01b8152600401612e02919061508e565b600060405180830381865afa158015612e1f573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190612e48919061553f565b9050600781600081518110612e6057612e5f615588565b5b6020026020010151036135c2576000600182600181518110612e8557612e84615588565b5b602002602001015114612ecf5760036000848152602001908152602001600020600501546003600085815260200190815260200160002060040154612eca91906155e6565b612f08565b60036000848152602001908152602001600020600501546003600085815260200190815260200160002060040154612f07919061561a565b5b9050600060036000858152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16856040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506003600085815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16856060019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600380600086815260200190815260200160002060120160149054906101000a900460ff1660ff16036135155784606001518560400151866080018760a0018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152508273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815250505060018360018151811061309f5761309e615588565b5b6020026020010151036132e0576130f78560400151866060015160036000888152602001908152602001600020600201546003600089815260200190815260200160002060050154866130f2919061561a565b6145a4565b90506131238560400151600360008781526020019081526020016000206002015487606001518461464c565b85600001818152505060007311d5db9473a6e017ba4d182987bc5ab198c04a1573ffffffffffffffffffffffffffffffffffffffff16636da42a1560036000888152602001908152602001600020600101546040518263ffffffff1660e01b8152600401613191919061508e565b600060405180830381865afa1580156131ae573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906131d7919061553f565b905060006001826000815181106131f1576131f0615588565b5b60200260200101511480613220575060068260008151811061321657613215615588565b5b6020026020010151145b80613246575060098260008151811061323c5761323b615588565b5b6020026020010151145b613266576003600087815260200190815260200160002060030154613283565b8160038151811061327a57613279615588565b5b60200260200101515b90506132ba87608001518860a0015183600360008b815260200190815260200160002060050154886132b591906155e6565b6145a4565b92506132d08760800151848960a001518461464c565b8760200181815250505050613510565b61332b85608001518660a00151600360008881526020019081526020016000206003015460036000898152602001908152602001600020600501548661332691906155e6565b6145a4565b90506133578560800151828760a00151600360008981526020019081526020016000206003015461464c565b85602001818152505060007311d5db9473a6e017ba4d182987bc5ab198c04a1573ffffffffffffffffffffffffffffffffffffffff16636da42a1560036000888152602001908152602001600020600001546040518263ffffffff1660e01b81526004016133c5919061508e565b600060405180830381865afa1580156133e2573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061340b919061553f565b9050600060018260008151811061342557613424615588565b5b60200260200101511480613454575060068260008151811061344a57613449615588565b5b6020026020010151145b8061347a57506009826000815181106134705761346f615588565b5b6020026020010151145b61349a5760036000878152602001908152602001600020600201546134b7565b816002815181106134ae576134ad615588565b5b60200260200101515b90506134ee8760400151886060015183600360008b815260200190815260200160002060050154886134e9919061561a565b6145a4565b925061350487604001518289606001518661464c565b87600001818152505050505b6135bb565b60006003600086815260200190815260200160002060030154600360008781526020019081526020016000206002015461354f919061561a565b90506135658660400151876060015183866145a4565b915060018460018151811061357d5761357c615588565b5b602002602001015114613591578181613594565b80825b80935081925050506135b086604001518288606001518561464c565b866000018181525050505b5050613815565b6009816000815181106135d8576135d7615588565b5b60200260200101510361381457846003600084815260200190815260200160002060000154036136e35760036000838152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506003600083815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836060019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506137c0565b6003600083815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060036000838152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836060019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250505b61380a8360400151826002815181106137dc576137db615588565b5b60200260200101518560600151846003815181106137fd576137fc615588565b5b602002602001015161464c565b8360000181815250505b5b8293505050505b919050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146138b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016138a8906153d6565b60405180910390fd5b6001600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508073ffffffffffffffffffffffffffffffffffffffff167f9772798610937341d23a69ec5e3f97727ff869179644b17db536f12ef374bfc460405160405180910390a250565b7311d5db9473a6e017ba4d182987bc5ab198c04a1581565b60006003600083815260200190815260200160002060120160159054906101000a900460ff16905060008160ff161161399f57600080fd5b60648160ff16141580156139b7575060c88160ff1614155b6139c057600080fd5b6003600083815260200190815260200160002060110160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614613a2e57600080fd5b613a7182336003600086815260200190815260200160002060120160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600061416d565b60646003600084815260200190815260200160002060120160156101000a81548160ff021916908360ff1602179055505050565b60006001600084815260200190815260200160002054905060006003600083815260200190815260200160002060110160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060008085600360008681526020019081526020016000206000015403613cb55760036000858152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166003600086815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168092508193505050600085600581518110613ba457613ba3615588565b5b60200260200101511115613cb05784600481518110613bc657613bc5615588565b5b6020026020010151600360008681526020019081526020016000206009016000828254613bf3919061561a565b9250508190555084600581518110613c0e57613c0d615588565b5b602002602001015160036000868152602001908152602001600020600a016000828254613c3b919061561a565b92505081905550600085600681518110613c5857613c57615588565b5b60200260200101511115613caf5784600681518110613c7a57613c79615588565b5b602002602001015160036000868152602001908152602001600020600b016000828254613ca7919061561a565b925050819055505b5b613e4e565b6003600085815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660036000868152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168092508193505050600085600581518110613d4157613d40615588565b5b60200260200101511115613e4d5784600481518110613d6357613d62615588565b5b602002602001015160036000868152602001908152602001600020600c016000828254613d90919061561a565b9250508190555084600581518110613dab57613daa615588565b5b602002602001015160036000868152602001908152602001600020600d016000828254613dd8919061561a565b92505081905550600085600681518110613df557613df4615588565b5b60200260200101511115613e4c5784600681518110613e1757613e16615588565b5b602002602001015160036000868152602001908152602001600020600e016000828254613e44919061561a565b925050819055505b5b5b600085600581518110613e6457613e63615588565b5b60200260200101511115613e9957613e98818487600581518110613e8b57613e8a615588565b5b60200260200101516146f4565b5b6000600167ffffffffffffffff811115613eb657613eb5614e59565b5b604051908082528060200260200182016040528015613ee45781602001602082028036833780820191505090505b509050600086600281518110613efd57613efc615588565b5b60200260200101511115613fe9578681600081518110613f2057613f1f615588565b5b6020026020010181815250507311d5db9473a6e017ba4d182987bc5ab198c04a1573ffffffffffffffffffffffffffffffffffffffff1663b55fb574826040518263ffffffff1660e01b8152600401613f799190614e1c565b6000604051808303816000875af1158015613f98573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190613fc1919061553f565b50613fe8838588600281518110613fdb57613fda615588565b5b60200260200101516146f4565b5b8681600081518110613ffe57613ffd615588565b5b6020026020010181815250507311d5db9473a6e017ba4d182987bc5ab198c04a1573ffffffffffffffffffffffffffffffffffffffff166375b02405826040518263ffffffff1660e01b81526004016140579190614e1c565b6000604051808303816000875af1158015614076573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061409f919061553f565b50600160008881526020019081526020016000206000905550505050505050565b6000807301c81c93f38f42497b4cebfa23eeb03f7ccfa8c773ffffffffffffffffffffffffffffffffffffffff166322fe7c6f8989898989896040518763ffffffff1660e01b815260040161411a96959493929190615aaf565b6020604051808303816000875af1158015614139573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061415d9190615b10565b9050809150509695505050505050565b60007301c81c93f38f42497b4cebfa23eeb03f7ccfa8c773ffffffffffffffffffffffffffffffffffffffff16637c0b052a8585856040518463ffffffff1660e01b81526004016141c093929190615b3d565b6020604051808303816000875af11580156141df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142039190615b10565b90508060036000878152602001908152602001600020600801600082825461422b919061561a565b925050819055505050505050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600080815260200190815260200160002060020154905081600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206001018190555081600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008081526020019081526020016000206002018190555060405180606001604052804281526020016000815260200182815250600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000848152602001908152602001600020600082015181600001556020820151816001015560408201518160020155905050505050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206001015490506000600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060020154905081600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206001018190555080600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060020181905550600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060008082016000905560018201600090556002820160009055505050505050565b6000807301c81c93f38f42497b4cebfa23eeb03f7ccfa8c773ffffffffffffffffffffffffffffffffffffffff166365593d7b878787876040518563ffffffff1660e01b81526004016145fa9493929190615800565b6040805180830381865afa158015614616573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061463a9190615b74565b90508091505080915050949350505050565b6000807301c81c93f38f42497b4cebfa23eeb03f7ccfa8c773ffffffffffffffffffffffffffffffffffffffff166366555804878787876040518563ffffffff1660e01b81526004016146a29493929190615bb4565b6040805180830381865afa1580156146be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146e29190615b74565b90508091505080915050949350505050565b6000823b90506000811115614808578373ffffffffffffffffffffffffffffffffffffffff1663095ea7b330846040518363ffffffff1660e01b815260040161473e929190615bf9565b6020604051808303816000875af115801561475d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147819190615c4e565b508373ffffffffffffffffffffffffffffffffffffffff166323b872dd3085856040518463ffffffff1660e01b81526004016147bf93929190615b3d565b6020604051808303816000875af11580156147de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148029190615c4e565b50614888565b8373ffffffffffffffffffffffffffffffffffffffff1663a9059cbb84846040518363ffffffff1660e01b8152600401614843929190615bf9565b6020604051808303816000875af1158015614862573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148869190615c4e565b505b50505050565b6040518060e001604052806000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600060ff1681525090565b604051806102a00160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600060ff168152602001600060ff1681525090565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000614a4f82614a24565b9050919050565b614a5f81614a44565b82525050565b6000602082019050614a7a6000830184614a56565b92915050565b6000604051905090565b600080fd5b600080fd5b614a9d81614a44565b8114614aa857600080fd5b50565b600081359050614aba81614a94565b92915050565b600060208284031215614ad657614ad5614a8a565b5b6000614ae484828501614aab565b91505092915050565b6000819050919050565b614b0081614aed565b8114614b0b57600080fd5b50565b600081359050614b1d81614af7565b92915050565b600080600060608486031215614b3c57614b3b614a8a565b5b6000614b4a86828701614b0e565b9350506020614b5b86828701614b0e565b9250506040614b6c86828701614b0e565b9150509250925092565b600080600080600080600080610100898b031215614b9757614b96614a8a565b5b6000614ba58b828c01614aab565b9850506020614bb68b828c01614aab565b9750506040614bc78b828c01614b0e565b9650506060614bd88b828c01614b0e565b9550506080614be98b828c01614b0e565b94505060a0614bfa8b828c01614b0e565b93505060c0614c0b8b828c01614b0e565b92505060e0614c1c8b828c01614b0e565b9150509295985092959890939650565b6000806000806000806000806000806101408b8d031215614c5057614c4f614a8a565b5b6000614c5e8d828e01614aab565b9a50506020614c6f8d828e01614aab565b9950506040614c808d828e01614b0e565b9850506060614c918d828e01614b0e565b9750506080614ca28d828e01614b0e565b96505060a0614cb38d828e01614b0e565b95505060c0614cc48d828e01614b0e565b94505060e0614cd58d828e01614b0e565b935050610100614ce78d828e01614b0e565b925050610120614cf98d828e01614b0e565b9150509295989b9194979a5092959850565b600080600060608486031215614d2457614d23614a8a565b5b6000614d3286828701614aab565b9350506020614d4386828701614b0e565b9250506040614d5486828701614b0e565b9150509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b614d9381614aed565b82525050565b6000614da58383614d8a565b60208301905092915050565b6000602082019050919050565b6000614dc982614d5e565b614dd38185614d69565b9350614dde83614d7a565b8060005b83811015614e0f578151614df68882614d99565b9750614e0183614db1565b925050600181019050614de2565b5085935050505092915050565b60006020820190508181036000830152614e368184614dbe565b905092915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b614e9182614e48565b810181811067ffffffffffffffff82111715614eb057614eaf614e59565b5b80604052505050565b6000614ec3614a80565b9050614ecf8282614e88565b919050565b600067ffffffffffffffff821115614eef57614eee614e59565b5b614ef882614e48565b9050602081019050919050565b82818337600083830152505050565b6000614f27614f2284614ed4565b614eb9565b905082815260208101848484011115614f4357614f42614e43565b5b614f4e848285614f05565b509392505050565b600082601f830112614f6b57614f6a614e3e565b5b8135614f7b848260208601614f14565b91505092915050565b600080600060608486031215614f9d57614f9c614a8a565b5b6000614fab86828701614aab565b9350506020614fbc86828701614b0e565b925050604084013567ffffffffffffffff811115614fdd57614fdc614a8f565b5b614fe986828701614f56565b9150509250925092565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61502881614ff3565b82525050565b6000602082019050615043600083018461501f565b92915050565b60008115159050919050565b61505e81615049565b82525050565b60006020820190506150796000830184615055565b92915050565b61508881614aed565b82525050565b60006020820190506150a3600083018461507f565b92915050565b6000602082840312156150bf576150be614a8a565b5b60006150cd84828501614b0e565b91505092915050565b6150df81614a44565b82525050565b600060ff82169050919050565b6150fb816150e5565b82525050565b6102a0820160008201516151186000850182614d8a565b50602082015161512b6020850182614d8a565b50604082015161513e6040850182614d8a565b5060608201516151516060850182614d8a565b5060808201516151646080850182614d8a565b5060a082015161517760a0850182614d8a565b5060c082015161518a60c0850182614d8a565b5060e082015161519d60e0850182614d8a565b506101008201516151b2610100850182614d8a565b506101208201516151c7610120850182614d8a565b506101408201516151dc610140850182614d8a565b506101608201516151f1610160850182614d8a565b50610180820151615206610180850182614d8a565b506101a082015161521b6101a0850182614d8a565b506101c08201516152306101c0850182614d8a565b506101e08201516152456101e08501826150d6565b5061020082015161525a6102008501826150d6565b5061022082015161526f6102208501826150d6565b506102408201516152846102408501826150d6565b506102608201516152996102608501826150f2565b506102808201516152ae6102808501826150f2565b50505050565b60006102a0820190506152ca6000830184615101565b92915050565b60e0820160008201516152e66000850182614d8a565b5060208201516152f96020850182614d8a565b50604082015161530c60408501826150d6565b50606082015161531f60608501826150d6565b50608082015161533260808501826150d6565b5060a082015161534560a08501826150d6565b5060c082015161535860c08501826150f2565b50505050565b600060e08201905061537360008301846152d0565b92915050565b600082825260208201905092915050565b7f4f6e6c79206f776e65722063616e2063616c6c20746869730000000000000000600082015250565b60006153c0601883615379565b91506153cb8261538a565b602082019050919050565b600060208201905081810360008301526153ef816153b3565b9050919050565b7f4f6e6c79206f7261636c652063616e2063616c6c207468697300000000000000600082015250565b600061542c601983615379565b9150615437826153f6565b602082019050919050565b6000602082019050818103600083015261545b8161541f565b9050919050565b600067ffffffffffffffff82111561547d5761547c614e59565b5b602082029050602081019050919050565b600080fd5b6000815190506154a281614af7565b92915050565b60006154bb6154b684615462565b614eb9565b905080838252602082019050602084028301858111156154de576154dd61548e565b5b835b8181101561550757806154f38882615493565b8452602084019350506020810190506154e0565b5050509392505050565b600082601f83011261552657615525614e3e565b5b81516155368482602086016154a8565b91505092915050565b60006020828403121561555557615554614a8a565b5b600082015167ffffffffffffffff81111561557357615572614a8f565b5b61557f84828501615511565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006155f182614aed565b91506155fc83614aed565b9250828203905081811115615614576156136155b7565b5b92915050565b600061562582614aed565b915061563083614aed565b9250828201905080821115615648576156476155b7565b5b92915050565b600060c0820190506156636000830189614a56565b6156706020830188614a56565b61567d6040830187614a56565b818103606083015261568f8186614dbe565b905081810360808301526156a38185614dbe565b905081810360a08301526156b78184614dbe565b9050979650505050505050565b6156cd816150e5565b81146156d857600080fd5b50565b6000815190506156ea816156c4565b92915050565b6000806040838503121561570757615706614a8a565b5b6000615715858286016156db565b925050602083015167ffffffffffffffff81111561573657615735614a8f565b5b61574285828601615511565b9150509250929050565b600060c0820190506157616000830189614a56565b61576e6020830188614a56565b61577b6040830187614a56565b615788606083018661507f565b615795608083018561507f565b6157a260a083018461507f565b979650505050505050565b6000806000606084860312156157c6576157c5614a8a565b5b60006157d4868287016156db565b93505060206157e586828701615493565b92505060406157f686828701615493565b9150509250925092565b60006080820190506158156000830187614a56565b6158226020830186614a56565b61582f604083018561507f565b61583c606083018461507f565b95945050505050565b60006020828403121561585b5761585a614a8a565b5b6000615869848285016156db565b91505092915050565b600061010082019050615888600083018b614a56565b615895602083018a614a56565b6158a26040830189614a56565b6158af606083018861507f565b6158bc608083018761507f565b6158c960a083018661507f565b6158d660c083018561507f565b6158e360e083018461507f565b9998505050505050505050565b6000806000806080858703121561590a57615909614a8a565b5b6000615918878288016156db565b9450506020615929878288016156db565b935050604061593a87828801615493565b925050606061594b87828801615493565b91505092959194509250565b600061596282614aed565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615994576159936155b7565b5b600182019050919050565b6000610120820190506159b5600083018c614a56565b6159c2602083018b614a56565b6159cf604083018a614a56565b6159dc606083018961507f565b6159e9608083018861507f565b6159f660a083018761507f565b615a0360c083018661507f565b615a1060e083018561507f565b615a1e61010083018461507f565b9a9950505050505050505050565b6000615a3782614aed565b9150615a4283614aed565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615a7b57615a7a6155b7565b5b828202905092915050565b6000604082019050615a9b600083018561507f565b615aa8602083018461507f565b9392505050565b600060c082019050615ac46000830189614a56565b615ad16020830188614a56565b615ade604083018761507f565b615aeb6060830186614a56565b615af8608083018561507f565b615b0560a083018461507f565b979650505050505050565b600060208284031215615b2657615b25614a8a565b5b6000615b3484828501615493565b91505092915050565b6000606082019050615b526000830186614a56565b615b5f6020830185614a56565b615b6c604083018461507f565b949350505050565b60008060408385031215615b8b57615b8a614a8a565b5b6000615b99858286016156db565b9250506020615baa85828601615493565b9150509250929050565b6000608082019050615bc96000830187614a56565b615bd6602083018661507f565b615be36040830185614a56565b615bf0606083018461507f565b95945050505050565b6000604082019050615c0e6000830185614a56565b615c1b602083018461507f565b9392505050565b615c2b81615049565b8114615c3657600080fd5b50565b600081519050615c4881615c22565b92915050565b600060208284031215615c6457615c63614a8a565b5b6000615c7284828501615c39565b9150509291505056fea26469706673582212208bf560699041302fdf0ffe26c519debb442e5d35f90bd1e014428b716756e7f064736f6c63430008100033

Deployed ByteCode

0x6080604052600436106101025760003560e01c80638da5cb5b11610095578063cada801411610064578063cada80141461033e578063caf4b41c1461037b578063df5dd1a5146103b8578063e06b4400146103e1578063e38d1a401461040c57610109565b80638da5cb5b14610282578063a97e5c93146102ad578063af640d0f146102ea578063c78f936f1461031557610109565b80632fd96ca9116100d15780632fd96ca9146101b657806330be1160146101df5780637bf02d6d146102085780638943ec021461024557610109565b80630147db0c1461010e5780630d711a9f14610139578063127e11971461016257806321c4227e1461018d57610109565b3661010957005b600080fd5b34801561011a57600080fd5b50610123610435565b6040516101309190614a65565b60405180910390f35b34801561014557600080fd5b50610160600480360381019061015b9190614ac0565b61044d565b005b34801561016e57600080fd5b5061017761057b565b6040516101849190614a65565b60405180910390f35b34801561019957600080fd5b506101b460048036038101906101af9190614b23565b610593565b005b3480156101c257600080fd5b506101dd60048036038101906101d89190614b76565b61151f565b005b3480156101eb57600080fd5b5061020660048036038101906102019190614c2c565b61198b565b005b34801561021457600080fd5b5061022f600480360381019061022a9190614d0b565b611f81565b60405161023c9190614e1c565b60405180910390f35b34801561025157600080fd5b5061026c60048036038101906102679190614f84565b612640565b604051610279919061502e565b60405180910390f35b34801561028e57600080fd5b50610297612653565b6040516102a49190614a65565b60405180910390f35b3480156102b957600080fd5b506102d460048036038101906102cf9190614ac0565b612679565b6040516102e19190615064565b60405180910390f35b3480156102f657600080fd5b506102ff6126cf565b60405161030c919061508e565b60405180910390f35b34801561032157600080fd5b5061033c600480360381019061033791906150a9565b6126d5565b005b34801561034a57600080fd5b50610365600480360381019061036091906150a9565b612ae7565b60405161037291906152b4565b60405180910390f35b34801561038757600080fd5b506103a2600480360381019061039d91906150a9565b612d3d565b6040516103af919061535e565b60405180910390f35b3480156103c457600080fd5b506103df60048036038101906103da9190614ac0565b613821565b005b3480156103ed57600080fd5b506103f661394f565b6040516104039190614a65565b60405180910390f35b34801561041857600080fd5b50610433600480360381019061042e91906150a9565b613967565b005b736f8a583c11615c7cf713a76e79131fdf8761c3fe81565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104dd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104d4906153d6565b60405180910390fd5b6000600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508073ffffffffffffffffffffffffffffffffffffffff167f8f0e1537186f631af722391ce4e08495881ee25f0d06ed39dd7e8db6ce25d3c860405160405180910390a250565b7301c81c93f38f42497b4cebfa23eeb03f7ccfa8c781565b60011515600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514610626576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161061d90615442565b60405180910390fd5b60005a905060006001600086815260200190815260200160002054905060646003600083815260200190815260200160002060120160159054906101000a900460ff1660ff161461067657600080fd5b60006003600083815260200190815260200160002060110160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060007311d5db9473a6e017ba4d182987bc5ab198c04a1573ffffffffffffffffffffffffffffffffffffffff16636da42a15886040518263ffffffff1660e01b8152600401610700919061508e565b600060405180830381865afa15801561071d573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610746919061553f565b905060078160008151811061075e5761075d615588565b5b60200260200101510361119557600060018260018151811061078357610782615588565b5b6020026020010151146107cd57600360008581526020019081526020016000206005015460036000868152602001908152602001600020600401546107c891906155e6565b610806565b60036000858152602001908152602001600020600501546003600086815260200190815260200160002060040154610805919061561a565b5b905061081061488e565b60036000868152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16816040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506003600086815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16816060019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600380600087815260200190815260200160002060120160149054906101000a900460ff1660ff1603610ed3578860036000878152602001908152602001600020600001541461095257600360008681526020019081526020016000206000015461096a565b60036000868152602001908152602001600020600101545b81602001818152505060007311d5db9473a6e017ba4d182987bc5ab198c04a1573ffffffffffffffffffffffffffffffffffffffff16636da42a1583602001516040518263ffffffff1660e01b81526004016109c6919061508e565b600060405180830381865afa1580156109e3573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610a0c919061553f565b905060606000600667ffffffffffffffff811115610a2d57610a2c614e59565b5b604051908082528060200260200182016040528015610a5b5781602001602082028036833780820191505090505b509050600360008981526020019081526020016000206002015481600081518110610a8957610a88615588565b5b602002602001018181525050600360008981526020019081526020016000206003015481600181518110610ac057610abf615588565b5b6020026020010181815250508481600281518110610ae157610ae0615588565b5b602002602001018181525050600360008981526020019081526020016000206005015481600381518110610b1857610b17615588565b5b602002602001018181525050600360008981526020019081526020016000206006015481600481518110610b4f57610b4e615588565b5b602002602001018181525050600360008981526020019081526020016000206007015481600581518110610b8657610b85615588565b5b602002602001018181525050736f8a583c11615c7cf713a76e79131fdf8761c3fe73ffffffffffffffffffffffffffffffffffffffff1663b10557348886604001518760600151858b896040518763ffffffff1660e01b8152600401610bf19695949392919061564e565b600060405180830381865afa158015610c0e573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610c3791906156f0565b8560c0018194508260ff1660ff16815250505060008460c0015160ff161115610cf05733600360008a815260200190815260200160002060120160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508360c00151600360008a815260200190815260200160002060120160156101000a81548160ff021916908360ff16021790555050505050505050505061151a565b610cfa8c87613aa5565b600084602001511115610d1657610d15846020015184613aa5565b5b84600360008a815260200190815260200160002060040181905550600082600081518110610d4757610d46615588565b5b60200260200101511115610de15760008b9050610da688866040015185600081518110610d7757610d76615588565b5b6020026020010151886060015187600181518110610d9857610d97615588565b5b6020026020010151866140c0565b905088600160008381526020019081526020016000208190555080600360008b81526020019081526020016000206000018190555050610dfe565b6000600360008a8152602001908152602001600020600001819055505b600082600281518110610e1457610e13615588565b5b60200260200101511115610eae5760008a9050610e7388866060015185600281518110610e4457610e43615588565b5b6020026020010151886040015187600381518110610e6557610e64615588565b5b6020026020010151866140c0565b905088600160008381526020019081526020016000208190555080600360008b81526020019081526020016000206001018190555050610ecb565b6000600360008a8152602001908152602001600020600101819055505b50505061118e565b600060036000878152602001908152602001600020600301546003600088815260200190815260200160002060020154610f0d919061561a565b9050736f8a583c11615c7cf713a76e79131fdf8761c3fe73ffffffffffffffffffffffffffffffffffffffff1663fe908a9c86846040015185606001518588600360008e8152602001908152602001600020600601546040518763ffffffff1660e01b8152600401610f849695949392919061574c565b606060405180830381865afa158015610fa1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc591906157ad565b8460c001856000018660200183815250838152508360ff1660ff1681525050505060648260c0015160ff160361108d57610fff8a85613aa5565b8060036000888152602001908152602001600020600201819055508260036000888152602001908152602001600020600401819055506110538583604001518460000151856060015186602001518e6140c0565b905085600160008381526020019081526020016000208190555080600360008881526020019081526020016000206000018190555061118c565b60c88260c0015160ff16036110f7576110a68a85613aa5565b6000600360008881526020019081526020016000206000018190555060c86003600088815260200190815260200160002060120160156101000a81548160ff021916908360ff16021790555061118b565b336003600088815260200190815260200160002060120160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508160c001516003600088815260200190815260200160002060120160156101000a81548160ff021916908360ff1602179055505050505050505061151a565b5b505b50506114fe565b6009816000815181106111ab576111aa615588565b5b6020026020010151036114f45760008060008960036000888152602001908152602001600020600001541461124d576003600087815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660036000888152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166112bc565b60036000878152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166003600088815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff165b91509150736f8a583c11615c7cf713a76e79131fdf8761c3fe73ffffffffffffffffffffffffffffffffffffffff1663ad148af486848760028151811061130657611305615588565b5b60200260200101518860028151811061132257611321615588565b5b60200260200101516040518563ffffffff1660e01b81526004016113499493929190615800565b602060405180830381865afa158015611366573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138a9190615845565b925060008360ff16111561142857336003600088815260200190815260200160002060120160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550826003600088815260200190815260200160002060120160156101000a81548160ff021916908360ff1602179055505050505050505061151a565b6114328a85613aa5565b600061147886848760028151811061144d5761144c615588565b5b6020026020010151858960038151811061146a57611469615588565b5b60200260200101518f6140c0565b90508660016000838152602001908152602001600020819055508a6003600089815260200190815260200160002060000154036114cf578060036000898152602001908152602001600020600001819055506114eb565b8060036000898152602001908152602001600020600101819055505b505050506114fd565b5050505061151a565b5b6115158383335a8861151091906155e6565b61416d565b505050505b505050565b611527614926565b868160400181815250508581606001818152505084816080018181525050838160a0018181525050828160c001818152505088816101e0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508781610200019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250503381610220019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600080736f8a583c11615c7cf713a76e79131fdf8761c3fe73ffffffffffffffffffffffffffffffffffffffff1663acbfa21d338d8d8d8d8d8d8d6040518963ffffffff1660e01b8152600401611662989796959493929190615872565b608060405180830381865afa15801561167f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a391906158f0565b866102800187610260018296508397508460ff1660ff168152508460ff1660ff1681525050505050606483610280015160ff16146116e057600080fd5b6116ee338c848d85896140c0565b836000018181525050600080815461170590615957565b919050819055506000805490508360036000838152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015560a0820151816005015560c0820151816006015560e082015181600701556101008201518160080155610120820151816009015561014082015181600a015561016082015181600b015561018082015181600c01556101a082015181600d01556101c082015181600e01556101e082015181600f0160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102008201518160100160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102208201518160110160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102408201518160120160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102608201518160120160146101000a81548160ff021916908360ff1602179055506102808201518160120160156101000a81548160ff021916908360ff160217905550905050806001600086600001518152602001908152602001600020819055506119503382614239565b807ff9e873657e730881eafc125ef40143f79658208a374f800d4b5b34d98432e6ea60405160405180910390a2505050505050505050505050565b611993614926565b6000600267ffffffffffffffff8111156119b0576119af614e59565b5b6040519080825280602002602001820160405280156119de5781602001602082028036833780820191505090505b509050736f8a583c11615c7cf713a76e79131fdf8761c3fe73ffffffffffffffffffffffffffffffffffffffff166390b5ef77338e8e8e8e8e8e8e8e6040518a63ffffffff1660e01b8152600401611a3e9998979695949392919061599f565b606060405180830381865afa158015611a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a7f91906157ad565b846102800184600081518110611a9857611a97615588565b5b6020026020010185600181518110611ab357611ab2615588565b5b6020026020010183815250838152508360ff1660ff16815250505050606582610280015160ff1603611afe578a8c809c50819d505050606482610280019060ff16908160ff16815250505b606482610280015160ff1614611b1357600080fd5b898260400181815250508882606001818152505087826080018181525050868260a0018181525050858260c0018181525050848260e00181815250508b826101e0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508a82610200019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250503382610220019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600382610260019060ff16908160ff16815250506000808154611c1c90615957565b91905081905550600080549050600082600081518110611c3f57611c3e615588565b5b60200260200101511115611ca657611c8033846101e001518d86610200015186600081518110611c7257611c71615588565b5b60200260200101518a6140c0565b836000018181525050806001600085600001518152602001908152602001600020819055505b600082600181518110611cbc57611cbb615588565b5b60200260200101511115611d2357611cfd3384610200015184600181518110611ce857611ce7615588565b5b6020026020010151866101e001518e896140c0565b836020018181525050806001600085602001518152602001908152602001600020819055505b8260036000838152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015560a0820151816005015560c0820151816006015560e082015181600701556101008201518160080155610120820151816009015561014082015181600a015561016082015181600b015561018082015181600c01556101a082015181600d01556101c082015181600e01556101e082015181600f0160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102008201518160100160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102208201518160110160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102408201518160120160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102608201518160120160146101000a81548160ff021916908360ff1602179055506102808201518160120160156101000a81548160ff021916908360ff160217905550905050611f453382614239565b807ff9e873657e730881eafc125ef40143f79658208a374f800d4b5b34d98432e6ea60405160405180910390a250505050505050505050505050565b6060600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008481526020019081526020016000206001015492506000830361203257600167ffffffffffffffff811115611ffc57611ffb614e59565b5b60405190808252806020026020018201604052801561202a5781602001602082028036833780820191505090505b509050612639565b600080600e846120429190615a2c565b67ffffffffffffffff81111561205b5761205a614e59565b5b6040519080825280602002602001820160405280156120895781602001602082028036833780820191505090505b50905060005b8481101561263257600086031561263257858284806120ad90615957565b9550815181106120c0576120bf615588565b5b602002602001018181525050600260008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008781526020019081526020016000206000015482848061212c90615957565b95508151811061213f5761213e615588565b5b6020026020010181815250506003600087815260200190815260200160002060120160149054906101000a900460ff1660ff1682848061217e90615957565b95508151811061219157612190615588565b5b60200260200101818152505060007311d5db9473a6e017ba4d182987bc5ab198c04a1573ffffffffffffffffffffffffffffffffffffffff166336511013600360008a815260200190815260200160002060000154600360008b8152602001908152602001600020600101546040518363ffffffff1660e01b815260040161221a929190615a86565b600060405180830381865afa158015612237573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190612260919061553f565b90508060008151811061227657612275615588565b5b602002602001015183858061228a90615957565b96508151811061229d5761229c615588565b5b602002602001018181525050806001815181106122bd576122bc615588565b5b60200260200101518385806122d190615957565b9650815181106122e4576122e3615588565b5b6020026020010181815250508060028151811061230457612303615588565b5b602002602001015183858061231890615957565b96508151811061232b5761232a615588565b5b6020026020010181815250508060038151811061234b5761234a615588565b5b602002602001015183858061235f90615957565b96508151811061237257612371615588565b5b60200260200101818152505060036000888152602001908152602001600020600901548385806123a190615957565b9650815181106123b4576123b3615588565b5b60200260200101818152505060036000888152602001908152602001600020600a01548385806123e390615957565b9650815181106123f6576123f5615588565b5b60200260200101818152505060036000888152602001908152602001600020600c015483858061242590615957565b96508151811061243857612437615588565b5b60200260200101818152505060036000888152602001908152602001600020600d015483858061246790615957565b96508151811061247a57612479615588565b5b60200260200101818152505060036000888152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168385806124df90615957565b9650815181106124f2576124f1615588565b5b6020026020010181815250506003600088815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1683858061255790615957565b96508151811061256a57612569615588565b5b6020026020010181815250506003600088815260200190815260200160002060120160159054906101000a900460ff1660ff168385806125a990615957565b9650815181106125bc576125bb615588565b5b602002602001018181525050600260008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600088815260200190815260200160002060010154965050808061262a90615957565b91505061208f565b5080925050505b9392505050565b6000638943ec0260e01b90509392505050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b60005481565b6000600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000838152602001908152602001600020600001541161273557600080fd5b60006003600083815260200190815260200160002060120160159054906101000a900460ff16905060648160ff1614158015612775575060c88160ff1614155b156127be576127bd82336003600086815260200190815260200160002060120160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600061416d565b5b60c88160ff161461295a5760006003600084815260200190815260200160002060000154905060006003600085815260200190815260200160002060010154905060008211156128ab5760007311d5db9473a6e017ba4d182987bc5ab198c04a1573ffffffffffffffffffffffffffffffffffffffff16636da42a15846040518263ffffffff1660e01b8152600401612857919061508e565b600060405180830381865afa158015612874573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061289d919061553f565b90506128a98382613aa5565b505b60008111156129575760007311d5db9473a6e017ba4d182987bc5ab198c04a1573ffffffffffffffffffffffffffffffffffffffff16636da42a15836040518263ffffffff1660e01b8152600401612903919061508e565b600060405180830381865afa158015612920573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190612949919061553f565b90506129558282613aa5565b505b50505b61296433836143d3565b60036000838152602001908152602001600020600080820160009055600182016000905560028201600090556003820160009055600482016000905560058201600090556006820160009055600782016000905560088201600090556009820160009055600a820160009055600b820160009055600c820160009055600d820160009055600e820160009055600f820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556010820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556011820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556012820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556012820160146101000a81549060ff02191690556012820160156101000a81549060ff02191690555050817fa72f695a885e7ae6c69d169d271a0fff49ed6dea3bf49329e817a3cc4666cb4560405160405180910390a25050565b612aef614926565b60036000838152602001908152602001600020604051806102a001604052908160008201548152602001600182015481526020016002820154815260200160038201548152602001600482015481526020016005820154815260200160068201548152602001600782015481526020016008820154815260200160098201548152602001600a8201548152602001600b8201548152602001600c8201548152602001600d8201548152602001600e8201548152602001600f820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016010820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016011820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016012820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016012820160149054906101000a900460ff1660ff1660ff1681526020016012820160159054906101000a900460ff1660ff1660ff16815250509050919050565b612d4561488e565b612d4d61488e565b6000600160008581526020019081526020016000205490506003600082815260200190815260200160002060120160159054906101000a900460ff168260c0019060ff16908160ff168152505060648260c0015160ff1614612db357819250505061381c565b60007311d5db9473a6e017ba4d182987bc5ab198c04a1573ffffffffffffffffffffffffffffffffffffffff16636da42a15866040518263ffffffff1660e01b8152600401612e02919061508e565b600060405180830381865afa158015612e1f573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190612e48919061553f565b9050600781600081518110612e6057612e5f615588565b5b6020026020010151036135c2576000600182600181518110612e8557612e84615588565b5b602002602001015114612ecf5760036000848152602001908152602001600020600501546003600085815260200190815260200160002060040154612eca91906155e6565b612f08565b60036000848152602001908152602001600020600501546003600085815260200190815260200160002060040154612f07919061561a565b5b9050600060036000858152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16856040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506003600085815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16856060019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600380600086815260200190815260200160002060120160149054906101000a900460ff1660ff16036135155784606001518560400151866080018760a0018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152508273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815250505060018360018151811061309f5761309e615588565b5b6020026020010151036132e0576130f78560400151866060015160036000888152602001908152602001600020600201546003600089815260200190815260200160002060050154866130f2919061561a565b6145a4565b90506131238560400151600360008781526020019081526020016000206002015487606001518461464c565b85600001818152505060007311d5db9473a6e017ba4d182987bc5ab198c04a1573ffffffffffffffffffffffffffffffffffffffff16636da42a1560036000888152602001908152602001600020600101546040518263ffffffff1660e01b8152600401613191919061508e565b600060405180830381865afa1580156131ae573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906131d7919061553f565b905060006001826000815181106131f1576131f0615588565b5b60200260200101511480613220575060068260008151811061321657613215615588565b5b6020026020010151145b80613246575060098260008151811061323c5761323b615588565b5b6020026020010151145b613266576003600087815260200190815260200160002060030154613283565b8160038151811061327a57613279615588565b5b60200260200101515b90506132ba87608001518860a0015183600360008b815260200190815260200160002060050154886132b591906155e6565b6145a4565b92506132d08760800151848960a001518461464c565b8760200181815250505050613510565b61332b85608001518660a00151600360008881526020019081526020016000206003015460036000898152602001908152602001600020600501548661332691906155e6565b6145a4565b90506133578560800151828760a00151600360008981526020019081526020016000206003015461464c565b85602001818152505060007311d5db9473a6e017ba4d182987bc5ab198c04a1573ffffffffffffffffffffffffffffffffffffffff16636da42a1560036000888152602001908152602001600020600001546040518263ffffffff1660e01b81526004016133c5919061508e565b600060405180830381865afa1580156133e2573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061340b919061553f565b9050600060018260008151811061342557613424615588565b5b60200260200101511480613454575060068260008151811061344a57613449615588565b5b6020026020010151145b8061347a57506009826000815181106134705761346f615588565b5b6020026020010151145b61349a5760036000878152602001908152602001600020600201546134b7565b816002815181106134ae576134ad615588565b5b60200260200101515b90506134ee8760400151886060015183600360008b815260200190815260200160002060050154886134e9919061561a565b6145a4565b925061350487604001518289606001518661464c565b87600001818152505050505b6135bb565b60006003600086815260200190815260200160002060030154600360008781526020019081526020016000206002015461354f919061561a565b90506135658660400151876060015183866145a4565b915060018460018151811061357d5761357c615588565b5b602002602001015114613591578181613594565b80825b80935081925050506135b086604001518288606001518561464c565b866000018181525050505b5050613815565b6009816000815181106135d8576135d7615588565b5b60200260200101510361381457846003600084815260200190815260200160002060000154036136e35760036000838152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506003600083815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836060019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506137c0565b6003600083815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060036000838152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836060019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250505b61380a8360400151826002815181106137dc576137db615588565b5b60200260200101518560600151846003815181106137fd576137fc615588565b5b602002602001015161464c565b8360000181815250505b5b8293505050505b919050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146138b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016138a8906153d6565b60405180910390fd5b6001600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508073ffffffffffffffffffffffffffffffffffffffff167f9772798610937341d23a69ec5e3f97727ff869179644b17db536f12ef374bfc460405160405180910390a250565b7311d5db9473a6e017ba4d182987bc5ab198c04a1581565b60006003600083815260200190815260200160002060120160159054906101000a900460ff16905060008160ff161161399f57600080fd5b60648160ff16141580156139b7575060c88160ff1614155b6139c057600080fd5b6003600083815260200190815260200160002060110160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614613a2e57600080fd5b613a7182336003600086815260200190815260200160002060120160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600061416d565b60646003600084815260200190815260200160002060120160156101000a81548160ff021916908360ff1602179055505050565b60006001600084815260200190815260200160002054905060006003600083815260200190815260200160002060110160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060008085600360008681526020019081526020016000206000015403613cb55760036000858152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166003600086815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168092508193505050600085600581518110613ba457613ba3615588565b5b60200260200101511115613cb05784600481518110613bc657613bc5615588565b5b6020026020010151600360008681526020019081526020016000206009016000828254613bf3919061561a565b9250508190555084600581518110613c0e57613c0d615588565b5b602002602001015160036000868152602001908152602001600020600a016000828254613c3b919061561a565b92505081905550600085600681518110613c5857613c57615588565b5b60200260200101511115613caf5784600681518110613c7a57613c79615588565b5b602002602001015160036000868152602001908152602001600020600b016000828254613ca7919061561a565b925050819055505b5b613e4e565b6003600085815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660036000868152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168092508193505050600085600581518110613d4157613d40615588565b5b60200260200101511115613e4d5784600481518110613d6357613d62615588565b5b602002602001015160036000868152602001908152602001600020600c016000828254613d90919061561a565b9250508190555084600581518110613dab57613daa615588565b5b602002602001015160036000868152602001908152602001600020600d016000828254613dd8919061561a565b92505081905550600085600681518110613df557613df4615588565b5b60200260200101511115613e4c5784600681518110613e1757613e16615588565b5b602002602001015160036000868152602001908152602001600020600e016000828254613e44919061561a565b925050819055505b5b5b600085600581518110613e6457613e63615588565b5b60200260200101511115613e9957613e98818487600581518110613e8b57613e8a615588565b5b60200260200101516146f4565b5b6000600167ffffffffffffffff811115613eb657613eb5614e59565b5b604051908082528060200260200182016040528015613ee45781602001602082028036833780820191505090505b509050600086600281518110613efd57613efc615588565b5b60200260200101511115613fe9578681600081518110613f2057613f1f615588565b5b6020026020010181815250507311d5db9473a6e017ba4d182987bc5ab198c04a1573ffffffffffffffffffffffffffffffffffffffff1663b55fb574826040518263ffffffff1660e01b8152600401613f799190614e1c565b6000604051808303816000875af1158015613f98573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190613fc1919061553f565b50613fe8838588600281518110613fdb57613fda615588565b5b60200260200101516146f4565b5b8681600081518110613ffe57613ffd615588565b5b6020026020010181815250507311d5db9473a6e017ba4d182987bc5ab198c04a1573ffffffffffffffffffffffffffffffffffffffff166375b02405826040518263ffffffff1660e01b81526004016140579190614e1c565b6000604051808303816000875af1158015614076573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061409f919061553f565b50600160008881526020019081526020016000206000905550505050505050565b6000807301c81c93f38f42497b4cebfa23eeb03f7ccfa8c773ffffffffffffffffffffffffffffffffffffffff166322fe7c6f8989898989896040518763ffffffff1660e01b815260040161411a96959493929190615aaf565b6020604051808303816000875af1158015614139573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061415d9190615b10565b9050809150509695505050505050565b60007301c81c93f38f42497b4cebfa23eeb03f7ccfa8c773ffffffffffffffffffffffffffffffffffffffff16637c0b052a8585856040518463ffffffff1660e01b81526004016141c093929190615b3d565b6020604051808303816000875af11580156141df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142039190615b10565b90508060036000878152602001908152602001600020600801600082825461422b919061561a565b925050819055505050505050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600080815260200190815260200160002060020154905081600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206001018190555081600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008081526020019081526020016000206002018190555060405180606001604052804281526020016000815260200182815250600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000848152602001908152602001600020600082015181600001556020820151816001015560408201518160020155905050505050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206001015490506000600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060020154905081600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206001018190555080600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060020181905550600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060008082016000905560018201600090556002820160009055505050505050565b6000807301c81c93f38f42497b4cebfa23eeb03f7ccfa8c773ffffffffffffffffffffffffffffffffffffffff166365593d7b878787876040518563ffffffff1660e01b81526004016145fa9493929190615800565b6040805180830381865afa158015614616573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061463a9190615b74565b90508091505080915050949350505050565b6000807301c81c93f38f42497b4cebfa23eeb03f7ccfa8c773ffffffffffffffffffffffffffffffffffffffff166366555804878787876040518563ffffffff1660e01b81526004016146a29493929190615bb4565b6040805180830381865afa1580156146be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146e29190615b74565b90508091505080915050949350505050565b6000823b90506000811115614808578373ffffffffffffffffffffffffffffffffffffffff1663095ea7b330846040518363ffffffff1660e01b815260040161473e929190615bf9565b6020604051808303816000875af115801561475d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147819190615c4e565b508373ffffffffffffffffffffffffffffffffffffffff166323b872dd3085856040518463ffffffff1660e01b81526004016147bf93929190615b3d565b6020604051808303816000875af11580156147de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148029190615c4e565b50614888565b8373ffffffffffffffffffffffffffffffffffffffff1663a9059cbb84846040518363ffffffff1660e01b8152600401614843929190615bf9565b6020604051808303816000875af1158015614862573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148869190615c4e565b505b50505050565b6040518060e001604052806000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600060ff1681525090565b604051806102a00160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600060ff168152602001600060ff1681525090565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000614a4f82614a24565b9050919050565b614a5f81614a44565b82525050565b6000602082019050614a7a6000830184614a56565b92915050565b6000604051905090565b600080fd5b600080fd5b614a9d81614a44565b8114614aa857600080fd5b50565b600081359050614aba81614a94565b92915050565b600060208284031215614ad657614ad5614a8a565b5b6000614ae484828501614aab565b91505092915050565b6000819050919050565b614b0081614aed565b8114614b0b57600080fd5b50565b600081359050614b1d81614af7565b92915050565b600080600060608486031215614b3c57614b3b614a8a565b5b6000614b4a86828701614b0e565b9350506020614b5b86828701614b0e565b9250506040614b6c86828701614b0e565b9150509250925092565b600080600080600080600080610100898b031215614b9757614b96614a8a565b5b6000614ba58b828c01614aab565b9850506020614bb68b828c01614aab565b9750506040614bc78b828c01614b0e565b9650506060614bd88b828c01614b0e565b9550506080614be98b828c01614b0e565b94505060a0614bfa8b828c01614b0e565b93505060c0614c0b8b828c01614b0e565b92505060e0614c1c8b828c01614b0e565b9150509295985092959890939650565b6000806000806000806000806000806101408b8d031215614c5057614c4f614a8a565b5b6000614c5e8d828e01614aab565b9a50506020614c6f8d828e01614aab565b9950506040614c808d828e01614b0e565b9850506060614c918d828e01614b0e565b9750506080614ca28d828e01614b0e565b96505060a0614cb38d828e01614b0e565b95505060c0614cc48d828e01614b0e565b94505060e0614cd58d828e01614b0e565b935050610100614ce78d828e01614b0e565b925050610120614cf98d828e01614b0e565b9150509295989b9194979a5092959850565b600080600060608486031215614d2457614d23614a8a565b5b6000614d3286828701614aab565b9350506020614d4386828701614b0e565b9250506040614d5486828701614b0e565b9150509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b614d9381614aed565b82525050565b6000614da58383614d8a565b60208301905092915050565b6000602082019050919050565b6000614dc982614d5e565b614dd38185614d69565b9350614dde83614d7a565b8060005b83811015614e0f578151614df68882614d99565b9750614e0183614db1565b925050600181019050614de2565b5085935050505092915050565b60006020820190508181036000830152614e368184614dbe565b905092915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b614e9182614e48565b810181811067ffffffffffffffff82111715614eb057614eaf614e59565b5b80604052505050565b6000614ec3614a80565b9050614ecf8282614e88565b919050565b600067ffffffffffffffff821115614eef57614eee614e59565b5b614ef882614e48565b9050602081019050919050565b82818337600083830152505050565b6000614f27614f2284614ed4565b614eb9565b905082815260208101848484011115614f4357614f42614e43565b5b614f4e848285614f05565b509392505050565b600082601f830112614f6b57614f6a614e3e565b5b8135614f7b848260208601614f14565b91505092915050565b600080600060608486031215614f9d57614f9c614a8a565b5b6000614fab86828701614aab565b9350506020614fbc86828701614b0e565b925050604084013567ffffffffffffffff811115614fdd57614fdc614a8f565b5b614fe986828701614f56565b9150509250925092565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61502881614ff3565b82525050565b6000602082019050615043600083018461501f565b92915050565b60008115159050919050565b61505e81615049565b82525050565b60006020820190506150796000830184615055565b92915050565b61508881614aed565b82525050565b60006020820190506150a3600083018461507f565b92915050565b6000602082840312156150bf576150be614a8a565b5b60006150cd84828501614b0e565b91505092915050565b6150df81614a44565b82525050565b600060ff82169050919050565b6150fb816150e5565b82525050565b6102a0820160008201516151186000850182614d8a565b50602082015161512b6020850182614d8a565b50604082015161513e6040850182614d8a565b5060608201516151516060850182614d8a565b5060808201516151646080850182614d8a565b5060a082015161517760a0850182614d8a565b5060c082015161518a60c0850182614d8a565b5060e082015161519d60e0850182614d8a565b506101008201516151b2610100850182614d8a565b506101208201516151c7610120850182614d8a565b506101408201516151dc610140850182614d8a565b506101608201516151f1610160850182614d8a565b50610180820151615206610180850182614d8a565b506101a082015161521b6101a0850182614d8a565b506101c08201516152306101c0850182614d8a565b506101e08201516152456101e08501826150d6565b5061020082015161525a6102008501826150d6565b5061022082015161526f6102208501826150d6565b506102408201516152846102408501826150d6565b506102608201516152996102608501826150f2565b506102808201516152ae6102808501826150f2565b50505050565b60006102a0820190506152ca6000830184615101565b92915050565b60e0820160008201516152e66000850182614d8a565b5060208201516152f96020850182614d8a565b50604082015161530c60408501826150d6565b50606082015161531f60608501826150d6565b50608082015161533260808501826150d6565b5060a082015161534560a08501826150d6565b5060c082015161535860c08501826150f2565b50505050565b600060e08201905061537360008301846152d0565b92915050565b600082825260208201905092915050565b7f4f6e6c79206f776e65722063616e2063616c6c20746869730000000000000000600082015250565b60006153c0601883615379565b91506153cb8261538a565b602082019050919050565b600060208201905081810360008301526153ef816153b3565b9050919050565b7f4f6e6c79206f7261636c652063616e2063616c6c207468697300000000000000600082015250565b600061542c601983615379565b9150615437826153f6565b602082019050919050565b6000602082019050818103600083015261545b8161541f565b9050919050565b600067ffffffffffffffff82111561547d5761547c614e59565b5b602082029050602081019050919050565b600080fd5b6000815190506154a281614af7565b92915050565b60006154bb6154b684615462565b614eb9565b905080838252602082019050602084028301858111156154de576154dd61548e565b5b835b8181101561550757806154f38882615493565b8452602084019350506020810190506154e0565b5050509392505050565b600082601f83011261552657615525614e3e565b5b81516155368482602086016154a8565b91505092915050565b60006020828403121561555557615554614a8a565b5b600082015167ffffffffffffffff81111561557357615572614a8f565b5b61557f84828501615511565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006155f182614aed565b91506155fc83614aed565b9250828203905081811115615614576156136155b7565b5b92915050565b600061562582614aed565b915061563083614aed565b9250828201905080821115615648576156476155b7565b5b92915050565b600060c0820190506156636000830189614a56565b6156706020830188614a56565b61567d6040830187614a56565b818103606083015261568f8186614dbe565b905081810360808301526156a38185614dbe565b905081810360a08301526156b78184614dbe565b9050979650505050505050565b6156cd816150e5565b81146156d857600080fd5b50565b6000815190506156ea816156c4565b92915050565b6000806040838503121561570757615706614a8a565b5b6000615715858286016156db565b925050602083015167ffffffffffffffff81111561573657615735614a8f565b5b61574285828601615511565b9150509250929050565b600060c0820190506157616000830189614a56565b61576e6020830188614a56565b61577b6040830187614a56565b615788606083018661507f565b615795608083018561507f565b6157a260a083018461507f565b979650505050505050565b6000806000606084860312156157c6576157c5614a8a565b5b60006157d4868287016156db565b93505060206157e586828701615493565b92505060406157f686828701615493565b9150509250925092565b60006080820190506158156000830187614a56565b6158226020830186614a56565b61582f604083018561507f565b61583c606083018461507f565b95945050505050565b60006020828403121561585b5761585a614a8a565b5b6000615869848285016156db565b91505092915050565b600061010082019050615888600083018b614a56565b615895602083018a614a56565b6158a26040830189614a56565b6158af606083018861507f565b6158bc608083018761507f565b6158c960a083018661507f565b6158d660c083018561507f565b6158e360e083018461507f565b9998505050505050505050565b6000806000806080858703121561590a57615909614a8a565b5b6000615918878288016156db565b9450506020615929878288016156db565b935050604061593a87828801615493565b925050606061594b87828801615493565b91505092959194509250565b600061596282614aed565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615994576159936155b7565b5b600182019050919050565b6000610120820190506159b5600083018c614a56565b6159c2602083018b614a56565b6159cf604083018a614a56565b6159dc606083018961507f565b6159e9608083018861507f565b6159f660a083018761507f565b615a0360c083018661507f565b615a1060e083018561507f565b615a1e61010083018461507f565b9a9950505050505050505050565b6000615a3782614aed565b9150615a4283614aed565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615a7b57615a7a6155b7565b5b828202905092915050565b6000604082019050615a9b600083018561507f565b615aa8602083018461507f565b9392505050565b600060c082019050615ac46000830189614a56565b615ad16020830188614a56565b615ade604083018761507f565b615aeb6060830186614a56565b615af8608083018561507f565b615b0560a083018461507f565b979650505050505050565b600060208284031215615b2657615b25614a8a565b5b6000615b3484828501615493565b91505092915050565b6000606082019050615b526000830186614a56565b615b5f6020830185614a56565b615b6c604083018461507f565b949350505050565b60008060408385031215615b8b57615b8a614a8a565b5b6000615b99858286016156db565b9250506020615baa85828601615493565b9150509250929050565b6000608082019050615bc96000830187614a56565b615bd6602083018661507f565b615be36040830185614a56565b615bf0606083018461507f565b95945050505050565b6000604082019050615c0e6000830185614a56565b615c1b602083018461507f565b9392505050565b615c2b81615049565b8114615c3657600080fd5b50565b600081519050615c4881615c22565b92915050565b600060208284031215615c6457615c63614a8a565b5b6000615c7284828501615c39565b9150509291505056fea26469706673582212208bf560699041302fdf0ffe26c519debb442e5d35f90bd1e014428b716756e7f064736f6c63430008100033