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:03.934204Z
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); } 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 gave_2; // было отдано второго токена // 0 uint256 received_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 = 0x5cec09F125f4839656164A5109BC076DAAbD6Ed6; // Контракт с депозитами address public constant contractOrders = 0x951D1F73f30716fE0d3E9f9998486fd1F48b68A1; // Контракт с книгами ордеров address public constant contractBotsHelp = 0x0Ae75C6CDf6949B900Be26d8c0fD52943e30422F; // Вспомогательный контракт ботов 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 - цена в токене с максимальным приоритетом require(msg.sender == tx.origin, "Only EOA"); // Другие контракты не могут создавать бота 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 - будет установлен токен с минимальным приоритетом (сперва идет ордер продажи, а затем ордер покупки) require(msg.sender == tx.origin, "Only EOA"); // Другие контракты не могут создавать бота 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 { // перевод токена с баланса этого контракта 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(); // начинаем расчет газа для оракула //require(msg.sender == tx.origin, "Only EOA"); // Другие контракты не могут быть оракулом 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]; // получил при обмене - второго токена } } 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[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":"gave_2","internalType":"uint256"},{"type":"uint256","name":"received_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
0x608060405273ebe894814554c8382ea6a24ccddf1527407a24f6600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555034801561006557600080fd5b50615b8180620000766000396000f3fe6080604052600436106101025760003560e01c80638da5cb5b11610095578063cada801411610064578063cada80141461033e578063caf4b41c1461037b578063df5dd1a5146103b8578063e06b4400146103e1578063e38d1a401461040c57610109565b80638da5cb5b14610282578063a97e5c93146102ad578063af640d0f146102ea578063c78f936f1461031557610109565b80632fd96ca9116100d15780632fd96ca9146101b657806330be1160146101df5780637bf02d6d146102085780638943ec021461024557610109565b80630147db0c1461010e5780630d711a9f14610139578063127e11971461016257806321c4227e1461018d57610109565b3661010957005b600080fd5b34801561011a57600080fd5b50610123610435565b60405161013091906148f3565b60405180910390f35b34801561014557600080fd5b50610160600480360381019061015b919061494e565b61044d565b005b34801561016e57600080fd5b5061017761057b565b60405161018491906148f3565b60405180910390f35b34801561019957600080fd5b506101b460048036038101906101af91906149b1565b610593565b005b3480156101c257600080fd5b506101dd60048036038101906101d89190614a04565b61151f565b005b3480156101eb57600080fd5b5061020660048036038101906102019190614aba565b6119e3565b005b34801561021457600080fd5b5061022f600480360381019061022a9190614b99565b612031565b60405161023c9190614caa565b60405180910390f35b34801561025157600080fd5b5061026c60048036038101906102679190614e12565b6126f0565b6040516102799190614ebc565b60405180910390f35b34801561028e57600080fd5b50610297612703565b6040516102a491906148f3565b60405180910390f35b3480156102b957600080fd5b506102d460048036038101906102cf919061494e565b612729565b6040516102e19190614ef2565b60405180910390f35b3480156102f657600080fd5b506102ff61277f565b60405161030c9190614f1c565b60405180910390f35b34801561032157600080fd5b5061033c60048036038101906103379190614f37565b612785565b005b34801561034a57600080fd5b5061036560048036038101906103609190614f37565b612b87565b6040516103729190615118565b60405180910390f35b34801561038757600080fd5b506103a2600480360381019061039d9190614f37565b612dc9565b6040516103af91906151c2565b60405180910390f35b3480156103c457600080fd5b506103df60048036038101906103da919061494e565b6138ad565b005b3480156103ed57600080fd5b506103f66139db565b60405161040391906148f3565b60405180910390f35b34801561041857600080fd5b50610433600480360381019061042e9190614f37565b6139f3565b005b730ae75c6cdf6949b900be26d8c0fd52943e30422f81565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104dd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104d49061523a565b60405180910390fd5b6000600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508073ffffffffffffffffffffffffffffffffffffffff167f8f0e1537186f631af722391ce4e08495881ee25f0d06ed39dd7e8db6ce25d3c860405160405180910390a250565b735cec09f125f4839656164a5109bc076daabd6ed681565b60011515600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514610626576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161061d906152a6565b60405180910390fd5b60005a905060006001600086815260200190815260200160002054905060646003600083815260200190815260200160002060100160159054906101000a900460ff1660ff161461067657600080fd5b600060036000838152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073951d1f73f30716fe0d3e9f9998486fd1f48b68a173ffffffffffffffffffffffffffffffffffffffff16636da42a15886040518263ffffffff1660e01b81526004016107009190614f1c565b600060405180830381865afa15801561071d573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061074691906153a3565b905060078160008151811061075e5761075d6153ec565b5b602002602001015103611195576000600182600181518110610783576107826153ec565b5b6020026020010151146107cd57600360008581526020019081526020016000206005015460036000868152602001908152602001600020600401546107c8919061544a565b610806565b60036000858152602001908152602001600020600501546003600086815260200190815260200160002060040154610805919061547e565b5b905061081061472a565b60036000868152602001908152602001600020600d0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16816040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060036000868152602001908152602001600020600e0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16816060019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600380600087815260200190815260200160002060100160149054906101000a900460ff1660ff1603610ed3578860036000878152602001908152602001600020600001541461095257600360008681526020019081526020016000206000015461096a565b60036000868152602001908152602001600020600101545b816020018181525050600073951d1f73f30716fe0d3e9f9998486fd1f48b68a173ffffffffffffffffffffffffffffffffffffffff16636da42a1583602001516040518263ffffffff1660e01b81526004016109c69190614f1c565b600060405180830381865afa1580156109e3573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610a0c91906153a3565b905060606000600667ffffffffffffffff811115610a2d57610a2c614ce7565b5b604051908082528060200260200182016040528015610a5b5781602001602082028036833780820191505090505b509050600360008981526020019081526020016000206002015481600081518110610a8957610a886153ec565b5b602002602001018181525050600360008981526020019081526020016000206003015481600181518110610ac057610abf6153ec565b5b6020026020010181815250508481600281518110610ae157610ae06153ec565b5b602002602001018181525050600360008981526020019081526020016000206005015481600381518110610b1857610b176153ec565b5b602002602001018181525050600360008981526020019081526020016000206006015481600481518110610b4f57610b4e6153ec565b5b602002602001018181525050600360008981526020019081526020016000206007015481600581518110610b8657610b856153ec565b5b602002602001018181525050730ae75c6cdf6949b900be26d8c0fd52943e30422f73ffffffffffffffffffffffffffffffffffffffff1663b10557348886604001518760600151858b896040518763ffffffff1660e01b8152600401610bf1969594939291906154b2565b600060405180830381865afa158015610c0e573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610c379190615554565b8560c0018194508260ff1660ff16815250505060008460c0015160ff161115610cf05733600360008a815260200190815260200160002060100160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508360c00151600360008a815260200190815260200160002060100160156101000a81548160ff021916908360ff16021790555050505050505050505061151a565b610cfa8c87613b31565b600084602001511115610d1657610d15846020015184613b31565b5b84600360008a815260200190815260200160002060040181905550600082600081518110610d4757610d466153ec565b5b60200260200101511115610de15760008b9050610da688866040015185600081518110610d7757610d766153ec565b5b6020026020010151886060015187600181518110610d9857610d976153ec565b5b602002602001015186614072565b905088600160008381526020019081526020016000208190555080600360008b81526020019081526020016000206000018190555050610dfe565b6000600360008a8152602001908152602001600020600001819055505b600082600281518110610e1457610e136153ec565b5b60200260200101511115610eae5760008a9050610e7388866060015185600281518110610e4457610e436153ec565b5b6020026020010151886040015187600381518110610e6557610e646153ec565b5b602002602001015186614072565b905088600160008381526020019081526020016000208190555080600360008b81526020019081526020016000206001018190555050610ecb565b6000600360008a8152602001908152602001600020600101819055505b50505061118e565b600060036000878152602001908152602001600020600301546003600088815260200190815260200160002060020154610f0d919061547e565b9050730ae75c6cdf6949b900be26d8c0fd52943e30422f73ffffffffffffffffffffffffffffffffffffffff1663fe908a9c86846040015185606001518588600360008e8152602001908152602001600020600601546040518763ffffffff1660e01b8152600401610f84969594939291906155b0565b606060405180830381865afa158015610fa1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc59190615611565b8460c001856000018660200183815250838152508360ff1660ff1681525050505060648260c0015160ff160361108d57610fff8a85613b31565b8060036000888152602001908152602001600020600201819055508260036000888152602001908152602001600020600401819055506110538583604001518460000151856060015186602001518e614072565b905085600160008381526020019081526020016000208190555080600360008881526020019081526020016000206000018190555061118c565b60c88260c0015160ff16036110f7576110a68a85613b31565b6000600360008881526020019081526020016000206000018190555060c86003600088815260200190815260200160002060100160156101000a81548160ff021916908360ff16021790555061118b565b336003600088815260200190815260200160002060100160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508160c001516003600088815260200190815260200160002060100160156101000a81548160ff021916908360ff1602179055505050505050505061151a565b5b505b50506114fe565b6009816000815181106111ab576111aa6153ec565b5b6020026020010151036114f45760008060008960036000888152602001908152602001600020600001541461124d5760036000878152602001908152602001600020600e0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660036000888152602001908152602001600020600d0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166112bc565b60036000878152602001908152602001600020600d0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660036000888152602001908152602001600020600e0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff165b91509150730ae75c6cdf6949b900be26d8c0fd52943e30422f73ffffffffffffffffffffffffffffffffffffffff1663ad148af4868487600281518110611306576113056153ec565b5b602002602001015188600281518110611322576113216153ec565b5b60200260200101516040518563ffffffff1660e01b81526004016113499493929190615664565b602060405180830381865afa158015611366573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138a91906156a9565b925060008360ff16111561142857336003600088815260200190815260200160002060100160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550826003600088815260200190815260200160002060100160156101000a81548160ff021916908360ff1602179055505050505050505061151a565b6114328a85613b31565b600061147886848760028151811061144d5761144c6153ec565b5b6020026020010151858960038151811061146a576114696153ec565b5b60200260200101518f614072565b90508660016000838152602001908152602001600020819055508a6003600089815260200190815260200160002060000154036114cf578060036000898152602001908152602001600020600001819055506114eb565b8060036000898152602001908152602001600020600101819055505b505050506114fd565b5050505061151a565b5b6115158383335a88611510919061544a565b61411f565b505050505b505050565b3273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461158d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161158490615722565b60405180910390fd5b6115956147c2565b868160400181815250508581606001818152505084816080018181525050838160a0018181525050828160c001818152505088816101a0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505087816101c0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505033816101e0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600080730ae75c6cdf6949b900be26d8c0fd52943e30422f73ffffffffffffffffffffffffffffffffffffffff1663acbfa21d338d8d8d8d8d8d8d6040518963ffffffff1660e01b81526004016116d0989796959493929190615742565b608060405180830381865afa1580156116ed573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061171191906157c0565b866102400187610220018296508397508460ff1660ff168152508460ff1660ff1681525050505050606483610240015160ff161461174e57600080fd5b61175c338c848d8589614072565b836000018181525050600080815461177390615827565b919050819055506000805490508360036000838152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015560a0820151816005015560c0820151816006015560e082015181600701556101008201518160080155610120820151816009015561014082015181600a015561016082015181600b015561018082015181600c01556101a082015181600d0160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101c082015181600e0160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101e082015181600f0160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102008201518160100160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102208201518160100160146101000a81548160ff021916908360ff1602179055506102408201518160100160156101000a81548160ff021916908360ff160217905550905050806001600086600001518152602001908152602001600020819055506119a833826141eb565b807ff9e873657e730881eafc125ef40143f79658208a374f800d4b5b34d98432e6ea60405160405180910390a2505050505050505050505050565b3273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611a51576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a4890615722565b60405180910390fd5b611a596147c2565b6000600267ffffffffffffffff811115611a7657611a75614ce7565b5b604051908082528060200260200182016040528015611aa45781602001602082028036833780820191505090505b509050730ae75c6cdf6949b900be26d8c0fd52943e30422f73ffffffffffffffffffffffffffffffffffffffff166390b5ef77338e8e8e8e8e8e8e8e6040518a63ffffffff1660e01b8152600401611b049998979695949392919061586f565b606060405180830381865afa158015611b21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b459190615611565b846102400184600081518110611b5e57611b5d6153ec565b5b6020026020010185600181518110611b7957611b786153ec565b5b6020026020010183815250838152508360ff1660ff16815250505050606582610240015160ff1603611bc4578a8c809c50819d505050606482610240019060ff16908160ff16815250505b606482610240015160ff1614611bd957600080fd5b898260400181815250508882606001818152505087826080018181525050868260a0018181525050858260c0018181525050848260e00181815250508b826101a0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508a826101c0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505033826101e0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600382610220019060ff16908160ff16815250506000808154611ce290615827565b91905081905550600080549050600082600081518110611d0557611d046153ec565b5b60200260200101511115611d6c57611d4633846101a001518d866101c0015186600081518110611d3857611d376153ec565b5b60200260200101518a614072565b836000018181525050806001600085600001518152602001908152602001600020819055505b600082600181518110611d8257611d816153ec565b5b60200260200101511115611de957611dc333846101c0015184600181518110611dae57611dad6153ec565b5b6020026020010151866101a001518e89614072565b836020018181525050806001600085602001518152602001908152602001600020819055505b8260036000838152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015560a0820151816005015560c0820151816006015560e082015181600701556101008201518160080155610120820151816009015561014082015181600a015561016082015181600b015561018082015181600c01556101a082015181600d0160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101c082015181600e0160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101e082015181600f0160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102008201518160100160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102208201518160100160146101000a81548160ff021916908360ff1602179055506102408201518160100160156101000a81548160ff021916908360ff160217905550905050611ff533826141eb565b807ff9e873657e730881eafc125ef40143f79658208a374f800d4b5b34d98432e6ea60405160405180910390a250505050505050505050505050565b6060600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000848152602001908152602001600020600101549250600083036120e257600167ffffffffffffffff8111156120ac576120ab614ce7565b5b6040519080825280602002602001820160405280156120da5781602001602082028036833780820191505090505b5090506126e9565b600080600e846120f291906158fc565b67ffffffffffffffff81111561210b5761210a614ce7565b5b6040519080825280602002602001820160405280156121395781602001602082028036833780820191505090505b50905060005b848110156126e25760008603156126e2578582848061215d90615827565b9550815181106121705761216f6153ec565b5b602002602001018181525050600260008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000878152602001908152602001600020600001548284806121dc90615827565b9550815181106121ef576121ee6153ec565b5b6020026020010181815250506003600087815260200190815260200160002060100160149054906101000a900460ff1660ff1682848061222e90615827565b955081518110612241576122406153ec565b5b602002602001018181525050600073951d1f73f30716fe0d3e9f9998486fd1f48b68a173ffffffffffffffffffffffffffffffffffffffff166336511013600360008a815260200190815260200160002060000154600360008b8152602001908152602001600020600101546040518363ffffffff1660e01b81526004016122ca929190615956565b600060405180830381865afa1580156122e7573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061231091906153a3565b905080600081518110612326576123256153ec565b5b602002602001015183858061233a90615827565b96508151811061234d5761234c6153ec565b5b6020026020010181815250508060018151811061236d5761236c6153ec565b5b602002602001015183858061238190615827565b965081518110612394576123936153ec565b5b602002602001018181525050806002815181106123b4576123b36153ec565b5b60200260200101518385806123c890615827565b9650815181106123db576123da6153ec565b5b602002602001018181525050806003815181106123fb576123fa6153ec565b5b602002602001015183858061240f90615827565b965081518110612422576124216153ec565b5b602002602001018181525050600360008881526020019081526020016000206009015483858061245190615827565b965081518110612464576124636153ec565b5b60200260200101818152505060036000888152602001908152602001600020600a015483858061249390615827565b9650815181106124a6576124a56153ec565b5b60200260200101818152505060036000888152602001908152602001600020600b01548385806124d590615827565b9650815181106124e8576124e76153ec565b5b60200260200101818152505060036000888152602001908152602001600020600c015483858061251790615827565b96508151811061252a576125296153ec565b5b60200260200101818152505060036000888152602001908152602001600020600d0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1683858061258f90615827565b9650815181106125a2576125a16153ec565b5b60200260200101818152505060036000888152602001908152602001600020600e0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1683858061260790615827565b96508151811061261a576126196153ec565b5b6020026020010181815250506003600088815260200190815260200160002060100160159054906101000a900460ff1660ff1683858061265990615827565b96508151811061266c5761266b6153ec565b5b602002602001018181525050600260008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008881526020019081526020016000206001015496505080806126da90615827565b91505061213f565b5080925050505b9392505050565b6000638943ec0260e01b90509392505050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b60005481565b6000600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002060000154116127e557600080fd5b60006003600083815260200190815260200160002060100160159054906101000a900460ff16905060648160ff1614158015612825575060c88160ff1614155b1561286e5761286d82336003600086815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600061411f565b5b60c88160ff1614612a0a57600060036000848152602001908152602001600020600001549050600060036000858152602001908152602001600020600101549050600082111561295b57600073951d1f73f30716fe0d3e9f9998486fd1f48b68a173ffffffffffffffffffffffffffffffffffffffff16636da42a15846040518263ffffffff1660e01b81526004016129079190614f1c565b600060405180830381865afa158015612924573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061294d91906153a3565b90506129598382613b31565b505b6000811115612a0757600073951d1f73f30716fe0d3e9f9998486fd1f48b68a173ffffffffffffffffffffffffffffffffffffffff16636da42a15836040518263ffffffff1660e01b81526004016129b39190614f1c565b600060405180830381865afa1580156129d0573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906129f991906153a3565b9050612a058282613b31565b505b50505b612a143383614385565b60036000838152602001908152602001600020600080820160009055600182016000905560028201600090556003820160009055600482016000905560058201600090556006820160009055600782016000905560088201600090556009820160009055600a820160009055600b820160009055600c820160009055600d820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600e820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600f820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556010820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556010820160146101000a81549060ff02191690556010820160156101000a81549060ff02191690555050817fa72f695a885e7ae6c69d169d271a0fff49ed6dea3bf49329e817a3cc4666cb4560405160405180910390a25050565b612b8f6147c2565b600360008381526020019081526020016000206040518061026001604052908160008201548152602001600182015481526020016002820154815260200160038201548152602001600482015481526020016005820154815260200160068201548152602001600782015481526020016008820154815260200160098201548152602001600a8201548152602001600b8201548152602001600c8201548152602001600d820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600e820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600f820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016010820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016010820160149054906101000a900460ff1660ff1660ff1681526020016010820160159054906101000a900460ff1660ff1660ff16815250509050919050565b612dd161472a565b612dd961472a565b6000600160008581526020019081526020016000205490506003600082815260200190815260200160002060100160159054906101000a900460ff168260c0019060ff16908160ff168152505060648260c0015160ff1614612e3f5781925050506138a8565b600073951d1f73f30716fe0d3e9f9998486fd1f48b68a173ffffffffffffffffffffffffffffffffffffffff16636da42a15866040518263ffffffff1660e01b8152600401612e8e9190614f1c565b600060405180830381865afa158015612eab573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190612ed491906153a3565b9050600781600081518110612eec57612eeb6153ec565b5b60200260200101510361364e576000600182600181518110612f1157612f106153ec565b5b602002602001015114612f5b5760036000848152602001908152602001600020600501546003600085815260200190815260200160002060040154612f56919061544a565b612f94565b60036000848152602001908152602001600020600501546003600085815260200190815260200160002060040154612f93919061547e565b5b9050600060036000858152602001908152602001600020600d0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16856040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060036000858152602001908152602001600020600e0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16856060019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600380600086815260200190815260200160002060100160149054906101000a900460ff1660ff16036135a15784606001518560400151866080018760a0018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152508273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815250505060018360018151811061312b5761312a6153ec565b5b60200260200101510361336c5761318385604001518660600151600360008881526020019081526020016000206002015460036000898152602001908152602001600020600501548661317e919061547e565b614556565b90506131af856040015160036000878152602001908152602001600020600201548760600151846145fe565b856000018181525050600073951d1f73f30716fe0d3e9f9998486fd1f48b68a173ffffffffffffffffffffffffffffffffffffffff16636da42a1560036000888152602001908152602001600020600101546040518263ffffffff1660e01b815260040161321d9190614f1c565b600060405180830381865afa15801561323a573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061326391906153a3565b9050600060018260008151811061327d5761327c6153ec565b5b602002602001015114806132ac57506006826000815181106132a2576132a16153ec565b5b6020026020010151145b806132d257506009826000815181106132c8576132c76153ec565b5b6020026020010151145b6132f257600360008781526020019081526020016000206003015461330f565b81600381518110613306576133056153ec565b5b60200260200101515b905061334687608001518860a0015183600360008b81526020019081526020016000206005015488613341919061544a565b614556565b925061335c8760800151848960a00151846145fe565b876020018181525050505061359c565b6133b785608001518660a0015160036000888152602001908152602001600020600301546003600089815260200190815260200160002060050154866133b2919061544a565b614556565b90506133e38560800151828760a0015160036000898152602001908152602001600020600301546145fe565b856020018181525050600073951d1f73f30716fe0d3e9f9998486fd1f48b68a173ffffffffffffffffffffffffffffffffffffffff16636da42a1560036000888152602001908152602001600020600001546040518263ffffffff1660e01b81526004016134519190614f1c565b600060405180830381865afa15801561346e573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061349791906153a3565b905060006001826000815181106134b1576134b06153ec565b5b602002602001015114806134e057506006826000815181106134d6576134d56153ec565b5b6020026020010151145b8061350657506009826000815181106134fc576134fb6153ec565b5b6020026020010151145b613526576003600087815260200190815260200160002060020154613543565b8160028151811061353a576135396153ec565b5b60200260200101515b905061357a8760400151886060015183600360008b81526020019081526020016000206005015488613575919061547e565b614556565b92506135908760400151828960600151866145fe565b87600001818152505050505b613647565b6000600360008681526020019081526020016000206003015460036000878152602001908152602001600020600201546135db919061547e565b90506135f1866040015187606001518386614556565b9150600184600181518110613609576136086153ec565b5b60200260200101511461361d578181613620565b80825b809350819250505061363c8660400151828860600151856145fe565b866000018181525050505b50506138a1565b600981600081518110613664576136636153ec565b5b6020026020010151036138a0578460036000848152602001908152602001600020600001540361376f5760036000838152602001908152602001600020600d0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060036000838152602001908152602001600020600e0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836060019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505061384c565b60036000838152602001908152602001600020600e0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060036000838152602001908152602001600020600d0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836060019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250505b613896836040015182600281518110613868576138676153ec565b5b6020026020010151856060015184600381518110613889576138886153ec565b5b60200260200101516145fe565b8360000181815250505b5b8293505050505b919050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461393d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016139349061523a565b60405180910390fd5b6001600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508073ffffffffffffffffffffffffffffffffffffffff167f9772798610937341d23a69ec5e3f97727ff869179644b17db536f12ef374bfc460405160405180910390a250565b73951d1f73f30716fe0d3e9f9998486fd1f48b68a181565b60006003600083815260200190815260200160002060100160159054906101000a900460ff16905060008160ff1611613a2b57600080fd5b60648160ff1614158015613a43575060c88160ff1614155b613a4c57600080fd5b60036000838152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614613aba57600080fd5b613afd82336003600086815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600061411f565b60646003600084815260200190815260200160002060100160156101000a81548160ff021916908360ff1602179055505050565b600060016000848152602001908152602001600020549050600060036000838152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060008085600360008681526020019081526020016000206000015403613cd45760036000858152602001908152602001600020600d0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660036000868152602001908152602001600020600e0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168092508193505050600085600581518110613c3057613c2f6153ec565b5b60200260200101511115613ccf5784600481518110613c5257613c516153ec565b5b6020026020010151600360008681526020019081526020016000206009016000828254613c7f919061547e565b9250508190555084600581518110613c9a57613c996153ec565b5b602002602001015160036000868152602001908152602001600020600a016000828254613cc7919061547e565b925050819055505b613e00565b60036000858152602001908152602001600020600e0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660036000868152602001908152602001600020600d0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168092508193505050600085600581518110613d6057613d5f6153ec565b5b60200260200101511115613dff5784600481518110613d8257613d816153ec565b5b602002602001015160036000868152602001908152602001600020600b016000828254613daf919061547e565b9250508190555084600581518110613dca57613dc96153ec565b5b602002602001015160036000868152602001908152602001600020600c016000828254613df7919061547e565b925050819055505b5b600085600581518110613e1657613e156153ec565b5b60200260200101511115613e4b57613e4a818487600581518110613e3d57613e3c6153ec565b5b60200260200101516146a6565b5b6000600167ffffffffffffffff811115613e6857613e67614ce7565b5b604051908082528060200260200182016040528015613e965781602001602082028036833780820191505090505b509050600086600281518110613eaf57613eae6153ec565b5b60200260200101511115613f9b578681600081518110613ed257613ed16153ec565b5b60200260200101818152505073951d1f73f30716fe0d3e9f9998486fd1f48b68a173ffffffffffffffffffffffffffffffffffffffff1663b55fb574826040518263ffffffff1660e01b8152600401613f2b9190614caa565b6000604051808303816000875af1158015613f4a573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190613f7391906153a3565b50613f9a838588600281518110613f8d57613f8c6153ec565b5b60200260200101516146a6565b5b8681600081518110613fb057613faf6153ec565b5b60200260200101818152505073951d1f73f30716fe0d3e9f9998486fd1f48b68a173ffffffffffffffffffffffffffffffffffffffff166375b02405826040518263ffffffff1660e01b81526004016140099190614caa565b6000604051808303816000875af1158015614028573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061405191906153a3565b50600160008881526020019081526020016000206000905550505050505050565b600080735cec09f125f4839656164a5109bc076daabd6ed673ffffffffffffffffffffffffffffffffffffffff166322fe7c6f8989898989896040518763ffffffff1660e01b81526004016140cc9695949392919061597f565b6020604051808303816000875af11580156140eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061410f91906159e0565b9050809150509695505050505050565b6000735cec09f125f4839656164a5109bc076daabd6ed673ffffffffffffffffffffffffffffffffffffffff16637c0b052a8585856040518463ffffffff1660e01b815260040161417293929190615a0d565b6020604051808303816000875af1158015614191573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141b591906159e0565b9050806003600087815260200190815260200160002060080160008282546141dd919061547e565b925050819055505050505050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600080815260200190815260200160002060020154905081600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206001018190555081600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008081526020019081526020016000206002018190555060405180606001604052804281526020016000815260200182815250600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000848152602001908152602001600020600082015181600001556020820151816001015560408201518160020155905050505050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206001015490506000600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060020154905081600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206001018190555080600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060020181905550600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060008082016000905560018201600090556002820160009055505050505050565b600080735cec09f125f4839656164a5109bc076daabd6ed673ffffffffffffffffffffffffffffffffffffffff166365593d7b878787876040518563ffffffff1660e01b81526004016145ac9493929190615664565b6040805180830381865afa1580156145c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145ec9190615a44565b90508091505080915050949350505050565b600080735cec09f125f4839656164a5109bc076daabd6ed673ffffffffffffffffffffffffffffffffffffffff166366555804878787876040518563ffffffff1660e01b81526004016146549493929190615a84565b6040805180830381865afa158015614670573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146949190615a44565b90508091505080915050949350505050565b8273ffffffffffffffffffffffffffffffffffffffff1663a9059cbb83836040518363ffffffff1660e01b81526004016146e1929190615ac9565b6020604051808303816000875af1158015614700573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147249190615b1e565b50505050565b6040518060e001604052806000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600060ff1681525090565b60405180610260016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600060ff168152602001600060ff1681525090565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006148dd826148b2565b9050919050565b6148ed816148d2565b82525050565b600060208201905061490860008301846148e4565b92915050565b6000604051905090565b600080fd5b600080fd5b61492b816148d2565b811461493657600080fd5b50565b60008135905061494881614922565b92915050565b60006020828403121561496457614963614918565b5b600061497284828501614939565b91505092915050565b6000819050919050565b61498e8161497b565b811461499957600080fd5b50565b6000813590506149ab81614985565b92915050565b6000806000606084860312156149ca576149c9614918565b5b60006149d88682870161499c565b93505060206149e98682870161499c565b92505060406149fa8682870161499c565b9150509250925092565b600080600080600080600080610100898b031215614a2557614a24614918565b5b6000614a338b828c01614939565b9850506020614a448b828c01614939565b9750506040614a558b828c0161499c565b9650506060614a668b828c0161499c565b9550506080614a778b828c0161499c565b94505060a0614a888b828c0161499c565b93505060c0614a998b828c0161499c565b92505060e0614aaa8b828c0161499c565b9150509295985092959890939650565b6000806000806000806000806000806101408b8d031215614ade57614add614918565b5b6000614aec8d828e01614939565b9a50506020614afd8d828e01614939565b9950506040614b0e8d828e0161499c565b9850506060614b1f8d828e0161499c565b9750506080614b308d828e0161499c565b96505060a0614b418d828e0161499c565b95505060c0614b528d828e0161499c565b94505060e0614b638d828e0161499c565b935050610100614b758d828e0161499c565b925050610120614b878d828e0161499c565b9150509295989b9194979a5092959850565b600080600060608486031215614bb257614bb1614918565b5b6000614bc086828701614939565b9350506020614bd18682870161499c565b9250506040614be28682870161499c565b9150509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b614c218161497b565b82525050565b6000614c338383614c18565b60208301905092915050565b6000602082019050919050565b6000614c5782614bec565b614c618185614bf7565b9350614c6c83614c08565b8060005b83811015614c9d578151614c848882614c27565b9750614c8f83614c3f565b925050600181019050614c70565b5085935050505092915050565b60006020820190508181036000830152614cc48184614c4c565b905092915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b614d1f82614cd6565b810181811067ffffffffffffffff82111715614d3e57614d3d614ce7565b5b80604052505050565b6000614d5161490e565b9050614d5d8282614d16565b919050565b600067ffffffffffffffff821115614d7d57614d7c614ce7565b5b614d8682614cd6565b9050602081019050919050565b82818337600083830152505050565b6000614db5614db084614d62565b614d47565b905082815260208101848484011115614dd157614dd0614cd1565b5b614ddc848285614d93565b509392505050565b600082601f830112614df957614df8614ccc565b5b8135614e09848260208601614da2565b91505092915050565b600080600060608486031215614e2b57614e2a614918565b5b6000614e3986828701614939565b9350506020614e4a8682870161499c565b925050604084013567ffffffffffffffff811115614e6b57614e6a61491d565b5b614e7786828701614de4565b9150509250925092565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b614eb681614e81565b82525050565b6000602082019050614ed16000830184614ead565b92915050565b60008115159050919050565b614eec81614ed7565b82525050565b6000602082019050614f076000830184614ee3565b92915050565b614f168161497b565b82525050565b6000602082019050614f316000830184614f0d565b92915050565b600060208284031215614f4d57614f4c614918565b5b6000614f5b8482850161499c565b91505092915050565b614f6d816148d2565b82525050565b600060ff82169050919050565b614f8981614f73565b82525050565b61026082016000820151614fa66000850182614c18565b506020820151614fb96020850182614c18565b506040820151614fcc6040850182614c18565b506060820151614fdf6060850182614c18565b506080820151614ff26080850182614c18565b5060a082015161500560a0850182614c18565b5060c082015161501860c0850182614c18565b5060e082015161502b60e0850182614c18565b50610100820151615040610100850182614c18565b50610120820151615055610120850182614c18565b5061014082015161506a610140850182614c18565b5061016082015161507f610160850182614c18565b50610180820151615094610180850182614c18565b506101a08201516150a96101a0850182614f64565b506101c08201516150be6101c0850182614f64565b506101e08201516150d36101e0850182614f64565b506102008201516150e8610200850182614f64565b506102208201516150fd610220850182614f80565b50610240820151615112610240850182614f80565b50505050565b60006102608201905061512e6000830184614f8f565b92915050565b60e08201600082015161514a6000850182614c18565b50602082015161515d6020850182614c18565b5060408201516151706040850182614f64565b5060608201516151836060850182614f64565b5060808201516151966080850182614f64565b5060a08201516151a960a0850182614f64565b5060c08201516151bc60c0850182614f80565b50505050565b600060e0820190506151d76000830184615134565b92915050565b600082825260208201905092915050565b7f4f6e6c79206f776e65722063616e2063616c6c20746869730000000000000000600082015250565b60006152246018836151dd565b915061522f826151ee565b602082019050919050565b6000602082019050818103600083015261525381615217565b9050919050565b7f4f6e6c79206f7261636c652063616e2063616c6c207468697300000000000000600082015250565b60006152906019836151dd565b915061529b8261525a565b602082019050919050565b600060208201905081810360008301526152bf81615283565b9050919050565b600067ffffffffffffffff8211156152e1576152e0614ce7565b5b602082029050602081019050919050565b600080fd5b60008151905061530681614985565b92915050565b600061531f61531a846152c6565b614d47565b90508083825260208201905060208402830185811115615342576153416152f2565b5b835b8181101561536b578061535788826152f7565b845260208401935050602081019050615344565b5050509392505050565b600082601f83011261538a57615389614ccc565b5b815161539a84826020860161530c565b91505092915050565b6000602082840312156153b9576153b8614918565b5b600082015167ffffffffffffffff8111156153d7576153d661491d565b5b6153e384828501615375565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006154558261497b565b91506154608361497b565b92508282039050818111156154785761547761541b565b5b92915050565b60006154898261497b565b91506154948361497b565b92508282019050808211156154ac576154ab61541b565b5b92915050565b600060c0820190506154c760008301896148e4565b6154d460208301886148e4565b6154e160408301876148e4565b81810360608301526154f38186614c4c565b905081810360808301526155078185614c4c565b905081810360a083015261551b8184614c4c565b9050979650505050505050565b61553181614f73565b811461553c57600080fd5b50565b60008151905061554e81615528565b92915050565b6000806040838503121561556b5761556a614918565b5b60006155798582860161553f565b925050602083015167ffffffffffffffff81111561559a5761559961491d565b5b6155a685828601615375565b9150509250929050565b600060c0820190506155c560008301896148e4565b6155d260208301886148e4565b6155df60408301876148e4565b6155ec6060830186614f0d565b6155f96080830185614f0d565b61560660a0830184614f0d565b979650505050505050565b60008060006060848603121561562a57615629614918565b5b60006156388682870161553f565b9350506020615649868287016152f7565b925050604061565a868287016152f7565b9150509250925092565b600060808201905061567960008301876148e4565b61568660208301866148e4565b6156936040830185614f0d565b6156a06060830184614f0d565b95945050505050565b6000602082840312156156bf576156be614918565b5b60006156cd8482850161553f565b91505092915050565b7f4f6e6c7920454f41000000000000000000000000000000000000000000000000600082015250565b600061570c6008836151dd565b9150615717826156d6565b602082019050919050565b6000602082019050818103600083015261573b816156ff565b9050919050565b600061010082019050615758600083018b6148e4565b615765602083018a6148e4565b61577260408301896148e4565b61577f6060830188614f0d565b61578c6080830187614f0d565b61579960a0830186614f0d565b6157a660c0830185614f0d565b6157b360e0830184614f0d565b9998505050505050505050565b600080600080608085870312156157da576157d9614918565b5b60006157e88782880161553f565b94505060206157f98782880161553f565b935050604061580a878288016152f7565b925050606061581b878288016152f7565b91505092959194509250565b60006158328261497b565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036158645761586361541b565b5b600182019050919050565b600061012082019050615885600083018c6148e4565b615892602083018b6148e4565b61589f604083018a6148e4565b6158ac6060830189614f0d565b6158b96080830188614f0d565b6158c660a0830187614f0d565b6158d360c0830186614f0d565b6158e060e0830185614f0d565b6158ee610100830184614f0d565b9a9950505050505050505050565b60006159078261497b565b91506159128361497b565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561594b5761594a61541b565b5b828202905092915050565b600060408201905061596b6000830185614f0d565b6159786020830184614f0d565b9392505050565b600060c08201905061599460008301896148e4565b6159a160208301886148e4565b6159ae6040830187614f0d565b6159bb60608301866148e4565b6159c86080830185614f0d565b6159d560a0830184614f0d565b979650505050505050565b6000602082840312156159f6576159f5614918565b5b6000615a04848285016152f7565b91505092915050565b6000606082019050615a2260008301866148e4565b615a2f60208301856148e4565b615a3c6040830184614f0d565b949350505050565b60008060408385031215615a5b57615a5a614918565b5b6000615a698582860161553f565b9250506020615a7a858286016152f7565b9150509250929050565b6000608082019050615a9960008301876148e4565b615aa66020830186614f0d565b615ab360408301856148e4565b615ac06060830184614f0d565b95945050505050565b6000604082019050615ade60008301856148e4565b615aeb6020830184614f0d565b9392505050565b615afb81614ed7565b8114615b0657600080fd5b50565b600081519050615b1881615af2565b92915050565b600060208284031215615b3457615b33614918565b5b6000615b4284828501615b09565b9150509291505056fea264697066735822122019d8abc0ce51426296fc5251d58d7ccdfdd241ae2fa49554147dc9681798e0cf64736f6c63430008100033
Deployed ByteCode
0x6080604052600436106101025760003560e01c80638da5cb5b11610095578063cada801411610064578063cada80141461033e578063caf4b41c1461037b578063df5dd1a5146103b8578063e06b4400146103e1578063e38d1a401461040c57610109565b80638da5cb5b14610282578063a97e5c93146102ad578063af640d0f146102ea578063c78f936f1461031557610109565b80632fd96ca9116100d15780632fd96ca9146101b657806330be1160146101df5780637bf02d6d146102085780638943ec021461024557610109565b80630147db0c1461010e5780630d711a9f14610139578063127e11971461016257806321c4227e1461018d57610109565b3661010957005b600080fd5b34801561011a57600080fd5b50610123610435565b60405161013091906148f3565b60405180910390f35b34801561014557600080fd5b50610160600480360381019061015b919061494e565b61044d565b005b34801561016e57600080fd5b5061017761057b565b60405161018491906148f3565b60405180910390f35b34801561019957600080fd5b506101b460048036038101906101af91906149b1565b610593565b005b3480156101c257600080fd5b506101dd60048036038101906101d89190614a04565b61151f565b005b3480156101eb57600080fd5b5061020660048036038101906102019190614aba565b6119e3565b005b34801561021457600080fd5b5061022f600480360381019061022a9190614b99565b612031565b60405161023c9190614caa565b60405180910390f35b34801561025157600080fd5b5061026c60048036038101906102679190614e12565b6126f0565b6040516102799190614ebc565b60405180910390f35b34801561028e57600080fd5b50610297612703565b6040516102a491906148f3565b60405180910390f35b3480156102b957600080fd5b506102d460048036038101906102cf919061494e565b612729565b6040516102e19190614ef2565b60405180910390f35b3480156102f657600080fd5b506102ff61277f565b60405161030c9190614f1c565b60405180910390f35b34801561032157600080fd5b5061033c60048036038101906103379190614f37565b612785565b005b34801561034a57600080fd5b5061036560048036038101906103609190614f37565b612b87565b6040516103729190615118565b60405180910390f35b34801561038757600080fd5b506103a2600480360381019061039d9190614f37565b612dc9565b6040516103af91906151c2565b60405180910390f35b3480156103c457600080fd5b506103df60048036038101906103da919061494e565b6138ad565b005b3480156103ed57600080fd5b506103f66139db565b60405161040391906148f3565b60405180910390f35b34801561041857600080fd5b50610433600480360381019061042e9190614f37565b6139f3565b005b730ae75c6cdf6949b900be26d8c0fd52943e30422f81565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104dd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104d49061523a565b60405180910390fd5b6000600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508073ffffffffffffffffffffffffffffffffffffffff167f8f0e1537186f631af722391ce4e08495881ee25f0d06ed39dd7e8db6ce25d3c860405160405180910390a250565b735cec09f125f4839656164a5109bc076daabd6ed681565b60011515600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514610626576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161061d906152a6565b60405180910390fd5b60005a905060006001600086815260200190815260200160002054905060646003600083815260200190815260200160002060100160159054906101000a900460ff1660ff161461067657600080fd5b600060036000838152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073951d1f73f30716fe0d3e9f9998486fd1f48b68a173ffffffffffffffffffffffffffffffffffffffff16636da42a15886040518263ffffffff1660e01b81526004016107009190614f1c565b600060405180830381865afa15801561071d573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061074691906153a3565b905060078160008151811061075e5761075d6153ec565b5b602002602001015103611195576000600182600181518110610783576107826153ec565b5b6020026020010151146107cd57600360008581526020019081526020016000206005015460036000868152602001908152602001600020600401546107c8919061544a565b610806565b60036000858152602001908152602001600020600501546003600086815260200190815260200160002060040154610805919061547e565b5b905061081061472a565b60036000868152602001908152602001600020600d0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16816040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060036000868152602001908152602001600020600e0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16816060019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600380600087815260200190815260200160002060100160149054906101000a900460ff1660ff1603610ed3578860036000878152602001908152602001600020600001541461095257600360008681526020019081526020016000206000015461096a565b60036000868152602001908152602001600020600101545b816020018181525050600073951d1f73f30716fe0d3e9f9998486fd1f48b68a173ffffffffffffffffffffffffffffffffffffffff16636da42a1583602001516040518263ffffffff1660e01b81526004016109c69190614f1c565b600060405180830381865afa1580156109e3573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610a0c91906153a3565b905060606000600667ffffffffffffffff811115610a2d57610a2c614ce7565b5b604051908082528060200260200182016040528015610a5b5781602001602082028036833780820191505090505b509050600360008981526020019081526020016000206002015481600081518110610a8957610a886153ec565b5b602002602001018181525050600360008981526020019081526020016000206003015481600181518110610ac057610abf6153ec565b5b6020026020010181815250508481600281518110610ae157610ae06153ec565b5b602002602001018181525050600360008981526020019081526020016000206005015481600381518110610b1857610b176153ec565b5b602002602001018181525050600360008981526020019081526020016000206006015481600481518110610b4f57610b4e6153ec565b5b602002602001018181525050600360008981526020019081526020016000206007015481600581518110610b8657610b856153ec565b5b602002602001018181525050730ae75c6cdf6949b900be26d8c0fd52943e30422f73ffffffffffffffffffffffffffffffffffffffff1663b10557348886604001518760600151858b896040518763ffffffff1660e01b8152600401610bf1969594939291906154b2565b600060405180830381865afa158015610c0e573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610c379190615554565b8560c0018194508260ff1660ff16815250505060008460c0015160ff161115610cf05733600360008a815260200190815260200160002060100160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508360c00151600360008a815260200190815260200160002060100160156101000a81548160ff021916908360ff16021790555050505050505050505061151a565b610cfa8c87613b31565b600084602001511115610d1657610d15846020015184613b31565b5b84600360008a815260200190815260200160002060040181905550600082600081518110610d4757610d466153ec565b5b60200260200101511115610de15760008b9050610da688866040015185600081518110610d7757610d766153ec565b5b6020026020010151886060015187600181518110610d9857610d976153ec565b5b602002602001015186614072565b905088600160008381526020019081526020016000208190555080600360008b81526020019081526020016000206000018190555050610dfe565b6000600360008a8152602001908152602001600020600001819055505b600082600281518110610e1457610e136153ec565b5b60200260200101511115610eae5760008a9050610e7388866060015185600281518110610e4457610e436153ec565b5b6020026020010151886040015187600381518110610e6557610e646153ec565b5b602002602001015186614072565b905088600160008381526020019081526020016000208190555080600360008b81526020019081526020016000206001018190555050610ecb565b6000600360008a8152602001908152602001600020600101819055505b50505061118e565b600060036000878152602001908152602001600020600301546003600088815260200190815260200160002060020154610f0d919061547e565b9050730ae75c6cdf6949b900be26d8c0fd52943e30422f73ffffffffffffffffffffffffffffffffffffffff1663fe908a9c86846040015185606001518588600360008e8152602001908152602001600020600601546040518763ffffffff1660e01b8152600401610f84969594939291906155b0565b606060405180830381865afa158015610fa1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc59190615611565b8460c001856000018660200183815250838152508360ff1660ff1681525050505060648260c0015160ff160361108d57610fff8a85613b31565b8060036000888152602001908152602001600020600201819055508260036000888152602001908152602001600020600401819055506110538583604001518460000151856060015186602001518e614072565b905085600160008381526020019081526020016000208190555080600360008881526020019081526020016000206000018190555061118c565b60c88260c0015160ff16036110f7576110a68a85613b31565b6000600360008881526020019081526020016000206000018190555060c86003600088815260200190815260200160002060100160156101000a81548160ff021916908360ff16021790555061118b565b336003600088815260200190815260200160002060100160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508160c001516003600088815260200190815260200160002060100160156101000a81548160ff021916908360ff1602179055505050505050505061151a565b5b505b50506114fe565b6009816000815181106111ab576111aa6153ec565b5b6020026020010151036114f45760008060008960036000888152602001908152602001600020600001541461124d5760036000878152602001908152602001600020600e0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660036000888152602001908152602001600020600d0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166112bc565b60036000878152602001908152602001600020600d0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660036000888152602001908152602001600020600e0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff165b91509150730ae75c6cdf6949b900be26d8c0fd52943e30422f73ffffffffffffffffffffffffffffffffffffffff1663ad148af4868487600281518110611306576113056153ec565b5b602002602001015188600281518110611322576113216153ec565b5b60200260200101516040518563ffffffff1660e01b81526004016113499493929190615664565b602060405180830381865afa158015611366573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138a91906156a9565b925060008360ff16111561142857336003600088815260200190815260200160002060100160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550826003600088815260200190815260200160002060100160156101000a81548160ff021916908360ff1602179055505050505050505061151a565b6114328a85613b31565b600061147886848760028151811061144d5761144c6153ec565b5b6020026020010151858960038151811061146a576114696153ec565b5b60200260200101518f614072565b90508660016000838152602001908152602001600020819055508a6003600089815260200190815260200160002060000154036114cf578060036000898152602001908152602001600020600001819055506114eb565b8060036000898152602001908152602001600020600101819055505b505050506114fd565b5050505061151a565b5b6115158383335a88611510919061544a565b61411f565b505050505b505050565b3273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461158d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161158490615722565b60405180910390fd5b6115956147c2565b868160400181815250508581606001818152505084816080018181525050838160a0018181525050828160c001818152505088816101a0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505087816101c0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505033816101e0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600080730ae75c6cdf6949b900be26d8c0fd52943e30422f73ffffffffffffffffffffffffffffffffffffffff1663acbfa21d338d8d8d8d8d8d8d6040518963ffffffff1660e01b81526004016116d0989796959493929190615742565b608060405180830381865afa1580156116ed573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061171191906157c0565b866102400187610220018296508397508460ff1660ff168152508460ff1660ff1681525050505050606483610240015160ff161461174e57600080fd5b61175c338c848d8589614072565b836000018181525050600080815461177390615827565b919050819055506000805490508360036000838152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015560a0820151816005015560c0820151816006015560e082015181600701556101008201518160080155610120820151816009015561014082015181600a015561016082015181600b015561018082015181600c01556101a082015181600d0160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101c082015181600e0160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101e082015181600f0160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102008201518160100160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102208201518160100160146101000a81548160ff021916908360ff1602179055506102408201518160100160156101000a81548160ff021916908360ff160217905550905050806001600086600001518152602001908152602001600020819055506119a833826141eb565b807ff9e873657e730881eafc125ef40143f79658208a374f800d4b5b34d98432e6ea60405160405180910390a2505050505050505050505050565b3273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611a51576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a4890615722565b60405180910390fd5b611a596147c2565b6000600267ffffffffffffffff811115611a7657611a75614ce7565b5b604051908082528060200260200182016040528015611aa45781602001602082028036833780820191505090505b509050730ae75c6cdf6949b900be26d8c0fd52943e30422f73ffffffffffffffffffffffffffffffffffffffff166390b5ef77338e8e8e8e8e8e8e8e6040518a63ffffffff1660e01b8152600401611b049998979695949392919061586f565b606060405180830381865afa158015611b21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b459190615611565b846102400184600081518110611b5e57611b5d6153ec565b5b6020026020010185600181518110611b7957611b786153ec565b5b6020026020010183815250838152508360ff1660ff16815250505050606582610240015160ff1603611bc4578a8c809c50819d505050606482610240019060ff16908160ff16815250505b606482610240015160ff1614611bd957600080fd5b898260400181815250508882606001818152505087826080018181525050868260a0018181525050858260c0018181525050848260e00181815250508b826101a0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508a826101c0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505033826101e0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600382610220019060ff16908160ff16815250506000808154611ce290615827565b91905081905550600080549050600082600081518110611d0557611d046153ec565b5b60200260200101511115611d6c57611d4633846101a001518d866101c0015186600081518110611d3857611d376153ec565b5b60200260200101518a614072565b836000018181525050806001600085600001518152602001908152602001600020819055505b600082600181518110611d8257611d816153ec565b5b60200260200101511115611de957611dc333846101c0015184600181518110611dae57611dad6153ec565b5b6020026020010151866101a001518e89614072565b836020018181525050806001600085602001518152602001908152602001600020819055505b8260036000838152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015560a0820151816005015560c0820151816006015560e082015181600701556101008201518160080155610120820151816009015561014082015181600a015561016082015181600b015561018082015181600c01556101a082015181600d0160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101c082015181600e0160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101e082015181600f0160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102008201518160100160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102208201518160100160146101000a81548160ff021916908360ff1602179055506102408201518160100160156101000a81548160ff021916908360ff160217905550905050611ff533826141eb565b807ff9e873657e730881eafc125ef40143f79658208a374f800d4b5b34d98432e6ea60405160405180910390a250505050505050505050505050565b6060600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000848152602001908152602001600020600101549250600083036120e257600167ffffffffffffffff8111156120ac576120ab614ce7565b5b6040519080825280602002602001820160405280156120da5781602001602082028036833780820191505090505b5090506126e9565b600080600e846120f291906158fc565b67ffffffffffffffff81111561210b5761210a614ce7565b5b6040519080825280602002602001820160405280156121395781602001602082028036833780820191505090505b50905060005b848110156126e25760008603156126e2578582848061215d90615827565b9550815181106121705761216f6153ec565b5b602002602001018181525050600260008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000878152602001908152602001600020600001548284806121dc90615827565b9550815181106121ef576121ee6153ec565b5b6020026020010181815250506003600087815260200190815260200160002060100160149054906101000a900460ff1660ff1682848061222e90615827565b955081518110612241576122406153ec565b5b602002602001018181525050600073951d1f73f30716fe0d3e9f9998486fd1f48b68a173ffffffffffffffffffffffffffffffffffffffff166336511013600360008a815260200190815260200160002060000154600360008b8152602001908152602001600020600101546040518363ffffffff1660e01b81526004016122ca929190615956565b600060405180830381865afa1580156122e7573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061231091906153a3565b905080600081518110612326576123256153ec565b5b602002602001015183858061233a90615827565b96508151811061234d5761234c6153ec565b5b6020026020010181815250508060018151811061236d5761236c6153ec565b5b602002602001015183858061238190615827565b965081518110612394576123936153ec565b5b602002602001018181525050806002815181106123b4576123b36153ec565b5b60200260200101518385806123c890615827565b9650815181106123db576123da6153ec565b5b602002602001018181525050806003815181106123fb576123fa6153ec565b5b602002602001015183858061240f90615827565b965081518110612422576124216153ec565b5b602002602001018181525050600360008881526020019081526020016000206009015483858061245190615827565b965081518110612464576124636153ec565b5b60200260200101818152505060036000888152602001908152602001600020600a015483858061249390615827565b9650815181106124a6576124a56153ec565b5b60200260200101818152505060036000888152602001908152602001600020600b01548385806124d590615827565b9650815181106124e8576124e76153ec565b5b60200260200101818152505060036000888152602001908152602001600020600c015483858061251790615827565b96508151811061252a576125296153ec565b5b60200260200101818152505060036000888152602001908152602001600020600d0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1683858061258f90615827565b9650815181106125a2576125a16153ec565b5b60200260200101818152505060036000888152602001908152602001600020600e0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1683858061260790615827565b96508151811061261a576126196153ec565b5b6020026020010181815250506003600088815260200190815260200160002060100160159054906101000a900460ff1660ff1683858061265990615827565b96508151811061266c5761266b6153ec565b5b602002602001018181525050600260008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008881526020019081526020016000206001015496505080806126da90615827565b91505061213f565b5080925050505b9392505050565b6000638943ec0260e01b90509392505050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b60005481565b6000600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002060000154116127e557600080fd5b60006003600083815260200190815260200160002060100160159054906101000a900460ff16905060648160ff1614158015612825575060c88160ff1614155b1561286e5761286d82336003600086815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600061411f565b5b60c88160ff1614612a0a57600060036000848152602001908152602001600020600001549050600060036000858152602001908152602001600020600101549050600082111561295b57600073951d1f73f30716fe0d3e9f9998486fd1f48b68a173ffffffffffffffffffffffffffffffffffffffff16636da42a15846040518263ffffffff1660e01b81526004016129079190614f1c565b600060405180830381865afa158015612924573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061294d91906153a3565b90506129598382613b31565b505b6000811115612a0757600073951d1f73f30716fe0d3e9f9998486fd1f48b68a173ffffffffffffffffffffffffffffffffffffffff16636da42a15836040518263ffffffff1660e01b81526004016129b39190614f1c565b600060405180830381865afa1580156129d0573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906129f991906153a3565b9050612a058282613b31565b505b50505b612a143383614385565b60036000838152602001908152602001600020600080820160009055600182016000905560028201600090556003820160009055600482016000905560058201600090556006820160009055600782016000905560088201600090556009820160009055600a820160009055600b820160009055600c820160009055600d820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600e820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600f820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556010820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556010820160146101000a81549060ff02191690556010820160156101000a81549060ff02191690555050817fa72f695a885e7ae6c69d169d271a0fff49ed6dea3bf49329e817a3cc4666cb4560405160405180910390a25050565b612b8f6147c2565b600360008381526020019081526020016000206040518061026001604052908160008201548152602001600182015481526020016002820154815260200160038201548152602001600482015481526020016005820154815260200160068201548152602001600782015481526020016008820154815260200160098201548152602001600a8201548152602001600b8201548152602001600c8201548152602001600d820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600e820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600f820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016010820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016010820160149054906101000a900460ff1660ff1660ff1681526020016010820160159054906101000a900460ff1660ff1660ff16815250509050919050565b612dd161472a565b612dd961472a565b6000600160008581526020019081526020016000205490506003600082815260200190815260200160002060100160159054906101000a900460ff168260c0019060ff16908160ff168152505060648260c0015160ff1614612e3f5781925050506138a8565b600073951d1f73f30716fe0d3e9f9998486fd1f48b68a173ffffffffffffffffffffffffffffffffffffffff16636da42a15866040518263ffffffff1660e01b8152600401612e8e9190614f1c565b600060405180830381865afa158015612eab573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190612ed491906153a3565b9050600781600081518110612eec57612eeb6153ec565b5b60200260200101510361364e576000600182600181518110612f1157612f106153ec565b5b602002602001015114612f5b5760036000848152602001908152602001600020600501546003600085815260200190815260200160002060040154612f56919061544a565b612f94565b60036000848152602001908152602001600020600501546003600085815260200190815260200160002060040154612f93919061547e565b5b9050600060036000858152602001908152602001600020600d0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16856040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060036000858152602001908152602001600020600e0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16856060019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600380600086815260200190815260200160002060100160149054906101000a900460ff1660ff16036135a15784606001518560400151866080018760a0018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152508273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815250505060018360018151811061312b5761312a6153ec565b5b60200260200101510361336c5761318385604001518660600151600360008881526020019081526020016000206002015460036000898152602001908152602001600020600501548661317e919061547e565b614556565b90506131af856040015160036000878152602001908152602001600020600201548760600151846145fe565b856000018181525050600073951d1f73f30716fe0d3e9f9998486fd1f48b68a173ffffffffffffffffffffffffffffffffffffffff16636da42a1560036000888152602001908152602001600020600101546040518263ffffffff1660e01b815260040161321d9190614f1c565b600060405180830381865afa15801561323a573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061326391906153a3565b9050600060018260008151811061327d5761327c6153ec565b5b602002602001015114806132ac57506006826000815181106132a2576132a16153ec565b5b6020026020010151145b806132d257506009826000815181106132c8576132c76153ec565b5b6020026020010151145b6132f257600360008781526020019081526020016000206003015461330f565b81600381518110613306576133056153ec565b5b60200260200101515b905061334687608001518860a0015183600360008b81526020019081526020016000206005015488613341919061544a565b614556565b925061335c8760800151848960a00151846145fe565b876020018181525050505061359c565b6133b785608001518660a0015160036000888152602001908152602001600020600301546003600089815260200190815260200160002060050154866133b2919061544a565b614556565b90506133e38560800151828760a0015160036000898152602001908152602001600020600301546145fe565b856020018181525050600073951d1f73f30716fe0d3e9f9998486fd1f48b68a173ffffffffffffffffffffffffffffffffffffffff16636da42a1560036000888152602001908152602001600020600001546040518263ffffffff1660e01b81526004016134519190614f1c565b600060405180830381865afa15801561346e573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061349791906153a3565b905060006001826000815181106134b1576134b06153ec565b5b602002602001015114806134e057506006826000815181106134d6576134d56153ec565b5b6020026020010151145b8061350657506009826000815181106134fc576134fb6153ec565b5b6020026020010151145b613526576003600087815260200190815260200160002060020154613543565b8160028151811061353a576135396153ec565b5b60200260200101515b905061357a8760400151886060015183600360008b81526020019081526020016000206005015488613575919061547e565b614556565b92506135908760400151828960600151866145fe565b87600001818152505050505b613647565b6000600360008681526020019081526020016000206003015460036000878152602001908152602001600020600201546135db919061547e565b90506135f1866040015187606001518386614556565b9150600184600181518110613609576136086153ec565b5b60200260200101511461361d578181613620565b80825b809350819250505061363c8660400151828860600151856145fe565b866000018181525050505b50506138a1565b600981600081518110613664576136636153ec565b5b6020026020010151036138a0578460036000848152602001908152602001600020600001540361376f5760036000838152602001908152602001600020600d0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060036000838152602001908152602001600020600e0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836060019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505061384c565b60036000838152602001908152602001600020600e0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060036000838152602001908152602001600020600d0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836060019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250505b613896836040015182600281518110613868576138676153ec565b5b6020026020010151856060015184600381518110613889576138886153ec565b5b60200260200101516145fe565b8360000181815250505b5b8293505050505b919050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461393d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016139349061523a565b60405180910390fd5b6001600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508073ffffffffffffffffffffffffffffffffffffffff167f9772798610937341d23a69ec5e3f97727ff869179644b17db536f12ef374bfc460405160405180910390a250565b73951d1f73f30716fe0d3e9f9998486fd1f48b68a181565b60006003600083815260200190815260200160002060100160159054906101000a900460ff16905060008160ff1611613a2b57600080fd5b60648160ff1614158015613a43575060c88160ff1614155b613a4c57600080fd5b60036000838152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614613aba57600080fd5b613afd82336003600086815260200190815260200160002060100160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600061411f565b60646003600084815260200190815260200160002060100160156101000a81548160ff021916908360ff1602179055505050565b600060016000848152602001908152602001600020549050600060036000838152602001908152602001600020600f0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060008085600360008681526020019081526020016000206000015403613cd45760036000858152602001908152602001600020600d0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660036000868152602001908152602001600020600e0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168092508193505050600085600581518110613c3057613c2f6153ec565b5b60200260200101511115613ccf5784600481518110613c5257613c516153ec565b5b6020026020010151600360008681526020019081526020016000206009016000828254613c7f919061547e565b9250508190555084600581518110613c9a57613c996153ec565b5b602002602001015160036000868152602001908152602001600020600a016000828254613cc7919061547e565b925050819055505b613e00565b60036000858152602001908152602001600020600e0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660036000868152602001908152602001600020600d0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168092508193505050600085600581518110613d6057613d5f6153ec565b5b60200260200101511115613dff5784600481518110613d8257613d816153ec565b5b602002602001015160036000868152602001908152602001600020600b016000828254613daf919061547e565b9250508190555084600581518110613dca57613dc96153ec565b5b602002602001015160036000868152602001908152602001600020600c016000828254613df7919061547e565b925050819055505b5b600085600581518110613e1657613e156153ec565b5b60200260200101511115613e4b57613e4a818487600581518110613e3d57613e3c6153ec565b5b60200260200101516146a6565b5b6000600167ffffffffffffffff811115613e6857613e67614ce7565b5b604051908082528060200260200182016040528015613e965781602001602082028036833780820191505090505b509050600086600281518110613eaf57613eae6153ec565b5b60200260200101511115613f9b578681600081518110613ed257613ed16153ec565b5b60200260200101818152505073951d1f73f30716fe0d3e9f9998486fd1f48b68a173ffffffffffffffffffffffffffffffffffffffff1663b55fb574826040518263ffffffff1660e01b8152600401613f2b9190614caa565b6000604051808303816000875af1158015613f4a573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190613f7391906153a3565b50613f9a838588600281518110613f8d57613f8c6153ec565b5b60200260200101516146a6565b5b8681600081518110613fb057613faf6153ec565b5b60200260200101818152505073951d1f73f30716fe0d3e9f9998486fd1f48b68a173ffffffffffffffffffffffffffffffffffffffff166375b02405826040518263ffffffff1660e01b81526004016140099190614caa565b6000604051808303816000875af1158015614028573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061405191906153a3565b50600160008881526020019081526020016000206000905550505050505050565b600080735cec09f125f4839656164a5109bc076daabd6ed673ffffffffffffffffffffffffffffffffffffffff166322fe7c6f8989898989896040518763ffffffff1660e01b81526004016140cc9695949392919061597f565b6020604051808303816000875af11580156140eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061410f91906159e0565b9050809150509695505050505050565b6000735cec09f125f4839656164a5109bc076daabd6ed673ffffffffffffffffffffffffffffffffffffffff16637c0b052a8585856040518463ffffffff1660e01b815260040161417293929190615a0d565b6020604051808303816000875af1158015614191573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141b591906159e0565b9050806003600087815260200190815260200160002060080160008282546141dd919061547e565b925050819055505050505050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600080815260200190815260200160002060020154905081600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206001018190555081600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008081526020019081526020016000206002018190555060405180606001604052804281526020016000815260200182815250600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000848152602001908152602001600020600082015181600001556020820151816001015560408201518160020155905050505050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206001015490506000600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060020154905081600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206001018190555080600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060020181905550600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060008082016000905560018201600090556002820160009055505050505050565b600080735cec09f125f4839656164a5109bc076daabd6ed673ffffffffffffffffffffffffffffffffffffffff166365593d7b878787876040518563ffffffff1660e01b81526004016145ac9493929190615664565b6040805180830381865afa1580156145c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145ec9190615a44565b90508091505080915050949350505050565b600080735cec09f125f4839656164a5109bc076daabd6ed673ffffffffffffffffffffffffffffffffffffffff166366555804878787876040518563ffffffff1660e01b81526004016146549493929190615a84565b6040805180830381865afa158015614670573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146949190615a44565b90508091505080915050949350505050565b8273ffffffffffffffffffffffffffffffffffffffff1663a9059cbb83836040518363ffffffff1660e01b81526004016146e1929190615ac9565b6020604051808303816000875af1158015614700573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147249190615b1e565b50505050565b6040518060e001604052806000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600060ff1681525090565b60405180610260016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600060ff168152602001600060ff1681525090565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006148dd826148b2565b9050919050565b6148ed816148d2565b82525050565b600060208201905061490860008301846148e4565b92915050565b6000604051905090565b600080fd5b600080fd5b61492b816148d2565b811461493657600080fd5b50565b60008135905061494881614922565b92915050565b60006020828403121561496457614963614918565b5b600061497284828501614939565b91505092915050565b6000819050919050565b61498e8161497b565b811461499957600080fd5b50565b6000813590506149ab81614985565b92915050565b6000806000606084860312156149ca576149c9614918565b5b60006149d88682870161499c565b93505060206149e98682870161499c565b92505060406149fa8682870161499c565b9150509250925092565b600080600080600080600080610100898b031215614a2557614a24614918565b5b6000614a338b828c01614939565b9850506020614a448b828c01614939565b9750506040614a558b828c0161499c565b9650506060614a668b828c0161499c565b9550506080614a778b828c0161499c565b94505060a0614a888b828c0161499c565b93505060c0614a998b828c0161499c565b92505060e0614aaa8b828c0161499c565b9150509295985092959890939650565b6000806000806000806000806000806101408b8d031215614ade57614add614918565b5b6000614aec8d828e01614939565b9a50506020614afd8d828e01614939565b9950506040614b0e8d828e0161499c565b9850506060614b1f8d828e0161499c565b9750506080614b308d828e0161499c565b96505060a0614b418d828e0161499c565b95505060c0614b528d828e0161499c565b94505060e0614b638d828e0161499c565b935050610100614b758d828e0161499c565b925050610120614b878d828e0161499c565b9150509295989b9194979a5092959850565b600080600060608486031215614bb257614bb1614918565b5b6000614bc086828701614939565b9350506020614bd18682870161499c565b9250506040614be28682870161499c565b9150509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b614c218161497b565b82525050565b6000614c338383614c18565b60208301905092915050565b6000602082019050919050565b6000614c5782614bec565b614c618185614bf7565b9350614c6c83614c08565b8060005b83811015614c9d578151614c848882614c27565b9750614c8f83614c3f565b925050600181019050614c70565b5085935050505092915050565b60006020820190508181036000830152614cc48184614c4c565b905092915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b614d1f82614cd6565b810181811067ffffffffffffffff82111715614d3e57614d3d614ce7565b5b80604052505050565b6000614d5161490e565b9050614d5d8282614d16565b919050565b600067ffffffffffffffff821115614d7d57614d7c614ce7565b5b614d8682614cd6565b9050602081019050919050565b82818337600083830152505050565b6000614db5614db084614d62565b614d47565b905082815260208101848484011115614dd157614dd0614cd1565b5b614ddc848285614d93565b509392505050565b600082601f830112614df957614df8614ccc565b5b8135614e09848260208601614da2565b91505092915050565b600080600060608486031215614e2b57614e2a614918565b5b6000614e3986828701614939565b9350506020614e4a8682870161499c565b925050604084013567ffffffffffffffff811115614e6b57614e6a61491d565b5b614e7786828701614de4565b9150509250925092565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b614eb681614e81565b82525050565b6000602082019050614ed16000830184614ead565b92915050565b60008115159050919050565b614eec81614ed7565b82525050565b6000602082019050614f076000830184614ee3565b92915050565b614f168161497b565b82525050565b6000602082019050614f316000830184614f0d565b92915050565b600060208284031215614f4d57614f4c614918565b5b6000614f5b8482850161499c565b91505092915050565b614f6d816148d2565b82525050565b600060ff82169050919050565b614f8981614f73565b82525050565b61026082016000820151614fa66000850182614c18565b506020820151614fb96020850182614c18565b506040820151614fcc6040850182614c18565b506060820151614fdf6060850182614c18565b506080820151614ff26080850182614c18565b5060a082015161500560a0850182614c18565b5060c082015161501860c0850182614c18565b5060e082015161502b60e0850182614c18565b50610100820151615040610100850182614c18565b50610120820151615055610120850182614c18565b5061014082015161506a610140850182614c18565b5061016082015161507f610160850182614c18565b50610180820151615094610180850182614c18565b506101a08201516150a96101a0850182614f64565b506101c08201516150be6101c0850182614f64565b506101e08201516150d36101e0850182614f64565b506102008201516150e8610200850182614f64565b506102208201516150fd610220850182614f80565b50610240820151615112610240850182614f80565b50505050565b60006102608201905061512e6000830184614f8f565b92915050565b60e08201600082015161514a6000850182614c18565b50602082015161515d6020850182614c18565b5060408201516151706040850182614f64565b5060608201516151836060850182614f64565b5060808201516151966080850182614f64565b5060a08201516151a960a0850182614f64565b5060c08201516151bc60c0850182614f80565b50505050565b600060e0820190506151d76000830184615134565b92915050565b600082825260208201905092915050565b7f4f6e6c79206f776e65722063616e2063616c6c20746869730000000000000000600082015250565b60006152246018836151dd565b915061522f826151ee565b602082019050919050565b6000602082019050818103600083015261525381615217565b9050919050565b7f4f6e6c79206f7261636c652063616e2063616c6c207468697300000000000000600082015250565b60006152906019836151dd565b915061529b8261525a565b602082019050919050565b600060208201905081810360008301526152bf81615283565b9050919050565b600067ffffffffffffffff8211156152e1576152e0614ce7565b5b602082029050602081019050919050565b600080fd5b60008151905061530681614985565b92915050565b600061531f61531a846152c6565b614d47565b90508083825260208201905060208402830185811115615342576153416152f2565b5b835b8181101561536b578061535788826152f7565b845260208401935050602081019050615344565b5050509392505050565b600082601f83011261538a57615389614ccc565b5b815161539a84826020860161530c565b91505092915050565b6000602082840312156153b9576153b8614918565b5b600082015167ffffffffffffffff8111156153d7576153d661491d565b5b6153e384828501615375565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006154558261497b565b91506154608361497b565b92508282039050818111156154785761547761541b565b5b92915050565b60006154898261497b565b91506154948361497b565b92508282019050808211156154ac576154ab61541b565b5b92915050565b600060c0820190506154c760008301896148e4565b6154d460208301886148e4565b6154e160408301876148e4565b81810360608301526154f38186614c4c565b905081810360808301526155078185614c4c565b905081810360a083015261551b8184614c4c565b9050979650505050505050565b61553181614f73565b811461553c57600080fd5b50565b60008151905061554e81615528565b92915050565b6000806040838503121561556b5761556a614918565b5b60006155798582860161553f565b925050602083015167ffffffffffffffff81111561559a5761559961491d565b5b6155a685828601615375565b9150509250929050565b600060c0820190506155c560008301896148e4565b6155d260208301886148e4565b6155df60408301876148e4565b6155ec6060830186614f0d565b6155f96080830185614f0d565b61560660a0830184614f0d565b979650505050505050565b60008060006060848603121561562a57615629614918565b5b60006156388682870161553f565b9350506020615649868287016152f7565b925050604061565a868287016152f7565b9150509250925092565b600060808201905061567960008301876148e4565b61568660208301866148e4565b6156936040830185614f0d565b6156a06060830184614f0d565b95945050505050565b6000602082840312156156bf576156be614918565b5b60006156cd8482850161553f565b91505092915050565b7f4f6e6c7920454f41000000000000000000000000000000000000000000000000600082015250565b600061570c6008836151dd565b9150615717826156d6565b602082019050919050565b6000602082019050818103600083015261573b816156ff565b9050919050565b600061010082019050615758600083018b6148e4565b615765602083018a6148e4565b61577260408301896148e4565b61577f6060830188614f0d565b61578c6080830187614f0d565b61579960a0830186614f0d565b6157a660c0830185614f0d565b6157b360e0830184614f0d565b9998505050505050505050565b600080600080608085870312156157da576157d9614918565b5b60006157e88782880161553f565b94505060206157f98782880161553f565b935050604061580a878288016152f7565b925050606061581b878288016152f7565b91505092959194509250565b60006158328261497b565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036158645761586361541b565b5b600182019050919050565b600061012082019050615885600083018c6148e4565b615892602083018b6148e4565b61589f604083018a6148e4565b6158ac6060830189614f0d565b6158b96080830188614f0d565b6158c660a0830187614f0d565b6158d360c0830186614f0d565b6158e060e0830185614f0d565b6158ee610100830184614f0d565b9a9950505050505050505050565b60006159078261497b565b91506159128361497b565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561594b5761594a61541b565b5b828202905092915050565b600060408201905061596b6000830185614f0d565b6159786020830184614f0d565b9392505050565b600060c08201905061599460008301896148e4565b6159a160208301886148e4565b6159ae6040830187614f0d565b6159bb60608301866148e4565b6159c86080830185614f0d565b6159d560a0830184614f0d565b979650505050505050565b6000602082840312156159f6576159f5614918565b5b6000615a04848285016152f7565b91505092915050565b6000606082019050615a2260008301866148e4565b615a2f60208301856148e4565b615a3c6040830184614f0d565b949350505050565b60008060408385031215615a5b57615a5a614918565b5b6000615a698582860161553f565b9250506020615a7a858286016152f7565b9150509250929050565b6000608082019050615a9960008301876148e4565b615aa66020830186614f0d565b615ab360408301856148e4565b615ac06060830184614f0d565b95945050505050565b6000604082019050615ade60008301856148e4565b615aeb6020830184614f0d565b9392505050565b615afb81614ed7565b8114615b0657600080fd5b50565b600081519050615b1881615af2565b92915050565b600060208284031215615b3457615b33614918565b5b6000615b4284828501615b09565b9150509291505056fea264697066735822122019d8abc0ce51426296fc5251d58d7ccdfdd241ae2fa49554147dc9681798e0cf64736f6c63430008100033